2012-04-25 43 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可能会更好。