CloseWindow并没有最小化我刚刚启动的流程窗口

时间:2016-02-02 14:32:23

标签: c++ winapi

嗯我想在启动窗口后最小化窗口,但它没有生效,我也不知道我做错了什么。你能指出下面代码中的错误吗?

除了打开一个窗口外什么也没发生。

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);

该代码应该最小化窗口,但我不知道它为什么没有。

2 个答案:

答案 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;
}

STARTUPINFO structure

  

wShowWindow
  如果dwFlags指定STARTF_USESHOWWINDOW,则此成员可以是ShowWindow函数的nCmdShow参数中可以指定的任何值,SW_SHOWDEFAULT除外。否则,将忽略此成员。

     

对于GUI进程,第一次调用ShowWindow时,将忽略其nCmdShow参数wShowWindow指定默认值。在后续的ShowWindow调用中,如果ShowWindow的nCmdShow参数设置为SW_SHOWDEFAULT,则使用wShowWindow成员。

ShowWindow function

  

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;
}