2012-04-25 75 views
4

目前,我可以使用System.Diagnostics.Process.GetProcesses()獲得主窗口正在運行的進程列表,並執行一個簡單的LINQ查詢。通過C#中的點擊獲取一個流程窗口句柄。

然後,我可以導入user32.dllSetWindowPos函數,我操縱其他進程的窗口參數。

好的,它的工作原理。現在我想選擇一個進程的窗口,比方說calc.exe,點擊它。換句話說,我想用一個鉤子來獲取一個Process對象(然後是MainWindowHandle),當我單擊它的窗口時它會捕獲進程名稱。

我該如何做到這一點?

回答

5

我不知道這是如何在C#中完成的,但你也已經標記了這個問題WinAPI,所以我可以在那裏幫助。在WinAPI的,這是可以做到像這樣:

#include <stdio.h> 
#include <Windows.h> 
#include <Psapi.h> 
#pragma comment(lib, "Psapi.lib") 

int main(void) 
{ 
    /* Hacky loop for proof of concept */ 
    while(TRUE) { 
    Sleep(100); 

    if(GetAsyncKeyState(VK_F12)) { 
     break; 
    } 

    if(GetAsyncKeyState(VK_LBUTTON)) { 
     HWND hwndPt; 
     POINT pt; 

     if(!GetCursorPos(&pt)) { 
     wprintf(L"GetCursorPos failed with %d\n", GetLastError()); 
     break; 
     } 

     if((hwndPt = WindowFromPoint(pt)) != NULL) { 
     DWORD dwPID; 
     HANDLE hProcess; 

     GetWindowThreadProcessId(hwndPt, &dwPID); 

     hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, dwPID); 

     if(hProcess == NULL) { 
      wprintf(L"OpenProcess failed with error: %d\n", GetLastError()); 
     } else { 
      wchar_t lpFileName[MAX_PATH]; 
      DWORD dwSize = _countof(lpFileName); 

      QueryFullProcessImageName(hProcess, 0, lpFileName, &dwSize); 
      wprintf(L"%s\n", lpFileName); 

      CloseHandle(hProcess); 
     } 
     } 
    } 
    } 

    return EXIT_SUCCESS; 
} 

結果舉例:

result

在這種情況下,我只是輪詢來獲取鼠標點擊。更正確的方法是使用某種窗口鉤子。

+0

您可能需要捕獲鼠標才能夠在另一個窗口上接收點擊。 – 2012-04-25 15:27:50

+0

@MartinLiversage:可以使用'GetAsyncKeyState'。 – 2012-04-25 15:38:33

+0

我在獲取光標位置時遇到了一些問題。我打電話給GetCursorPos,但我得到的X座標類似於6,47208716579385E-312和Y座標爲0.發生了什麼事? – daliz 2012-04-25 15:44:56

1

正如Mike Kwan所說,儘管兩種方法都有自己的缺點,但還是會寫得更好,但是bjarneds已經在這方面做了很好的工作。看看@DotNET Object Spy。它用C#編寫,將滿足您的需求和更多。

您還應該注意,使用鉤子在一天中變得多餘。取決於你想做什麼,其他winapis像GetForegroundWindow可能會更好。