跟我一起玩Win32开发(12):使用控件——单选按钮
今天,咱们还是接着玩“控件斗地主”,这是我原创的超级游戏,有益身心健康,玩一朝,十年少。
哦,对,脑细胞极速运动了一下,想起了一个问题,这个破问题虽然网上有很多种解决方案,但是,并没有让所有人都解决问题。
不知道大家有没有调用过LoadIconMetric函数,这个函数在静态库Comctl32.lib中有定义(当然,动态库也有),不过,创建项目的时候,默认并没有引用它的,于是,大家知道,解决调用的方法就是在代码中加上:
- #pragma comment(lib, "Comctl32.lib")
我一般习惯这种方法,这样不必去修改项目属性。但是,很多朋友说过,在Win 7以后的系统,依然没有成功,我也尝到了调用失败的“甜头”,我一直在想,这是为什么呢?
于是,我又试了另一种方法,就是用LoadLibrary加载Comctl32.dll,然后通过函数指针去调用它:
- typedef LRESULT (WINAPI * pLoadICMT)(.......);
但结果还是没成功,GetProcAddress返回的地址为0,又一次尝到了失败带来的“刺激”感。
直到某一天,我在写某程序时,从上一文中大家都看到,那个按钮的视觉风格和Win9x/2000差不多,似乎没有XP那种充满美学水准的效果。其实,这是因为我们的程序没有启用视觉效果,默认情况下,使用版本5中的控件,而要有XP以上的风格,是在版本6的控件内库中才有。
当然方法可以很多人都知道,就是定义一个用于视觉效果的清单文件,本质是XML格式。不过我用的开发工具是VS 2005之后的版本,就不用弄个XML文件那么麻烦了,直接到MSDN上复制粘贴这段代码放到你的代码文件(.cpp)中,就是这个,直接抄过来就行了,适当的时候,要巧用MSDN上的资源。
- // 开启视觉效果 Copy from MSDN
- #pragma comment(linker,"\"/manifestdependency:type='win32' \
- name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \
- processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
version是版本号,要有好看的效果,记得要6,不要写用低版本的。processorArchitecture是处理器平台,x86或amd64,用*号最好,通杀。
真是巧啊,原来这么一来,噗,LoadIconMetric也能调用了。总的来说,就是在代码文件加上以下内容:
- #include <CommCtrl.h> //包含头文件
- // 导入静态库
- #pragma comment(lib, "Comctl32.lib")
- // 开启视觉效果 Copy from MSDN
- #pragma comment(linker,"\"/manifestdependency:type='win32' \
- name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \
- processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
这问题干掉了,开始今天的吹牛大行动。
单选按钮,是的,在WinForm里面你肯定知道,RadioButto,复选框就是CheckBox。不过那个时候.NET还没那么猛,那个时代,就是玩VB6,所以我知道VB里面,单选按钮叫Option吧。
然后找遍了Win32的控件库,怎么没见Radio和CheckBox,于是,我陷入了万分痛苦之中。不久后阅读MSDN文档,我就明白了,其实这两个玩意儿都是BUTTON类的,只是应用了不同的style罢了。
好的,咱们先来弄一个单选的吧。
- case WM_CREATE:
- {
- CreateWindow(L"Button",L"这玩意儿好",
- BS_RADIOBUTTON | WS_CHILD | WS_VISIBLE,
- 10,10,150,28,
- hwnd, (HMENU)IDC_RADBTN1,
- (HINSTANCE)GetWindowLongPtr(hwnd, GWLP_HINSTANCE),
- NULL);
- }
- return 0;
应用BS_RADIOBUTTON样式,就可以使按钮变成单选按钮,不过,别忘了WS_CHILD | WS_VISIBLE。
运行一下。
不过,当你点击它的时候,会发现它并不会选中,那是因为BS_RADIOBUTTON样式不会自动让它选上。我们换一种可以自动处理的样式,带AUTO打头的。
就是用 BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE,如下图的预览结果。
接下来,我们多创建几个吧。
- /*-----------------------------------------------------------------*/
- //控件ID
- #define IDC_RADBTN1 50001
- #define IDC_RADBTN2 50002
- #define IDC_RADBTN3 50003
- #define IDC_RADBTNBLUE 51001
- #define IDC_RADBTNRED 51002
- #define IDC_RADBTNGREEN 51003
- /*-----------------------------------------------------------------*/
- // 消息处理函数
- LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
- {
- switch(msg)
- {
- case WM_CREATE:
- {
- // 获取当前实例句柄
- HINSTANCE hthisapp = (HINSTANCE)GetWindowLongPtr(hwnd, GWLP_HINSTANCE);
- // 纵坐标,控件将以此作为基准,
- // 排列时依次增加
- int yLoc = 0;
- // 用来显示文本
- yLoc += 10;
- CreateWindow(L"Static",L"请问你的性别是:",
- SS_SIMPLE | WS_CHILD | WS_VISIBLE,
- 10,yLoc,160,18,
- hwnd, NULL,
- hthisapp,
- NULL);
- // 第一组单选按钮
- yLoc += 22;
- CreateWindow(L"Button",L"男",
- WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON | WS_GROUP,
- 12, yLoc, 60, 16,
- hwnd,
- (HMENU)IDC_RADBTN1,
- hthisapp,NULL);
- yLoc += 20;
- CreateWindow(L"Button",L"女",
- WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON,
- 12,yLoc, 60, 16,
- hwnd,(HMENU)IDC_RADBTN2,hthisapp,NULL);
- yLoc += 20;
- CreateWindow(L"Button",L"人妖",WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON,
- 12,yLoc,60,16,hwnd,(HMENU)IDC_RADBTN3,hthisapp,NULL);
- // 显示文本
- yLoc += 38;
- CreateWindow(L"Static",L"你喜欢哪一种颜色?",
- WS_CHILD | WS_VISIBLE | SS_SIMPLE,
- 10,yLoc,150,18,hwnd,NULL,hthisapp,NULL);
- //第二组单选按钮
- yLoc += 22;
- CreateWindow(L"Button",L"蓝色",WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON | WS_GROUP,
- 12,yLoc,60,16,hwnd,(HMENU)IDC_RADBTNBLUE,hthisapp,NULL);
- yLoc += 20;
- CreateWindow(L"Button",L"红色",WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON,
- 12,yLoc,60,16,hwnd,(HMENU)IDC_RADBTNRED,hthisapp,NULL);
- yLoc += 20;
- CreateWindow(L"Button",L"绿色",WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON,
- 12,yLoc,60,16,hwnd,(HMENU)IDC_RADBTNGREEN,hthisapp,NULL);
- }
- return 0;
- case WM_DESTROY:
- PostQuitMessage(0); //平安退出
- return 0;
- default:
- return DefWindowProc(hwnd,msg,wParam,lParam);
- }
- return 0;
- }
在创建单选框中,为什么有些加了WS_GROUP样式,而有些未加呢?
其实是这样的,既然单选按钮是单选的,那么,任何一个单选按钮都与其他的单选按钮是互斥的关系。所以,在同一个容器(本例是同一个窗口)中就需要把单选按钮进行分组。
同一组中的单选按钮相互排斥,他的分组方法:
顺序,以Tab键顺序为参考,这个不用我介绍,你随便打开一个窗口,然后多按几下Tab键你就懂了,如果不懂,那你真的无可救药了。
凡是设置了WS_GROUP的单选框做为一组中的首元素,随后的所有单选按钮都和它在同一组,直到下一个设置了WS_GROUP样式的单选按钮。用上面的例子来说吧。
性别一组中,第一个应用了WS_GROUP的是“男”,随后的“女”和“人妖”都与“男”在同一组,因为后面一个“蓝色”设置了WS_GROUP样式。所以,
第一组为:男,女,人妖;
第二组为:蓝色,红色,绿色。
显然,用了BS_AUTORADIOBUTTON后,系统就会自动处理选择状态了。
完整的代码清单如下:
- #include <Windows.h>
- #include <WindowsX.h>
- #include <CommCtrl.h> //包含头文件
- // 导入静态库
- #pragma comment(lib, "Comctl32.lib")
- // 开启视觉效果 Copy from MSDN
- #pragma comment(linker,"\"/manifestdependency:type='win32' \
- name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \
- processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
- // 先声明一个WindowProc回调
- LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
- // 入口点
- int WINAPI wWinMain(HINSTANCE hTheApp, HINSTANCE hPrevApp, LPWSTR lpCmd, int nShow)
- {
- PCWSTR cn = L"My"; // 窗口名
- PCWSTR tt = L"应用程序"; // 窗口标题
- // 设计窗口类
- WNDCLASS wc = { sizeof(WNDCLASS) };
- wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
- wc.lpfnWndProc = WindowProc;
- wc.style = CS_HREDRAW | CS_VREDRAW;
- LoadIconMetric(hTheApp, IDI_APPLICATION, LIM_SMALL, &wc.hIcon);
- wc.lpszClassName = cn;
- wc.hInstance = hTheApp;
- RegisterClass(&wc); // 注册窗口类
- // 创建窗口
- HWND hwnd = CreateWindow(cn, tt,WS_OVERLAPPEDWINDOW,
- 28,34,400,330,NULL,NULL,hTheApp,NULL);
- if( !hwnd)
- { /* 如果窗口创建失败,
- 那继续执行也没有意义
- 长痛不如短痛,结束吧。
- */
- return 0;
- }
- ShowWindow(hwnd,nShow); //显示窗口
- UpdateWindow(hwnd); //更新窗口
- // 消息循环
- MSG msg;
- while(GetMessage(&msg,NULL,0,0))
- {
- TranslateMessage(&msg);
- DispatchMessage(&msg); //调度消息到WindowProc回调
- }
- return 0;
- }
- /*-----------------------------------------------------------------*/
- //控件ID
- #define IDC_RADBTN1 50001
- #define IDC_RADBTN2 50002
- #define IDC_RADBTN3 50003
- #define IDC_RADBTNBLUE 51001
- #define IDC_RADBTNRED 51002
- #define IDC_RADBTNGREEN 51003
- #define IDC_BTN_OK 1107 //确定按钮ID
- /*-----------------------------------------------------------------*/
- // 消息处理函数
- LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
- {
- switch(msg)
- {
- case WM_CREATE:
- {
- // 获取当前实例句柄
- HINSTANCE hthisapp = (HINSTANCE)GetWindowLongPtr(hwnd, GWLP_HINSTANCE);
- // 纵坐标,控件将以此作为基准,
- // 排列时依次增加
- int yLoc = 0;
- // 用来显示文本
- yLoc += 10;
- CreateWindow(L"Static",L"请问你的性别是:",
- SS_SIMPLE | WS_CHILD | WS_VISIBLE,
- 10,yLoc,160,18,
- hwnd, NULL,
- hthisapp,
- NULL);
- // 第一组单选按钮
- yLoc += 22;
- CreateWindow(L"Button",L"男",
- WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON | WS_GROUP,
- 12, yLoc, 60, 16,
- hwnd,
- (HMENU)IDC_RADBTN1,
- hthisapp,NULL);
- yLoc += 20;
- CreateWindow(L"Button",L"女",
- WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON,
- 12,yLoc, 60, 16,
- hwnd,(HMENU)IDC_RADBTN2,hthisapp,NULL);
- yLoc += 20;
- CreateWindow(L"Button",L"人妖",WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON,
- 12,yLoc,60,16,hwnd,(HMENU)IDC_RADBTN3,hthisapp,NULL);
- // 显示文本
- yLoc += 38;
- CreateWindow(L"Static",L"你喜欢哪一种颜色?",
- WS_CHILD | WS_VISIBLE | SS_SIMPLE,
- 10,yLoc,150,18,hwnd,NULL,hthisapp,NULL);
- //第二组单选按钮
- yLoc += 22;
- CreateWindow(L"Button",L"蓝色",WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON | WS_GROUP,
- 12,yLoc,60,16,hwnd,(HMENU)IDC_RADBTNBLUE,hthisapp,NULL);
- yLoc += 20;
- CreateWindow(L"Button",L"红色",WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON,
- 12,yLoc,60,16,hwnd,(HMENU)IDC_RADBTNRED,hthisapp,NULL);
- yLoc += 20;
- CreateWindow(L"Button",L"绿色",WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON,
- 12,yLoc,60,16,hwnd,(HMENU)IDC_RADBTNGREEN,hthisapp,NULL);
- // 创建一个确定按钮
- CreateWindow(L"Button",L"确定",WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,
- 230,180,80,27,hwnd,(HMENU)IDC_BTN_OK,hthisapp,NULL);
- }
- return 0;
- case WM_DESTROY:
- PostQuitMessage(0); //平安退出
- return 0;
- default:
- return DefWindowProc(hwnd,msg,wParam,lParam);
- }
- return 0;
- }
跟我一起玩Win32开发(12):使用控件——单选按钮的更多相关文章
- 跟我一起玩Win32开发(转自CSDN-东邪独孤)
跟我一起玩Win32开发(1):关于C++的几个要点 跟我一起玩Win32开发(2):完整的开发流程 跟我一起玩Win32开发(3):窗口的重绘 跟我一起玩Win32开发(4):创建菜单 跟我一起玩W ...
- 跟我一起玩Win32开发(17):启动和结束进程
这里我再次说明一下,我不知道为什么,现在的人那么喜欢走极端,估计是价值观都“升级”了的缘故吧. 我撰写这一系列Win32相关的文章,并不是叫大家一定要用Win32去开发项目,仅仅是给大家了解一下,Wi ...
- python开发_tkinter_窗口控件_自己制作的Python IDEL_博主推荐(二)
在上一篇blog:python开发_tkinter_窗口控件_自己制作的Python IDEL_博主推荐 中介绍了python中的tkinter的一些东西,你可能对tkinter有一定的了解了.这篇b ...
- RS开发日期提示控件默认为昨天之进阶篇
时隔<RS开发日期提示控件默认为昨天>这篇博文已经很久了,请原谅我隔了这么久才继续来写这篇笔记.也希望读到这篇笔记的朋友可以从这篇笔记中学习到一些关于RS日期控件和JS的一些应用知识,当然 ...
- Android零基础入门第17节:Android开发第一个控件,TextView属性和方法大全
原文:Android零基础入门第17节:Android开发第一个控件,TextView属性和方法大全 前面简单学习了一些Android UI的一些基础知识,那么接下来我们一起来详细学习Android的 ...
- 基于Jquery WeUI的微信开发H5页面控件的经验总结(1)
在微信开发H5页面的时候,往往借助于WeUI或者Jquery WeUI等基础上进行界面效果的开发,由于本人喜欢在Asp.net的Web界面上使用JQuery,因此比较倾向于使用 jQuery WeUI ...
- 基于Jquery WeUI的微信开发H5页面控件的经验总结(2)
在微信开发H5页面的时候,往往借助于WeUI或者Jquery WeUI等基础上进行界面效果的开发,由于本人喜欢在Asp.net的Web界面上使用JQuery,因此比较倾向于使用 jQuery WeUI ...
- WinForm界面开发之布局控件"WeifenLuo.WinFormsUI.Docking"的使用
WinForm界面开发之布局控件"WeifenLuo.WinFormsUI.Docking"的使用 转自:http://www.cnblogs.com/wuhuacong/arch ...
- Android开发之日历控件实现
Android开发之日历控件实现:以下都是转载的. 日历控件 日历控件 日历控件 日历控件
- Qt 开发 MS VC 控件终极篇
Qt 开发 MS VC 控件终极篇 1. 使用 MSVC2015 通过项目向导创建 Qt ActiveQt Server 解决方案 项目配置:以下文件需要修改 1. 项目属性页->项目属性-&g ...
随机推荐
- 光纤与PON基础概念整理
近期有幸接触到通讯这一领域,此文专门用于整理记录. 首先是光纤与光缆 光纤(OpticalFiber,OF)是用来导光的透明介质纤维,一根有用化的光纤是由多层透明介质构成,一般能够分为三部分:折射率 ...
- BZOJ 2115: [Wc2011] Xor DFS + 线性基
2115: [Wc2011] Xor Time Limit: 10 Sec Memory Limit: 259 MB Description Input 第一行包含两个整数N和 M, 表示该无向图中 ...
- Principle of least astonishment
Principle of least astonishment - Wikipedia https://en.wikipedia.org/wiki/Principle_of_least_astonis ...
- MySQL alter语句
1:删除列 ALTER TABLE [表名字] DROP [列名称] 2:增加列 ALTER TABLE [表名字] ADD [列名称] INT NOT NULL COMMENT '注释说明' 3: ...
- (C)strcpy ,strncpy和strlcpy的基本用法
好多人已经知道利用strncpy替代strcpy来防止缓冲区越界. 但是如果还要考虑运行效率的话,也许strlcpy是一个更好的方式. 1. strcpy strcpy 是依据 /0 作为结束判断的, ...
- Linux时间子系统之三:时间的维护者:timekeeper【转】
本文转载自:http://blog.csdn.net/droidphone/article/details/7989566 本系列文章的前两节讨论了用于计时的时钟源:clocksource,以及内核内 ...
- POJ 3750 小孩报数问题 (线性表思想 约瑟夫问题 数组模拟运算的 没用循环链表,控制好下标的指向就很容易了)
小孩报数问题 Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 10423 Accepted: 4824 Descripti ...
- Getting Started with xUnit.net (desktop)
https://xunit.github.io/docs/getting-started-desktop.html In this article, we will demonstrate getti ...
- SpringBoot快速HelloWorld入门
1.新建maven项目 2.pom.xml 里添加SpringBoot所依赖的jar包 <parent> <groupId>org.springframework.boot&l ...
- MySQL性能优化-I/O相关配置参数
本文介绍InnoDB和MyISAM两种存储引擎的I/O相关参数配置. 1.InnoDB I/O相关配置 Innodb是一种事务型的存储引擎,为了减少提交事务时产生的io开销,innodb采用了写日志 ...