C++ CDialog:为什么SetParent(this)更改视觉样式?
我在C++ CDialog:为什么SetParent(this)更改视觉样式?,c++,visual-studio,winapi,visual-c++,mfc,C++,Visual Studio,Winapi,Visual C++,Mfc,我在CView派生类m_wndTestDlg.create(CTestDlg::IDD,this)中创建一个非模态的CDialog并使用以下代码显示/隐藏和移动对话框 h文件: class CTestView : public CView { : CTestDlg m_wndTestDlg; : } cpp文件: void CTestView::OnInitialUpdate() { CView::OnInitialUpdate(); m_wndTest
CView
派生类m_wndTestDlg.create(CTestDlg::IDD,this)中创建一个非模态的CDialog
代码>并使用以下代码显示/隐藏和移动对话框
h文件:
class CTestView : public CView
{
:
CTestDlg m_wndTestDlg;
:
}
cpp文件:
void CTestView::OnInitialUpdate()
{
CView::OnInitialUpdate();
m_wndTestDlg.Create(CTestDlg::IDD, this);
}
void CTestView::OnDialog1()
{
BOOL b = m_wndTestDlg.IsWindowVisible();
if (b)
m_wndTestDlg.ShowWindow(SW_HIDE);
else {
m_wndTestDlg.ShowWindow(SW_SHOW);
// if (!m_wndTestDlg.IsWindowVisible()) { // still not viewable, outside ParentScreen, move to top of CView
m_wndTestDlg.SetParent(this);
m_wndTestDlg.SetWindowPos(&CWnd::wndTop, 0, 0, 0, 0, SWP_NOSIZE | SWP_SHOWWINDOW);
}
}
我不明白为什么SetParent
将视觉样式更改为旧的WinXP样式?如果SetParent
的目的是将对话框保持在视图前面,那么以下操作可能会起作用(也可能不起作用,取决于UI的具体情况)。但是,如果原因是将对话框剪裁到父视图,那么这将没有帮助,尽管它仍试图解释原因
这里的主要问题是Windows如何将视觉样式应用于子窗口(子窗口的后代)的不一致性,或者更确切地说,它没有这样做。这个问题不仅限于VC++或MFC,而且已经注意到,,(最后一个链接是dotnet/winforms上的开放案例,但也有参考)。由于此问题,将对话框作为视图的子对象重新设置父对象将“丢失”主题
这里的另一个复杂之处是,所讨论的窗口是一个对话框,而对话框是。只需调用SetParent
即可更改对话框的父级,但保留其所有者。这违反了我们的规则。此外,要求更新样式位以删除WS\u弹出窗口
,并添加WS\u子项
。但是,一旦对话框成为视图的子对象,清除所有者或修复样式位都不会更改样式设置行为
另一种方法是更改对话框的所有者,而不是其父对象,在这种情况下,实际上会应用视觉样式。这将按Z顺序将对话框保持在其所有者面前,但不会将其剪裁到所有者区域。但是,需要注意的是,所有者必须是弹出窗口或重叠窗口,因此不能将其设置为视图本身(即子窗口),而是设置为其最近的弹出/重叠祖先窗口。在具有单个顶级窗口的UI中,这通常意味着只有一个主窗口
下面是示例代码,内联了一些注释,以及不起作用的#if 0
部分
应用程序是否已启用?是的,我不想在这里意外禁用SetParent的对话视觉样式(此),那么您肯定遇到了与以下问题不同的问题。A会有帮助。@dxlv谢谢链接,不,这是同样的问题。SetParent(此)将CDialog作为CView的子级。有人评论说:这是Windows10的东西,不能改变。他们放弃了保持视觉样式渲染器兼容的尝试,你只能获得传统的Win7外观。或者,这可能有一天会实现。是的,这就解释了问题。然而,这并不能解决我的问题。我对一个文档使用多个视图,并且每个无模式对话框都与特定视图相关联,因此这里强制要求每个对话框都是父视图的子视图。使用带有嵌入CTestDlg的CDockablePane?@TomTomTom问题是,对话框是自有窗口,不能也是子窗口。您仍然可以让他们通过处理WM\u WINDOWPOSCHANGING
消息来管理自己在Z顺序中的位置,以便将每个对话框保持在其关联视图的顶部。我已尝试使用WM\u WINDOWPOSCHANGING
来管理它。管理所有条件都是非常复杂和棘手的。而且并不总是像预期的那样工作。我现在终于使用了CDockablePane
并嵌入了CTestDlg。此解决方法解决了无模式对话框的视觉样式问题。
void CTestView::OnInitialUpdate()
{
CView::OnInitialUpdate();
// dialog gets created with parent = desktop window
// owner = app main window
m_wndTestDlg.Create(IDD_ABOUTBOX, this);
// visual styles *are* applied at this point
m_wndTestDlg.ShowWindow(SW_SHOW);
}
void CTestView::OnDialog1()
{
if (m_wndTestDlg.IsWindowVisible())
{ m_wndTestDlg.ShowWindow(SW_HIDE); }
else
{
#if 0 // visual styles *not* applied to test dialog
// the following make re-parenting consistent with the rules
// but visual styles are still not applied
// ::SetWindowLongPtr(m_wndTestDlg.m_hWnd, GWLP_HWNDPARENT, NULL);
// m_wndTestDlg.ModifyStyle(WS_POPUP | WS_CHILD, WS_CHILD);
m_wndTestDlg.SetParent(this);
#else // visual styles *are* applied to test dialog
// for an owned window, the following sets the owner, not the parent
// the new owner must be ws_popup or ws_overlapped, thus ga_root
::SetWindowLongPtr(m_wndTestDlg.m_hWnd, GWLP_HWNDPARENT, (LONG_PTR)::GetAncestor(m_hWnd, GA_ROOT));
#endif
m_wndTestDlg.SetWindowPos(&CWnd::wndTop, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW);
}
}