无需键盘和鼠标,交互和焦点即可创建流程

时间:2017-09-15 04:58:57

标签: c++ winapi win32gui win32-process windows-process

如何在没有鼠标和键盘焦点和交互的情况下创建/生成 Win32 进程?

有人提到最合适的 Win API 功能来创建窗口进程而不显示为最顶层的窗口,但是在其他打开的窗口中留下来?

(假设你必须产生/创建窗口(不是全屏) Direct3D 程序可执行文件的过程,并且该程序由父程序终止,因此不需要用户交互但是因此,当它被创建时,它应该显示在其他已经打开的窗口后面。)

1 个答案:

答案 0 :(得分:0)

启动具有非活动SW_ *值的流程是不够的,但如果您是前台窗口,还可以调用LockSetForegroundWindow来禁用SetForegroundWindow

void backgroundcalc_simple()
{
    LockSetForegroundWindow(LSFW_LOCK);
    ShellExecute(NULL, NULL, TEXT("Calc"), NULL, NULL, SW_SHOWNA);
    // Cannot unlock here without a hacky call to Sleep
}

如果您的应用程序不需要SetForegroundWindow,那么您无需解锁,但无论如何都可能这样做:

BOOL CALLBACK ProcessHasVisibleWindowProc(HWND hWnd, LPARAM Param)
{
    if (IsWindowVisible(hWnd) && (WS_CAPTION & GetWindowLongPtr(hWnd, GWL_STYLE)))
    {
        DWORD thispid, *wantedpid = (DWORD*) Param;
        if (GetWindowThreadProcessId(hWnd, &thispid) && thispid == *wantedpid)
        {
            *wantedpid = 0;
            return FALSE;
        }
    }
    return TRUE;
}
BOOL ProcessHasVisibleWindow(DWORD Pid)
{
    if (!Pid) return FALSE;
    EnumWindows(ProcessHasVisibleWindowProc, (LPARAM) &Pid);
    return Pid == 0;
}

BOOL WaitForVisibleProcessWindow(DWORD Pid, DWORD Timeout)
{
    DWORD start = GetTickCount();
    for (;;)
    {
        if (ProcessHasVisibleWindow(Pid)) return TRUE;
        if (GetTickCount() - start >= Timeout && Timeout != INFINITE) break;
        Sleep(50);
    }
    return FALSE;
}

void backgroundcalc()
{
    STARTUPINFO si;
    PROCESS_INFORMATION pi;
    ZeroMemory(&si, sizeof(si));
    si.cb = sizeof(si);
    si.dwFlags = STARTF_FORCEOFFFEEDBACK|STARTF_USESHOWWINDOW;
    si.wShowWindow = SW_SHOWNA;
    WCHAR cmd[MAX_PATH];
    lstrcpy(cmd, TEXT("Calc"));
    LockSetForegroundWindow(LSFW_LOCK);
    if (CreateProcess(NULL, cmd, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
    {
        WaitForInputIdle(pi.hProcess, 3333);
        WaitForVisibleProcessWindow(pi.dwProcessId, 1000*10);
        CloseHandle(pi.hProcess);
        CloseHandle(pi.hThread);
    }
    LockSetForegroundWindow(LSFW_UNLOCK);
}