获取控制台窗口的句柄(HWND)和程序中输出回车键

来源:互联网 发布:什么手机电影软件最好 编辑:程序博客网 时间:2024/05/23 12:59

一、获取窗口句柄基于类名或窗口名称: http://support.microsoft.com/kb/124103/zh-cn

Win32 API 提供用于获取与一个控制台应用程序相关联的窗口句柄没有直接方法。但是,您可以获得通过调用 FindWindow() 窗口句柄。此函数可检索窗口句柄基于类名或窗口名称。 


调用以确定当前的控制台标题 GetConsoleTitle()。然后提供当前的控制台标题,以 FindWindow()。

因为多个窗口可能具有相同的标题,您应更改当前的控制台窗口标题,以一个唯一的标题。这将有助于防止将返回错误的窗口句柄。若要更改当前的控制台窗口标题中使用 SetConsoleTitle()。下面是此过程:

  1. 调用 GetConsoleTitle() 保存当前控制台窗口标题。
  2. 调用 SetConsoleTitle() 若要更改控制台标题到唯一的标题。
  3. 若要确保窗口标题的调用 Sleep(40) 已更新。
  4. 如果操作失败,调用 FindWindow NULL uniquetitle),以获取该 HWND 此调用将返回 HWND--或 NULL。
  5. 从步骤 1,要还原原始的窗口标题检索调用 SetConsoleTitle() 具有值。
您应该测试结果的 HWND。例如对于您可以测试以查看是否返回的 HWND 与当前进程在 HWND 上调用 GetWindowText() 并将结果与 GetConsoleTitle() 进行比较。

生成的 HWND 是不能保证是适用于所有的窗口句柄操作。

示例代码

下面的函数检索当前控制台应用程序窗口句柄 (HWND)。如果此函数成功,返回值是控制台窗口的句柄。如果将失败函数返回值为 NULL。某些错误检查被省略,为简洁起见。
   HWND GetConsoleHwnd(void)   {       #define MY_BUFSIZE 1024 // Buffer size for console window titles.       HWND hwndFound;         // This is what is returned to the caller.       char pszNewWindowTitle[MY_BUFSIZE]; // Contains fabricated                                           // WindowTitle.       char pszOldWindowTitle[MY_BUFSIZE]; // Contains original                                           // WindowTitle.       // Fetch current window title.       GetConsoleTitle(pszOldWindowTitle, MY_BUFSIZE);       // Format a "unique" NewWindowTitle.       wsprintf(pszNewWindowTitle,"%d/%d",                   GetTickCount(),                   GetCurrentProcessId());       // Change current window title.       SetConsoleTitle(pszNewWindowTitle);       // Ensure window title has been updated.       Sleep(40);       // Look for NewWindowTitle.       hwndFound=FindWindow(NULL, pszNewWindowTitle);       // Restore original window title.       SetConsoleTitle(pszOldWindowTitle);       return(hwndFound);   }


二、使用GetConsoleWindow函数:http://hi.baidu.com/console_app/blog/item/196387028b1893e409fa9330.html

作者:Defanive
博客:Console.Dec.Cn(Hi.Baidu.Com/Console_App)

窗口,都有其唯一的句柄(hWnd)。得到了窗口句柄,能够做很多事情。控制台程序,若能在窗口效果上下文章,那么这个第三方工具将会很成功。

网上给出的常用方法:

HWND hw=FindWindow("ConsoleWindowClass",NULL);

这不失为一个好方法,但是单从Class方面入手保险度不高。

API函数FindWindow有两个参数,类名与窗口标题。当不提供窗口标题的时候,返回的句柄为同类窗口中Z序最高的窗口句柄。虽然说执行只是一瞬间,但是保险起见,还是提供下标题窗口,更保险。

char strTitle[255];
GetConsoleTitle(strTitle, 255);
HWND hw=FindWindow("ConsoleWindowClass",strTitle);

当然,如果要精益求精,还有更保险的办法,用 Kernel32.dll 中部分未公布的API。在用 eXeScope 导出 Kernel32.dll 中控制台相关的API之后,发现有一个名为GetConsoleWindow的API。查找参考了部分资料后,提供如下代码,能够动态载入这个API并获得窗口句柄。

首先需要全局声明:

typedef HWND (WINAPI *PROCGETCONSOLEWINDOW)();
PROCGETCONSOLEWINDOW GetConsoleWindow;

然后再Main()函数开头中输入以下内容:

HMODULE hKernel32 = GetModuleHandle("kernel32");
GetConsoleWindow = (PROCGETCONSOLEWINDOW)GetProcAddress(hKernel32,"GetConsoleWindow");

完成了动态载入API函数GetConsoleWindow的任务。需要使用时可如下:

HWND cmd=GetConsoleWindow();

个人认为,使用API函数GetConsoleWindow是最安全,也是最好的方法。在更大的控制台编程中,可能随时需要用到AttachConsole来改变程序的宿主控制台,这个时候再用前两种方法就不够好了。尽管载入的代码很长,但是通用性更高。


三、控制台中使用程序输出回车键

(1):

 INPUT key[1] = {0};
  key[0].type = INPUT_KEYBOARD;
  key[0].ki.wVk = VK_RETURN;
  key[0].ki.dwFlags = 0;
  key[0].ki.time = 0;
  key[0].ki.wScan = 0;//VK_RETURN;
  key[0].ki.dwExtraInfo = 0;
  SendInput(1, key, sizeof(key));

(2):

keybd_event(0xd,0,0,0);

   (3):

   获取控制台的句柄(HWND)后,可以使用这个句柄,向控制台发送Enter键的ASCLL消息。

  SendMessage(hwndFound,WM_CHAR,0x0d,0);


其中方法(1)(2),可能会影响到其他的应用程序,方法(3)验证没有出现影响其它应用程序的现象。