2013-07-30 4 views
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, как показано здесь. Оба метода возвращают пустые строки.

Как я могу получить заголовок окна?

+0

Я посетил этот вопрос: http://stackoverflow.com/questions/7063316/getwindowtext-returning-empty-string-and-strange-error Но на самом деле он не содержит решения, которое удовлетворяет моему вопросу. – DeleteMe

+0

Это также NoneOfMyBusiness, почему вы используете строки ANSI, а не строки Unicode? Это 2013 год, все программы для Windows должны быть полностью Unicode. Замените 'char' и' SendMessageA' на 'wchar_t' и' SendMessageW'. Убедитесь, что для вашего проекта определен символ UNICODE. –

+0

Поскольку конечный результат должен быть в char, потому что он экспортируется на древний язык сценариев, который не понимает wchar_t. – DeleteMe

ответ

1

Следующий код подходит для подобной проблемы. В моем случае я ищу дескриптор окна приложения, чтобы я мог родительский DLL. Я определяю приложение по его заголовку. Его код C++ Builder, поэтому некоторые части могут быть незнакомы. Я прокомментирую различия, которые я вижу. Основной из них - использование приложения, я не уверен, что эквивалент не-Embarcadero, но каждый запущенный экземпляр кода имеет экземпляр приложения, который управляет контуром сообщений и так далее. Я установил приложение Application-> dll для вызывающих приложений 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) , поэтому он возвращает вам пустую строку. Укажите вместо этого значение MAX_PATH.