嗯我想在启动窗口后最小化窗口,但它没有生效,我也不知道我做错了什么。你能指出下面代码中的错误吗?
除了打开一个窗口外什么也没发生。
HWND g_hwnd;
int g_nFound;
BOOL CALLBACK FindHwndFromPID(HWND hwnd, LPARAM lParam);
HWND GetHwndFromPID(DWORD dwProcessId)
{
g_hwnd = NULL;
g_nFound = 0;
EnumWindows(FindHwndFromPID, (LPARAM)dwProcessId);
if (g_hwnd) // we found one...
return (g_hwnd);
// nothing found :-(
return (NULL);
}
BOOL CALLBACK FindHwndFromPID(HWND hwnd, LPARAM lParam)
{
DWORD dwPID2Find = (DWORD)lParam;
DWORD dwPID = 0;
if (GetWindowThreadProcessId(hwnd, &dwPID))
{
if (dwPID == dwPID2Find)
{
g_hwnd = hwnd;
return (FALSE);
}
}
return (TRUE);
}
int main
{
..../
if (!CreateProcessA(NULL, // No module name (use command line)
command_line.GetBuffer(),
NULL, // Process handle not inheritable
NULL, // Thread handle not inhberitable
FALSE, // Set handle inheritance to FALSE
0, // No creation flags
NULL, // Use parent's environment block
NULL, // Use parent's starting directory
&si, // Pointer to STARTUPINFO structure
&pi) // Pointer to PROCESS_INFORMATION structure
)
{
//... error handling
return 0;
}
WaitForInputIdle(pi.hProcess, 1000);
HWND hwnds = GetHwndFromPID(pi.dwProcessId);
printf("Process Handle %d, hwnd id: %p ",pi.dwProcessId, hwnds);
CloseWindow(hwnds);
该代码应该最小化窗口,但我不知道它为什么没有。
答案 0 :(得分:4)
你这是错误的方式。要求生成的流程最初最小化的官方和记录的方式是在调用STARTUPINFO
时使用CreateProcess()
结构,例如:
int main()
{
STARTUPINFO si;
ZeroMemory(&si, sizeof(si));
si.cbSize = sizeof(si);
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_MINIMIZE;
//...
if (!CreateProcessA(..., &si, ...))
{
//... error handling
return 0;
}
//...
return 0;
}
wShowWindow
如果dwFlags指定STARTF_USESHOWWINDOW,则此成员可以是ShowWindow函数的nCmdShow参数中可以指定的任何值,SW_SHOWDEFAULT除外。否则,将忽略此成员。对于GUI进程,第一次调用ShowWindow时,将忽略其nCmdShow参数wShowWindow指定默认值。在后续的ShowWindow调用中,如果ShowWindow的nCmdShow参数设置为SW_SHOWDEFAULT,则使用wShowWindow成员。
nCmdShow [in]
键入:int控制窗口的显示方式。 如果启动应用程序的程序提供STARTUPINFO结构,则应用程序第一次调用ShowWindow时将忽略此参数。否则,第一次调用ShowWindow时,该值应该是WinMain函数在其nCmdShow参数中获得的值。
...
应用程序第一次调用ShowWindow时,它应该使用WinMain函数的nCmdShow参数作为其nCmdShow参数。对ShowWindow的后续调用必须使用给定列表中的一个值,而不是WinMain函数的nCmdShow参数指定的值。
如nCmdShow参数的讨论中所述,如果启动应用程序的程序在结构中指定启动信息,则在第一次调用ShowWindow时会忽略nCmdShow值。在这种情况下,ShowWindow使用STARTUPINFO结构中指定的信息来显示窗口。在后续调用中,应用程序必须调用ShowWindow并将nCmdShow设置为SW_SHOWDEFAULT,以使用启动应用程序的程序提供的启动信息。此行为适用于以下情况:
•应用程序通过调用CreateWindow并设置WS_VISIBLE标志来创建其主窗口。
•应用程序通过调用CreateWindow并清除WS_VISIBLE标志来创建其主窗口,然后调用ShowWindow并设置SW_SHOW标志以使其可见。
答案 1 :(得分:1)
因为应用程序窗口可能不属于已启动的进程,而是属于其子进程,所以您必须通过在比较中包含父进程来深入FindHwndFromPID
。
我们也不会依靠WaitForInputIdle()
自己,你必须给创建过程足够的时间来完全初始化。
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <tlhelp32.h>
HWND g_hwnd;
int g_nFound;
BOOL CALLBACK FindHwndFromPID(HWND hwnd, LPARAM lParam);
/*___________________________________________________________________________________________________
*/
HWND GetHwndFromPID(DWORD dwProcessId)
{
g_hwnd = NULL;
g_nFound = 0;
EnumWindows(FindHwndFromPID, (LPARAM)dwProcessId);
if (g_hwnd) // we found one...
return (g_hwnd);
// nothing found :-(
return (NULL);
}
/*___________________________________________________________________________________________________
*/
DWORD GetParentProcess(DWORD pid){
PROCESSENTRY32 p32={sizeof(PROCESSENTRY32)};
DWORD ParentPID=0;
HANDLE hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0 );
if(Process32First(hSnapShot,&p32)){
do{
if(p32.th32ProcessID==pid){
ParentPID = p32.th32ParentProcessID;
break;
}
}while(Process32Next(hSnapShot,&p32));
}
CloseHandle(hSnapShot);
return ParentPID;
}
/*___________________________________________________________________________________________________
*/
int __stdcall WindowText(HWND hWnd,LPSTR lpString,int nMaxCount){
int ret;
ret=SendMessage(hWnd,WM_GETTEXTLENGTH,0,0);
if(ret){
ret=SendMessage(hWnd,WM_GETTEXT,nMaxCount,(LPARAM)lpString);
}
return ret;
}
/*___________________________________________________________________________________________________
*/
BOOL CALLBACK FindHwndFromPID(HWND hwnd, LPARAM lParam){
DWORD dwPID2Find = (DWORD)lParam;
DWORD dwPID = 0;
if(GetWindowLong(hwnd,GWLP_HWNDPARENT) || !IsWindowVisible(hwnd))
return 1;
if (GetWindowThreadProcessId(hwnd, &dwPID)){
if ((dwPID == dwPID2Find) || ( GetParentProcess(dwPID) == dwPID2Find)){
g_hwnd = hwnd;
return (FALSE);
}
}
return (TRUE);
}
/*___________________________________________________________________________________________________
*/
int main(){
PROCESS_INFORMATION pi;
STARTUPINFO si={sizeof(si)};
TCHAR exename[]=TEXT("write.exe"); // writable buffer (for Unicode bug.)
if (!CreateProcess(NULL,exename,NULL, NULL,FALSE, 0, NULL,NULL,&si, &pi)){
return 0;
}
//WaitForInputIdle(pi.hProcess, 1000); // this alown will not always work (process may have children)
// give enough time to process to fully initialize
// put all in a loop until you
// get the window handle or timeout.
HWND hwnds = GetHwndFromPID(pi.dwProcessId);
for( int i=0 ;i<1000;i++ ){
if(hwnds)
break;
Sleep(10);
hwnds = GetHwndFromPID(pi.dwProcessId);
}
printf("Process Handle %d, hwnd id: %p ",pi.dwProcessId, hwnds);
CloseWindow(hwnds);
return 0;
}