TL; DR:GetWindowText win32 api在Windows 10上改变了行为吗?
我有一些代码循环遍历桌面上的所有窗口,找到一个标题包含一些文本的窗口。
当此代码点击名为“”且带有“URL Moniker Notification Window”类的窗口时,它会挂起GetWindowText。
GetWindowText正在尝试发送消息,我的猜测是WM_GETTEXT。
此窗口是exe“SearchUI.exe”的一部分,该进程已暂停,无法处理消息。
阅读时:https://blogs.msdn.microsoft.com/oldnewthing/20030821-00/?p=42833/ 根据规则2,这不应该发生。
这段代码多年来一直运作良好。 (赢7,8,8.1)
GetWindowText在Windows 10中的更改行为是什么?
更新: 有问题的代码。
public static int HwndGet(string partialTitle, string klassenavn)
{
partialTitle = partialTitle ?? "";
var cTitleTemp = new StringBuilder(255);
var hWndTemp = FindWindowEx((IntPtr)0, (IntPtr)0, null, null);
var nypartialTitle = partialTitle.ToUpper();
while (hWndTemp != (IntPtr)0)
{
GetWindowText(hWndTemp, cTitleTemp, cTitleTemp.Capacity);
string sTitleTemp = cTitleTemp.ToString();
sTitleTemp = sTitleTemp.ToUpper();
if (sTitleTemp.StartsWith(nypartialTitle, StringComparison.CurrentCultureIgnoreCase))
{
var className = new StringBuilder(255);
GetClassName(hWndTemp, className, 255);
//sTitleTemp: " + sTitleTemp + " ClassName: " + ClassName);
if (className.ToString().StartsWith(klassenavn, StringComparison.CurrentCultureIgnoreCase))
{
return (int)hWndTemp;
}
}
hWndTemp = GetWindow(hWndTemp, GwHwndnext);
}
return 0; // does not find the window
}
堆栈追踪:
答案 0 :(得分:1)
您使用的代码不是“安全”。无法保证在调用FindWindowsEx
和GetWindow(GwHwndnext)
之间窗口的顺序不会发生变化。出于这个原因,还有另一个API,EnumWindows
,它是“安全的”。你可以尝试一下。
这里有一个示例程序(基于找到的here)。
public static class WndSearcher
{
public static IntPtr SearchForWindow(string wndclass, string title)
{
var sd = new SearchData { Wndclass = wndclass, Title = title };
EnumWindows(sd.EnumWindowsProc, IntPtr.Zero);
return sd.hWndFound;
}
private class SearchData
{
// You can put any dicks or Doms in here...
public string Wndclass;
public string Title;
public IntPtr hWndFound;
public bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam)
{
// Check classname and title
var sb = new StringBuilder(1024);
int res = GetClassName(hWnd, sb, sb.Capacity);
if (res == 0)
{
throw new Win32Exception();
}
if (sb.ToString().StartsWith(Wndclass, StringComparison.CurrentCultureIgnoreCase))
{
sb.Clear();
res = GetWindowText(hWnd, sb, sb.Capacity);
if (res == 0)
{
int error = Marshal.GetLastWin32Error();
if (error != 0)
{
throw new Win32Exception(error);
}
}
if (sb.ToString().StartsWith(Title, StringComparison.CurrentCultureIgnoreCase))
{
hWndFound = hWnd;
// Found the wnd, halt enumeration
return false;
}
}
return true;
}
}
[return: MarshalAs(UnmanagedType.Bool)]
private delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
}
然后像
一样使用它IntPtr ptr = WndSearcher.SearchForWindow("classname", "windowname");