前置学习:低级鼠标hook,获得鼠标状态。
这个在原来获得鼠标状态的基础上,加上一个事件处理即可。
TopWind就是一个可以置顶窗口的文件,避免复制粘贴的时候的来回切换(大窗口与小窗口),算是一个实用的工具(至少我蛮喜欢的),所以自己就仿造了写了一个,利用之前的那个鼠标hook。
界面如图所示,可以看到是置顶和恢复。
两个函数:
//置顶
IsOk = ::SetWindowPos( hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
//恢复
IsOk = ::SetWindowPos( hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
函数:SetWindowPos
函数原型:WINUSERAPI BOOL WINAPI SetWindowPos(HWND hWnd,HWND hWndInsertAfter,int X,int Y,int cx,_In_ int cy, UINTuFlags);
参数:
hwnd
在z序中的位于被置位的窗口前的窗口句柄。该参数必须为一个窗口句柄
hWndlnsertAfter
用于标识在z-顺序的此 CWnd 对象之前的 CWnd 对象。如果uFlags参数中设置了SWP_NOZORDER标记则本参数将被忽略。可为下列值之一:
-
HWND_BOTTOM:值为1,将窗口置于Z序的底部。如果参数hWnd标识了一个顶层窗口,则窗口失去顶级位置,并且被置在其他窗口的底部。
-
HWND_NOTOPMOST:值为-2,将窗口置于所有非顶层窗口之上(即在所有顶层窗口之后)。如果窗口已经是非顶层窗口则该标志不起作用。
-
HWND_TOP:值为0,将窗口置于Z序的顶部。
-
HWND_TOPMOST:值为-1,将窗口置于所有非顶层窗口之上。即使窗口未被激活窗口也将保持顶级位置。
查看该参数的使用方法,请看说明部分。
x
以客户坐标指定窗口新位置的左边界。
Y
以客户坐标指定窗口新位置的顶边界。
cx
以像素指定窗口的新的宽度。
cy
以像素指定窗口的新的高度。
uFlags
窗口尺寸和定位的标志。该参数可以是下列值的组合:
-
SWP_ASYNCWINDOWPOS:如果调用进程不拥有窗口,系统会向拥有窗口的线程发出需求。这就防止调用线程在其他线程处理需求的时候发生死锁。
-
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函数。
增加功能的代码:
1 if (wParam == WM_LBUTTONDOWN) 2 { 3 BOOL IsOk = FALSE; 4 HWND hWnd = ::WindowFromPoint(MouseHookStruct->pt); 5 6 7 //获得父窗口 8 while (::GetParent(hWnd)) 9 { 10 hWnd = ::GetParent(hWnd); 11 } 12 13 14 15 TCHAR title[MAX_PATH]; 16 ::GetWindowText(hWnd, title, MAX_PATH); 17 18 19 20 if (__IsDO == TRUE) 21 { 22 //HWND_TOPMOST 窗口置顶 23 //SWP_NOMOVE | SWP_NOSIZE 不改变窗口大小和位置 24 25 IsOk = ::SetWindowPos( 26 hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); 27 //BringWindowToTop(); 28 GetDlgItem(IDC_BUTTON_DO)->EnableWindow(TRUE); 29 if (IsOk) 30 { 31 if (wcscmp(title,L"") == 0) 32 { 33 v1.Format(_T("%s %s"), STATE3, L" no get title"); 34 SetDlgItemText(IDC_STATIC_STATE, v1); 35 } 36 else 37 { 38 v1.Format(_T("%s %s"), STATE3, title); 39 SetDlgItemText(IDC_STATIC_STATE, v1); 40 } 41 42 } 43 else 44 { 45 v1.Format(_T("%s %s"), STATE3_1, title); 46 SetDlgItemText(IDC_STATIC_STATE, v1); 47 } 48 49 } 50 else 51 { 52 IsOk = ::SetWindowPos( 53 hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); 54 GetDlgItem(IDC_BUTTON_UNDO)->EnableWindow(TRUE); 55 if (IsOk) 56 { 57 if (wcscmp(title, L"") == 0) 58 { 59 v1.Format(_T("%s %s"), STATE4, L" no get title"); 60 SetDlgItemText(IDC_STATIC_STATE, v1); 61 } 62 else 63 { 64 v1.Format(_T("%s %s"), STATE4, title); 65 SetDlgItemText(IDC_STATIC_STATE, v1); 66 } 67 68 } 69 else 70 { 71 v1.Format(_T("%s %s"), STATE4_1, title); 72 SetDlgItemText(IDC_STATIC_STATE, v1); 73 } 74 75 } 76 StopHook(); 77 }
就是获得鼠标点击的hwnd,然后因为不一定是点击的父窗口,所以就寻找他的父窗口,必须寻找到父窗口之后方可以置顶。
所以其中注意要写上:
1 //获得父窗口 2 while (::GetParent(hWnd)) 3 { 4 hWnd = ::GetParent(hWnd); 5 }
来获取父窗口,其他的基本和之前写的mousehook一致,附上源代码。
链接:http://pan.baidu.com/s/1jHUHUZW 密码:u84a