QT应用隐藏启动外部应用

    技术2022-07-17  79

    最近在开发的一个项目需要用QT调用Unity的应用。想到的办法就是启动Unity应用,嵌入到QT应用中。

    由于Unity应用加载需要时间,而且无法隐藏加载窗口(本人不熟悉unity开发)。因此采用外部调用的方式加载unity应用。

    一、QT 调用Unity程序CreateProcess

    STARTUPINFO si;     si.cb = sizeof(STARTUPINFO);     si.lpReserved = NULL;     si.lpDesktop = NULL;     si.lpTitle = NULL;      si.dwFlags = STARTF_USESHOWWINDOW| STARTF_USESTDHANDLES;      si.wShowWindow = SW_HIDE;     si.cbReserved2 = NULL;     si.lpReserved2 = NULL;     std::wstring str = path.toStdWString();     BOOL ret = CreateProcess(NULL, (LPTSTR)str.c_str(), NULL, NULL, FALSE, CREATE_SUSPENDED|CREATE_NO_WINDOW, NULL, NULL, &si, &pi);

    此时untiy.exe以进程挂起的方式隐藏创建,且没有新的窗口。

    二、第一次显示的时候可以调用解挂,并设置unity.exe与应用程序的窗口关系

        ::ResumeThread((HANDLE)pi.hThread);     HWND childHwnd = NULL;     while (true)     {         childHwnd = FindWindowA(NULL, m_strExeWndName.c_str());         if (childHwnd != NULL)         {             break;         }     }     //2、延时,这个很重要,一定要大于50        Sleep(3200);

        //4、设置父窗口      HWND parentHwnd = (HWND)ui.mWidget->winId();      SetParent(childHwnd, parentHwnd);  //5、设置窗口位置     SetWindowPos(childHwnd, HWND_TOPMOST, 0, 0, nWidth, nHeight, SWP_FRAMECHANGED);

    三、关闭进程     TerminateProcess(pi.hProcess, 0);//终止进程     ::CloseHandle(pi.hThread);     ::CloseHandle(pi.hProcess);

    四、设置Unity窗口属性

    unity窗口是以windows形式build的。此时会带有边框、标题栏。需要隐藏边框和标题栏。

    此处代码可参见:https://blog.csdn.net/ldy597321444/article/details/86595786

    注意:unity窗口如果是全屏创建的,此时到了QT应用中,不能自适应窗口的大小。需要保证unity窗口的大小和QT中展示Unity应用部分的窗口大小一致。

    STARTF_USESIZE| STARTF_USEPOSITION两个属性,并不能更改Unity窗口的大小。详见MSDN。

    研究过程记录:

    1、首先想到的是隐藏Unity程序的边框,但是本人对于Unity不熟悉,仅隐藏了脚本加载后的边框,没有隐藏掉加载时的边框;

    2、不能使用QT通过CreateProcess调用进程后,再修改unity窗口的属性。此时,已经显示并获取到了Unity窗口的属性。方法1和2,均会产生unity加载窗口,且加载后会有位置的移动。因此有了第三种方案,在加载进程时改变窗口状态。

    3、CreateProcess时,使用线程挂起的方式,并设置窗口的隐藏。

    Processed: 0.009, SQL: 9