【问题标题】:Why does FindWindowEx() produce null results?为什么 FindWindowEx() 会产生空结果?
【发布时间】:2013-11-06 09:42:51
【问题描述】:

我试图找到一个名为“VirtualKeyboard”的打开窗口。 目前这是使用以下代码实现的:-

LPCWSTR WindowName =L"SoftKeyboard.exe*32";

HWND Find = ::FindWindowEx(0, 0,WindowName, 0);
cout<<Find<<endl;

WindowName 是从任务管理器中获取的,我已经将它初始化为名为 SoftKeyboard.exe*32 的进程名称。我还使用名为 Virtual_Keyboard 的任务名称对其进行了测试,但两者都产生 NULL 结果。窗口在运行前打开这个程序。

我在包含“HWND Find = ::FindWindowEx(0, 0,WindowName, 0);”的行处放置了一个断点。在 Autos 窗口中出现以下内容:-

 -      Find    0xcccccccccccccccc {unused=??? }    HWND__ *
        unused  CXX0030: Error: expression cannot be evaluated  

如何纠正?为什么会出现这种情况?是否从任务管理器中提取 WindowName?是否有其他方法可以找到此窗口?

【问题讨论】:

  • Variable Find 将仅在其初始化的行之后被初始化。
  • 没错,但 cout 显示的输出
  • 阅读代码最后两行产生的错误信息。
  • 您将两个问题混为一谈。第一个问题是 Find 变量未在 FindWindowEx 行上初始化。将断点移动到下一行,您将看到 Find 变量已正确初始化。第二个问题是为什么FindWindowEx 返回 0。它返回 0 因为没有名为“SoftKeyboard.exe*32”的窗口类的窗口。此字符串不是窗口类的命名方式。只是进程在任务管理器中的命名方式,与窗口类名不同。
  • 窗口类名是出现在窗口顶部的标题名称,如果我错了,请纠正我。这将是Virtual_Keyboard。我确实将它移到了下面:-- Find 0x0000000000000000 {unused=? ?? } HWND__ * 和未使用的 CXX0030:错误:无法评估表达式出现在自动窗口中。

标签: visual-studio-2010 visual-c++ msdn


【解决方案1】:

你必须找出你要查找的窗口的窗口类名。您目前只知道创建窗口的进程是 SoftKeyboard.exe。首先,您必须确定此进程的进程 ID。在任务管理器中,进程 ID 通常位于第二列,紧挨着可执行文件名称。使用 Spy++ 或以下临时代码来发现属于该进程的所有窗口类名称:

BOOL CALLBACK WriteWindowClass(HWND hWnd, LPARAM lParam)
{
    DWORD nThreadID, nProcessID;
    nThreadID = GetWindowThreadProcessId(hWnd, &nProcessID);

    if (nProcessID == XXX) // Write SoftKeyboard's Process ID instead of XXX
    {
        WCHAR szClassName[256];
        GetClassName(hWnd, szClassName, 256);

        std::wcout << szClassName << std::endl;
    }

    return TRUE;
}

int wmain(int argc, wchar_t* argv[]) 
{
    EnumWindows(WriteWindowClass, 0);

    return 0;
}

您可能只会在控制台中看到一行。此行中的文本为类名,此文本应作为第三个参数提供给FindWindowEx,而不是现有的“SoftKeyboard.exe*32”。

对于“未使用的 CXX0030”问题,只需用谷歌搜索:未使用的 CXX0030。你会发现这是正常的。

【讨论】:

  • 这段代码工作正常,但是确实出现了一个小问题,进程ID不是一个恒定值。每次我打开和关闭虚拟键盘应用程序时,进程ID都会改变,怎么能这个解决了吗?
  • 我想走的路线是找到给定进程名称的进程ID,在这种情况下它是SoftKeyboard。参考cplusplus.com/forum/windows/12137 但是,我还没有测试它,将不得不回复您是否有效。如果您知道更简单的解决方案,欢迎提出任何建议。
  • @Kribz,上面代码的目的不是为了找到窗口。目的是查找窗口类名。您只需运行代码一次。当您获得窗口类名称时,使用它来调用FindWindowEx,就像您从一开始就想要的那样。请阅读代码后的文字。
  • @Kribz,上面的代码是临时的。一旦你获得了窗口类名,你就不再需要代码了,所以删除它。
【解决方案2】:

窗口类名不是出现在窗口顶部的名称。确定窗口类名的唯一方法是使用 Visual Studio 自带的 Spy++ 工具。

【讨论】:

  • 谢谢,这很有帮助,这是错误发生的原因吗?
猜你喜欢
  • 2017-06-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-10
  • 2018-02-05
相关资源
最近更新 更多