ShellExecute開啟外部程式,再用GetForegroundWindow()抓取問題 |
答題得分者是:aftcast
|
ttnnrsseb
中階會員 ![]() ![]() ![]() 發表:31 回覆:77 積分:51 註冊:2004-11-22 發送簡訊給我 |
|
aftcast
站務副站長 ![]() ![]() ![]() ![]() ![]() 發表:81 回覆:1485 積分:1763 註冊:2002-11-21 發送簡訊給我 |
你好,
請參考! [code cpp] BOOL CALLBACK EnumWindowsCallBackFnc(HWND hwnd, LPARAM lParam) { ::SetWindowPos(hwnd, //handle of window HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE); ::SetWindowTextA(hwnd, "被蕭沖改變了!"); return false; } //--------------------------------------------------------------------------- void __fastcall TForm1::Button1Click(TObject *Sender) { STARTUPINFO si; PROCESS_INFORMATION pi; // LPTSTR szCmdline="mspaint.exe"; //小畫家 LPTSTR szCmdline="notepad.exe"; ::GetStartupInfo(&si); // Start the child process. if( !CreateProcess( NULL, szCmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi ) ) { ShowMessage(String().sprintf("CreateProcess failed (%d).\n", GetLastError())); return; } // WaitForInputIdle對小畫家這程式來說,看來是沒用的,所以還是要sleep一下 if (WAIT_TIMEOUT==WaitForInputIdle(pi.hProcess, 5000L)) { ShowMessage("Over Time"); // 若超過 5000 MS 的時間時 } //::Sleep(500); // #define STRICT 下面的方法才會不comipler錯誤 EnumWindowsCallBackFnc // define 在 project option裡。用 (WNDENUMPROC) 強轉也行,但個人覺得不好 BOOL bResult = ::EnumThreadWindows( pi.dwThreadId, EnumWindowsCallBackFnc, NULL); // Close process and thread handles. CloseHandle( pi.hProcess ); CloseHandle( pi.hThread ); } //--------------------------------------------------------------------------- [/code] ===================引 用 ttnnrsseb 文 章=================== 請教各位先進, 我用ShellExecute開啟一個外部程式,因為無法從視窗的名稱去抓(有可能不固定),所以我用GetForegroundWindow()去抓最上層的視窗。 ShellExecute呼叫完,通常也要Delay個500ms等它開啟才能抓的到。
如果這段期間去點到別的視窗,變成最上層的話,就會抓錯視窗了! 不知有無方法可以避免這個情況的發生? 例如ShellExecute開啟後就是StayOnTop,或是可以準確知道視窗開啟的時間? 謝謝!
------
蕭沖 --All ideas are worthless unless implemented-- C++ Builder Delphi Taiwan G+ 社群 http://bit.ly/cbtaiwan |
ttnnrsseb
中階會員 ![]() ![]() ![]() 發表:31 回覆:77 積分:51 註冊:2004-11-22 發送簡訊給我 |
|
aftcast
站務副站長 ![]() ![]() ![]() ![]() ![]() 發表:81 回覆:1485 積分:1763 註冊:2002-11-21 發送簡訊給我 |
你好,可以明確的講你要開的是哪個嗎?
"C:\\windows\\system32\\control.exe mmsys.cpl"; 這是否也只是一個例子? 因為我還有別的辦法,但要明確的知道你要開的是什麼,不好給我例子。 因為你說標題會變來變去,關於這點…很少的程式如此,多數會如此都是一些防毒、修護程式之類的才會換來換去。 如果你可以給我明確的你要開的命令 (即使我沒那個程式),或許我還有解決的辦法喔! ===================引 用 ttnnrsseb 文 章=================== 感謝先進的回覆, 我開notepad測試是OK的。 但如果我要抓的是mmsys.cpl的視窗,它的開啟是用 [code cpp] LPTSTR szCmdline="C:\\windows\\system32\\control.exe mmsys.cpl"; [/code] 所以 pi.dwThreadId 應該是屬於 control.exe 的,找不到 mmsys.cpl 的HWND。 沒先說明,不好意思!
------
蕭沖 --All ideas are worthless unless implemented-- C++ Builder Delphi Taiwan G+ 社群 http://bit.ly/cbtaiwan |
ttnnrsseb
中階會員 ![]() ![]() ![]() 發表:31 回覆:77 積分:51 註冊:2004-11-22 發送簡訊給我 |
|
aftcast
站務副站長 ![]() ![]() ![]() ![]() ![]() 發表:81 回覆:1485 積分:1763 註冊:2002-11-21 發送簡訊給我 |
你好,有一個可能不是最完美的解。但請試看看!
請於shellexecute 或createprocess後執行下面 [code cpp] #include "psapi.h" #pragma link "psapi.lib" char buf[256] = {0}; HWND hwnd = 0; HANDLE hProc = 0; DWORD pId = 0; while (1) { ::ZeroMemory(buf,256); hwnd = ::FindWindow("#32770",NULL); ::GetWindowText(hwnd,buf,255); //ShowMessage(buf); ::ZeroMemory(buf,256); GetWindowThreadProcessId(hwnd, &pId); hProc = OpenProcess(PROCESS_ALL_ACCESS, false, pId); ::GetModuleBaseName(hProc,0,buf,sizeof(buf)); //ShowMessage(buf); if (AnsiString(buf) != AnsiString("rundll32.exe")) ::SendMessage(hwnd,WM_CLOSE,0,0); else break; } ::SetWindowPos(hwnd, //handle of window HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE); ::SetWindowTextA(hwnd, "被蕭沖改變了!"); [/code] ===================引 用 ttnnrsseb 文 章=================== 不好意思,我是要開mmsys.cpl。 不過程式有可能在不同語系的OS執行,所以不能抓名稱是指這個意思。 我在想是不是有什麼方式可以先幫它的視窗改個特定的名字,就可以用特定名字去FindWindow ?
------
蕭沖 --All ideas are worthless unless implemented-- C++ Builder Delphi Taiwan G+ 社群 http://bit.ly/cbtaiwan |
ttnnrsseb
中階會員 ![]() ![]() ![]() 發表:31 回覆:77 積分:51 註冊:2004-11-22 發送簡訊給我 |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |