从进程名称获取窗口标题

3

我正在尝试编写一个程序,可以获取进程的窗口标题。 在我描述问题之前,这是代码:

#include <Windows.h>
#include <string>
#include <Psapi.h>
#include <algorithm>

std::string window_title;
std::string search_for;    

BOOL CALLBACK EnumWindowCallback(HWND hWindow, LPARAM param)
{
    if ( IsWindow( hWindow ) == TRUE )
    {
        DWORD pid = 0;

        if ( GetWindowThreadProcessId( hWindow, &pid ) != 0 )
        {
            HANDLE hProcess;
            hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, pid );
            if ( hProcess != 0 )
            {
                std::string path;
                CHAR name[MAX_PATH];
                GetModuleFileNameExA( hProcess, NULL, name, sizeof(name) / sizeof(CHAR) );
                path = name;
                unsigned int slash = path.find_last_of('\\');
                if ( slash != std::string::npos ){
                    std::string proc_name = path.substr( slash + 1, path.length() );
                    std::transform(proc_name.begin(), proc_name.end(), proc_name.begin(), ::tolower);
                    if ( proc_name == search_for )
                    {
                        CHAR finalTitle[MAX_PATH];
                        ZeroMemory( finalTitle, sizeof(finalTitle) );
                        SendMessageA( hWindow, WM_GETTEXT, (WPARAM)sizeof(CHAR)/sizeof(MAX_PATH), (LPARAM)finalTitle );
                        window_title = finalTitle;
                        return FALSE;
                    }
                }
            }
        }
    }
    return TRUE;
};

const char* __stdcall GetWinTitleByProcessName( const char* title )
{
    search_for = title;
    std::transform(search_for.begin(), search_for.end(), search_for.begin(), ::tolower);
    if ( EnumWindows( (WNDENUMPROC)EnumWindowCallback, 0 ) == FALSE )
    {
        return window_title.c_str();
    }

    return "NOTFOUND";
}

int WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR, int )
{
    MessageBoxA( NULL, GetWinTitleByProcessName("chrome.exe"), "Test", MB_OK);
}

该程序目前可以正常运行,但当我需要获取窗口的实际标题时就会出现问题。我尝试使用GetWindowText和SendMessage方法,如下所示。但两种方法都返回空字符串。 我应该如何获取窗口标题?

我已经访问了这个问题:http://stackoverflow.com/questions/7063316/getwindowtext-returning-empty-string-and-strange-error 但它并没有真正包含一个满足我的问题的解决方案。 - DeleteMe
你使用 ANSI 字符串而不是 Unicode 字符串也不关我的事吧?现在已经是 2013 年了,所有的 Windows 程序都应该完全支持 Unicode。请将 charSendMessageA 替换为 wchar_tSendMessageW。确保你的项目中定义了 UNICODE 符号。 - Cody Gray
因为最终结果需要是char类型,因为它将被导出到一种古老的脚本语言,该语言不理解wchar_t。 - DeleteMe
如果您在使用CreateWindowW创建的窗口上调用SendMessageA,则可能会失败。请调用IsWindowUnicode并使用适当的SendMessageA/W变体。 - IInspectable
@Cody 感谢您指出这一点,确实是 RegisterClass 确定窗口的字符集。尽管我找不到任何官方文档,但似乎没有进行任何翻译。 @None 您是否尝试过使用 GetWindowText 而不是发送 WM_GETTEXT 消息? - IInspectable
显示剩余3条评论
2个回答

1
以下代码适用于类似的问题。在我的情况下,我正在寻找应用程序的窗口句柄,以便可以将dll设置为其父级。我通过其标题来识别该应用程序。这是C++Builder代码,因此某些部分可能不熟悉。我会评论我发现的区别。主要区别是使用Application,我不确定非Embarcadero等效项是什么,但每个运行的代码实例都有一个管理消息循环等的Application实例。我将我的dll的Application->Handle设置为调用应用程序的hWnd,以使其从任务栏中移除,等等。此代码适用于xp、vista 32和win7 64。
   void HideDLL() {
      if (Application->Handle == 0) {
         SearchObject *so = new SearchObject();
         so->Caption = L"MyCallingApp";
         so->Handle = 0;
         EnumWindows((WNDENUMPROC)EnumWindowsProc, (long)so);
         Application->Handle = so->Handle;

         delete so;
      }

   }
   BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lparam) {

      bool result;
      SearchObject *so = (SearchObject*)lparam;
      wchar_t *caption = new wchar_t[STR_DEFAULT];

      GetWindowTextW(hWnd, caption, STR_DEFAULT);
      // String is an Embarcadero type representing UnicodeString
      String Caption = caption;
      // Pos is a wrapper around strstr I think
      // the actual caption in my case is decorated with some other stuff
      // I only know that it will start with the name of the app
      if (Caption.Pos(so->Caption) > 0) {
         so->Handle = hWnd;
         result = false;
      } else {
         result = true;
      }
      delete caption;
      return result;
   }

希望这有所帮助。

1
似乎(WPARAM)sizeof(CHAR)/sizeof(MAX_PATH)会返回零,因为sizeof(char)肯定比最大路径小,所以你告诉WinAPI你的变量长度为零,这就是为什么它返回空字符串给你。请指定MAX_PATH值。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接