调整大小光标显示在固定对话框框的边框上

Resize cursor is showing on the border of a fixed dialog frame

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

背景

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

class CChristianLifeMinistryStudentsDlg : public CDialogEx

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

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

发生了什么

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

我不明白为什么会这样。

光标管理

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

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

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

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

间谍结果

根据要求,我刚刚使用 Spy 检查了 window 样式:

正如预期的那样,我们突然设置了 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()。在 that 方法中,它是这样做的:

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 作为我的基础 class。这是 MFC 中的错误吗?

澄清

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

但在这种情况下,弹出窗口不需要。但这是因为我的弹出窗口是从 CDialogEx 派生的,所以才会发生这种情况。

剧情变厚了

所以这是总是用CDialog::OnInitDialog调用的MFC代码:

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,因此框架不会调整大小。

那么它为什么认为有效?

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

我不得不将所有这些属性设置回 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 代码将边框设置为粗,但它没有充分更改以启用对话框大小调整。但那是另一回事!

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