问题描述
我需要为桌面上的某些应用程序窗口创建一个水印窗口(markHwnd),水印窗口样式为:
uint dwStyle = Win32API.WS_CLIPSIBLINGS |
Win32API.WS_CLIPCHILDREN |
Win32API.WS_POPUP;
uint dwExStyle = Win32API.WS_EX_layered |
Win32API.WS_EX_TRANSPARENT |
Win32API.WS_EX_NOACTIVATE |
Win32API.WS_EX_nopARENTNOTIFY |
Win32API.WS_EX_TOOLWINDOW;
markHwnd = Win32API.CreateWindowEx(dwExStyle,wndclassRegResult,ti.ToString(),dwStyle,IntPtr.Zero,wndclasshInstance,IntPtr.Zero);
然后将其设置为应用程序窗口(targetHwnd)的自有窗口,有两种选择:
- SetwindowLongPtr(markHwnd,(int)Win32API.GWL.GWL_HWNDPARENT, targetHwnd);
- SetParent(markHwnd,targetHwnd);
建议哪个?
解决方法
请勿使用GWLP_HWNDPARENT索引调用SetWindowLongPtr来更改子窗口的父窗口。而是使用SetParent函数。
该文档所隐含的是GWLP_HWNDPARENT
实际上更改了顶层窗口的所有者,而不是子窗口的 parent 。根据雷蒙德·陈(Raymond Chen)的说法:
https://devblogs.microsoft.com/oldnewthing/20100315-00/?p=14613
现在,一个窗口可以有一个父窗口,也可以有一个所有者,或者既没有窗口又没有窗口,但是永远不能拥有两者。
然后他继续说明CreateWindow/Ex()
如何根据新窗口是否具有WS_CHILD
样式来分配所有者和父母。
SetParent()
文档说:
出于兼容性原因,SetParent不会修改其父级正在更改的窗口的WS_CHILD或WS_POPUP窗口样式。
因此,SetWindowLongPtr(GWLP_HWNDPARENT)
用于更改顶级窗口的所有者,而SetParent()
用于更改子窗口的父级。