Windows 标准控件:按钮控件的使用

该文章根据 CC-BY-4.0 协议发表,转载请遵循该协议。
本文地址:https://fenying.net/post/2011/07/20/windows-sdk-command-button/

本文展示 Windows 标准控件之按钮控件的使用方法。

以下程序在 Windows 7 简体中文破解版、Visual C++ 2008 专业版、Windows 7 SDK 环境下编译通过。

  1/* File Begin */
  2// wTest.cpp : 定义应用程序的入口点。
  3// This is a Win32 Application C Project.
  4// Author: Fenying
  5// Time: 2011-07-20
  6// Version: 0.0.0.1
  7// (C) Maple Knights & Fenying Studio Reserved.
  8// Description: Windows 7 Ultimate SP1 & Visual C++ 2008 Pro & Windows 7 SDK & Win32 Application C Project are required.
  9
 10#include <tchar.h>
 11#include <Windows.h>
 12#include <CommCtrl.h>
 13
 14#ifdef NULL
 15    #undef NULL
 16    #define NULL 0
 17#else
 18    #define NULL 0
 19#endif
 20
 21//[0] 使用系统主题
 22#pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
 23
 24//[A] 全局变量:
 25HINSTANCE hInst;                                // 当前实例
 26LPCTSTR szTitle;                                // 标题栏文本
 27LPCTSTR szWindowClass;                          // 主窗口类名
 28HWND hBtnO;                                     // 第一个按钮句柄
 29HFONT hForeFont;                                // 默认字体
 30
 31//[B] 此代码模块中包含的函数的前向声明:
 32LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
 33INT_PTR CALLBACK    About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
 34void SetFont(HWND hWndDst);
 35HWND CreateButton(DWORD dwStyle, LPCTSTR pTitle, HWND hParent, INT x, INT y, INT width, INT height, WORD wID);
 36
 37//[C] 宏常量
 38
 39#define GLOBAL_FORE_FONT_NAME        _T("Tahoma")
 40#define BTN_PUSHBUTTON               1
 41#define BTN_DEFPUSHBUTTON            2
 42#define BTN_CHECKBOX                 3
 43#define BTN_AUTOCHECKBOX             4
 44#define BTN_3STATECHECKBOX           5
 45#define BTN_AUTO3STATECHECKBOX       6
 46#define BTN_GROUPBOX                 7
 47#define BTN_RADIOBOX                 8
 48#define BTN_AUTORADIOBOX             9
 49#define BTN_COMMNADLINK              10
 50#define BTN_DEFCOMMNADLINK           11
 51#define BTN_SPLITBUTTON              12
 52#define BTN_DEFSPLITBUTTON           13
 53
 54//[D] 主函数
 55int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) {
 56
 57    MSG msg;
 58    WNDCLASSEX wcex;
 59    HWND hWnd;
 60
 61    // 初始化字符串
 62    szWindowClass = _T("my_wnd_cls");
 63    szTitle = _T("Hello World");
 64
 65    // 初始化默认字体
 66    hForeFont = CreateFontW(14,0,0,0,0,0,0,0,DEFAULT_CHARSET,0,0,0,0, GLOBAL_FORE_FONT_NAME);
 67
 68    // 注册窗口类
 69    wcex.cbSize = sizeof(WNDCLASSEX);
 70
 71    wcex.style            = CS_HREDRAW | CS_VREDRAW;
 72    wcex.lpfnWndProc      = WndProc;
 73    wcex.cbClsExtra       = 0;
 74    wcex.cbWndExtra       = 0;
 75    wcex.hInstance        = hInstance;
 76    wcex.hIcon            = NULL;
 77    wcex.hCursor          = LoadCursor(NULL, IDC_ARROW);
 78    wcex.hbrBackground    = (HBRUSH)(COLOR_WINDOW+1);
 79    wcex.lpszMenuName     = NULL;
 80    wcex.lpszClassName    = szWindowClass;
 81    wcex.hIconSm          = NULL;
 82
 83    RegisterClassEx(&wcex);
 84
 85    // 创建窗体
 86    hInst = hInstance; // 将实例句柄存储在全局变量中
 87
 88    hWnd = CreateWindow(szWindowClass, szTitle, WS_TABSTOP|WS_OVERLAPPEDWINDOW, 200, 0, 800, 600, NULL, NULL, hInstance, NULL);
 89
 90    if (!hWnd) {
 91        MessageBox(NULL,_T("Failed to create a window."), szTitle, MB_OK);
 92        return FALSE;
 93    }
 94
 95    ShowWindow(hWnd, nCmdShow);
 96    UpdateWindow(hWnd);
 97
 98    // 主消息循环:
 99    while (GetMessage(&msg, NULL, 0, 0)) {
100        TranslateMessage(&msg);
101        DispatchMessage(&msg);
102    }
103
104    return (int) msg.wParam;
105}
106
107//[E] 消息回调函数
108LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
109    int wmId, wmEvent;
110    HWND hCtl;
111
112    switch (uMsg) {
113    case WM_CREATE: // 当窗体被创建时
114
115        // 创建一个标准命令按钮 Push Button
116        hBtnO = CreateButton(BS_PUSHBUTTON, _T("Button"), hWnd, 50, 50, 200, 32, BTN_PUSHBUTTON);
117
118        // 创建一个缺省标准命令按钮 Default Push Button
119         CreateButton(BS_DEFPUSHBUTTON, _T("Default Button"), hWnd, 50, 85, 200, 32, BTN_DEFPUSHBUTTON);
120
121        // 创建一个二态复选框 CheckBox,其被单击时不会自动改变选择状态
122        CreateButton(BS_CHECKBOX, _T("CheckBox"), hWnd, 50, 120, 200, 24, BTN_CHECKBOX);
123
124        // 创建一个二态自动复选框 Auto CheckBox,其被单击时会自动改变选择状态
125        CreateButton(BS_AUTOCHECKBOX, _T("Auto CheckBox"), hWnd, 50, 150, 200, 24, BTN_AUTOCHECKBOX);
126
127        // 创建一个三态复选框 3 State CheckBox,其被单击时不会自动改变选择状态
128        CreateButton(BS_3STATE, _T("3 State CheckBox"), hWnd, 50, 180, 200, 24, BTN_3STATECHECKBOX);
129
130        // 创建一个三态自动复选框 Auto 3 State CheckBox,其被单击时会自动改变选择状态
131        CreateButton(BS_AUTO3STATE, _T("Auto 3 State CheckBox"), hWnd, 50, 210, 200, 24, BTN_AUTO3STATECHECKBOX);
132
133        // 创建一个组合框 Group Box
134        CreateButton(BS_GROUPBOX, _T("Group Box"), hWnd, 50, 240, 200, 100, BTN_GROUPBOX);
135
136        // 创建一个单选框 Radio Box,其被单击时不会自动改变选择状态
137        CreateButton(BS_RADIOBUTTON, _T("Radio Box"), hWnd, 50, 350, 200, 24, BTN_RADIOBOX);
138
139        // 创建一个自动单选框 Auto Radio Box,其被单击时会自动改变选择状态
140        CreateButton(BS_AUTORADIOBUTTON, _T("Auto Radio Box"), hWnd, 50, 380, 200, 24, BTN_AUTORADIOBOX);
141
142        // 创建一个自动单选框 Auto Radio Box,其被单击时会自动改变选择状态
143        CreateButton(BS_AUTORADIOBUTTON, _T("Auto Radio Box"), hWnd, 50, 410, 200, 24, BTN_AUTORADIOBOX);
144
145        // Windows Vista Required.
146#if _WIN32_WINNT >= 0x600
147
148        // 创建一个命令链接按钮 Command Link
149        CreateButton(BS_COMMANDLINK, _T("Command Link"), hWnd, 300, 50, 200, 48, BTN_COMMNADLINK);
150
151        // 创建一个缺省命令链接按钮 Def Command Link
152        CreateButton(BS_DEFCOMMANDLINK, _T("Def Command Link"), hWnd, 300, 100, 200, 48, BTN_DEFCOMMNADLINK);
153
154        // 创建一个分割按钮 Split Button
155        CreateButton(BS_SPLITBUTTON, _T("Split Button"), hWnd, 300, 150, 200, 48, BTN_SPLITBUTTON);
156
157        // 创建一个缺省分割按钮 Def Split Button
158        CreateButton(BS_DEFSPLITBUTTON, _T("Def Split Button"), hWnd, 300, 200, 200, 48, BTN_DEFSPLITBUTTON);
159
160#endif
161        //
162
163        break;
164
165    case WM_COMMAND:  //控件事件
166        hCtl    = (HWND)lParam;
167        wmId    = LOWORD(wParam); // wParam 的低字表示控件标识,即 CreateWindowEx 函数的 hMenu 参数
168        wmEvent = HIWORD(wParam); // wParam 的高字表示控件事件
169        if (lParam)
170            switch (wmId) {
171            case BTN_PUSHBUTTON:    //命令按钮的事件
172                switch (wmEvent) {
173                case BN_CLICKED: // 单击事件。
174                    /*******************************************************
175                     * 单击事件消息。
176                     *******************************************************/
177                    MessageBox(hWnd, _T("Hi, You clicked the command button"), szTitle, MB_OK);
178                    break;
179                case BN_DOUBLECLICKED:
180                    /*******************************************************
181                     * 双击事件消息。
182                     * 此消息不能和 BN_CLICKED 同时处理,否则无法接收此消息。
183                     * BS_USERBUTTON, BS_RADIOBUTTON, BS_OWNERDRAW 三种按钮可
184                     * 以自动支持此消息,其他按钮必须添加 BS_NOTIFY 样式。
185                     *******************************************************/
186                    MessageBox(hWnd, _T("Hi, You double clicked the command button"), szTitle, MB_OK);
187                    break;
188                default:
189                    goto onNothing;
190                }
191                break;
192
193            case BTN_DEFPUSHBUTTON:    //缺省命令按钮的事件
194                switch (wmEvent) {
195                case BN_CLICKED: // 单击事件。
196                    switch (SendMessage(hBtnO, BM_GETSTATE, 0, 0)) {
197                    /*******************************************************
198                     * BM_GETSTATE - 获取 Push Button 的状态,
199                     * 返回值取如下值:
200                     *    BST_PUSHED       -    已按下
201                     *    BST_UNCHECKED    -    未按下
202                     *******************************************************/
203                    case BST_PUSHED:
204                        SendMessage(hBtnO, BM_SETSTATE, BST_UNCHECKED, 0);
205                    /*******************************************************
206                     * BM_SETSTATE - 设置 Push Button 的状态,
207                     * 其第三个参数 wParam 决定按钮的状态
208                     *    BST_PUSHED       -    已按下
209                     *    BST_UNCHECKED    -    未按下
210                     *******************************************************/
211                        break;
212                    case BST_UNCHECKED:
213                        SendMessage(hBtnO, BM_SETSTATE, BST_PUSHED, 0);
214                        break;
215                    default:
216                        goto onNothing;
217                    }
218                    break;
219                default:
220                    goto onNothing;
221                }
222                break;
223
224            case BTN_COMMNADLINK: //命令链接按钮
225                switch (wmEvent) {
226                case BN_CLICKED: // 单击事件。
227                    MessageBox(hWnd, _T("Hi, You clicked the default command button"), szTitle, MB_OK);
228                    break;
229                default:
230                    goto onNothing;
231                }
232                break;
233
234
235            case BTN_CHECKBOX:    //二态复选框的事件
236                switch (wmEvent) {
237                case BN_CLICKED:
238                    switch (SendMessage(hCtl, BM_GETCHECK, 0, 0)) {
239                        /*******************************************************
240                         * BM_GETCHECK - 获取单/复选框选中状态
241                         * 其返回值可取如下:
242                         *    BST_CHECKED          -    已选中状态
243                         *    BST_UNCHECKED        -    未选中状态
244                         *    BST_INDETERMINATE    -    默认选中状态(三态复选框支持)
245                         *******************************************************/
246                    case BST_CHECKED:
247                        SendMessage(hCtl, BM_SETCHECK, BST_UNCHECKED, 0); //设置为灰色钩
248                        /*******************************************************
249                         * BM_SETCHECK - 设置单/复选框选中状态
250                         * 其第三个参数 wParam 可取如下值作为单/复选框的选中状态:
251                         *    BST_CHECKED          -    已选中状态
252                         *    BST_UNCHECKED        -    未选中状态
253                         *    BST_INDETERMINATE    -    默认选中状态(三态复选框支持)
254                         *******************************************************/
255                        break;
256                    case BST_UNCHECKED: //未选中时
257                        SendMessage(hCtl, BM_SETCHECK, BST_CHECKED, 0);
258                        break;
259                    default:
260                        goto onNothing;
261                    }
262                    break;
263                case BN_SETFOCUS:
264                    /*******************************************************
265                     * BN_SETFOCUS - 获取焦点通知
266                     * 当一个按钮具有 BS_NOTIFY 时,如果获得了焦点,会收到此
267                     * 通知消息。
268                     *******************************************************/
269                    SetWindowText(hCtl, _T("With Focus."));
270                    break;
271                case BN_KILLFOCUS:
272                    /*******************************************************
273                     * BN_KILLFOCUS - 失去焦点通知
274                     * 当一个按钮具有 BS_NOTIFY 时,如果失去了焦点,会收到此
275                     * 通知消息。
276                     *******************************************************/
277                    SetWindowText(hCtl, _T("Without Focus."));
278                    break;
279                default:
280                    goto onNothing;
281                }
282                break;
283
284            case BTN_3STATECHECKBOX: //三态复选框的事件
285                switch (wmEvent) {
286                case BN_CLICKED:
287                    switch (SendMessage(hCtl, BM_GETCHECK, 0, 0)) {
288                    case BST_CHECKED: // 选中时
289                        SendMessage(hCtl, BM_SETCHECK, BST_INDETERMINATE, 0); // 设置为灰色钩
290                        break;
291                    case BST_UNCHECKED: // 未选中时
292                        SendMessage(hCtl, BM_SETCHECK, BST_CHECKED, 0); // 设置为选中
293                        break;
294                    case BST_INDETERMINATE: //灰色钩子时,这个灰色钩子必须有 BS_AUTO3STATE 的样式
295                        SendMessage(hCtl, BM_SETCHECK, BST_UNCHECKED, 0); // 设置为未选中
296                        break;
297                    default:
298                        goto onNothing;
299                    }
300                    break;
301                default:
302                    goto onNothing;
303                }
304                break;
305
306            case BTN_RADIOBOX: //单选框的事件
307                switch (wmEvent) {
308                case BN_CLICKED:
309                    switch (SendMessage(hCtl, BM_GETCHECK, 0, 0)) {
310                    case BST_CHECKED: // 选中时
311                        SendMessage(hCtl, BM_SETCHECK, BST_UNCHECKED, 0); // 设置为灰色钩
312                        break;
313                    case BST_UNCHECKED: // 未选中时
314                        SendMessage(hCtl, BM_SETCHECK, BST_CHECKED, 0); // 设置为选中
315                        break;
316                    default:
317                        goto onNothing;
318                    }
319                    break;
320                default:
321                    goto onNothing;
322                }
323                break;
324
325            default:
326                goto onNothing;
327            }
328        // 分析菜单选择:
329        break;
330    case WM_DESTROY:
331        PostQuitMessage(0);
332        break;
333    default:
334        goto onNothing;
335    }
336    return 0;
337onNothing:
338    return DefWindowProc(hWnd, uMsg, wParam, lParam);
339}
340
341//[F] 设置字体
342void SetFont(HWND hWndDst) {
343    PostMessage(hWndDst, WM_SETFONT, (WPARAM)hForeFont, 1);
344}
345
346//[G] 创建按钮控件
347HWND CreateButton(DWORD dwStyle, LPCTSTR pTitle, HWND hParent, INT x, INT y, INT width, INT height, WORD wID) {
348    HWND hTmp;
349    if (hTmp =  CreateWindowEx(NULL, WC_BUTTON, pTitle, BS_NOTIFY|WS_TABSTOP|WS_CHILD|WS_VISIBLE| dwStyle, x, y, width, height, hParent, (HMENU)wID, hInst, NULL))
350        SetFont(hTmp);
351
352    return hTmp;
353}
354
355/* File End */
comments powered by Disqus