MFC绘制不规则窗体的方法_C 语言

本文实例讲述了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;
}

希望本文所述对大家的MFC程序设计有所帮助。

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索mfc
, 绘制
不规则窗体
mfc 绘制窗体边框、css3绘制不规则图形、qt不规则窗体、c 不规则窗体、ios 绘制不规则图形,以便于您获取更多的相关知识。

时间: 2025-01-21 03:03:10

MFC绘制不规则窗体的方法_C 语言的相关文章

MFC绘制不规则窗体的方法

  本文实例讲述了MFC 绘制不规则窗体的方法.分享给大家供大家参考.具体分析如下: 实现过程: 1.首先创建基于DLG的MFC应用程序,命名为:tryBGDlg,并将DLG的属性设置为:Title Bar :False ,其它设置不变 2.制作两幅图像,其中的一幅黑白图像,是根据播放器外观来制作的,其中白色区域是要保留的最终在桌面上显示的区域.将这两幅图像添加到工程中,第一个ID号设置为IDB_INTERFACE,第二个ID号设置为:IDB_MASK 3.在CtryBGDlg类中添加一个在函数

MFC对话框自定义消息映射的方法_C 语言

本文实例讲述了MFC对话框自定义消息映射的方法.分享给大家供大家参考.具体实现方法如下: 1.定义消息: 复制代码 代码如下: #define WM_MYMSG (WM_USER+100) 2.定义消息响应函数: LPESULT CSLYARDlg::OnMymsg(WPARAM wParam, LPARAM lParam) { // TODO return 0; } 3.在窗口类头文件的AFX_MSG中声明消息响应函数: // Generated message map functions /

排列和组合算法的实现方法_C语言经典案例_C 语言

排列和组合算法是考查递归的常见算法,这两种算法能用递归简洁地实现. 本人在经过多次摸索和思考之后,总结如下,以供参考. 程序代码如下: #include <stdio.h> #include <stdlib.h> char array[] = "abcd"; #define N 4 #define M 3 int queue[N] = {0}; int top = 0; int flag[N] = {0}; void perm(int s, int n) { i

C++获得其他程序窗体控件中信息的方法_C 语言

本文实例讲述了C++获得其他程序窗体控件中信息的方法.分享给大家供大家参考.具体分析如下: 这里演示了获得其他程序窗体控件信息的方法, 用FindWindow API找到文本框句柄,用SendMessage(WM_GETTEXT)获得文本 #include <windows.h> BOOL CALLBACK EnumChildProc(HWND hWnd,LPARAM lParam); int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrev

C++ CTreeview的checkbox使用方法_C 语言

1. 消息事件    (1)鼠标点击当前ITEM的CHECKBOX:引发NM_CLICK事件并传递TVHT_ONITEMSTATEICON.    (2)鼠标点击当前ITEM的TEXT:引发NM_CLICK事件.    (3)鼠标点击新ITEM的CHECKBOX:引发TVN_SELCHANGED事件.NM_CLICK事件并传递TVHT_ONITEMSTATEICON.    (4)鼠标点击新ITEM的TEXT:引发NM_CLICK事件.TVN_SELCHANGED事件. 2. 消息事件总结   

C语言+win32api写窗体应用程序_C 语言

昨晚看了一下win32api编程的知识,我在网上搜索了许多教程,一个美化版的windows编程,代码错漏百出,缺字,翻译难懂生硬,术语不专业,一个windows.c编程,模糊,而且用的是VC++6.0,由于我的电脑装不上vc++6.0,只能用vs2008,许多操作和函数都不太一样了.在网上找到一篇博客园的win32api编程的文章,照抄下来,结果编译下来几十个错误--晕死了. 后来还是参照以下四个步骤,自己查MSDN用C语言写出来了,晕死,英文不好,话说,金山词霸对MSDN的整句翻译很专业啊.

MFC实现在文件尾追加数据的方法_C 语言

本文实例讲述了MFC实现在文件尾追加数据的方法.分享给大家供大家参考.具体如下: BOOL CDelDlg::WritetoFile(CString sValue) { CString sFile = GetExePath() + "\\1.log"; CStdioFile file; if(file.Open(sFile, CFile::modeCreate | CFile::modeWrite | CFile::modeNoTruncate)) { file.SeekToEnd()

C和MFC巧妙获取外网IP的两种实现方法_C 语言

本文以C与MFC的两个实例详述了取外网IP的两种实现方法,具体实现代码如下: MFC语言实现获取外网IP: # include <windows.h> # include <urlmon.h> # pragma comment(lib,"URLMON.lib") void main() { URLDownloadToFile(NULL,"http://www.ip138.com/ip2city.asp","ip.txt",

MFC程序对文件的处理方法_C 语言

对文件的处理是MFC程序设计中非常常见的应用.本文就以实例形式做一简单叙述.具体方法如下: 1.CFileDialog的应用 格式如下: CFileDialog::CFileDialog( BOOL bOpenFileDialog, LPCTSTR lpszDefExt = NULL, LPCTSTR lpszFileName = NULL, DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, LPCTSTR lpszFilter =