chapter2_2 非矩形窗口

来源:互联网 发布:java项目开发案例代码 编辑:程序博客网 时间:2024/05/16 09:21
 
CHAPTER2 追加各种处理
                       --非矩形窗口
 
非矩形窗口
 
windows里提供的改变窗口形状的API:设定指定窗口的窗口区域,使操作系统不显示窗口区域以外的部分。
 
Win32 API SetWindowRgn
int SetWindowRgn(
 HWND hWnd,     // handle to window
 HRGN hRgn,     // handle to region
 BOOL bRedraw   // window redraw option
);
 
MFC CWnd::SetWindowRgn
int SetWindowRgn( HRGN hRgn, BOOL bRedraw );
 
这里的重点是找到这个窗口区域(HRGN hRgn)
 
制作窗口区域(一)
 
制作区域用的API
API
 
CreateEllipticRgn
  建立椭圆形的区域
CreatePolyPolygonRgn
  建立复数个多边形构成的区域
CreatePolygonRgn
  建立多边形的区域
CreateRectRgn
  建立矩形的区域
CreateRoundRectRgn
  建立圆角矩形的区域
CombineRgn
  连接两个区域为一个新的区域
 
ExtCreateRegion函数从一个指定的区域或交换数据中创建一个区域。
HRGN ExtCreateRegion(
 CONST XFORM *lpXform,     // transformation data
 DWORD nCount,             // size of region data
 CONST RGNDATA *lpRgnData // region data buffer
);
 
这里我没有用书上给的方法,他的方法是基于自己编写的显示图片函数的。
 
实现方法:
SetWindowRgn( HRGN hRgn, BOOL bRedraw );函数将一个窗口区域hRgn分配给窗口hWnd,系统只显示该区域标示的地方,区域以外系统不会显示。
程序代码:
1、CMainFrame::RecalcLayout中更改窗口大小,使其与图片大小相同(600x120)。(SetWindowPos与MoveWindow起相同作用)
 
2、编辑函数SetupRegin,用来获取系统显示的窗口区域。
void CTextView::SetupRegion()
{
       CRgn wndRgn,rgnTemp;
       COLORREF color;
 
       //将位图选入设备描述表中
       HBITMAP hBitmap;
       HBITMAP hOldBitmap = NULL;
       HDC hdc;
       CClientDC dc(this);
       hdc = CreateCompatibleDC(dc.m_hDC);
       hBitmap = (HBITMAP)LoadImage(AfxGetInstanceHandle(),"TextFrame.BMP",IMAGE_BITMAP,
                              600,120,LR_CREATEDIBSECTION | LR_LOADFROMFILE);
       hOldBitmap = (HBITMAP)SelectObject(hdc,hBitmap);
       SelectObject(hdc,hBitmap);
 
       //这个函数要放到OnCreate中,此时窗口应该还没有创建,不能用GetWindowRect
       //获得窗口区域(虽然我们也知道窗口是600x120)。但是因为窗口和图片大小一致
       //在这里获得图片的宽度和高度数据
       DIBSECTION ds;
       BITMAPINFOHEADER &bm = ds.dsBmih; //做一个引用,就是别名
       GetObject(hBitmap,sizeof(ds),&ds);//将位图信息取出交给ds
       int width = bm.biWidth;           //得到位图宽度值
       int height = bm.biHeight;         //得到位图高度值
 
       //创建位图形状的不规则区域
       int x , y ;
       wndRgn.CreateRectRgn(0,0,width,height);//注意函数的变量是逻辑坐标,所以这样设置
 
       //获取位图每一像素颜色,与指定颜色相同就把它创建成一个矩形区域
       //然后从wndRgn抠除
       for(x=0;x<=width;x++)
       {
              for(y=0;y<=height;y++)
              {
                     //将位图中的绿色区域抠掉
            color = GetPixel(hdc,x,y);
                     if(color == RGB(0,255,0))
                     {
                            rgnTemp.CreateRectRgn(x,y,x+1,y+1);
                            wndRgn.CombineRgn(&wndRgn,&rgnTemp,RGN_XOR);//异或操作,抠掉选中矩形
                            rgnTemp.DeleteObject();
                     }
              }
       }
 
       if(hOldBitmap)
       {
              SelectObject(hdc,hOldBitmap);
       }
 
       //将不规则区域分配给窗体,也就是创建不规则窗体
       SetWindowRgn((HRGN)wndRgn,TRUE);
       DeleteObject(hBitmap);
       DeleteObject(hOldBitmap);
       DeleteDC(hdc);
}
 
3、在CTextView::OnCreate中调用SetupRegion。
 
4、在CTextView::PreCreateWindow中改变窗口样式(window syle)
cs.style = WS_POPUP | WS_VISIBLE;
cs.dwExStyle &= ~WS_EX_CLIENTEDGE;
 
5、在CTextView::OnPaint中载入背景图片(其实应该写在OnNcPaint或OnEraseBkgnd中)
void CTextView::OnPaint()
{
       CPaintDC dc(this); // device context for painting
      
       // TODO: Add your message handler code here
       // Do not call CFrameWnd::OnPaint() for painting messages      
 
       HBITMAP hBitmap; //声明位图句柄
       HDC hdc;          //声明设备描述表句柄
       hdc = CreateCompatibleDC(dc.m_hDC); //创建兼容DC
       //创建位图句柄
       hBitmap = (HBITMAP)LoadImage(AfxGetInstanceHandle(),"TextFrame.BMP",IMAGE_BITMAP,
                              600,120,LR_CREATEDIBSECTION | LR_LOADFROMFILE);
       SelectObject(hdc,hBitmap);//将位图句柄选入兼容DC
 
    CRect rect;
       GetClientRect(&rect); //获得客户端区域大小
       BitBlt(dc.m_hDC, 0,0,
                     rect.Width(),rect.Height(),
                     hdc, //兼容DC
                     0,0,SRCCOPY);
       DeleteObject(hBitmap);
       DeleteDC(hdc);
 
    dc.SetBkMode(TRANSPARENT);
       dc.TextOut(120, 20,"文字区域");
}
 
6、处理WM_NCHITTEST消息,使当点击窗口任何位置时都能移动窗口。在这里返回HTCAPTION时,windows会认为现在按在标题栏上。
UINT CTextView::OnNcHitTest(CPoint point)
{
       // TODO: Add your message handler code here and/or call default
       return HTCAPTION;
}
 
原创粉丝点击