【问题标题】:Get a a process window handle by click in C#通过在 C# 中单击获取进程窗口句柄
【发布时间】:2012-05-06 07:31:12
【问题描述】:

目前,我可以使用 System.Diagnostics.Process.GetProcesses() 并执行一个简单的 LINQ 查询来获取带有主窗口的正在运行的进程列表。

然后,我可以导入user32.dllSetWindowPos 函数并操作其他进程的窗口参数。

好的,它有效。现在我想通过单击来选择一个进程的窗口,比如说 calc.exe。换句话说,我想获得一个带有钩子的 Process 对象(然后是 MainWindowHandle),当我单击其窗口时,该钩子会捕获进程名称。

我怎样才能做到这一点?

【问题讨论】:

    标签: c# winapi process click hook


    【解决方案1】:

    我不知道这是如何在 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;
    }
    

    示例结果:

    在这种情况下,我只是通过轮询来获得鼠标点击。更合适的方法是使用某种 windows 挂钩。

    【讨论】:

    • 您可能需要捕获鼠标才能接收对另一个窗口的点击。
    • @MartinLiversage: GetAsyncKeyState 可以用于此。
    • 我在获取光标位置时遇到了一些问题。我正在调用 GetCursorPos,但我得到的 X 坐标为 6,47208716579385E-312,而 Y 坐标为 0。这是怎么回事?
    • @MikeKwan:但是如果我将鼠标指针移动到另一个窗口并单击它,我的应用程序会失去焦点并且不会获得鼠标单击事件。也就是说,除非我抓住了鼠标。
    • @MartinLiversage:据我所知,您不需要为GetAsyncKeyState 捕获鼠标。
    【解决方案2】:

    正如 Mike Kwan 所说,虽然这两种方法都有各自的缺点,但最好还是编写一个钩子,但 bjarneds 已经在这方面做了很好的工作。看看@DotNET Object Spy。它是用 C# 编写的,可以满足您的需求等等。

    您还应该注意,使用钩子正变得越来越多余。根据您的需要,GetForegroundWindow 等其他 winapi 可能会更好。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-08
      • 2010-11-30
      相关资源
      最近更新 更多