调整大小光标显示在固定对话框框架

时间:2018-03-19 11:50:58

标签: mfc visual-studio-2017 border cdialog

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

上下文

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

class CChristianLifeMinistryStudentsDlg : public CDialogEx

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

Settings

主应用程序(也基于CDialogEx)有一个固定的窗口。这表现得很正确。

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

发生了什么

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

Frame cursor

我不明白为什么会这样。

光标管理

在"编辑器中#34;产生这个弹出窗口我确实有一些像这样的游标管理:

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

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

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

间谍结果

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

Spy Results

正如预期的那样,当它不在资源编辑器中时,我们突然设置了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中的错误吗?

澄清

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

Editor

但在这种情况下,弹出窗口不需要。但这是因为我的弹出窗口来自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);返回TRUE。结果,对话框最终调用InitDynamicLayout。在我弹出的其他对话框中,这不会发生。相反,bResult最终为FALSE,因此框架不会调整大小。

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

1 个答案:

答案 0 :(得分:1)

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

Dynamic

我必须将所有这些属性设置回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手动重置每个控件。但是,我猜您可以手动修改文本文件。

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

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

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