博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
窗体皮肤实现 - 在VC中简单实现绘制(五)
阅读量:4473 次
发布时间:2019-06-08

本文共 11893 字,大约阅读时间需要 39 分钟。

到第四部分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

 

 

转载于:https://www.cnblogs.com/gleam/p/3986395.html

你可能感兴趣的文章
二叉树——套路化解题--1.最大搜索二叉子树
查看>>
python测试工程师高端基础面试题整理
查看>>
梳理一下 html 中的一些基本概念
查看>>
SQL Server 2008 备份数据库
查看>>
ab测试 uwsgi遇到的问题
查看>>
Beanstalkd
查看>>
ThreadLocal工作原理
查看>>
Unity5 官方教程笔记(2D Rogue Like)02 —— BoardManager
查看>>
设计模式
查看>>
u-boot2011.09 启动流程记录
查看>>
c#中如何跨线程调用windows窗体控件?
查看>>
opencv相关
查看>>
UPC 2188 Balls(DP)
查看>>
重组索引(带统计索引重组时间)
查看>>
Linux&UNIX上卸载GoldenGate的方法
查看>>
HTML语义化标签
查看>>
Java实现HTML转PDF的总结
查看>>
人工智能实战_第三次作业_田博
查看>>
第1章 游戏之乐——买书问题
查看>>
mysql的导入和导出
查看>>