MFC异形窗口

MFC异形窗口

Windows中所有窗口显示默认为矩形,很多时候我们希望窗口的形状可以随意变化。这个时候我们就需要使用MFC的CRgn类,

每一个窗口都有一个自己的CRgn,定义了当前窗口的显示区域,CRgn就好像是在一张图片上添加了相框,相框的形状就决定了

窗口的显示范围。当然显示区域之外就属于其他窗口。

一,多边形窗口

        CRect rc;
GetWindowRect(&rc); //获取窗口矩形(大小)

CPoint ptVertex[4]; //多边形顶点数组,形状为平行四边形
ptVertex[0].x = rc.Width() / 2;;
ptVertex[0].y = 0;
ptVertex[1].x = 0;
ptVertex[1].y = rc.Height()/2;
ptVertex[2].x = rc.Width()/2;
ptVertex[2].y = rc.Height();
ptVertex[3].x = rc.Width();
ptVertex[3].y = rc.Height() / 2;

CRgn m_rgn;   //定义窗口显示区域
m_rgn.CreatePolygonRgn(ptVertex, 4, ALTERNATE);//根据顶点数组创建窗口的显示区域

SetWindowRgn(m_rgn, TRUE);//添加到当前窗口

代码直接放在OnInitDialog()方法里。

运行效果如图

这个时候是拖不动窗口的,要添加WM_NCHITTEST消息处理函数

LRESULT CGDI对象Dlg::OnNcHitTest(CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
UINT nHitTest = CDialog::OnNcHitTest(point);
if (nHitTest == HTCLIENT)
nHitTest = HTCAPTION;
return nHitTest;
}

添加完之后点击对话框客户区就可以拖动窗口了。

二,两区域进行连接

CRgn rgn1;
rgn1.CreateRoundRectRgn(0, 0, 300, 200, 15, 15);
CRgn rgn2;
rgn2.CreateRectRgn(133, 83, 168, 118);
rgn1.CombineRgn(&rgn1, &rgn2, RGN_XOR);
SetWindowRgn(rgn1, true);

CombineRgn的第三个参数指定合并两个源区域时要执行的操作。 可以是以下任一值:

  • RGN_AND,使用两个区域的重叠区域(交集)。
  • RGN_COPY,创建区域 1(由 pRgn1 标识)的副本。
  • RGN_DIFF,创建由区域 1(由 pRgn1 标识)中不属于区域 2(由 pRgn2 标识)的区域组成的区域。
  • RGN_OR,将两个区域整体合并(联合)。
  • RGN_XOR,将两个区域合并,但删除重叠区域。

效果如图:

中间的那块区域被删掉了

还可以再OnPaint()函数里给区域上色

void CGDI对象Dlg::OnPaint()
{
        CPaintDC dc(this);
CRgn rgn1;
rgn1.CreateRoundRectRgn(0, 0, 300, 200, 15, 15);
CRgn rgn2;
rgn2.CreateRectRgn(133, 83, 168, 118);
rgn1.CombineRgn(&rgn1, &rgn2, RGN_XOR);

CBrush brush(RGB(0, 200, 200));
dc.SelectObject(&brush);
dc.FillRgn(&rgn1, &brush);
}

三,根据图片定义窗口

将图像显示在对话框上(使对话框和图像一样大)

CGDI对象Dlg类添加成员变量

CBitmap m_img;

在OnInitDialog()方法里添加如下代码

m_img.LoadBitmap(IDB_BITMAP3);
BITMAP logBitmap;
m_img.GetBitmap(&logBitmap);
MoveWindow(0, 0, logBitmap.bmWidth, logBitmap.bmHeight);
CDC memDc;
memDc.CreateCompatibleDC(NULL);
memDc.SelectObject(&m_img);

在OnPaint()方法里添加如下代码

CPaintDC dc(this);
BITMAP logBitmap;
m_img.GetBitmap(&logBitmap);
CDC memDc;
memDc.CreateCompatibleDC(NULL);
memDc.SelectObject(&m_img);
dc.BitBlt(0, 0, logBitmap.bmWidth, logBitmap.bmHeight, &memDc,
0, 0, SRCCOPY);

我的图片(格式是bmp):

运行程序,就可以把图片加载到对话框上了:

但这只是把图片添加到对话框上,还没有实现不规则窗口,还要在在OnInitDialog()方法里添加如下代码,添加在上一次代码的下面

        m_img.LoadBitmap(IDB_BITMAP1);
BITMAP logBitmap;
m_img.GetBitmap(&logBitmap);
MoveWindow(0, 0, logBitmap.bmWidth, logBitmap.bmHeight);
CDC memDc;
memDc.CreateCompatibleDC(NULL);
memDc.SelectObject(&m_img);

CRgn rgn;
rgn.CreateRectRgn(0, 0, logBitmap.bmWidth, logBitmap.bmHeight);
for (int i = 0; i < logBitmap.bmHeight; i++)
{
for (int j = 0; j < logBitmap.bmWidth; j++)
{
CRgn temp;
temp.CreateRectRgn(j, i, j + 1, i + 1);
if (memDc.GetPixel(j, i) == 0xFFFFFF)
{
rgn.CombineRgn(&rgn, &temp, RGN_XOR);
}

}
}
SetWindowRgn(rgn, true);

运行效果

和之前一次运行的效果没什么区别,那是因为图片没选取好。试试下面这张图片

运行效果

窗口现在是这个精灵的形状,图片的白色部分被删除了。

if(memDc.GetPixel(j, i)==0xFFFFFF)

{

rgn.CombineRgn(&rgn,&temp, RGN_XOR);

}

实现这个功能的代码就是这段。通过判断像素块的颜色是不是白色,如果是白色就将这块区域和整个对话框合并(RGN_XOR)就删除了白色的区域。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值