VC不规则窗口实现—位图区域裁剪
2015-11-03 19:14
447 查看
既然默认创建的窗口是矩形区域,只要把不想显示的区域透明化,剩下的不就是不规则窗口了吗?!接下来所谓的窗口透明化,我们直接使用CRgn类来实现创建、裁剪和合并区域的功能,然后再使用SetWindowRgn函数来进行整个窗体的区域绘制。
不规则窗口,顾名思义,就是窗口的形状不是长方形、正方形或者圆形,而是一些不规则的图形。例如我们常常看到的一些可设置皮肤的窗口,机器人形状,五角星图形窗口一样等等。那应该如何实现呢?窗口贴图?
OK,就算我们采用窗口贴图的方式,默认的窗口创建还是只会显示规规矩矩的矩形对话框,无法实现该效果。可世上无难事,聪明的人总会能找到方法。根据网上提供的方法,在贴图的基础上,我们采用创建、裁剪和合并区域的方法来进行不规则窗口的创建。
在这里,我们要实现下图为例来讲解一下实现方法。
解题思路:
既然默认创建的窗口是矩形区域,只要把不想显示的区域透明化,剩下的不就是不规则窗口了吗?!接下来所谓的窗口透明化,我们直接使用CRgn类来实现创建、裁剪和合并区域的功能,然后再使用SetWindowRgn函数来进行整个窗体的区域绘制。
SetWindowRgn 函数是设置了一个窗口的区域。只有被包含在这个区域内的地方才会被重绘,而不包含在区域内的其他区域系统将不会显示。
于是要求设计MM给我把要去掉的位图区域加上纯红颜色,如下图所示:
1.把位图中不想显示的区域用另外的颜色填充,上图使用了红色RGB(255,0,0);
2.加载位图到对话框中,然后创建一个初始为0的区域;
3.以一个像素点为单位,从位图的最左边(0,0)位置开始扫描,然后到右下角(width,height)结束;
4.如果遇到是一个纯红色像素的,跳过,继续扫描;如果下一个遇到不是纯红色像素,则记录该点X1坐标,然后继续扫描;直到遇到纯红色像素,此时记录下该点X2坐标,用CreateRectRgn创建一个像素高的(x1,y,x2,y+1)区域,然后用CombineRgn与原先按要求创建好的区域进行合并,如此类推;
5.最后使用SetWindowRgn函数设置最终的窗体区域,成功。
ps:因为用PS填充的时候,红色和白色相交的地方会出现颜色渐变的情况,注意此时应该一个点一个点地用纯红色填充(RGB(255,0,0))同时程序中的颜色取值应使用范围值。
代码:
调用代码:
ps:这里的对话框创建不要使用DoModal (),因为它是模态对话框的。为了能够隐藏和灵活调用显示对话框,我们应该使用Create来创建对话框。
OK,完工。
不规则窗口,顾名思义,就是窗口的形状不是长方形、正方形或者圆形,而是一些不规则的图形。例如我们常常看到的一些可设置皮肤的窗口,机器人形状,五角星图形窗口一样等等。那应该如何实现呢?窗口贴图?
OK,就算我们采用窗口贴图的方式,默认的窗口创建还是只会显示规规矩矩的矩形对话框,无法实现该效果。可世上无难事,聪明的人总会能找到方法。根据网上提供的方法,在贴图的基础上,我们采用创建、裁剪和合并区域的方法来进行不规则窗口的创建。
在这里,我们要实现下图为例来讲解一下实现方法。
解题思路:
既然默认创建的窗口是矩形区域,只要把不想显示的区域透明化,剩下的不就是不规则窗口了吗?!接下来所谓的窗口透明化,我们直接使用CRgn类来实现创建、裁剪和合并区域的功能,然后再使用SetWindowRgn函数来进行整个窗体的区域绘制。
SetWindowRgn 函数是设置了一个窗口的区域。只有被包含在这个区域内的地方才会被重绘,而不包含在区域内的其他区域系统将不会显示。
于是要求设计MM给我把要去掉的位图区域加上纯红颜色,如下图所示:
1.把位图中不想显示的区域用另外的颜色填充,上图使用了红色RGB(255,0,0);
2.加载位图到对话框中,然后创建一个初始为0的区域;
3.以一个像素点为单位,从位图的最左边(0,0)位置开始扫描,然后到右下角(width,height)结束;
4.如果遇到是一个纯红色像素的,跳过,继续扫描;如果下一个遇到不是纯红色像素,则记录该点X1坐标,然后继续扫描;直到遇到纯红色像素,此时记录下该点X2坐标,用CreateRectRgn创建一个像素高的(x1,y,x2,y+1)区域,然后用CombineRgn与原先按要求创建好的区域进行合并,如此类推;
5.最后使用SetWindowRgn函数设置最终的窗体区域,成功。
ps:因为用PS填充的时候,红色和白色相交的地方会出现颜色渐变的情况,注意此时应该一个点一个点地用纯红色填充(RGB(255,0,0))同时程序中的颜色取值应使用范围值。
代码:
void CIrregularWindowDlg::OnPaint() { CPaintDC dc(this); // device context for painting CDC picDC,memDC; CBitmap *pOldBmp; BITMAP bm; CRgn wndRgn; CRgn rgnTemp; //保存临时region int iX=0, iLeftX=0; CRect rcClient, rtWindow; CFont *pOldFont; GetClientRect(rcClient); picDC.CreateCompatibleDC (&dc); pOldBmp = picDC.SelectObject (&m_bitmap); //没加载图片成功,退出 if (pOldBmp==NULL) { OnCancel(); } m_bitmap.GetBitmap(&bm); //创建总的窗体区域,初始region为0 wndRgn.CreateRectRgn(0,0,0,0); for(int y=0; y<=bm.bmHeight; y++) { iX = 0; do { //跳过透明色找到下一个非透明色的点. while (iX <= bm.bmWidth && (picDC.GetPixel(iX, y) >= m_TargetStartColor && picDC.GetPixel(iX, y) <= m_TargetEndColor)) iX++; //记住这个起始点 iLeftX = iX; //寻找下个透明色的点 while (iX <= bm.bmWidth && (picDC.GetPixel(iX, y) < m_TargetStartColor || picDC.GetPixel(iX, y) > m_TargetEndColor)) ++iX; //创建一个包含起点与重点间高为1像素的临时"region" rgnTemp.CreateRectRgn(iLeftX, y, iX, y+1); //合并到主"region". wndRgn.CombineRgn(&wndRgn, &rgnTemp, RGN_OR); //删除临时"region",否则下次创建时和出错 rgnTemp.DeleteObject(); }while(iX <= bm.bmWidth); } CWnd * pWnd = dc.GetWindow(); pWnd->SetWindowRgn(wndRgn,TRUE); pWnd->SetForegroundWindow(); pOldFont = picDC.SelectObject(m_pSysFont); if (m_pTargetFont!=NULL) { picDC.SelectObject(m_pTargetFont); } picDC.SetBkMode(TRANSPARENT); picDC.SetTextColor(m_clTargetColor); picDC.DrawText(m_strText, m_rcText, DT_WORDBREAK); picDC.SelectObject(pOldFont); dc.BitBlt (0, 0, bm.bmWidth, bm.bmHeight, &picDC, 0, 0, SRCCOPY); dc.SelectObject(pOldBmp); } void CIrregularWindowDlg::InitDialogInfo() { if (!m_bitmap.LoadBitmap(m_uiResourceID)) { CDialog::OnCancel(); return; } BITMAP bm; CRect rtWindow; m_bitmap.GetBitmap(&bm); GetWindowRect(&rtWindow); rtWindow.right = rtWindow.left+bm.bmWidth; rtWindow.bottom =rtWindow.top +bm.bmHeight; MoveWindow(&rtWindow); } void CIrregularWindowDlg::SetReplacePicColorRange(COLORREF TargetStartColor, COLORREF TargetEndColor) { m_TargetStartColor = TargetStartColor; m_TargetEndColor = TargetEndColor; } /************************************************************************/ /* 加载位图 /************************************************************************/ BOOL CIrregularWindowDlg::SetLoadBitmap(UINT BitmapID) { if (BitmapID>0) { m_uiResourceID = BitmapID; } else { return FALSE; } return TRUE; } /************************************************************************/ /* 设置对话框显示的文字,可支持换行\n 参数: rcText:文字位置,CRect类型 lstrText:显示的内容 /************************************************************************/ void CIrregularWindowDlg::SetDrawText(CRect rcText, CString lstrText) { m_rcText = rcText; m_strText = _T(""); m_strText = lstrText; } /************************************************************************/ /* 设置对话框显示的文字字体 参数: fontObject:字体指针 /************************************************************************/ void CIrregularWindowDlg::SetDrawTextFont(CFont *fontObject) { if (fontObject!=NULL) { m_pTargetFont = fontObject; } } /************************************************************************/ /* 设置对话框显示的文字字体颜色 参数: clValue:目标颜色 /************************************************************************/ void CIrregularWindowDlg::SetDrawTextColor(COLORREF clTargetValue) { m_clTargetColor = clTargetValue; } void CIrregularWindowDlg::OnClose() { // TODO: Add your message handler code here and/or call default // 删除字体 if (m_pSysFont) { m_pSysFont->DeleteObject(); delete m_pSysFont; m_pSysFont = NULL; } if (m_pTargetFont) { m_pTargetFont->DeleteObject(); delete m_pTargetFont; m_pTargetFont = NULL; } CDialog::OnClose(); }
调用代码:
// 系统默认字体 m_pSysFont = new CFont; m_pSysFont->CreateFont(12, // nHeight 0, // nWidth 0, // nEscapement 0, // nOrientation FW_NORMAL, // nWeight FALSE, // bItalic FALSE, // bUnderline 0, // cStrikeOut ANSI_CHARSET, // nCharSet OUT_DEFAULT_PRECIS, // nOutPrecision CLIP_DEFAULT_PRECIS, // nClipPrecision DEFAULT_QUALITY, // nQuality DEFAULT_PITCH | FF_SWISS, // nPitchAndFamily _T("宋体")); // lpszFac m_pIrrDlg = new CIrregularWindowDlg; ASSERT(m_pIrrDlg); if (!m_pIrrDlg->SetLoadBitmap(IDB_IRREGULAR_PICTURE)) { return FALSE; } m_pIrrDlg->SetDrawTextFont(m_pSysFont); m_pIrrDlg->SetDrawTextColor(RGB(95,107,122)); m_pIrrDlg->SetReplacePicColorRange(RGB(200,5,5), RGB(255,5,5)); m_pIrrDlg->Create(CIrregularWindowDlg::IDD, this); m_pIrrDlg->ShowWindow(SW_HIDE);
ps:这里的对话框创建不要使用DoModal (),因为它是模态对话框的。为了能够隐藏和灵活调用显示对话框,我们应该使用Create来创建对话框。
OK,完工。
相关文章推荐
- LR错误: Commands out of sync; you can't run this command now 解决方法
- 修改林地所有权等在属性表中显示不出来
- 二进制, 八进制, 十六进制 输出的表示方法
- java.lang.IllegalStateException: Fragement no longer exists for key f0: index 0
- jquery判断radio选中及获取值
- 用反射获取类属性值并且赋值
- 用UglifyJS2合并压缩混淆JS代码
- .Net Framework 4.5.2 on Windows 10
- 关于文件夹的一些操作
- 数组的真实类型必须是泛型类型的子类型
- Asp.Net MVC3 简单入门第一季(一)环境准备
- 1602液晶显示
- SpringData JPA的学习笔记之环境搭建
- 网站跳舞人代码
- 【Linux 内核】文件系统(四)
- Add header and footer to some file
- 通过View寻找ViewController
- 【数据结构与算法分析】1.4 用printOut函数输出任意实数
- 欧拉函数专题
- Asp.Net MVC3 简单入门第一季(二)详解Asp.Net MVC3项目