自定义绘制的MDI子框架客户端矩形和消息问题

时间:2018-06-20 19:34:47

标签: visual-c++ mfc mdi

我正在尝试创建一个从CMDIChildWndEx派生的类,该类以Windows 10样式绘制子框架(主题彩色标题栏,具有透明尺寸的透明区域之外的单个像素边框,不允许使用3D框架),而不是旧式的浅蓝色默认值。

我在绘制框架,设置区域等方面正在取得进展,但是由于父CView类绘制的客户区域位于错误的位置,所以我的窗口不会从窗口的左上方移动主机,它不接收OnLButtonDownOnMouseMove消息,我需要重写这些消息来处理调整大小,移动和系统菜单按钮,因为窗口不再具有非工作区。

我最初尝试使用CMFCVisualManager处理此问题,但它不影响MDI子框架。我做了短暂的尝试,并很快放弃了,因为CMFCVisualManager实际上没有文档记录,并且我需要访问的大多数成员变量都受到保护。

我遵循了一些创建自定义绘制的SDI应用程序的示例,并对其中的一些代码进行了调整以满足我的需求。

我遇到的第一个问题是,在我覆盖的OnNcPaint函数中,GetWindowDC()没有返回整个窗口的设备上下文,而是仅返回一个子区域(比客户端矩形稍大)。 ,而不是窗口矩形)。我发现我必须调用GetParent()->GetWindowDC()才能获得“正确的” DC,至少在其剪辑矩形的正确大小(与我设置的窗口区域的大小相同)方面进行校正。我怀疑不得不打电话给父DC是第二个问题的根本原因...

第二个问题是CView类在其OnDraw函数中接收到的客户区位置错误。它位于(初始)窗口底部左上角右下方4像素处,而不是在标题栏下方。我怀疑这里的问题是我在定义自定义绘制的非客户区域时缺少了一些东西(因此也缺少了所需客户区域的偏移量)。我曾经认为,将窗口区域(在OnCreateClientOnSize中)定义为在客户矩形的上方和左侧偏移(即,窗口区域的左上角坐标为负)会为我做到这一点,但事实并非如此。我假设我需要覆盖OnNcCalcSize,但我还没有尝试过。

与第二个问题有关,窗口大小未正确调整。如果我调整窗口大小(使用窗口顶部或左侧的基本NC区域),则客户区域将按预期调整大小,但我的窗口仍位于主框架客户区域的左上方。同样,我怀疑这与不得不使用GetParent()->GetWindowDC()有关。

最后一个问题是我的窗口没有收到OnLButtonDownOnMouseMove消息。它确实接收到OnNcLButtonDown和OnNcMouseMove,但这并没有真正的帮助,因为非客户区域是错误的(再次,我认为我可能需要覆盖OnNcCalcSize并可能处理WM_NCHITTEST)。

很明显,我不会显示整个课程,因为那会浪费空间,并且计算和绘制框架的细节并没有真正的意义。但是这是我已经重写的基本功能。

OnCreateClient:

BOOL CChildFrameEx::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)
{
// Get client rectangle
CRect rectClient;
GetClientRect(&rectClient);

// Calculate new region
CRect rectRegion;
rectRegion = CRect(rectClient.left - m_nWindowClipPad - 1, rectClient.top - m_nCaptionHeight - 2 - m_nWindowClipPad, rectClient.right + m_nWindowClipPad + 1, rectClient.bottom + m_nWindowClipPad + 1);

m_rgnWindow.Detach();
m_rgnWindow.CreateRectRgnIndirect(rectRegion);

m_rectWindow = rectRegion;

// Set new region
VERIFY(SetWindowRgn(m_rgnWindow, TRUE));

return CMDIChildWndEx::OnCreateClient(lpcs, pContext);
}

LoadFrame:

BOOL CChildFrameEx::LoadFrame(UINT nIDResource, DWORD dwDefaultStyle, CWnd* pParentWnd, CCreateContext* pContext)
{
BOOL bReturn;
bReturn = CMDIChildWndEx::LoadFrame(nIDResource, dwDefaultStyle, pParentWnd, pContext);

if (bReturn) {
    ModifyStyle(WS_CAPTION, WS_CLIPCHILDREN);
    ModifyStyleEx(WS_EX_CLIENTEDGE, WS_EX_TRANSPARENT, SWP_FRAMECHANGED);
}

return bReturn;
}

OnNcPaint:

void CChildFrameEx::OnNcPaint()
{
CDC* pDC = GetParent()->GetWindowDC();
.
.
.
}

OnSize:

void CChildFrameEx::OnSize(UINT nType, int cx, int cy)
{
// Get client rectangle
CRect rectClient;
GetClientRect(&rectClient);

// Calculate new region
CRect rectRegion;
rectRegion = CRect(rectClient.left - m_nWindowClipPad - 1, rectClient.top - m_nCaptionHeight - 2 - m_nWindowClipPad, rectClient.right + m_nWindowClipPad + 1, rectClient.bottom + m_nWindowClipPad + 1);

m_rgnWindow.Detach();
m_rgnWindow.CreateRectRgnIndirect(rectRegion);
.
.
.
// Call base version
CMDIChildWndEx::OnSize(nType, cx, cy);
}

如果可以帮忙,我可以上传正在发生的事情的屏幕截图,但希望上面的描述可以解决问题。

我非常感谢您提供有关如何使其正常工作的示例建议!谢谢。

0 个答案:

没有答案
相关问题