2

在这里为您提供一个最小的工作示例有点困难,但我将尝试解释我刚刚注意到的这个问题。

上下文

所以,我有一个常规CDialogEx派生类,定义如下:

class CChristianLifeMinistryStudentsDlg : public CDialogEx

我已将其设置为边框不会调整大小:

设置

主应用程序(也是CDialogEx基于)有一个固定的窗口。那行为是正确的。

  • 用户从菜单中显示一个可调整大小的对话框(编辑器)。
  • 在这个对话框上是一个用户可以按下的按钮,它将依次显示我所指的弹出模式对话框。

发生什么了

当显示此对话框时,当您将鼠标悬停在对话框边框上时,我注意到了这一点:

帧光标

我不明白为什么会这样。

光标管理

在产生这个弹出窗口的“编辑器”中,我确实有一些像这样的光标管理:

BOOL CChristianLifeMinistryEditorDlg::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
    if (CPersistentWaitCursor::WaitCursorShown())
    {
        RestoreWaitCursor();
        return TRUE;
    }

    return CDialogEx::OnSetCursor(pWnd, nHitTest, message);
}

但是,我暂时尝试从没有游标管理的主应用程序对话框中调用此弹出窗口,结果仍然相同。

间谍结果

根据要求,我刚刚使用 Spy 来检查窗口样式:

间谍结果

果然不出所料我们突然WS_THICKFRAME设置了,当它不在资源编辑器中时!

所以

在我的 RC 文件中,对话框DS_MODALFRAME设置了标志,但在运行时它最终WS_THICKFRAME设置了。据我所知,我从未对这些受影响的对话框对象进行这些更改。

更新

我发现了以下内容:

BOOL CChristianLifeMinistryStudentsDlg::OnInitDialog()
{
    LONG_PTR lStyle = GetWindowLongPtr(GetSafeHwnd(), GWL_STYLE);
    if (lStyle & WS_THICKFRAME)
        AfxMessageBox(_T("Thick"));
    else if (lStyle & DS_MODALFRAME)
        AfxMessageBox(_T("Modal"));

    CDialogEx::OnInitDialog();

如果我在调用之前放置检查代码,CDialogEx::OnInitDialog();则样式设置为DS_MODALFRAME. 但是,如果我在调用放置相同的检查代码,则CDialogEx::OnInitDialog();它会更改为WS_THICKFRAME. 为什么?

好的

因此,该CDialogEx::OnInitDialog方法调用CWnd::LoadDynamicLayoutResource(LPCTSTR lpszResourceName). 这反过来调用CWnd::InitDynamicLayout(). 在方法中,它这样做:

if (!bIsChild && (pDialog != NULL || pPropSheet != NULL))
{
    CRect rect;
    GetClientRect(&rect);

    ModifyStyle(DS_MODALFRAME, WS_POPUP | WS_THICKFRAME);
    ::AdjustWindowRectEx(&rect, GetStyle(), ::IsMenu(GetMenu()->GetSafeHmenu()), GetExStyle());

    SetWindowPos(NULL, 0, 0, rect.Width(), rect.Height(), SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOOWNERZORDER);
}

我们去吧。所以这是因为我正在使用CDialogEx我的基类。这是MFC中的错误吗?

澄清

“编辑器”(拥有按钮的弹出窗口的父窗口)确实使用动态布局功能:

编辑

但在这种情况下,弹出窗口不需要。但这是因为我的弹出窗口源于CDialogEx这种情况。

情节变厚了

所以这是始终使用以下命令调用的 MFC 代码CDialog::OnInitDialog

BOOL CWnd::LoadDynamicLayoutResource(LPCTSTR lpszResourceName)
{
    if (GetSafeHwnd() == NULL || !::IsWindow(GetSafeHwnd()) || lpszResourceName == NULL)
    {
        return FALSE;
    }

    // find resource handle
    DWORD dwSize = 0;
    LPVOID lpResource = NULL;
    HGLOBAL hResource = NULL;
    if (lpszResourceName != NULL)
    {
        HINSTANCE hInst = AfxFindResourceHandle(lpszResourceName, RT_DIALOG_LAYOUT);
        HRSRC hDlgLayout = ::FindResource(hInst, lpszResourceName, RT_DIALOG_LAYOUT);
        if (hDlgLayout != NULL)
        {
            // load it
            dwSize = SizeofResource(hInst, hDlgLayout);
            hResource = LoadResource(hInst, hDlgLayout);
            if (hResource == NULL)
                return FALSE;
            // lock it
            lpResource = LockResource(hResource);
            ASSERT(lpResource != NULL);
        }
    }

    // Use lpResource
    BOOL bResult = CMFCDynamicLayout::LoadResource(this, lpResource, dwSize);

    // cleanup
    if (lpResource != NULL && hResource != NULL)
    {
        UnlockResource(hResource);
        FreeResource(hResource);
    }

    if (bResult)
    {
        InitDynamicLayout();
    }

    return bResult;
}

由于某种原因,此调用BOOL bResult = CMFCDynamicLayout::LoadResource(this, lpResource, dwSize);是 return TRUE。结果,对话框最终调用InitDynamicLayout. 在我的其他弹出对话框中,这不会发生。取而代之的是,bResult最终FALSE框架没有调整大小。

那么为什么它认为它有效呢?

4

1 回答 1

2

解决了。我不记得这样做了,但出于某种原因,我在对话框上的一些控件设置了动态属性。例如:

动态的

我不得不将所有这些属性设置回None. 然后它表现得很好。


通过在文本编辑器中打开资源文件,您可以轻松判断给定对话框资源是否具有任何动态属性。例如:

IDD_DIALOG_OUR_CHRISTIAN_LIFE_AND_MINISTRY_MATERIAL AFX_DIALOG_LAYOUT
BEGIN
    0,
    0, 0, 0, 0,
    0, 0, 0, 0,
    0, 0, 0, 0,
    0, 0, 0, 0,
    0, 0, 0, 0,
    0, 0, 10, 0,
    0, 0, 0, 0,
    50, 0, 0, 0,
    50, 0, 0, 0,
    0, 0, 0, 0,
    0, 0, 10, 0,
    0, 0, 0, 0,
    50, 0, 0, 0,
    50, 0, 0, 0,
    0, 0, 0, 0,
    0, 0, 10, 0,
    0, 0, 0, 0,
    50, 0, 0, 0,
    50, 0, 0, 0,
    0, 0, 0, 0,
    0, 0, 0, 0
END

如果出现上述情况,那么您的对话框将被视为具有动态布局,因此对话框的设置将被修改:

ModifyStyle(DS_MODALFRAME, WS_POPUP | WS_THICKFRAME);

资源在没有动态控件属性时将如下所示:

IDD_DIALOG_OUR_CHRISTIAN_LIFE_AND_MINISTRY_MATERIAL AFX_DIALOG_LAYOUT
BEGIN
    0
END

我选择通过 IDE 手动重置每个控件。但是,我想您可以手动修改文本文件。


至于为什么我首先拥有具有动态属性的控件,好吧,我不能告诉你。我过去可能一直在摆弄对话框,并没有意识到边框的副作用。或者,我可能已经将控件从一个资源复制到另一个资源,并且它带有动态值。

有趣的旁注是,虽然 MFC 代码将边框设置为粗边框,但它并没有对其进行充分更改以启用对话框调整大小。但那是另一回事了!

至少我们现在知道问题的原因以及如何轻松识别资源中具有动态布局的对话框。

于 2018-03-19T19:39:06.037 回答