今天,咱们还是接着玩“控件斗地主”,这是我原创的超级游戏,有益身心健康,玩一朝,十年少。

哦,对,脑细胞极速运动了一下,想起了一个问题,这个破问题虽然网上有很多种解决方案,但是,并没有让所有人都解决问题。

不知道大家有没有调用过LoadIconMetric函数,这个函数在静态库Comctl32.lib中有定义(当然,动态库也有),不过,创建项目的时候,默认并没有引用它的,于是,大家知道,解决调用的方法就是在代码中加上:

  1. #pragma comment(lib, "Comctl32.lib")

我一般习惯这种方法,这样不必去修改项目属性。但是,很多朋友说过,在Win 7以后的系统,依然没有成功,我也尝到了调用失败的“甜头”,我一直在想,这是为什么呢?

于是,我又试了另一种方法,就是用LoadLibrary加载Comctl32.dll,然后通过函数指针去调用它:

  1. typedef LRESULT (WINAPI * pLoadICMT)(.......);

但结果还是没成功,GetProcAddress返回的地址为0,又一次尝到了失败带来的“刺激”感。

直到某一天,我在写某程序时,从上一文中大家都看到,那个按钮的视觉风格和Win9x/2000差不多,似乎没有XP那种充满美学水准的效果。其实,这是因为我们的程序没有启用视觉效果,默认情况下,使用版本5中的控件,而要有XP以上的风格,是在版本6的控件内库中才有。

当然方法可以很多人都知道,就是定义一个用于视觉效果的清单文件,本质是XML格式。不过我用的开发工具是VS 2005之后的版本,就不用弄个XML文件那么麻烦了,直接到MSDN上复制粘贴这段代码放到你的代码文件(.cpp)中,就是这个,直接抄过来就行了,适当的时候,要巧用MSDN上的资源。

  1. // 开启视觉效果 Copy from MSDN
  2. #pragma comment(linker,"\"/manifestdependency:type='win32' \
  3. name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \
  4. processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")

version是版本号,要有好看的效果,记得要6,不要写用低版本的。processorArchitecture是处理器平台,x86或amd64,用*号最好,通杀。

真是巧啊,原来这么一来,噗,LoadIconMetric也能调用了。总的来说,就是在代码文件加上以下内容:

  1. #include <CommCtrl.h> //包含头文件
  2. // 导入静态库
  3. #pragma comment(lib, "Comctl32.lib")
  4. // 开启视觉效果 Copy from MSDN
  5. #pragma comment(linker,"\"/manifestdependency:type='win32' \
  6. name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \
  7. processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")

这问题干掉了,开始今天的吹牛大行动。

单选按钮,是的,在WinForm里面你肯定知道,RadioButto,复选框就是CheckBox。不过那个时候.NET还没那么猛,那个时代,就是玩VB6,所以我知道VB里面,单选按钮叫Option吧。

然后找遍了Win32的控件库,怎么没见Radio和CheckBox,于是,我陷入了万分痛苦之中。不久后阅读MSDN文档,我就明白了,其实这两个玩意儿都是BUTTON类的,只是应用了不同的style罢了。

好的,咱们先来弄一个单选的吧。

  1. case WM_CREATE:
  2. {
  3. CreateWindow(L"Button",L"这玩意儿好",
  4. BS_RADIOBUTTON | WS_CHILD | WS_VISIBLE,
  5. 10,10,150,28,
  6. hwnd, (HMENU)IDC_RADBTN1,
  7. (HINSTANCE)GetWindowLongPtr(hwnd, GWLP_HINSTANCE),
  8. NULL);
  9. }
  10. return 0;

应用BS_RADIOBUTTON样式,就可以使按钮变成单选按钮,不过,别忘了WS_CHILD | WS_VISIBLE。

运行一下。

不过,当你点击它的时候,会发现它并不会选中,那是因为BS_RADIOBUTTON样式不会自动让它选上。我们换一种可以自动处理的样式,带AUTO打头的。

就是用 BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE,如下图的预览结果。

接下来,我们多创建几个吧。

  1. /*-----------------------------------------------------------------*/
  2. //控件ID
  3. #define IDC_RADBTN1     50001
  4. #define IDC_RADBTN2     50002
  5. #define IDC_RADBTN3     50003
  6. #define IDC_RADBTNBLUE      51001
  7. #define IDC_RADBTNRED       51002
  8. #define IDC_RADBTNGREEN     51003
  9. /*-----------------------------------------------------------------*/
  10. // 消息处理函数
  11. LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  12. {
  13. switch(msg)
  14. {
  15. case WM_CREATE:
  16. {
  17. // 获取当前实例句柄
  18. HINSTANCE hthisapp = (HINSTANCE)GetWindowLongPtr(hwnd, GWLP_HINSTANCE);
  19. // 纵坐标,控件将以此作为基准,
  20. // 排列时依次增加
  21. int yLoc = 0;
  22. // 用来显示文本
  23. yLoc += 10;
  24. CreateWindow(L"Static",L"请问你的性别是:",
  25. SS_SIMPLE | WS_CHILD | WS_VISIBLE,
  26. 10,yLoc,160,18,
  27. hwnd, NULL,
  28. hthisapp,
  29. NULL);
  30. // 第一组单选按钮
  31. yLoc += 22;
  32. CreateWindow(L"Button",L"男",
  33. WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON | WS_GROUP,
  34. 12, yLoc, 60, 16,
  35. hwnd,
  36. (HMENU)IDC_RADBTN1,
  37. hthisapp,NULL);
  38. yLoc += 20;
  39. CreateWindow(L"Button",L"女",
  40. WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON,
  41. 12,yLoc, 60, 16,
  42. hwnd,(HMENU)IDC_RADBTN2,hthisapp,NULL);
  43. yLoc += 20;
  44. CreateWindow(L"Button",L"人妖",WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON,
  45. 12,yLoc,60,16,hwnd,(HMENU)IDC_RADBTN3,hthisapp,NULL);
  46. // 显示文本
  47. yLoc += 38;
  48. CreateWindow(L"Static",L"你喜欢哪一种颜色?",
  49. WS_CHILD | WS_VISIBLE | SS_SIMPLE,
  50. 10,yLoc,150,18,hwnd,NULL,hthisapp,NULL);
  51. //第二组单选按钮
  52. yLoc += 22;
  53. CreateWindow(L"Button",L"蓝色",WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON | WS_GROUP,
  54. 12,yLoc,60,16,hwnd,(HMENU)IDC_RADBTNBLUE,hthisapp,NULL);
  55. yLoc += 20;
  56. CreateWindow(L"Button",L"红色",WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON,
  57. 12,yLoc,60,16,hwnd,(HMENU)IDC_RADBTNRED,hthisapp,NULL);
  58. yLoc += 20;
  59. CreateWindow(L"Button",L"绿色",WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON,
  60. 12,yLoc,60,16,hwnd,(HMENU)IDC_RADBTNGREEN,hthisapp,NULL);
  61. }
  62. return 0;
  63. case WM_DESTROY:
  64. PostQuitMessage(0); //平安退出
  65. return 0;
  66. default:
  67. return DefWindowProc(hwnd,msg,wParam,lParam);
  68. }
  69. return 0;
  70. }

在创建单选框中,为什么有些加了WS_GROUP样式,而有些未加呢?

其实是这样的,既然单选按钮是单选的,那么,任何一个单选按钮都与其他的单选按钮是互斥的关系。所以,在同一个容器(本例是同一个窗口)中就需要把单选按钮进行分组。

同一组中的单选按钮相互排斥,他的分组方法:

顺序,以Tab键顺序为参考,这个不用我介绍,你随便打开一个窗口,然后多按几下Tab键你就懂了,如果不懂,那你真的无可救药了。

凡是设置了WS_GROUP的单选框做为一组中的首元素,随后的所有单选按钮都和它在同一组,直到下一个设置了WS_GROUP样式的单选按钮。用上面的例子来说吧。

性别一组中,第一个应用了WS_GROUP的是“男”,随后的“女”和“人妖”都与“男”在同一组,因为后面一个“蓝色”设置了WS_GROUP样式。所以,

第一组为:男,女,人妖;

第二组为:蓝色,红色,绿色。

显然,用了BS_AUTORADIOBUTTON后,系统就会自动处理选择状态了。

完整的代码清单如下:

    1. #include <Windows.h>
    2. #include <WindowsX.h>
    3. #include <CommCtrl.h> //包含头文件
    4. // 导入静态库
    5. #pragma comment(lib, "Comctl32.lib")
    6. // 开启视觉效果 Copy from MSDN
    7. #pragma comment(linker,"\"/manifestdependency:type='win32' \
    8. name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \
    9. processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
    10. // 先声明一个WindowProc回调
    11. LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
    12. // 入口点
    13. int WINAPI wWinMain(HINSTANCE hTheApp, HINSTANCE hPrevApp, LPWSTR lpCmd, int nShow)
    14. {
    15. PCWSTR cn = L"My"; // 窗口名
    16. PCWSTR tt = L"应用程序"; // 窗口标题
    17. // 设计窗口类
    18. WNDCLASS wc = { sizeof(WNDCLASS) };
    19. wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
    20. wc.lpfnWndProc = WindowProc;
    21. wc.style = CS_HREDRAW | CS_VREDRAW;
    22. LoadIconMetric(hTheApp, IDI_APPLICATION, LIM_SMALL, &wc.hIcon);
    23. wc.lpszClassName = cn;
    24. wc.hInstance = hTheApp;
    25. RegisterClass(&wc); // 注册窗口类
    26. // 创建窗口
    27. HWND hwnd = CreateWindow(cn, tt,WS_OVERLAPPEDWINDOW,
    28. 28,34,400,330,NULL,NULL,hTheApp,NULL);
    29. if( !hwnd)
    30. { /* 如果窗口创建失败,
    31. 那继续执行也没有意义
    32. 长痛不如短痛,结束吧。
    33. */
    34. return 0;
    35. }
    36. ShowWindow(hwnd,nShow); //显示窗口
    37. UpdateWindow(hwnd); //更新窗口
    38. // 消息循环
    39. MSG msg;
    40. while(GetMessage(&msg,NULL,0,0))
    41. {
    42. TranslateMessage(&msg);
    43. DispatchMessage(&msg); //调度消息到WindowProc回调
    44. }
    45. return 0;
    46. }
    47. /*-----------------------------------------------------------------*/
    48. //控件ID
    49. #define IDC_RADBTN1         50001
    50. #define IDC_RADBTN2         50002
    51. #define IDC_RADBTN3         50003
    52. #define IDC_RADBTNBLUE      51001
    53. #define IDC_RADBTNRED       51002
    54. #define IDC_RADBTNGREEN     51003
    55. #define IDC_BTN_OK          1107 //确定按钮ID
    56. /*-----------------------------------------------------------------*/
    57. // 消息处理函数
    58. LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
    59. {
    60. switch(msg)
    61. {
    62. case WM_CREATE:
    63. {
    64. // 获取当前实例句柄
    65. HINSTANCE hthisapp = (HINSTANCE)GetWindowLongPtr(hwnd, GWLP_HINSTANCE);
    66. // 纵坐标,控件将以此作为基准,
    67. // 排列时依次增加
    68. int yLoc = 0;
    69. // 用来显示文本
    70. yLoc += 10;
    71. CreateWindow(L"Static",L"请问你的性别是:",
    72. SS_SIMPLE | WS_CHILD | WS_VISIBLE,
    73. 10,yLoc,160,18,
    74. hwnd, NULL,
    75. hthisapp,
    76. NULL);
    77. // 第一组单选按钮
    78. yLoc += 22;
    79. CreateWindow(L"Button",L"男",
    80. WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON | WS_GROUP,
    81. 12, yLoc, 60, 16,
    82. hwnd,
    83. (HMENU)IDC_RADBTN1,
    84. hthisapp,NULL);
    85. yLoc += 20;
    86. CreateWindow(L"Button",L"女",
    87. WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON,
    88. 12,yLoc, 60, 16,
    89. hwnd,(HMENU)IDC_RADBTN2,hthisapp,NULL);
    90. yLoc += 20;
    91. CreateWindow(L"Button",L"人妖",WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON,
    92. 12,yLoc,60,16,hwnd,(HMENU)IDC_RADBTN3,hthisapp,NULL);
    93. // 显示文本
    94. yLoc += 38;
    95. CreateWindow(L"Static",L"你喜欢哪一种颜色?",
    96. WS_CHILD | WS_VISIBLE | SS_SIMPLE,
    97. 10,yLoc,150,18,hwnd,NULL,hthisapp,NULL);
    98. //第二组单选按钮
    99. yLoc += 22;
    100. CreateWindow(L"Button",L"蓝色",WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON | WS_GROUP,
    101. 12,yLoc,60,16,hwnd,(HMENU)IDC_RADBTNBLUE,hthisapp,NULL);
    102. yLoc += 20;
    103. CreateWindow(L"Button",L"红色",WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON,
    104. 12,yLoc,60,16,hwnd,(HMENU)IDC_RADBTNRED,hthisapp,NULL);
    105. yLoc += 20;
    106. CreateWindow(L"Button",L"绿色",WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON,
    107. 12,yLoc,60,16,hwnd,(HMENU)IDC_RADBTNGREEN,hthisapp,NULL);
    108. // 创建一个确定按钮
    109. CreateWindow(L"Button",L"确定",WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,
    110. 230,180,80,27,hwnd,(HMENU)IDC_BTN_OK,hthisapp,NULL);
    111. }
    112. return 0;
    113. case WM_DESTROY:
    114. PostQuitMessage(0); //平安退出
    115. return 0;
    116. default:
    117. return DefWindowProc(hwnd,msg,wParam,lParam);
    118. }
    119. return 0;
    120. }

跟我一起玩Win32开发(12):使用控件——单选按钮的更多相关文章

  1. 跟我一起玩Win32开发(转自CSDN-东邪独孤)

    跟我一起玩Win32开发(1):关于C++的几个要点 跟我一起玩Win32开发(2):完整的开发流程 跟我一起玩Win32开发(3):窗口的重绘 跟我一起玩Win32开发(4):创建菜单 跟我一起玩W ...

  2. 跟我一起玩Win32开发(17):启动和结束进程

    这里我再次说明一下,我不知道为什么,现在的人那么喜欢走极端,估计是价值观都“升级”了的缘故吧. 我撰写这一系列Win32相关的文章,并不是叫大家一定要用Win32去开发项目,仅仅是给大家了解一下,Wi ...

  3. python开发_tkinter_窗口控件_自己制作的Python IDEL_博主推荐(二)

    在上一篇blog:python开发_tkinter_窗口控件_自己制作的Python IDEL_博主推荐 中介绍了python中的tkinter的一些东西,你可能对tkinter有一定的了解了.这篇b ...

  4. RS开发日期提示控件默认为昨天之进阶篇

    时隔<RS开发日期提示控件默认为昨天>这篇博文已经很久了,请原谅我隔了这么久才继续来写这篇笔记.也希望读到这篇笔记的朋友可以从这篇笔记中学习到一些关于RS日期控件和JS的一些应用知识,当然 ...

  5. Android零基础入门第17节:Android开发第一个控件,TextView属性和方法大全

    原文:Android零基础入门第17节:Android开发第一个控件,TextView属性和方法大全 前面简单学习了一些Android UI的一些基础知识,那么接下来我们一起来详细学习Android的 ...

  6. 基于Jquery WeUI的微信开发H5页面控件的经验总结(1)

    在微信开发H5页面的时候,往往借助于WeUI或者Jquery WeUI等基础上进行界面效果的开发,由于本人喜欢在Asp.net的Web界面上使用JQuery,因此比较倾向于使用 jQuery WeUI ...

  7. 基于Jquery WeUI的微信开发H5页面控件的经验总结(2)

    在微信开发H5页面的时候,往往借助于WeUI或者Jquery WeUI等基础上进行界面效果的开发,由于本人喜欢在Asp.net的Web界面上使用JQuery,因此比较倾向于使用 jQuery WeUI ...

  8. WinForm界面开发之布局控件"WeifenLuo.WinFormsUI.Docking"的使用

    WinForm界面开发之布局控件"WeifenLuo.WinFormsUI.Docking"的使用 转自:http://www.cnblogs.com/wuhuacong/arch ...

  9. Android开发之日历控件实现

    Android开发之日历控件实现:以下都是转载的. 日历控件 日历控件 日历控件 日历控件

  10. Qt 开发 MS VC 控件终极篇

    Qt 开发 MS VC 控件终极篇 1. 使用 MSVC2015 通过项目向导创建 Qt ActiveQt Server 解决方案 项目配置:以下文件需要修改 1. 项目属性页->项目属性-&g ...

随机推荐

  1. Linux下VLAN功能的实现 (转)

    1.Linux网络栈下两层实现 1.1简介     VLAN是网络栈的一个附加功能,且位于下两层.首先来学习Linux中网络栈下两层的实现,再去看如何把VLAN这个功能附加上去.下两层涉及到具体的硬件 ...

  2. IP数据报首部格式

    IP协议提供不可靠.无连接的数据报传送服务. 不可靠:尽力而为地传输,不保证IP数据报能成功到达目的地. 无连接:每一个数据报之间相互独立地进行路由选择,可不按发送顺序接收. IP首部格式例如以下: ...

  3. java8--面向对象 上(疯狂java讲义3) 复习笔记

    1.初始化块总在构造器执行之前被调用 2.静态初始化块用于初始化类,在类初始化阶段被执行 3.如果继承树里的某个类要被初始化时,系统将会同时初始化该类的所有父类 4.一旦程序员为一个类提供了构造器,系 ...

  4. Rowkey is the Crux Rowkey Design

    Apache HBase ™ Reference Guide http://hbase.apache.org/book.html#rowkey.design The Effect of ColumnF ...

  5. 通过命令打包apk

    平时使用android studio打包,方便快捷,对命令不太熟悉,但在上传apk包到应用市场时,需要认领apk,“认领页的[选择APK]”不是上传您要更新的APK应用文件,而是下载我们提供的空包文件 ...

  6. Hadoop集群搭建-虚拟机安装(转)(一)

    1.软件准备 a).操作系统:CentOS-7-x86_64-DVD-1503-01 b).虚拟机:VMware-workstation-full-9.0.2-1031769(英文原版先安装)  VM ...

  7. ajax异步加载问题

    使用ajax异步加载数据,在之后需要用到这个数据时,应该将之后的js一并写入ajax函数中,否则后面的js不能找到动态拼接的dom节点. 或者将其封装成方法,在ajax动态加载数据的最后调用该方法.

  8. UIProgress控件的属性和方法

    进度条控件是IOS开发中一个简单的系统控件,使用总结如下: 初始化一个进度条: - (instancetype)initWithProgressViewStyle:(UIProgressViewSty ...

  9. sql索引原理以及优化

    http://itindex.net/detail/52237-%E7%B4%A2%E5%BC%95-%E5%8E%9F%E7%90%86 http://itindex.net/detail/5171 ...

  10. C语言一个单链表的实现

    -- 所谓链表记住一句即可:地址不连续,大家只是握个手而已: list0.c #include<stdio.h> #include<malloc.h> typedef int ...