1. 程式人生 > >獲取控制檯視窗的控制代碼(HWND)和程式中輸出回車鍵

獲取控制檯視窗的控制代碼(HWND)和程式中輸出回車鍵

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)驗證沒有出現影響其它應用程式的現象。