[英]launch another application as popup window
我有一个MFC应用程序,它会作为弹出窗口启动其他(通用窗口,黑盒)应用程序,并等待其完成。 父母与孩子之间不需要沟通/互动,应避免。 仅需要“子应用程序表现为父应用程序的模式对话框”。 正确的方法是什么?
可以在以下位置看到“启动另一个应用程序作为子窗口”的示例: 将应用程序激活为另一个应用程序的子窗口/弹出窗口,从而导致http://www.codeproject.com/Articles/18724/Hosting-exe-applications-进入一个对话 (这不是我想要的,我想要模式弹出行为)
为简单起见,我们可以假设启动和启动的应用程序都具有单个“堆栈”窗口(一个带有模态对话框的主窗口可以具有自己的模态对话框)。
我当前的伪代码(为简单起见,省略了错误处理和回调函数)
//get the current MFC dialog of launcher program we are launching the other app from
parentWnd = AfxGetMainWnd()->GetActiveWindow();
parentHwnd = parentWnd->GetSafeHwnd(); //HWND
// launch child and retrieve basic info from PROCESSINFO structure
CreateProcess(childExecutable); // => childProcessHandle, childProcessId
//get the "main" window of child application
EnumWindows(EnumProc_That_Retrieves_TopLevelWindow_With_childProcessId); // => childHwnd
//link the child window as popup
SetWindowLong(childHwnd, GW_OWNER, parentHwnd);
//disable input into parent window
parentWnd->EnableWindow(FALSE);
//remove taskbar entry for child
SetWindowLong(child, GWL_EXSTYLE, GetWindowLong(child, GWL_EXSTYLE)&~WS_APPWINDOW);
//now keep waiting for the child process termination and process parent messages (e.g. WM_PAINT)
while (MsgWaitForMultipleObjects(childProcessHandle and process QS_ALLINPUT) {
while (PeekMessage(PM_NOREMOVE)) AfxGetApp()->PumpMessage();
}
//re-enable input into parent window
parentWnd->EnableWindow(TRUE);
现在,我较小的问题是前景视觉样式(例如,前景=蓝色标题栏与背景=灰色标题栏)和键盘输入焦点行为:
1)最初删除子级WS_APPWINDOW样式将从子级应用程序中删除前景视觉和输入焦点。 在这一点上,没有应用程序具有焦点。
2)当用户单击任何父应用程序窗口时,将切换子前景的视觉样式。 键盘焦点保留在子应用程序中。 示例:子应用具有前景+焦点->第一次单击父项->子失去前景,保持焦点->单击父项第二次->子项获得前景,保持焦点->等等。
预期的行为(“常规” MFC弹出窗口会执行的操作):子应用程序具有前景+焦点->单击父项->子标题栏短暂闪烁并保留前景+焦点子应用程序没有前景+焦点->单击父项->子标题栏获得前景和键盘焦点
现在这是最严重的问题 :3)我遇到了一个MFC应用程序,当单独启动该应用程序时,用户可以打开“模式对话框堆栈” A-> B-> C-> D-> E,Windows的所有权完全匹配(E由D拥有,D由C拥有,等等)。 但是,如果我从MFC应用程序(M)中打开它,则所有权看起来就像M-> A-> B-> C,D,E(C,D,E都由B拥有,B由A拥有,A拥有通过我的应用窗口M)。 这会导致“没有支持的堆栈” http://blogs.msdn.com/b/oldnewthing/archive/2005/02/24/379635.aspx问题。 当我删除SetWindowLong(childHwnd, GW_OWNER, parentHwnd)
时,此行为消失了SetWindowLong(childHwnd, GW_OWNER, parentHwnd)
因此弄乱所有权可能会触发子应用程序的有害行为,但是如果没有这样做,我似乎无法保证模式对话框的前提是“一个位于另一个之上” 。
因此,还有一个大问题:执行此任务并避免出现我所描述的问题的正确方法是什么?
编辑
我们必须避免像@mfc所建议的那样弄乱所有者拥有的结构,因此,任务基本上是以另一种方式为我们的父子对重新实现窗口管理器的这一方面。 我已经使用Windows Hooks建立了解决方案的原型。 但是,完成它似乎相当复杂且乏味,因此我决定采用另一种原始方法(截止日期,截止日期)。 为了举例,我将描述两者的基本思想。
免责声明:只有父焦点挂钩已被确认可以正常工作,其余都是理论上的努力。 也许有一个更清洁/更轻量级的实现,可能会在实际的Windows窗口管理器实现中获得启发(记住整个要点是避免设置GW_OWNER,该功能对于窗口管理器来说很好用,但是会破坏子黑盒应用程序的行为)。
基本上在先前解决方案的第一点上应用了焦点开关,当单击父对象时,它会在子对象之间来回闪烁,从而在子对象上闪烁。
更改不属于您的其他窗口的父/子关系非常棘手且容易出错。 如果启动器程序与启动的程序没有通信,并且主要目的是避免与启动器有任何UI,则可以使用ShowWindow(SW_HIDE)在成功启动辅助程序后简单地隐藏启动器。 在隐藏模式下,它将继续监视启动的程序,并在辅助程序终止时取消隐藏自身。
尝试使用API函数“ ShellExecute()”。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.