【发布时间】:2017-05-11 07:32:23
【问题描述】:
我有一个 32 位 MFC 应用程序,它使用自定义库,重新编译成 x64 将是一场噩梦。一般来说,应用程序实际上并不需要以 64 位运行,除非有一种情况——即渲染内容以显示在对话窗口中,这可以受益于更大的寻址空间。
所以我的目标是“模仿”CDialog::DoModal 方法,但用于另一个进程中的对话。
我将该对话框窗口构建为一个独立的基于 x64 MFC 对话框的应用程序。它将文件路径作为输入参数,在内部完成所有工作,并返回简单的用户选择:OK、Cancel。
所以我从我的主要父进程执行以下操作:
//Error checks omitted for brevity
CString strCmd = L"D:\\C++\\MyDialogBasedApp.exe";
HWND hParWnd = this->GetSafeHwnd();
SHELLEXECUTEINFO sei = {0};
sei.cbSize = sizeof(sei);
sei.fMask = SEE_MASK_FLAG_NO_UI | SEE_MASK_UNICODE | SEE_MASK_NOCLOSEPROCESS;
sei.nShow = SW_SHOW;
sei.lpVerb = _T("open");
sei.lpFile = strCmd.GetBuffer();
sei.hwnd = hParWnd;
BOOL bInitted = SUCCEEDED(::CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE));
ShellExecuteEx(&sei);
DWORD dwProcID = ::GetProcessId(sei.hProcess);
//Try to get main Wnd handle for the child process
HWND hMainChildWnd = NULL;
for(;; ::Sleep(100))
{
hMainChildWnd = getHwndFromProcID(dwProcID);
if(hMainChildWnd)
break;
}
HWND hPrevParWnd = ::SetParent(hMainChildWnd, hParWnd);
if(hPrevParWnd)
{
//Wait for child process to close
::WaitForSingleObject(sei.hProcess, INFINITE);
//Reset parent back
::SetParent(hMainChildWnd, hPrevParWnd);
}
::CloseHandle(sei.hProcess);
if(bInitted)
::CoUninitialize();
getHwndFromProcID 的位置是 from here。
这有点工作,除了以下内容:
(1) 任务栏上有两个图标:一个用于我的主应用程序,一个用于子应用程序。有没有办法不显示子图标?
(2) 我可以将焦点从子窗口切换到父窗口,反之亦然。在实际的模态对话框窗口中,当子进程打开时,无法切换回父进程。有没有办法做到这一点?
(3) 如果我开始与父级交互,它似乎被“挂断”了,操作系统甚至会在其标题栏上显示它。
所以我很好奇是否有办法解决所有这些问题?
【问题讨论】:
标签: c++ windows winapi mfc modal-dialog