SetWindowPos <2>

本文深入解析了VB与VC中的SetWindowPos函数,详细介绍了其功能、参数及其在调整窗口位置、层级与大小方面的应用。通过实例代码展示了如何使用此函数实现窗口的动态管理。

VB: 
函数原型
  BOOL SetWindowPos(HWND hWnd,HWND hWndlnsertAfter,int X,int Y,int cx,int cy,UNIT.Flags); 
函数功能
  该函数改变一个子窗口,弹出式窗口式顶层窗口的尺寸,位置和Z序。 
  子窗口,弹出式窗口,及顶层窗口根据它们在屏幕上出现的顺序排序、顶层窗口设置的级别最高,并且被设置为Z序的第一个窗口。 
参数
  hWnd:窗口句柄。 
  hWndlnsertAfter:在z序中的位于被置位的窗口前的窗口句柄。该参数必须为一个窗口句柄,或下列值之一: 
  HWND_BOTTOM:将窗口置于Z序的底部。如果参数hWnd标识了一个顶层窗口,则窗口失去顶级位置,并且被置在其他窗口的底部。 
  HWND_NOTOPMOST:将窗口置于所有非顶层窗口之上(即在所有顶层窗口之后)。如果窗口已经是非顶层窗口则该标志不起作用。 
  HWND_TOP:将窗口置于Z序的顶部。 
  HWND_TOPMOST:将窗口置于所有非顶层窗口之上。即使窗口未被激活窗口也将保持顶级位置。 
  查看该参数的使用方法,请看说明部分。 
  x:以客户坐标指定窗口新位置的左边界。 
  Y:以客户坐标指定窗口新位置的顶边界。 
  cx:以像素指定窗口的新的宽度。 
  cy:以像素指定窗口的新的高度。 
  uFlags:窗口尺寸和定位的标志。该参数可以是下列值的组合: 
  SWP_ASNCWINDOWPOS:如果调用进程不拥有窗口,系统会向拥有窗口的线程发出需求。这就防止调用线程在其他线程处理需求的时候发生死锁。 
  SWP_DEFERERASE:防止产生WM_SYNCPAINT消息。 
  SWP_DRAWFRAME:在窗口周围画一个边框(定义在窗口类描述中)。 
  SWP_FRAMECHANGED:给窗口发送WM_NCCALCSIZE消息,即使窗口尺寸没有改变也会发送该消息。如果未指定这个标志,只有在改变了窗口尺寸时才发送WM_NCCALCSIZE。 
  SWP_HIDEWINDOW;隐藏窗口。 
  SWP_NOACTIVATE:不激活窗口。如果未设置标志,则窗口被激活,并被设置到其他最高级窗口或非最高级组的顶部(根据参数hWndlnsertAfter设置)。 
  SWP_NOCOPYBITS:清除客户区的所有内容。如果未设置该标志,客户区的有效内容被保存并且在窗口尺寸更新和重定位后拷贝回客户区。 
  SWP_NOMOVE:维持当前位置(忽略X和Y参数)。 
  SWP_NOOWNERZORDER:不改变z序中的所有者窗口的位置。 
  SWP_NOREDRAW:不重画改变的内容。如果设置了这个标志,则不发生任何重画动作。适用于客户区和非客户区(包括标题栏和滚动条)和任何由于窗回移动而露出的父窗口的所有部分。如果设置了这个标志,应用程序必须明确地使窗口无效并区重画窗口的任何部分和父窗口需要重画的部分。 
  SWP_NOREPOSITION;与SWP_NOOWNERZORDER标志相同。 
  SWP_NOSENDCHANGING:防止窗口接收WM_WINDOWPOSCHANGING消息。 
  SWP_NOSIZE:维持当前尺寸(忽略cx和Cy参数)。 
  SWP_NOZORDER:维持当前Z序(忽略hWndlnsertAfter参数)。 
  SWP_SHOWWINDOW:显示窗口。 
  返回值:如果函数成功,返回值为非零;如果函数失败,返回值为零。若想获得更多错误消息,请调用GetLastError函数。 
其它相关
  备注:如果设置了SWP_SHOWWINDOW和SWP_HIDEWINDOW标志,则窗口不能被移动和改变大小。如果使用SetWindowLong改变了窗口的某些数据,则必须调用函数SetWindowPos来作真正的改变。使用下列的组合标志:SWP_NOMOVEISWP_NOSIZEISWP_FRAMECHANGED。 
  有两种方法将窗口设为最顶层窗口:一种是将参数hWndlnsertAfter设置为HWND_TOPMOST并确保没有设置SWP_NOZORDER标志;另一种是设置窗口在Z序中的位置以使其在其他存在的窗口之上。当一个窗口被置为最顶层窗口时,属于它的所有窗口均为最顶层窗口,而它的所有者的z序并不改变。 
  如果HWND_TOPMOST和HWND_NOTOPMOST标志均未指定,即应用程序要求窗口在激活的同时改变其在Z序中的位置时,在参数hWndinsertAfter中指定的值只有在下列条件中才使用: 
  在hWndlnsertAfter参数中没有设定HWND_NOTOPMOST和HWND_TOPMOST标志。 
  由hWnd参数标识的窗口不是激活窗口。 
  如果未将一个非激活窗口设定到z序的顶端,应用程序不能激活该窗口。应用程序可以无任何限制地改变被激活窗口在Z序中的位置,或激活一个窗口并将其移到最高级窗口的顶部或非最高级窗口的顶部。 
  如果一个顶层窗口被重定位到z序的底部(HWND_BOTTOM)或在任何非最高序的窗口之后,该窗口就不再是最顶层窗口。当一个最顶层窗口被置为非最顶级,则它的所有者窗口和所属者窗口均为非最顶层窗口。 
  一个非最顶端窗口可以拥有一个最顶端窗口,但反之则不可以。任何属于顶层窗口的窗口(例如一个对话框)本身就被置为顶层窗口,以确保所有被属窗口都在它们的所有者之上。 
  如果应用程序不在前台,但应该位于前台,就应调用SetForegroundWindow函数来设置。 
  Windows CE:如果这是一个可见的顶层窗口,并且未指定SWP_NOACTIVATE标志,则这个函数将激活窗口、如果这是当前的激活窗口,并且指定了SWP_NOACTIVATE或SWP_HIDEWINDOW标志,则激活另外一个可见的顶层窗口。 
  当在这个函数中的nFlags参数里指定了SWP_FRAMECHANGED标志时,WindowsCE重画窗口的整个非客户区,这可能会改变客户区的大小。这也是重新计算客户区的唯一途径,也是通过调用SetwindowLong函数改变窗口风格后通常使用的方法。 
  SetWindowPos将使WM_WINDOWPOSCHANGED消息向窗口发送,在这个消息中传递的标志与传递给函数的相同。这个函数不传递其他消息。 
  Windows CE 1.0不支持在hWndlnsertAber参数中的HWND_TOPMOST和HWND_NOTOPMOST常量。 
  Windows CE1.0不支持在fuFags参数中的SWP_DRAWFRAME和SWP_NOCOPYBITS标志。 
  速查:Windows NT:3.1以上版本;Windows:95以上版本;Windows CE:1.0以上版本;头文件:winuser.h库文件:eser32lib。 
VB6中使用例子:
  加入本函数的声明Private Declare Function SetWindowPos Lib "user32" Alias "SetWindowPos" (ByVal hwnd As Long, ByVal hWndInsertAfter As Long, ByVal x As Long, ByVal y As Long, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As Long 
  新建个控件 Check1 
  '完整代码如下: 
  Private Sub Check1_Click() 
  Dim Q 
  If Check1.Value = 1 Then 
  Q = SetWindowPos(Me.hWnd, -1, 0, 0, 0, 0, 3) 
  Else 
  Q = SetWindowPos(Me.hWnd, -2, 0, 0, 0, 0, 3) 
  End If 
  End Sub 
  Private Sub Form_Load() 
  Check1.Caption = "点击窗口置前" 
  End Sub 
   
VC:
函数原型
  BOOL SetWindowPos(const CWnd* pWndInsertAfter, int x, int y, int cx, int cy,UINT nFlags); 
函数功能
  调用这个成员函数以改变子窗口、弹出窗口和顶层窗口的大小、位置和Z轴次序。窗口在屏幕上按照它们的Z轴次序排序。在Z轴次序上处于顶端的窗口将程序在所有其它窗口的顶部。子窗口的所有坐标都是客户坐标(相对于父窗口客户区的左上角)。窗口可以被移动到Z轴次序的顶部,既可以通过将pWndInsertAfter参数设为&wndTopMost,并确保没有设置SWP_NOZORDER标志,也可以通过设置窗口的Z轴次序使它位于所有现存的顶层窗口上方。当一个非顶层窗口被设为顶层窗口时,它拥有的窗口也被设为顶层的。它的拥有者不发生变化。如果顶层窗口被重新定位到Z轴次序的底部(&wndBottom)或任何非顶层窗口之后,则它将不再是顶层窗口。当顶层窗口被变为非顶层窗口时,它所有的拥有者和它拥有的所有窗口都被变为非顶层窗口。 
参数
  pWndInsertAfter 
  标识了在Z轴次序上位于这个CWnd对象之前的CWnd对象。这个参数可以是指向CWnd对象的指针,也可以是指向下列值的指针: 
  wndBottom 将窗口放在Z轴次序的底部。如果这个CWnd是一个顶层窗口,则窗口将失去它的顶层状态;系统将这个窗口放在其它所有窗口的底部。 
  wndTop 将窗口放在Z轴次序的顶部。 
  wndTopMost 将窗口放在所有非顶层窗口的上面。这个窗口将保持它的顶层位置,即使它失去了活动状态。 
  wndNoTopMost 将窗口重新定位到所有非顶层窗口的顶部(这意味着在所有的顶层窗口之下)。这个标志对那些已经是非顶层窗口的窗口没有作用。有关这个函数以及这些参数的使用规则参见说明部分。 
  x指定了窗口左边的新位置。 
  y指定了窗口顶部的新位置。 
  cx指定了窗口的新宽度。 
  cy指定了窗口的新高度。 
  nFlags指定了大小和位置选项。这个参数可以是下列值的组合: 
  SWP_DRAWFRAME 围绕窗口画出边框(在创建窗口的时候定义)。 
  SWP_FRAMECHANGED 向窗口发送一条WM_NCCALCSIZE消息,即使窗口的大小不会改变。如果没有指定这个标志,则仅当窗口的大小发生变化时才发送WM_NCCALCSIZE消息。 
  SWP_HIDEWINDOW 隐藏窗口。 
  SWP_NOACTIVATE 不激活窗口。如果没有设置这个标志,则窗口将被激活并移动到顶层或非顶层窗口组(依赖于pWndInsertAfter参数的设置)的顶部。 
  SWP_NOCOPYBITS 废弃这个客户区的内容。如果没有指定这个参数,则客户区的有效内容将被保存,并在窗口的大小或位置改变以后被拷贝回客户区。 
  SWP_NOMOVE 保持当前的位置(忽略x和y参数)。 
  SWP_NOOWNERZORDER 不改变拥有者窗口在Z轴次序上的位置。 
  SWP_NOREDRAW 不重画变化。如果设置了这个标志,则不发生任何种类的变化。这适用于客户区、非客户区(包括标题和滚动条)以及被移动窗口覆盖的父窗口的任何部分。当这个标志被设置的时候,应用程序必须明确地无效或重画要重画的窗口和父窗口的任何部分。 
  SWP_NOREPOSITION 与SWP_NOOWNERZORDER相同。 
  SWP_NOSENDCHANGING 防止窗口接收WM_WINDOWPOSCHANGING消息。 
  SWP_NOSIZE 保持当前的大小(忽略cx和cy参数)。 
  SWP_NOZORDER 保持当前的次序(忽略pWndInsertAfter)。 
  SWP_SHOWWINDOW 显示窗口。 
VC6中的使用例子
  BOOL CDesktopADDlg::OnInitDialog() 
  { 
  CDialog::OnInitDialog(); 
  // 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动 
  // 执行此操作 
  SetIcon(m_hIcon, TRUE); // 设置大图标 
  SetIcon(m_hIcon, FALSE); // 设置小图标 
  // TODO: 在此添加额外的初始化代码 
  int cx = GetSystemMetrics(SM_CXSCREEN); 
  int cy = GetSystemMetrics(SM_CYSCREEN); 
  int dx = 600; 
  int dy = 400; 
  SetWindowPos(&wndBottom,cx-dx,cy-dy,dx,dy,SWP_NOACTIVATE); //设置广告窗口浮动于右下角 
  return TRUE; // 除非将焦点设置到控件,否则返回 TRUE 
  } 

转载于:https://www.cnblogs.com/cwbo-win/articles/3410172.html

<HTML> <HEAD> <TITLE>智能倒计时器</TITLE> <HTA:APPLICATION ID="objHTA" SCROLL="no" SINGLEINSTANCE="yes" WINDOWSTATE="normal"> <SCRIPT language="VBScript"> Sub SetTopMost() On Error Resume Next Dim objShell Set objShell = CreateObject("WScript.Shell") hwnd = window.external.HWND ' 关键修正点 If hwnd = 0 Then MsgBox "无法获取窗口句柄", 16, "错误" Exit Sub End If Const SWP_NOMOVE = &H2, SWP_NOSIZE = &H1 objShell.Run "mshta vbscript:Execute(""CreateObject('Shell.Application').WindowSwitcher().SetWindowPos "" & " & hwnd & ", -1, 0, 0, 0, 0, " & (SWP_NOMOVE Or SWP_NOSIZE) & ")", 0, True End Sub ' 调用示例:点击按钮触发置顶 Sub btnSetTop_Click() SetTopMost End Sub Dim targetTime, isRunning Function ParseTime(input) If IsNumeric(input) Then ParseTime = DateAdd("s", CLng(input)*60, Now()) ' 使用CLng增强数值转换 Else MsgBox "请输入有效数字", 48, "错误" ParseTime = Null End If End Function Sub UpdateDisplay() Dim elapsed elapsed = DateDiff("s", Now(), targetTime) If isRunning then If elapsed < 0 Then display.innerHTML = FormatTime(Abs(elapsed)) & "(超时)" display.style.color = "red" Else display.innerHTML = FormatTime(elapsed) display.style.color = "green" End If End If If isRunning Then window.setTimeout "UpdateDisplay", 200 End Sub Function FormatTime(seconds) Dim h, m, s h = seconds \ 3600 m = (seconds Mod 3600) \ 60 s = seconds Mod 60 FormatTime = Right("0" & h,2) & ":" & Right("0" & m,2) & ":" & Right("0" & s,2) End Function Sub StartTimer() If Not isRunning Then targetTime = ParseTime(setTime.value) ' 移除Set关键字 If Not IsNull(targetTime) Then isRunning = True UpdateDisplay End If End If End Sub Sub StopTimer() isRunning = False display.innerHTML = "00:00:00" display.style.color = "black" End Sub </SCRIPT> </HEAD> <style> #display { font-size: 20px; margin: 5px; padding: 5px; border: 2px solid #ccc; } </style> <BODY> <button onclick="btnSetTop_Click">窗口置顶</button> <input type="text" id="setTime" size="4"> 分钟 <button onclick="StartTimer">启动</button> <button onclick="StopTimer">停止</button> <div id="display" style="font-family:Consolas"></div> </BODY> </HTML>无法找到置顶窗口句柄
05-11
<HTML> <HEAD> <TITLE>智能倒计时器</TITLE> <HTA:APPLICATION ID="objHTA" SCROLL="no" SINGLEINSTANCE="yes" CONTEXT="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" WINDOWSTATE="normal"> <SCRIPT language="VBScript"> Sub SetTopMost() Dim objShell On Error Resume Next Set objShell = CreateObject("Shell.Application") If Err.Number <> 0 Then WScript.Echo "无法创建 Shell.Application 对象" WScript.Quit End If Dim window, count count = 0 For Each window In objShell.Windows ' 过滤非浏览器窗口(示例) If InStr(window.LocationURL, "http") > 0 Then count = count + 1 WScript.Echo "窗口标题: " & window.Name End If Next WScript.Echo "共找到 " & count & " 个浏览器窗口" Set objShell = Nothing If hwnd = 0 Then MsgBox "未找到HTA窗口", 16, "错误" Exit Sub End If End Sub ' 调用示例:点击按钮触发置顶 Sub btnSetTop_Click() SetTopMost End Sub Dim targetTime, isRunning Function ParseTime(input) If IsNumeric(input) Then ParseTime = DateAdd("s", CLng(input)*60, Now()) ' 使用CLng增强数值转换 Else MsgBox "请输入有效数字", 48, "错误" ParseTime = Null End If End Function Sub UpdateDisplay() Dim elapsed elapsed = DateDiff("s", Now(), targetTime) If isRunning then If elapsed < 0 Then display.innerHTML = FormatTime(Abs(elapsed)) & "(超时)" display.style.color = "red" Else display.innerHTML = FormatTime(elapsed) display.style.color = "green" End If End If If isRunning Then window.setTimeout "UpdateDisplay", 200 End Sub Function FormatTime(seconds) Dim h, m, s h = seconds \ 3600 m = (seconds Mod 3600) \ 60 s = seconds Mod 60 FormatTime = Right("0" & h,2) & ":" & Right("0" & m,2) & ":" & Right("0" & s,2) End Function Sub StartTimer() If Not isRunning Then targetTime = ParseTime(setTime.value) ' 移除Set关键字 If Not IsNull(targetTime) Then isRunning = True UpdateDisplay End If End If End Sub Sub StopTimer() isRunning = False display.innerHTML = "00:00:00" display.style.color = "black" End Sub </SCRIPT> </HEAD> <style> #display { font-size: 20px; margin: 5px; padding: 5px; border: 2px solid #ccc; } </style> <BODY> <button onclick="btnSetTop_Click">窗口置顶</button> <input type="text" id="setTime" size="4"> 分钟 <button onclick="StartTimer">启动</button> <button onclick="StopTimer">停止</button> <div id="display" style="font-family:Consolas"></div> </BODY> </HTML>窗口无法置顶,找不到窗口句柄
最新发布
11-25
#include <iostream> #include <vector> #include <string> #include <thread> #include <mutex> #include <filesystem> #include <sstream> #include <locale> #include <codecvt> #ifdef _WIN32 #include <windows.h> #include <shellapi.h> #define PATH_SEPARATOR L"\\" #define OS_WINDOWS #else #include <unistd.h> #define PATH_SEPARATOR L"/" #endif namespace fs = std::filesystem; // 字符串转换函数 std::wstring ConvertToWString(const std::string& str) { try { // 使用标准库转换工具 std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter; return converter.from_bytes(str); } catch (...) { // 转换失败时返回默认错误信息 return L"转换错误"; } } // 修复日志输出函数 void OutputLog(const std::wstring& msg) { #ifdef OS_WINDOWS // OutputDebugStringW(msg.c_str()); // 输出到调试器 // OutputDebugStringW(L"\n"); // wprintf(L"%S\n", msg.c_str()); #endif //std::wcout << msg << std::endl; std::wcerr << msg << std::endl; // 输出到控制台 } // 检查管理员权限(跨平台) bool CheckAdminPrivileges() { #ifdef OS_WINDOWS BOOL isAdmin = FALSE; SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY; PSID AdministratorsGroup = nullptr; if (!AllocateAndInitializeSid(&NtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &AdministratorsGroup)) { return false; } if (!CheckTokenMembership(nullptr, AdministratorsGroup, &isAdmin)) { FreeSid(AdministratorsGroup); return false; } FreeSid(AdministratorsGroup); return (isAdmin != FALSE); #else return (getuid() == 0); // Linux root检查 #endif } // 实际的文件夹监控函数(Win32 API实现) void MonitorDirectoryWin32(LPCWSTR path) { HANDLE hDir = CreateFileW( path, FILE_LIST_DIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, nullptr ); if (hDir == INVALID_HANDLE_VALUE) { OutputLog(L"监控失败: " + std::wstring(path)); return; } BYTE buffer[4096]; DWORD bytesReturned; FILE_NOTIFY_INFORMATION* pNotify; while (ReadDirectoryChangesW( hDir, buffer, sizeof(buffer), TRUE, FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME, &bytesReturned, nullptr, nullptr)) { pNotify = (FILE_NOTIFY_INFORMATION*)buffer; do { std::wstring filename(pNotify->FileName, pNotify->FileNameLength / sizeof(WCHAR)); switch (pNotify->Action) { case FILE_ACTION_ADDED: OutputLog(L"添加: " + filename); break; case FILE_ACTION_REMOVED: OutputLog(L"删除: " + filename); break; case FILE_ACTION_MODIFIED: OutputLog(L"修改: " + filename); break; case FILE_ACTION_RENAMED_OLD_NAME: OutputLog(L"重命名前: " + filename); break; case FILE_ACTION_RENAMED_NEW_NAME: OutputLog(L"重命名后: " + filename); break; } pNotify = pNotify->NextEntryOffset ? (FILE_NOTIFY_INFORMATION*)((BYTE*)pNotify + pNotify->NextEntryOffset) : nullptr; } while (pNotify); } CloseHandle(hDir); } // 递归监控实现(优化线程管理) void MonitorSubdirectories(const std::wstring& rootDir) { std::vector<std::thread> threads; std::mutex mtx; auto monitorFunc = [&mtx](const std::wstring & path) { OutputLog(L"开始监控: " + path); MonitorDirectoryWin32(path.c_str()); }; // 添加根目录 threads.emplace_back(monitorFunc, rootDir); // 递归添加子目录 try { for (const auto& entry : fs::recursive_directory_iterator(rootDir)) { if (entry.is_directory()) { std::lock_guard lock(mtx); threads.emplace_back(monitorFunc, entry.path().wstring()); } } } catch (const fs::filesystem_error& e) { // 使用转换函数处理异常消息 OutputLog(L"目录遍历错误: " + ConvertToWString(e.what())); } // 等待所有线程完成 for (auto& t : threads) { if (t.joinable()) t.join(); } } int main() { // 设置本地化支持 //setlocale(LC_ALL, "chs"); setlocale(LC_ALL, ".UTF-8"); SetConsoleCP(CP_UTF8); SetConsoleOutputCP(CP_UTF8); // 管理员权限检查 if (!CheckAdminPrivileges()) { OutputLog(L"⚠️ 需要管理员权限,正在尝试重启..."); #ifdef OS_WINDOWS WCHAR exePath[MAX_PATH]; GetModuleFileNameW(nullptr, exePath, MAX_PATH); SHELLEXECUTEINFOW sei = { sizeof(sei) }; sei.lpVerb = L"runas"; sei.lpFile = exePath; sei.nShow = SW_SHOWNORMAL; if (!ShellExecuteExW(&sei)) { OutputLog(L"重启失败,错误代码: " + std::to_wstring(GetLastError())); } #endif return 1; } const std::wstring targetDir = L"E:\\Toolshed\\RedPanda-CPP\\projects"; OutputLog(L"🔍 开始监控目录: " + targetDir); MonitorSubdirectories(targetDir); return 0; } 帮我完善代码使用GCC写个Win32UI窗口,列表框{序号,路径文件名,文件修改时间,变化状态},右键菜单{开启监听/停止监听,打开文件,定位文件},监听的变化输出到窗口的列表,
08-10
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值