MFC编程实例:MFC绘制不规则窗体的方法
小标 2018-05-16 来源 : 阅读 1059 评论 0

摘要:本次MFC编程实例讲述了MFC 绘制不规则窗体的方法。分享给大家供大家参考。希望大家在MFC编程实例的学习的路上走的更远。

本次MFC编程实例讲述了MFC 绘制不规则窗体的方法。分享给大家供大家参考。希望大家在MFC编程实例的学习的路上走的更远。具体分析如下:

实现过程:

1、首先创建基于DLG的MFC应用程序,命名为:tryBGDlg,并将DLG的属性设置为:Title Bar :False ,其它设置不变

2、制作两幅图像,其中的一幅黑白图像,是根据播放器外观来制作的,其中白色区域是要保留的最终在桌面上显示的区域。将这两幅图像添加到工程中,第一个ID号设置为IDB_INTERFACE,第二个ID号设置为:IDB_MASK

 

3、在CtryBGDlg类中添加一个在函数:

函数说明:cBitmap是要传入的掩码位置变量,这里是指IDB_MASK创建的对象,TransColor是指要设为透明相素的RGB值


void CtryBGDlg::SetupRegion( CDC *pDC, CBitmap &cBitmap, COLORREF TransColor )

{

  CDC memDC;

  memDC.CreateCompatibleDC(pDC);

  CBitmap *pOldMemBmp=NULL;

  pOldMemBmp=memDC.SelectObject(&cBitmap);

  BITMAP bit;

  cBitmap.GetBitmap (&bit);

  CRgn crRgn, crRgnTmp;

  crRgn.CreateRectRgn(0, 0, 0, 0);//创建一个空区域

  int iX = 0;int iY = 0;

  for (iY = 0; iY < bit.bmHeight; iY++)

  {

    do

    {

      //skip over transparent pixels at start of lines.

      while (iX <= bit.bmWidth && memDC.GetPixel(iX, iY) == TransColor)

        iX++;

      //remember this pixel

      int iLeftX = iX;

      //now find first non transparent pixel

      while (iX <= bit.bmWidth && memDC.GetPixel(iX, iY) != TransColor)

        ++iX;

      //create a temp region on this info

      crRgnTmp.CreateRectRgn(iLeftX, iY, iX, iY+1);

      //combine into main region.

      crRgn.CombineRgn(&crRgn, &crRgnTmp, RGN_XOR);

      //delete the temp region for next pass (otherwise you'll get an ASSERT)

      crRgnTmp.DeleteObject();

    }while(iX < bit.bmWidth);

    iX = 0;

  }

  SetWindowRgn(crRgn, TRUE);

  iX = (GetSystemMetrics(SM_CXSCREEN))-700;

  iY = (GetSystemMetrics(SM_CYSCREEN)) / 2 - (bit.bmHeight / 2);

  SetWindowPos(&wndTop, iX, iY, bit.bmWidth, bit.bmHeight, NULL); 

  // Free resources.

  memDC.SelectObject(pOldMemBmp);

  // Put the original bitmap back (prevents memory leaks)

  memDC.DeleteDC();

  crRgn.DeleteObject();

}

   

4、在BOOL CtryBGDlg::OnInitDialog()函数中添加如下代码:


CBitmap bmp;

bmp.LoadBitmapW(IDB_MASK);

this->SetupRegion(this->GetWindowDC(),bmp,RGB(0,0,0));

   

5、添加对WM_ERASEBKGND消息响应,并在BOOL CtryBGDlg::OnEraseBkgnd(CDC* pDC)函数中添加如下代码


BOOL CtryBGDlg::OnEraseBkgnd(CDC* pDC)

{

  // TODO: 在此添加消息处理程序代码和/或调用默认值

  CRect rect;

  this->GetWindowRect(&rect);

  CDC memDC;

  CBitmap bmp;

  CBitmap *pOldBmp=NULL;

  bmp.LoadBitmapW(IDB_INTERFACE);

  memDC.CreateCompatibleDC(pDC);

  pOldBmp=memDC.SelectObject(&bmp);

  pDC->BitBlt(0,0,rect.Width(),rect.Height(),&memDC,0,0,SRCCOPY);

  if(pOldBmp)

  {

    memDC.SelectObject(pOldBmp);

  }

  return true;

// return CDialog::OnEraseBkgnd(pDC);

}

   

到此就实现了不规则窗体的创建,创建后的视图如开头所示。

6、一般我们还要实现对窗体的托动操作,实现方法如下:
添加对WM_NCHITTEST消息的响应,并在生成的LRESULT CtryBGDlg::OnNcHitTest(CPoint point)函数中添加如下代码:


LRESULT CtryBGDlg::OnNcHitTest(CPoint point)

{

  // TODO: 在此添加消息处理程序代码和/或调用默认值

  CRect rc;

  GetClientRect(&rc);

  ClientToScreen(&rc);

  return rc.PtInRect(point)  HTCAPTION : CDialog::OnNcHitTest(point);

// return CDialog::OnNcHitTest(point);

}

   

至此就完全实现了,不规则窗体的创建和对窗体托动消息的响应部分。

下面将细致的讲解具体实现原理及部分的代码的解析:

总原理:这个程序的原理主要是先用IDB_MASK图像计算出要设定的窗体的轮廓,然后利用SetWindowRgn()函数来对其进行更改。最后在窗体重绘的时候响应WM_ERASEBKGND消息,将窗体背景图片IDB_INTERFACE贴到窗体上。
 
利用IDB_MASK图像计算窗体轮廓的原理:

计算窗体轮廓的代码主要靠SetupRegion()函数来实现,考虑到窗体的不规则,应采取掩模位图的方式来对其进行描述,对于本例,其白色区域为要保留的不规则窗体的轮廓区域。这段代码首先是用crRgn.CreateRectRgn(0, 0, 0, 0)创建一个空的区域,然后对IDB_MASK图像的像素信息进行一列一列的枚举,计算出每列中不设为透明的区域,然后跟crRgn合并,所以最后的crRgn就是所要设定的区域。

核心代码为:

   

CRgn crRgn, crRgnTmp;

  //创建一个空区域

  crRgn.CreateRectRgn(0, 0, 0, 0);

  int iX = 0;int iY = 0;

  for (iY = 0; iY < bit.bmHeight; iY++)

  {

    do

    {

      //skip over transparent pixels at start of lines.

      //以一个相素列为单位,找到在这一个相素列中,第一个不是要设为透明相素的点iX。

      //然后再找到以这个iX为起点的,在这个一个相素列中最后跟他临近的最后一个不是透明的点。

      //然后将他们一起合并到crRgn中。

      while (iX <= bit.bmWidth && memDC.GetPixel(iX, iY) == TransColor)

        iX++;//在iY和iY+1这个相索列中,第一个不设为透明的点的X坐标

      int iLeftX = iX;//保存这个点的坐标

      while (iX <= bit.bmWidth && memDC.GetPixel(iX, iY) != TransColor)

        ++iX;//这是找到在iX最临近的不透明的X坐标

      crRgnTmp.CreateRectRgn(iLeftX, iY, iX, iY+1);//这四个点连在一起就是现在刚找到的不透明的区域

      //合并区域

      crRgn.CombineRgn(&crRgn, &crRgnTmp, RGN_OR);

      //记得最终要手动删除crRgnTmp对象

      crRgnTmp.DeleteObject();

    }while(iX < bit.bmWidth);

    //如果iX没有达到图片的末尾,说明还没有枚举完这一行,则在iY和iY+1这个行上,进行下一轮的//枚举

    iX = 0;

}

本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注职坐标编程语言VC/MFC频道!


本文由 @小标 发布于职坐标。未经许可,禁止转载。
喜欢 | 1 不喜欢 | 0
看完这篇文章有何感觉?已经有1人表态,100%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程