zoukankan      html  css  js  c++  java
  • VC----SDK下对窗口非客户区的操作

    窗口分成两大部分:客户区和非客户区。非客户区再次细分:标题栏,如图片中顶部深蓝色;左边框,如图片中红色部分;上边框,如图片中绿色部分;右边框,如图片中右侧天蓝色部分;底边框,如图片中下面棕色部分。

    之所以要有这样的区分,是因为,我在用函数SystemParametersInfo得到窗口的非客户区参数时,标题栏高度确实是上面深蓝色部分,不能达到客户区,在标题栏和客户区之间还有一个白色区域,我想这可能就是上边框吧。

    需要用到的几个函数:

    PatBlt:作用是在指定的矩形区域用指定的Brush画刷来填充这个区域。

    SystemParametersInfo得到系统的一些参数,比如标题栏的高度,边框宽度等。

    GetSystemMetrics:有点和上面函数相同,但是感觉没有上面的SystemParametersInfo函数精确。


    思路:在消息WM_NCPAINT,WM_NCACTIVATE,WM_MOVE响应时得到非客户区的DC(区别于客户区的DC),再得到矩形区域,用函数来填充颜色。拦截系统对这几个消息的处理。

    注意:使用的DC一定要是非客户区的DC,用GetWindowDC来得到句柄,不能用GetDC,因为GetDC得到的是客户区的DC,这个DC只能用来涂鸦客户区。得到边框的宽度时,比如顶部边框,绿色部分,要在得到的基础上+4,否则的话不能完全填充为指定的绿色,也是个疑问。

    	case WM_NOTIFY:
    	case WM_MOVE:
    	case WM_NCACTIVATE:
    	case WM_NCPAINT:
    		{
    			
    			//得到系统标题栏的信息:宽度、高度、矩形区域
    			int tbheight,tbwidth;
    			RECT wndrect,clientrect;
    			GetWindowRect(hwnd,&wndrect);
    			GetClientRect(hwnd,&clientrect);
    			tbheight= GetSystemMetrics(SM_CYSIZE);//标题栏宽度
    			//end 得到系统标题栏的信息
    			//填充标题栏
    			RECT rcWindow ;
    			GetWindowRect(hwnd,&rcWindow);
    			HDC hDc =  GetWindowDC(hwnd);
    			HBRUSH hBrush = CreateSolidBrush(RGB(25,0,255));
    			HBRUSH hOldbrush =(HBRUSH) SelectObject(hDc,(HGDIOBJ)hBrush);
    			PatBlt(hDc,0,0,wndrect.right-wndrect.left,tbheight,PATCOPY);
    			//end 填充标题栏
    			//填充边框
    			NONCLIENTMETRICS  nonmet;
    			nonmet.cbSize=sizeof(NONCLIENTMETRICS);
    			SystemParametersInfo(SPI_GETNONCLIENTMETRICS,sizeof(NONCLIENTMETRICS),&nonmet,0);
    
    			RECT borderleft,borderright,bordertop,borderbottom;
    			borderleft.left = 0;
    			borderleft.right = wndrect.left+7;
    			borderleft.top=tbheight;
    			borderleft.bottom=wndrect.bottom;
    			hBrush = CreateSolidBrush(RGB(200,0,0));
    			SelectObject(hDc,(HGDIOBJ)hBrush);
    			PatBlt(hDc,borderleft.left,borderleft.top,nonmet.iPaddedBorderWidth+4,borderleft.bottom-borderleft.top,PATCOPY);
    			SelectObject(hDc,(HGDIOBJ)hOldbrush);
    
    			bordertop.left=0;
    			bordertop.bottom=wndrect.top+nonmet.iCaptionHeight+nonmet.iPaddedBorderWidth+4;
    			bordertop.right = wndrect.right;
    			bordertop.top=nonmet.iCaptionHeight;
    			hBrush = CreateSolidBrush(RGB(0,200,0));
    			SelectObject(hDc,(HGDIOBJ)hBrush);
    			PatBlt(hDc,bordertop.left,bordertop.top,bordertop.right-bordertop.left,nonmet.iPaddedBorderWidth+5,PATCOPY);
    			SelectObject(hDc,(HGDIOBJ)hOldbrush);
    
    			borderright.left=wndrect.right-wndrect.left-nonmet.iPaddedBorderWidth-4;
    			borderright.top=nonmet.iCaptionHeight;
    			borderright.bottom=wndrect.bottom;
    			borderright.right = wndrect.right-wndrect.left;
    			hBrush = CreateSolidBrush(RGB(0,100,200));
    			SelectObject(hDc,(HGDIOBJ)hBrush);
    			PatBlt(hDc,borderright.left,borderright.top,nonmet.iPaddedBorderWidth+4,borderright.bottom-borderright.top,PATCOPY);
    			
    
    			borderbottom.bottom = wndrect.bottom;
    			borderbottom.left=nonmet.iPaddedBorderWidth+4;
    			borderbottom.right = wndrect.right-wndrect.left-nonmet.iPaddedBorderWidth-4;
    			borderbottom.top = wndrect.bottom-wndrect.top-nonmet.iPaddedBorderWidth-4;
    			hBrush = CreateSolidBrush(RGB(100,80,80));
    			SelectObject(hDc,(HGDIOBJ)hBrush);
    			PatBlt(hDc,borderbottom.left,borderbottom.top,borderbottom.right-borderbottom.left,nonmet.iPaddedBorderWidth+4,PATCOPY);
    			//end 填充边框
                            SelectObject(hDc,(HGDIOBJ)hOldbrush);
       ReleaseDC(hwnd,hDc);
    //DefWindowProc(hwnd,uMsg,wParam,lParam);
    return 0;//拦截系统的处理
    break;
    }
    
    对DC的解释参考文章:
    http://www.codeproject.com/Articles/89996/Drawing-in-Windows-101
    
    



    对标题栏的理解:

    在Win7下,设置主题为Basic类型的,得到一个界面如下:

     

     

    外圈棕色部分就是边框,和上面说的上边框的位置不同,在对QQ窗口进行最大化也会看到红色的部分,这个部分是标题栏的位置。

    几点注意:

    1、三个系统按钮是为标题按钮,标题按钮和标题栏的宽度是一样大小的。

    2、当最大化时,边框会消失。标准大小时,恢复状态。

    调整后上边框为上绿色,结果如下:


    而三个系统按钮就在最左边的位置 如图。

    像Aero主题 和QQ 、迅雷等的按钮会发生变化,是因为是对这三个按钮处理的结果,上面的程序也有一个问题:当在单击到三个按钮的位置时会出现这三个按钮。如下:

     

    就这个问题。

    调整后的结果,:





    对标题栏的理解:

    在Win7下,设置主题为Basic类型的,得到一个界面如下:

     

    外圈棕色部分就是边框,和上面说的上边框的位置不同,在对QQ窗口进行最大化也会看到红色的部分,这个部分是标题栏的位置。

    而三个系统按钮就在最左边的位置 如图。

    像Aero主题 和QQ 、迅雷等的按钮会发生变化,是因为是对这三个按钮处理的结果,上面的程序也有一个问题:当在单击到三个按钮的位置时会出现这三个按钮。如下:

    就这个问题。

     用位图来填充矩形:

    目标是把三个按钮给覆盖:

    			//处理三个按钮
    			//第一步:定位位置--在右边框的左边,右侧贴右边框,左侧可通过SystemParametersInfo得到按钮宽度iCaptionHeight,再*3;上下边框在标题栏内。
    			//第二步:用图片或者颜色给盖上,拦截NCLBUTTONDOWN消息。在单击位置在按钮区域时,分别发送3个消息,
    			RECT btnrect;
    			btnrect.bottom=nonmet.iCaptionHeight+nonmet.iBorderWidth;
    			btnrect.left=wndrect.right-wndrect.left-nonmet.iCaptionHeight*3-nonmet.iBorderWidth;
    			btnrect.right=btnrect.left+nonmet.iCaptionHeight*3;
    			btnrect.top=nonmet.iBorderWidth;
    
    			HDC hcomdc = CreateCompatibleDC(hDc);
    			HBITMAP hbmp = LoadBitmap(g_hInstance,MAKEINTRESOURCE(IDB_BITMAP4));
    			HBITMAP holdbmp=(HBITMAP)SelectObject(hcomdc,(HGDIOBJ)hbmp);
    			StretchBlt(hDc,btnrect.left-nonmet.iPaddedBorderWidth-14,btnrect.top+nonmet.iPaddedBorderWidth+4,nonmet.iCaptionHeight*3+12,nonmet.iCaptionHeight,hcomdc,0,0,60,20,SRCCOPY);
    			
    
    			//end处理三个按钮

    结果如图:

    拦截消息如下:

    		GetWindowRect(hwnd,&wndrect);
    		POINT *lpoint=(POINT *)lParam;
    		int xPos = GET_X_LPARAM(lParam); 
    		int yPos = GET_Y_LPARAM(lParam);
    		if(xPos>wndrect.left+btnrect.left-10&&xPos<wndrect.left+btnrect.right-10&&yPos>wndrect.top+btnrect.top+8&&yPos<wndrect.top+btnrect.bottom)
    			return 0;
    		break;


     把窗口进行圆角操作:

          需要在窗口大小变化后进行圆角操作。捕捉大小变化的消息是WM_SIZE, 这是窗口变化后的消息。代码如下:

        case WM_SIZE:
            {
            RECT wndRect;
            GetWindowRect(hWnd,&wndRect);
            HRGN hRgn=CreateRoundRectRgn(0,0,wndRect.right-wndRect.left,wndRect.bottom-wndRect.top,50,50);
            SetWindowRgn(hWnd,hRgn,true);
            if(hRgn)
                DeleteObject((HGDIOBJ)hRgn);
            break;
            }



  • 相关阅读:
    android调用google地图
    AndroidManifest.xml中android:configChanges的简介
    android消息推送机制
    用j4lChartAndroid实现3D图饼
    读《重构改善既有代码的设计》笔记一
    怎样删除data下的多余文件
    Mac OSX 10.8 下 配置 mysql+python+thrift开发环境
    新的征程
    练习1 四则运算的程序
    作业二四则运算
  • 原文地址:https://www.cnblogs.com/ddx-deng/p/3755833.html
Copyright © 2011-2022 走看看