C# 通过在C中单击获取进程窗口句柄#

C# 通过在C中单击获取进程窗口句柄#,c#,winapi,process,click,hook,C#,Winapi,Process,Click,Hook,目前,我可以使用System.Diagnostics.Process.GetProcesses()并执行一个简单的LINQ查询,在主窗口中获得正在运行的进程列表 然后,我可以导入user32.dll和SetWindowPos函数,并操作其他进程的窗口参数 好的,它起作用了。现在我想通过单击来选择一个进程的窗口,比如calc.exe。换句话说,我想获得一个进程对象(然后是MainWindowHandle),它带有一个钩子,当我点击它的窗口时,钩子会捕捉进程名称 我怎样才能做到这一点呢?我不知道如何

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

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

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


我怎样才能做到这一点呢?

我不知道如何在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;
}
#包括
#包括
#包括
#pragma注释(lib,“Psapi.lib”)
内部主(空)
{
/*用于概念证明的Hacky循环*/
while(TRUE){
睡眠(100);
if(GetAsyncKeyState(VK_F12)){
打破
}
if(GetAsyncKeyState(VK_LBUTTON)){
HWND-hwndPt;
点pt;
如果(!GetCursorPos(&pt)){
wprintf(L“GetCursorPos失败,错误为%d\n”,GetLastError());
打破
}
如果((hwndPt=WindowFromPoint(pt))!=NULL){
德沃德·德皮德;
处理hProcess;
GetWindowThreadProcessId(hwndPt和dwPID);
HPPROCESS=OpenProcess(进程查询有限信息,FALSE,dwPID);
if(hProcess==NULL){
wprintf(L“OpenProcess失败,错误:%d\n”,GetLastError());
}否则{
wchar_t lpFileName[MAX_PATH];
DWORD dwSize=_countof(lpFileName);
QueryFullProcessImageName(hProcess、0、lpFileName和dwSize);
wprintf(L“%s\n”,lpFileName);
CloseHandle(hProcess);
}
}
}
}
返回退出成功;
}
示例结果:


在本例中,我只是轮询以获得鼠标单击。更合适的方法是使用某种windows钩子。

正如Mike Kwan所说,编写钩子会更好,尽管这两种方法都有各自的缺点,但bjarneds已经在这方面做了很好的工作。看一看。它是用C#编写的,可以满足您的需要,甚至更多


您还应该注意到,使用钩子越来越多余。根据您想做什么,其他WinAPI(如
GetForegroundWindow
)可能会更好。

您可能需要捕获鼠标才能接收对另一个窗口的单击。@MartinLiversage:
GetAsyncKeyState
可以用于此。我在获取光标位置时遇到一些问题。我打电话给GetCursorPos,但我得到的X坐标是647208716579385E-312,Y坐标是0。发生了什么事?@MikeKwan:但如果我将鼠标指针移到另一个窗口并单击它,我的应用程序就会失去焦点,无法获得鼠标单击事件。也就是说,除非我已经捕获了鼠标。@MartinLiversage:据我所知,你不需要为
GetAsyncKeyState
捕获鼠标。