模拟Domodal解决办法

模拟Domodal
本帖最后由 VisualEleven 于 2015-11-11 18:18:12 编辑
问题描述:
本人程序完全基于win32,由于一些特殊原因无法使用DialogBoxXXX这样的函数去创建模态窗口
所有的窗口创建都是使用的CreateWindow这个API
可是大家都知道很多时候 是需要使用类似mfc里CDialog那样的DoModal来弹出窗口的.
我试图利用CreateWindow模拟它 我现在的代码是这样的,主要是消息循环 其它代码就随意看看了
int CWin32DialogBase::DoModal(HWND hWndParent, DWORD nStyle , DWORD dwExtendedStyle)
{
Create(hWndParent);
m_bModalMode = TRUE;
if (!IsWindow(m_hWnd))
{
_ASSERT(FALSE);
return m_nModalResult;
}
m_nFlags |= (WF_MODALLOOP | WF_CONTINUEMODAL);
MSG msg;
while (IsWindow(m_hWnd) && (m_nFlags & WF_CONTINUEMODAL) && GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}

m_nFlags &= ~WF_MODALLOOP;

if (::IsWindow(m_hWnd))
DestroyWindow(m_hWnd);

return m_nModalResult;
}

其中Create(hWndParent);一行就是创建一个非模态窗口
现在的问题是 如果用这种方式只弹出一个窗口的话 一切okay
但如果弹出两个的话就有问题了,先弹出来的无法通过EndDialog来关闭窗口,EndDialog代码如下:
int CWin32DialogBase::EndDialog(int nRetCode)
{
m_nModalResult = nRetCode;
if (!::IsWindow(m_hWnd))
{
_ASSERT(FALSE);
return FALSE;
}
//End modal loop
if (m_nFlags & WF_CONTINUEMODAL)
{
m_nFlags &= ~WF_CONTINUEMODAL;
PostMessage(m_hWnd, WM_NULL, 0, 0);
}
if (m_hWndParent && ::IsWindow(m_hWndParent))
{
EnableWindow(m_hWndParent, TRUE);
}
return ::EndDialog(m_hWnd, nRetCode);
}

问题的症结在于 弹出2个窗口后相当于主线程中有2个消息循环,这样想想也会出问题了
但怎么都想不到一个好的办法去模拟DoMo
请大侠们给点意见啊
------解决思路----------------------
直接翻VC自带的DoModal的源码
------解决思路----------------------
mfc 也是 用 Create , see DlgCore.cpp

int CDialog::DoModal()
{
// can be constructed with a resource template or InitModalIndirect
ASSERT(m_lpszTemplateName != NULL 
------解决思路----------------------
 m_hDialogTemplate != NULL 
------解决思路----------------------

m_lpDialogTemplate != NULL);

// load resource as necessary
LPCDLGTEMPLATE lpDialogTemplate = m_lpDialogTemplate;
HGLOBAL hDialogTemplate = m_hDialogTemplate;
HINSTANCE hInst = AfxGetResourceHandle();
if (m_lpszTemplateName != NULL)
{
hInst = AfxFindResourceHandle(m_lpszTemplateName, RT_DIALOG);
HRSRC hResource = ::FindResource(hInst, m_lpszTemplateName, RT_DIALOG);
hDialogTemplate = LoadResource(hInst, hResource);
}
if (hDialogTemplate != NULL)
lpDialogTemplate = (LPCDLGTEMPLATE)LockResource(hDialogTemplate);

// return -1 in case of failure to load the dialog template resource
if (lpDialogTemplate == NULL)
return -1;

// disable parent (before creating dialog)
HWND hWndParent = PreModal();
AfxUnhookWindowCreate();
BOOL bEnableParent = FALSE;
if (hWndParent != NULL && ::IsWindowEnabled(hWndParent))
{
::EnableWindow(hWndParent, FALSE);
bEnableParent = TRUE;
}

TRY
{
// create modeless dialog
AfxHookWindowCreate(this);
if (CreateDlgIndirect(lpDialogTemplate,
CWnd::FromHandle(hWndParent), hInst))
{
if (m_nFlags & WF_CONTINUEMODAL)
{
// enter modal loop
DWORD dwFlags = MLF_SHOWONIDLE;
if (GetStyle() & DS_NOIDLEMSG)
dwFlags 
------解决思路----------------------
= MLF_NOIDLEMSG;
VERIFY(RunModalLoop(dwFlags) == m_nModalResult);
}

// hide the window before enabling the parent, etc.
if (m_hWnd != NULL)
SetWindowPos(NULL, 0, 0, 0, 0, SWP_HIDEWINDOW
------解决思路----------------------

SWP_NOSIZE
------解决思路----------------------
SWP_NOMOVE
------解决思路----------------------
SWP_NOACTIVATE
------解决思路----------------------
SWP_NOZORDER);
}
}
CATCH_ALL(e)
{
DELETE_EXCEPTION(e);
m_nModalResult = -1;
}
END_CATCH_ALL

if (bEnableParent)
::EnableWindow(hWndParent, TRUE);
if (hWndParent != NULL && ::GetActiveWindow() == m_hWnd)
::SetActiveWindow(hWndParent);

// destroy modal window
DestroyWindow();
PostModal();

// unlock/free resources as necessary
if (m_lpszTemplateName != NULL 
------解决思路----------------------
 m_hDialogTemplate != NULL)
UnlockResource(hDialogTemplate);
if (m_lpszTemplateName != NULL)
FreeResource(hDialogTemplate);

return m_nModalResult;
}

------解决思路----------------------
你直接PostMesasge(WM_CLOSE)到之前的HWND不能关闭?
------解决思路----------------------
请参考duilib或者SOUI等开源UI库中的模态对话框实现
------解决思路----------------------
看看windows编程启示录, 有讲解, 有例子代码
------解决思路----------------------
“看来是无解了哦”
你写个 最简单的例子上传 到 你的资源,说明问题就行。