1

我有一个无模式对话框,我已使用 SetWindowRgn() 将形状更改为圆形。我想使用 FrameRgn 在它周围绘制一个彩色边框。这是我正在使用的代码

BOOL CMyDlg::OnInitDialog() 
 {
 CDialog::OnInitDialog(); m_Brush.CreateSolidBrush(RGB(255,255,255));
 CRect rcDialog;
 GetClientRect(rcDialog);

 // This Creates area assigned to Dialog: This goes directly below the above in OnInitDialog
 m_rgnShape.CreateRoundRectRgn(rcDialog.TopLeft().x, rcDialog.TopLeft().y,rcDialog.BottomRight().x,rcDialog.BottomRight().y, rcDialog.Width()/8, rcDialog.Height()/8);
::SetWindowRgn(GetSafeHwnd(), (HRGN)m_rgnShape, TRUE);

return TRUE; // return TRUE unless you set the focus to a control
  // EXCEPTION: OCX Property Pages should return FALSE

}

void CMyDlg::OnPaint() 
{
 CPaintDC dc(this); // device context for painting

 CBrush brush;
 brush.CreateSolidBrush(RGB(255,0,0));

  dc.FrameRgn(&m_rgnShape, &brush, 2, 2);
}

任何人都可以解释为什么 FrameRgn 无法正常工作,并可能在此处提供一些示例代码以使其正常工作。

4

1 回答 1

1

CWnd::SetWindowRgn文档所示:

成功调用 SetWindowRgn 后,操作系统拥有由区域句柄 hRgn 指定的区域。操作系统不会复制该区域,因此不要使用此区域句柄进行任何进一步的函数调用,也不要关闭此区域句柄。

这基本上意味着您不能再去将该区域用于其他目的,并且您也不能“失去”该区域。由于它是一个成员变量,所以最后一个问题不是您需要担心的问题。但是关于“不要使用它”部分,您会注意到FrameRgn(...)调用很可能返回零,表示尝试绘制时失败。

您可以做的是从CRgn对象中分离区域句柄并使用它来设置窗口区域,然后您可以像以前一样重新创建一个新的:

m_rgnShape.CreateRoundRectRgn(...);
HGDIOBJ hRgn = m_rgnShape.Detach();
::SetWindowRgn(GetSafeHwnd(), (HRGN)hRgn, TRUE);
m_rgnShape.CreateRoundRectRgn(...);

要获得更好的描述,请查看这篇介绍设置窗口区域的文章,使其看起来像一只猫。


编辑:您的评论提到现在,框架区域有效地抵消了一个 amount。该数量可能是您的窗口边框的大小。

当您调用 时GetClientRect,它返回窗口客户区的大小 - 您可以轻松绘制的部分,以及CPaintDC dc(this);在您的OnPaint()方法中执行时由设备上下文“描述”的部分。

偏移的原因是您的窗口有一个边框,您通常不会在该边框上绘制(有一些方法,但我们现在将忽略这些方法)。所以设备上下文描述了一个从你的窗口偏移的区域。

在您的情况下,最简单的解决方案可能是修改对话框模板以指定无边框。这当然会限制调整窗口的大小,但由于您已经设置了一个区域,我假设调整大小也不是一个选项。

于 2013-04-30T16:05:13.340 回答