首页 > 代码库 > 窗体皮肤实现 - 在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 }
窗体皮肤实现 - 在VC中简单实现绘制(五)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。