简体   繁体   English

如何在MFC中的非矩形窗口中绘制边框

[英]How to draw border in a non rectangular window in MFC

I have a mode less dialog that I have changed the shape into a roundrect using SetWindowRgn(). 我有一个无模式对话框,使用SetWindowRgn()将形状更改为圆角矩形。 I would like to draw a colored border around it using FrameRgn. 我想使用FrameRgn在其周围绘制彩色边框。 Here is the code I am using 这是我正在使用的代码

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);
}

Can anyone explain why the FrameRgn is not working, and maybe provide some sample code here that will make it work. 谁能解释为什么FrameRgn无法正常工作,也许可以在此处提供一些示例代码来使其正常工作。

As shown in the CWnd::SetWindowRgn documentation: CWnd::SetWindowRgn文档中所示:

After a successful call to SetWindowRgn, the operating system owns the region specified by the region handle hRgn. 成功调用SetWindowRgn后,操作系统将拥有由区域句柄hRgn指定的区域。 The operating system does not make a copy of the region, so do not make any further function calls with this region handle, and do not close this region handle. 操作系统不会复制该区域,因此不要使用该区域句柄进行任何其他函数调用,也不要关闭该区域句柄。

What this basically means is that you can't then go and use the region for another purpose, and you also can't "lose" the region. 这基本上意味着您不能再将该区域用于其他目的,也不能“丢失”该区域。 As it's a member variable, this last issue isn't a problem you need to worry about. 由于它是一个成员变量,因此最后一个问题不是您需要担心的问题。 But regarding the "do not use it" part, you will notice that the FrameRgn(...) call most likely returned zero, indicating the failure when trying to draw. 但是对于“请勿使用”部分,您会注意到FrameRgn(...)调用很可能返回零,表示尝试绘制时失败。

What you can do is to detach the region handle from the CRgn object and use that to set the window region, then you can recreate a new one as before: 您可以做的是将区域句柄与CRgn对象分离,并使用它来设置窗口区域,然后可以像以前一样重新创建一个新的句柄:

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

For a better description, have a look at this article which covers Setting a Window Region , to make it look like a cat. 为了获得更好的描述,请看一下涵盖设置窗口区域的文章,使它看起来像只猫。


Edit: Your comment mentions that now, the framed region is effectively offset by an amount . 编辑:您的评论中提到,现在,边框区域实际上被数量抵消 The amount is likely to be the size of the border of your window. 该数量很可能是窗口边框的大小。

When you call GetClientRect , it returns the size of the client area of the window - the part you can easily draw on, and the part that is "described" by the device context when you do CPaintDC dc(this); 当您调用GetClientRect ,它将返回窗口客户区的大小-您可以轻松绘制的部分,以及在执行CPaintDC dc(this);时由设备上下文“描述”的部分CPaintDC dc(this); in your OnPaint() method. 在您的OnPaint()方法中。

The reason for the offset is that your window has a border, which you don't normally draw on (there are ways, but we'll ignore those for now). 偏移的原因是您的窗口具有边框,通常您不会在边框上画线(有很多方法,但现在我们将忽略它们)。 So the device context describes an area that's offset from your window. 因此,设备上下文描述了一个偏离窗口的区域。

The simplest solution to this in your case is likely to be to modify the dialog template to specify no borders. 在这种情况下,最简单的解决方案可能是修改对话框模板以指定没有边框。 This will of course limit resizing the window, but as you've already set a region, I'm assuming resizing isn't an option either. 当然,这将限制调整窗口的大小,但是由于您已经设置了一个区域,因此我认为也不可能选择调整大小。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM