在我的一个程序中,我需要测试用户当前是否正在关注桌面/ shell窗口。目前我正在使用user32.dll中的GetShellWindow()并将结果与GetForegroundWindow()进行比较。
这种方法一直有效,直到有人更改了桌面壁纸,但是一旦壁纸被更改,GetShellWindow()的句柄就不再与GetForegroundWindow()中的句柄匹配了,我也不太了解为什么会这样。 (操作系统: Windows 7 32位)
有没有更好的方法来检查桌面是否专注?如果用户更改壁纸,最好不会被打破?
编辑:我设计了一个解决方法:我正在测试句柄,以便让孩子上课#34; SHELLDLL_DefView"。如果有,则桌面处于焦点状态。虽然它在我的电脑上工作并不意味着它会一直有效......
答案 0 :(得分:6)
由于Windows 7中有可用的壁纸幻灯片,因此事情发生了一些变化。 你是对的是WorkerW,但这只适用于壁纸设置为幻灯片效果。
当将壁纸模式设置为幻灯片放映时,您必须搜索班级WorkerW
的窗口并检查孩子是否有SHELLDLL_DefView
。
如果没有幻灯片显示,您可以使用旧的GetShellWindow()
。
几个月前我遇到了同样的问题,我写了一个函数来获得正确的窗口。不幸的是我找不到它。但以下应该有效。只缺少Win32 Imports:
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;
}
}
在您的情况下,您可以调用GetDesktopWindow(DesktopWindow.SHELLDLL_DefViewParent);
来获取顶级窗口,以检查它是否是前景窗口。
答案 1 :(得分:4)
以下是使用GetClassName()
检测桌面是否处于活动状态的解决方法:
您可以对这些内容进行测试,以了解桌面是否已成为焦点。
[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
}
}
}