windows 获取桌面/外壳窗口的句柄
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8364758/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Get handle to desktop / shell window
提问by MFH
In one of my programs I need to test if the user is currently focusing the desktop/shell window. Currently I'm using GetShellWindow() from user32.dll and compare the result to GetForegroundWindow().
在我的一个程序中,我需要测试用户当前是否正在关注桌面/shell 窗口。目前我正在使用 user32.dll 中的 GetShellWindow() 并将结果与 GetForegroundWindow() 进行比较。
This approach is working until someone changes the desktop wallpaper, but as soon as the wallpaper is changed the handle from GetShellWindow() doesn't match the one from GetForegroundWindow() anymore and I don't quite get why that is. (OS:Windows 7 32bit)
这种方法在有人更改桌面墙纸之前一直有效,但是一旦更改墙纸,GetShellWindow() 中的句柄就不再与 GetForegroundWindow() 中的句柄匹配,我不太明白为什么会这样。(操作系统:Windows 7 32 位)
Is there a better approach to check if the desktop is focused? Preferably one that won't be broken if the user changes the wallpaper?
有没有更好的方法来检查桌面是否聚焦?最好是用户更换墙纸时不会损坏的?
EDIT:I designed a workaround: I'm testing the handle to have a child of class "SHELLDLL_DefView". If it has, the desktop is on focus. Whilst it's working at my PC that doesn't mean it will work all the time…
编辑:我设计了一个解决方法:我正在测试句柄是否有一个“SHELLDLL_DefView”类的孩子。如果有,则桌面是焦点。虽然它在我的电脑上工作,但这并不意味着它会一直工作......
采纳答案by tklepzig
The thing changed a little bit since there are slideshows as wallpaper available in Windows 7. You are right with WorkerW, but this works only with wallpaper is set to slideshow effect.
事情发生了一些变化,因为在 Windows 7 中有幻灯片作为墙纸可用。您对 WorkerW 来说是正确的,但这仅适用于设置为幻灯片效果的墙纸。
When there is set the wallpaper mode to slideshow, you have to search for a window of class WorkerW
and check the children, whether there is a SHELLDLL_DefView
.
If there is no slideshow, you can use the good old GetShellWindow()
.
当壁纸模式设置为幻灯片时,你必须搜索一个班级窗口WorkerW
并检查孩子们是否有SHELLDLL_DefView
. 如果没有幻灯片,您可以使用旧的GetShellWindow()
.
I had the same problem some months ago and I wrote a function for getting the right window. Unfortunately I can't find it. But the following should work. Only the Win32 Imports are missing:
几个月前我遇到了同样的问题,我写了一个函数来获取正确的窗口。不幸的是我找不到它。但以下应该工作。仅缺少 Win32 导入:
public enum DesktopWindow
{
ProgMan,
SHELLDLL_DefViewParent,
SHELLDLL_DefView,
SysListView32
}
public static IntPtr GetDesktopWindow(DesktopWindow desktopWindow)
{
IntPtr _ProgMan = GetShellWindow();
IntPtr _SHELLDLL_DefViewParent = _ProgMan;
IntPtr _SHELLDLL_DefView = FindWindowEx(_ProgMan, IntPtr.Zero, "SHELLDLL_DefView", null);
IntPtr _SysListView32 = FindWindowEx(_SHELLDLL_DefView, IntPtr.Zero, "SysListView32", "FolderView");
if (_SHELLDLL_DefView == IntPtr.Zero)
{
EnumWindows((hwnd, lParam) =>
{
if (GetClassName(hwnd) == "WorkerW")
{
IntPtr child = FindWindowEx(hwnd, IntPtr.Zero, "SHELLDLL_DefView", null);
if (child != IntPtr.Zero)
{
_SHELLDLL_DefViewParent = hwnd;
_SHELLDLL_DefView = child;
_SysListView32 = FindWindowEx(child, IntPtr.Zero, "SysListView32", "FolderView"); ;
return false;
}
}
return true;
}, IntPtr.Zero);
}
switch (desktopWindow)
{
case DesktopWindow.ProgMan:
return _ProgMan;
case DesktopWindow.SHELLDLL_DefViewParent:
return _SHELLDLL_DefViewParent;
case DesktopWindow.SHELLDLL_DefView:
return _SHELLDLL_DefView;
case DesktopWindow.SysListView32:
return _SysListView32;
default:
return IntPtr.Zero;
}
}
In your case you would call GetDesktopWindow(DesktopWindow.SHELLDLL_DefViewParent);
to get the top-level window for checking whether it is the foreground window.
在您的情况下,您将调用GetDesktopWindow(DesktopWindow.SHELLDLL_DefViewParent);
获取顶级窗口以检查它是否是前台窗口。
回答by AJKenny84
Here is a workaround that uses GetClassName()
to detect if the desktop is active:
这是GetClassName()
用于检测桌面是否处于活动状态的解决方法:
- When Windows first starts, the desktop's Class is "Progman"
- After changing the wallpaper, the desktop's Class will be "WorkerW"
- Windows 首次启动时,桌面的 Class 为“Progman”
- 更换壁纸后,桌面的Class为“WorkerW”
You can test against these to see if the desktop is focused.
您可以针对这些进行测试以查看桌面是否已聚焦。
[DllImport("user32.dll")]
static extern int GetForegroundWindow();
[DllImport("user32.dll")]
static extern int GetClassName(int hWnd, StringBuilder lpClassName, int nMaxCount);
public void GetActiveWindow() {
const int maxChars = 256;
int handle = 0;
StringBuilder className = new StringBuilder(maxChars);
handle = GetForegroundWindow();
if (GetClassName(handle, className, maxChars) > 0) {
string cName = className.ToString();
if (cName == "Progman" || cName == "WorkerW") {
// desktop is active
} else {
// desktop is not active
}
}
}