首页 > 代码库 > 窗体皮肤实现 - 在VC中简单实现绘制(五)

窗体皮肤实现 - 在VC中简单实现绘制(五)

到第四部分Delphi XE3的代码能基本完成窗体界面的绘制。窗口中的其他控件的处理方法也是相同的,截获消息处理消息。

问题这个编译出来的个头可不小。Release版本竟然2.43M,完全是个胖子。系统中应该加入了大量基础代码(如泛型之类),用Delphi7编译出来应该能小一截。

使用默认Release的配置方案,没有第三方控件。

 

翻译到C++进行实验,发现明显这个个头没法比。Debug版本88.5K...~~~  这货确实小。可惜再小现公司项目也不会考虑用C++开发,有些悲剧。

 

C版本只实现了部分代码(第一篇内容),并没有全部实现。思路一样,只是换个表示方法而已。

 

代码中处理了四个消息,还是比较简单。只有 WM_WINDOWPOSCHANGING 消息的处理稍微长些。

  WM_NCPAINT                             --- 绘制非客户区

  WM_NCCALCSIZE                       --- 重新设置边缘宽度

  WM_NCACTIVATE                       --- 程序切换时重绘非客户去

  WM_WINDOWPOSCHANGING      --- 重设界面样式

重新绘制非客户区 WM_NCPAINT

// LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)    case WM_NCPAINT:        hdc = GetWindowDC(hWnd);        PaintNC(hWnd, hdc);        ReleaseDC(hWnd, hdc);        break;// 非客户去绘制void PaintNC(HWND hWnd, HDC dc){    HBRUSH hBrush;    RECT rw;    RECT rc;    POINT pt;    GetWindowRect(hWnd, &rw);    GetClientRect(hWnd, &rc);    pt.x = rc.left;    pt.y = rc.top;    ClientToScreen(hWnd, &pt);    OffsetRect(&rc, pt.x - rw.left, pt.y - rw.top);    ExcludeClipRect(dc, rc.left, rc.top, rc.right, rc.bottom);  // 扣除客户区    OffsetRect(&rw, -rw.left, -rw.top);    hBrush = CreateSolidBrush(0xBF7B18);    FillRect(dc, &rw, hBrush);    DeleteObject(hBrush);}

重新设置窗体边缘宽度 WM_NCCALCSIZE

1 //  设置窗体边框宽度2     case WM_NCCALCSIZE:3         ((LPNCCALCSIZE_PARAMS)lParam)->rgrc[0].left += 3;4         ((LPNCCALCSIZE_PARAMS)lParam)->rgrc[0].top += 55;5         ((LPNCCALCSIZE_PARAMS)lParam)->rgrc[0].right -= 4;6         ((LPNCCALCSIZE_PARAMS)lParam)->rgrc[0].bottom -= 4;7         break;

切换程序时重绘非客户去WM_NCACTIVATE

1     case WM_NCACTIVATE:2         PostMessage(hWnd, WM_NCPAINT, 1, 0);3         break;

设置窗体样式 WM_WINDOWPOSCHANGING

 1 // 有修改窗体尺寸时重设样式 2 // 3  4     case WM_WINDOWPOSCHANGING: 5         bChanged = FALSE; 6         if (!gChangeSizeCalled) { 7             bChanged = (((LPWINDOWPOS)lParam)->flags & SWP_FRAMECHANGED); 8             if ((((LPWINDOWPOS)lParam)->flags & SWP_NOMOVE) == 0){ 9                 gWindowSize.left = ((LPWINDOWPOS)lParam)->x;10                 gWindowSize.top = ((LPWINDOWPOS)lParam)->y;11             }12             if ((((LPWINDOWPOS)lParam)->flags & SWP_NOSIZE) == 0){13                 bChanged = bChanged || (((LPWINDOWPOS)lParam)->cx != gWindowSize.right) || (((LPWINDOWPOS)lParam)->cy != gWindowSize.bottom);14                 gWindowSize.right = ((LPWINDOWPOS)lParam)->cx;15                 gWindowSize.bottom = ((LPWINDOWPOS)lParam)->cy;16             }17             bChanged = bChanged && ((gWindowSize.right * gWindowSize.bottom) != 0);18 19             if (bChanged){20                 gChangeSizeCalled = TRUE;21                 __try {22                     hTmp = gRegion;23                     gRegion = CreateRoundRectRgn(0, 0, gWindowSize.right, gWindowSize.bottom, 3, 3);24                     SetWindowRgn(hWnd, gRegion, TRUE);25                     if (hTmp) 26                         DeleteObject(hTmp);27                 }28                 __finally {29                     gChangeSizeCalled = FALSE;30                 }31             }32         }33 34         if (!bChanged)35             return DefWindowProc(hWnd,message, wParam, lParam);36 37         break;

 

 

完整代码文件

  1 // skin.cpp : Defines the entry point for the application.  2 //  3   4 #include "stdafx.h"  5 #include "skin.h"  6   7 #define MAX_LOADSTRING 100  8   9 // Global Variables: 10 HINSTANCE hInst;                                // current instance 11 TCHAR szTitle[MAX_LOADSTRING];                    // The title bar text 12 TCHAR szWindowClass[MAX_LOADSTRING];            // the main window class name 13  14 HRGN gRegion = 0; 15 BOOL gChangeSizeCalled = FALSE; 16 RECT gWindowSize = {0,0,0,0}; 17  18 // Forward declarations of functions included in this code module: 19 ATOM                MyRegisterClass(HINSTANCE hInstance); 20 BOOL                InitInstance(HINSTANCE, int); 21 LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM); 22 INT_PTR CALLBACK    About(HWND, UINT, WPARAM, LPARAM); 23  24 void                PaintNC(HWND, HDC); 25  26  27 int APIENTRY _tWinMain(HINSTANCE hInstance, 28                      HINSTANCE hPrevInstance, 29                      LPTSTR    lpCmdLine, 30                      int       nCmdShow) 31 { 32     UNREFERENCED_PARAMETER(hPrevInstance); 33     UNREFERENCED_PARAMETER(lpCmdLine); 34  35      // TODO: Place code here. 36     MSG msg; 37     HACCEL hAccelTable; 38  39     // Initialize global strings 40     LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); 41     LoadString(hInstance, IDC_SKIN, szWindowClass, MAX_LOADSTRING); 42     MyRegisterClass(hInstance); 43  44     // Perform application initialization: 45     if (!InitInstance (hInstance, nCmdShow)) 46     { 47         return FALSE; 48     } 49  50     hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_SKIN)); 51  52     // Main message loop: 53     while (GetMessage(&msg, NULL, 0, 0)) 54     { 55         if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) 56         { 57             TranslateMessage(&msg); 58             DispatchMessage(&msg); 59         } 60     } 61  62     return (int) msg.wParam; 63 } 64  65  66  67 // 68 //  FUNCTION: MyRegisterClass() 69 // 70 //  PURPOSE: Registers the window class. 71 // 72 //  COMMENTS: 73 // 74 //    This function and its usage are only necessary if you want this code 75 //    to be compatible with Win32 systems prior to the ‘RegisterClassEx‘ 76 //    function that was added to Windows 95. It is important to call this function 77 //    so that the application will get ‘well formed‘ small icons associated 78 //    with it. 79 // 80 ATOM MyRegisterClass(HINSTANCE hInstance) 81 { 82     WNDCLASSEX wcex; 83  84     wcex.cbSize = sizeof(WNDCLASSEX); 85  86     wcex.style            = CS_HREDRAW | CS_VREDRAW; 87     wcex.lpfnWndProc    = WndProc; 88     wcex.cbClsExtra        = 0; 89     wcex.cbWndExtra        = 0; 90     wcex.hInstance        = hInstance; 91     wcex.hIcon            = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_SKIN)); 92     wcex.hCursor        = LoadCursor(NULL, IDC_ARROW); 93     wcex.hbrBackground    = (HBRUSH)(COLOR_WINDOW+1); 94     wcex.lpszMenuName    = MAKEINTRESOURCE(IDC_SKIN); 95     wcex.lpszClassName    = szWindowClass; 96     wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL)); 97  98     return RegisterClassEx(&wcex); 99 }100 101 //102 //   FUNCTION: InitInstance(HINSTANCE, int)103 //104 //   PURPOSE: Saves instance handle and creates main window105 //106 //   COMMENTS:107 //108 //        In this function, we save the instance handle in a global variable and109 //        create and display the main program window.110 //111 BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)112 {113    HWND hWnd;114 115    hInst = hInstance; // Store instance handle in our global variable116 117    hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,118       CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);119 120    if (!hWnd)121    {122       return FALSE;123    }124 125    ShowWindow(hWnd, nCmdShow);126    UpdateWindow(hWnd);127 128    return TRUE;129 }130 131 //132 //  FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)133 //134 //  PURPOSE:  Processes messages for the main window.135 //136 //  WM_COMMAND    - process the application menu137 //  WM_PAINT    - Paint the main window138 //  WM_DESTROY    - post a quit message and return139 //140 //141 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)142 {143     int wmId, wmEvent;144     PAINTSTRUCT ps;145     HDC hdc;146 147     HRGN hTmp;148     BOOL bChanged;149     LRESULT result;150 151     switch (message)152     {153     case WM_COMMAND:154         wmId    = LOWORD(wParam);155         wmEvent = HIWORD(wParam);156         // Parse the menu selections:157         switch (wmId)158         {159         case IDM_ABOUT:160             DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);161             break;162         case IDM_EXIT:163             DestroyWindow(hWnd);164             break;165         default:166             return DefWindowProc(hWnd, message, wParam, lParam);167         }168         break;169     case WM_PAINT:170         hdc = BeginPaint(hWnd, &ps);171         // TODO: Add any drawing code here...172         EndPaint(hWnd, &ps);173         break;174 175     case WM_NCPAINT:176         hdc = GetWindowDC(hWnd);177         PaintNC(hWnd, hdc);178         ReleaseDC(hWnd, hdc);179         break;180 181     case WM_NCCALCSIZE:182         ((LPNCCALCSIZE_PARAMS)lParam)->rgrc[0].left += 3;183         ((LPNCCALCSIZE_PARAMS)lParam)->rgrc[0].top += 55;184         ((LPNCCALCSIZE_PARAMS)lParam)->rgrc[0].right -= 4;185         ((LPNCCALCSIZE_PARAMS)lParam)->rgrc[0].bottom -= 4;186         break;187 188     case WM_NCACTIVATE:189         PostMessage(hWnd, WM_NCPAINT, 1, 0);190         break;191     192     case WM_WINDOWPOSCHANGING:193         bChanged = FALSE;194 195         if (!gChangeSizeCalled) {196             bChanged = (((LPWINDOWPOS)lParam)->flags & SWP_FRAMECHANGED);197 198             if ((((LPWINDOWPOS)lParam)->flags & SWP_NOMOVE) == 0){199                 gWindowSize.left = ((LPWINDOWPOS)lParam)->x;200                 gWindowSize.top = ((LPWINDOWPOS)lParam)->y;201             }202             if ((((LPWINDOWPOS)lParam)->flags & SWP_NOSIZE) == 0){203                 bChanged = bChanged || (((LPWINDOWPOS)lParam)->cx != gWindowSize.right) || (((LPWINDOWPOS)lParam)->cy != gWindowSize.bottom);204                 gWindowSize.right = ((LPWINDOWPOS)lParam)->cx;205                 gWindowSize.bottom = ((LPWINDOWPOS)lParam)->cy;206             }207 208             bChanged = bChanged && ((gWindowSize.right * gWindowSize.bottom) != 0);209 210             if (bChanged) 211             {212                 gChangeSizeCalled = TRUE;213                 __try {214                     hTmp = gRegion;215                     gRegion = CreateRoundRectRgn(0, 0, gWindowSize.right, gWindowSize.bottom, 3, 3);216                     SetWindowRgn(hWnd, gRegion, TRUE);217                     if (hTmp) 218                         DeleteObject(hTmp);219                 }220                 __finally {221                     gChangeSizeCalled = FALSE;222                 }223             }224         }225 226         if (!bChanged)227             return DefWindowProc(hWnd,message, wParam, lParam);228 229         break;230 231     case WM_DESTROY:232         PostQuitMessage(0);233         break;234 235     case WM_QUIT:236         if (gRegion) {237             DeleteObject(gRegion);238             gRegion = 0;239         }240         return DefWindowProc(hWnd, message, wParam, lParam);241 242     default:243         return DefWindowProc(hWnd, message, wParam, lParam);244     }245     return 0;246 }247 248 // Message handler for about box.249 INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)250 {251     UNREFERENCED_PARAMETER(lParam);252     switch (message)253     {254     case WM_INITDIALOG:255         return (INT_PTR)TRUE;256 257     case WM_COMMAND:258         if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)259         {260             EndDialog(hDlg, LOWORD(wParam));261             return (INT_PTR)TRUE;262         }263         break;264     }265     return (INT_PTR)FALSE;266 }267 268 void PaintNC(HWND hWnd, HDC dc)269 {270     HBRUSH hBrush;271     RECT rw;272     RECT rc;273     POINT pt;274 275     GetWindowRect(hWnd, &rw);276     GetClientRect(hWnd, &rc);277     pt.x = rc.left;278     pt.y = rc.top;279     ClientToScreen(hWnd, &pt);280     OffsetRect(&rc, pt.x - rw.left, pt.y - rw.top);281 282     ExcludeClipRect(dc, rc.left, rc.top, rc.right, rc.bottom);283 284     OffsetRect(&rw, -rw.left, -rw.top);285     hBrush = CreateSolidBrush(0xBF7B18);286     FillRect(dc, &rw, hBrush);287     DeleteObject(hBrush);288 }
单元 skin.cpp

 

窗体皮肤实现 - 在VC中简单实现绘制(五)