Win 32 编程之按钮消息响应(代码小错误修复)
最近不想用MFC写东西了,有没有安装Qt和其他图形化开发环境,只能捣鼓API了。于是乎,就有了以下的学习--
首先,老套的创建个Windows窗口,由于自己有点小懒,就直接用Hello Word的源码了。
#include <windows.h>
#include <stdio.h> // 窗口过程函数
LRESULT CALLBACK WinSunProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); int WINAPI WinMain(
HINSTANCE hInstance, // handle to current instance
HINSTANCE hPrevInstance, // handle to previous instance
LPSTR lpCmdLine, // command line
int nCmdShow // show state
) {
// 窗口类
WNDCLASS wndcls;
wndcls.cbClsExtra = ; // 类附加内存
wndcls.cbWndExtra = ; // 窗口附加内存
wndcls.hbrBackground = (HBRUSH) GetStockObject(COLOR_WINDOW); // 背景画刷句柄
wndcls.hCursor = LoadCursor(NULL, IDC_ARROW); // 窗口光标句柄
wndcls.hIcon = LoadIcon(NULL, IDI_APPLICATION); // 窗口图标句柄
wndcls.hInstance = hInstance; // 包含窗口过程函数的程序实例
wndcls.lpfnWndProc = WinSunProc; // 只想窗口过程函数的指针
wndcls.lpszClassName = "CRoot"; // 窗口类名称
wndcls.lpszMenuName = NULL; // 菜单资源
wndcls.style = CS_HREDRAW | CS_VREDRAW; // 窗口样式
RegisterClass(&wndcls); // 创建窗口, 定义一个变量用来保存成功创建窗口后返回的句柄
HWND hwnd;
hwnd = CreateWindow( // 窗口创建成功时返回为窗口分配的句柄 失败时返回NULL
"CRoot", // 窗口类名
"Hello World", // 窗口名字
WS_CAPTION|WS_SYSMENU, // 窗口样式
CW_USEDEFAULT, CW_USEDEFAULT, // 窗口左上角坐标
, , // 窗口宽高
NULL, // 父窗口句柄
NULL, // 窗口菜单句柄
hInstance, // 窗口所属应用程序实例
NULL // WM_CREATE消息附加参数lParam传入的数据指针
); // 显示及刷新窗口
ShowWindow(hwnd, SW_SHOWNORMAL);
UpdateWindow(hwnd); // 定义消息结构体
MSG msg;
while (GetMessage( // WM_QUIT消息返回0 错误返回-1
&msg, // 指向消息的结构体
NULL, // 指定接收属于哪一窗口的消息 通常设为NULL,用来接收属于调用线程的所有窗口的窗口消息
, // 获取消息的最小值 通常为0
)) // 获取消息的最大值 都设为0表示接收所有消息
{
TranslateMessage(&msg); // 将虚拟消息转换为字符消息 投递到调用线程的消息队列中 下次调用GetMessage时被取出
DispatchMessage(&msg); // 将消息传递给操作系统 由操作系统调用窗口过程函数对消息进行处理
}
return msg.wParam;
} // 窗口过程函数
LRESULT CALLBACK WinSunProc(
HWND hwnd, // 窗口句柄
UINT uMsg, // 消息代码
WPARAM wParam, // 附加参数
LPARAM lParam
)
{
switch(uMsg)
{
case WM_CHAR:
char szChar[];
sprintf(szChar, "char code is %d", wParam);
MessageBox(hwnd, szChar, "char", );
break; default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
} return ;
}
然后,我们要在消息循环里面添加创建Button的代码,因为Button是一个子窗口,所以创建方式也如同创建窗口一样,使用CreateWindow()函数。
而,此窗口要一开始跟随父窗口出现,所以要在父窗口创建时创建该Button。嗯,所以要在窗口过程函数里面监听下WM_CREATE消息。
代码片段:
switch(uMsg)
{
case WM_CHAR:
char szChar[];
sprintf(szChar, "char code is %d", wParam);
MessageBox(hwnd, szChar, "char", );
break;
case WM_CREATE:
CreateWindowEx(,"Button","按钮1",WS_VISIBLE|WS_CHILD,,,,,hwnd,(HMENU),,); default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
这里要说明一下啦,一开始我也搞得晕晕乎乎,不知道怎么搞Button的消息事件,这里我们用Button的ID啦。先看下微软的MSDN关于CreateWindow()函数
HWND WINAPI CreateWindow(
_In_opt_ LPCTSTR lpClassName,
_In_opt_ LPCTSTR lpWindowName,
_In_ DWORD dwStyle,
_In_ int x,
_In_ int y,
_In_ int nWidth,
_In_ int nHeight,
_In_opt_ HWND hWndParent,
_In_opt_ HMENU hMenu,
_In_opt_ HINSTANCE hInstance,
_In_opt_ LPVOID lpParam
);
关键点在参数HMENU hWndParent,第一眼一看是不是感觉像菜单?不错啦~确实在菜单中用到的。进一步看他的解释
hMenu [in, optional]
Type: HMENU
A handle to a menu, or specifies a child-window identifier depending on the window style. For an overlapped or pop-up window, hMenu identifies the menu to be used with the window; it can be NULL if the class menu is to be used. For a child window, hMenu specifies the child-window identifier, an integer value used by a dialog box control to notify its parent about events. The application determines the child-window identifier; it must be unique for all child windows with the same parent window.
红色选中大体意思说,当在做一个子窗口的时候,这个参数就是一个整形表示,用于标识这个子窗口,提供父窗口的消息处理。总的来说就是所谓的控件ID啦~
既然有标识,就好办啦,我们就判断是不是他,若是这个按钮,我们就让他响应相应的操作啦~~
但是怎么知道按钮被Click了呢?我们又得监听另一个消息WM_COMMAND,它有两个参数,其中一个就传输了所谓的控件ID
wParam
For a description of this parameter.
lParam
For a description of this parameter.
我们可以判断他如果是这个按钮的ID,我们就让他干某些事情。我们首先要转换下wParam的类型,否则和我们写的ID的类型不一样的。
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
switch (wmId)
{
case ()://之前我们创建按钮时,写的ID为0
//功能代码 //....... break; //...更多代码 }
好了,整体框架差不多完工啦,自己再加下代码啥的就没问题了。在这里,我再次浪费下篇幅,给出完整代码:
关于wmId一开始写程序没有编译,因为逻辑错误,未有注意到,忘记声明他了。为了防止被default给忽略掉,我们把他写在switch(uMsg)之前。
#include <windows.h>
#include <stdio.h>
#include <Windef.h> // 窗口过程函数
LRESULT CALLBACK WinSunProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); int WINAPI WinMain(
HINSTANCE hInstance, // handle to current instance
HINSTANCE hPrevInstance, // handle to previous instance
LPSTR lpCmdLine, // command line
int nCmdShow // show state
) {
// 窗口类
WNDCLASS wndcls;
wndcls.cbClsExtra = ; // 类附加内存
wndcls.cbWndExtra = ; // 窗口附加内存
wndcls.hbrBackground = (HBRUSH) GetStockObject(COLOR_WINDOW); // 背景画刷句柄
wndcls.hCursor = LoadCursor(NULL, IDC_ARROW); // 窗口光标句柄
wndcls.hIcon = LoadIcon(NULL, IDI_APPLICATION); // 窗口图标句柄
wndcls.hInstance = hInstance; // 包含窗口过程函数的程序实例
wndcls.lpfnWndProc = WinSunProc; // 只想窗口过程函数的指针
wndcls.lpszClassName = "CRoot"; // 窗口类名称
wndcls.lpszMenuName = NULL; // 菜单资源
wndcls.style = CS_HREDRAW | CS_VREDRAW; // 窗口样式
RegisterClass(&wndcls); // 创建窗口, 定义一个变量用来保存成功创建窗口后返回的句柄
HWND hwnd;
hwnd = CreateWindow( // 窗口创建成功时返回为窗口分配的句柄 失败时返回NULL
"CRoot", // 窗口类名
"Hello World", // 窗口名字
WS_CAPTION|WS_SYSMENU, // 窗口样式
CW_USEDEFAULT, CW_USEDEFAULT, // 窗口左上角坐标
, , // 窗口宽高
NULL, // 父窗口句柄
NULL, // 窗口菜单句柄
hInstance, // 窗口所属应用程序实例
NULL // WM_CREATE消息附加参数lParam传入的数据指针
); // 显示及刷新窗口
ShowWindow(hwnd, SW_SHOWNORMAL);
UpdateWindow(hwnd); // 定义消息结构体
MSG msg;
while (GetMessage( // WM_QUIT消息返回0 错误返回-1
&msg, // 指向消息的结构体
NULL, // 指定接收属于哪一窗口的消息 通常设为NULL,用来接收属于调用线程的所有窗口的窗口消息
, // 获取消息的最小值 通常为0
)) // 获取消息的最大值 都设为0表示接收所有消息
{
TranslateMessage(&msg); // 将虚拟消息转换为字符消息 投递到调用线程的消息队列中 下次调用GetMessage时被取出
DispatchMessage(&msg); // 将消息传递给操作系统 由操作系统调用窗口过程函数对消息进行处理
}
return msg.wParam;
} // 窗口过程函数
LRESULT CALLBACK WinSunProc(
HWND hwnd, // 窗口句柄
UINT uMsg, // 消息代码
WPARAM wParam, // 附加参数
LPARAM lParam
)
{
WORD wmId = LOWORD(wParam);
//WORD wmEvent = HIWORD(wParam);
switch(uMsg)
{
/*case WM_CHAR:
char szChar[20];
sprintf(szChar, "char code is %d", wParam);
MessageBox(hwnd, szChar, "char", 0);
break;*/
case WM_CREATE:
CreateWindowEx(,"Button","按钮1",WS_VISIBLE|WS_CHILD,,,,,hwnd,(HMENU),,);
break;
case WM_COMMAND:
switch (wmId)
{
case ://(HMENU) 和创建中的id对应
//这里写你要让按钮实现的功能
MessageBoxA(NULL,"Hello Button!","My TestProject",MB_OK);
}
break; default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
} return ;
}
目前已经在GNU GCC Compiler成功!
Win 32 编程之按钮消息响应(代码小错误修复)的更多相关文章
- 解决视图状态消息验证代码 (MAC) 错误
https://blog.csdn.net/bingtingabc/article/details/49148745 2015年10月15日 10:05:56 bingtingabc 阅读数:3397 ...
- Java中用FileInputStream和FileOutputStream读写txt文件,文件内容乱码的问题,另附循环代码小错误
乱码问题大概就是编码格式不一样,搜了很多都是这么说的,修改编码解决乱码问题链接: https://blog.csdn.net/weixin_42496466/article/details/81189 ...
- MFC 自绘按钮 消息响应
单检测到按下消息时,发送一个消息 m_pParent->PostMessage(WM_COMMAND, IDC_BUTTON1); 然后再在消息映射里建立映射. ON_COMMAND(IDC_B ...
- 那些年,被我蠢哭了的php代码小错误~~~
首先,我爱敲代码!!!而且我很喜欢修改bug,在看到那些bug的时候,我是兴奋的,毕竟当你解决这个bug之后感觉是很爽的. 在学习的过程中,看到无数的bug,有一些错误是很微小的,一般在PHP中都能通 ...
- MFC动态按钮的创建及其消息响应(自定义消息)
动态按钮(多个)的创建: 1.在类中声明并定义按钮控件的ID #define IDC_D_BTN 10000 2.在类的OnInitDialog()函数中动态创建按钮(建立按钮对象时最好建立对象的指针 ...
- MFC动态按钮的创建及其消息响应 和 自定义消息
原文链接: http://www.cnblogs.com/gaohongchen01/p/4046525.html 动态按钮(多个)的创建: 1.在类中声明并定义按钮控件的ID #define IDC ...
- 【Windows编程】入门篇——win 32窗口的hello word!
✍ Windows编程基础 1.Win 32应用程序基本类型 1) 控制台程序 不需要完善的windows窗口,可以使用DOS窗口方式显示 2) Win 32窗口程序 包含窗口的程序,可以通过窗 ...
- 为duilib的MenuDemo增加消息响应,优化代码和显示效果
转载请说明原出处,谢谢~~:http://blog.csdn.net/zhuhongshu/article/details/38253297 第一部分 我在前一段时间研究了怎么制作duilib的菜单, ...
- MFC控件编程之 按钮编辑框.静态文本的使用,以及访问控件的七种方法.
MFC控件编程之 按钮编辑框.静态文本的使用以及访问控件的七种方法. 一丶按钮.静态文本的通用属性. 他们都有一个属性.就是可以输入标题内容.以及可以自定义控件ID. 创建一个MFC Dlg对话框. ...
随机推荐
- 这交互炸了(四) :一分钟让你拥有微信拖拽透明返回PhotoView
本文已授权微信公众号:鸿洋(hongyangAndroid)原创首发 <交互炸了>或许是一系列高端特效教程, 文中会介绍一些比较炫酷的特效,以及实现的思路.特效实现本身也许不会有太大的难度 ...
- (Java)微信之个人公众账号开发(一)——进入开发者模式
本篇文章将教大家如何建立微信个人公众账号,(注意:后台全部是用javaweb相关技术开发),大家知道,现在微信公众账号分服务号和订阅号,现在我要讲的主要是个人微信公众账号的建立以及后台的开发,个人公众 ...
- Linux 高性能服务器编程——I/O复用的高级应用
高级应用一:非阻塞connect connect系统调用的man手册中有如下的一段内容: EINPROGRESS The socket is non-blocking and the connecti ...
- #pragma pack(x) CPU对齐
编译器会尽量把成员对齐以提高内存的命中率.对齐是可以更改的,使用"#pragma pack(x)" 可以改变编译器的对齐方式. C++固有类型的对界取编译器对齐方式与自身大小中较小 ...
- android SlidingmMenu的入门介绍
最近了解了SlidingMenu控件的使用,之前手机qq等软件都采用了这种控件,所以还是很有必要学些这个控件的使用方法. 这个控件是基于github的一个开源项目. 地址是: https://gith ...
- 【移动开发】EditText输入字数限制总结(包括中文输入内存溢出的解决方法)
限定EditText输入个数的解决方案很多,但是一般主要考虑两点,也就是处理两件事:(1)不同语言字符(英文.中文等)处理方式(2)输入字符达到数目后,是否仍然允许用户输入 第一点,涉及的东东其实蛮多 ...
- MySQL 存储过程探秘
关于存储过程的优点,本文不再阐述.这里只是对创建存储过程时可能遇到的问题做一下简单的分析. 必备基础 这里说的基础,是相关于如何创建一个存储过程的. DELIMITER:分隔符,定界符. 作用就是:作 ...
- [ExtJS5学习笔记]第十三节 Extjs5的Ext.each方法学习
本文地址:http://blog.csdn.net/sushengmiyan/article/details/39009555 sencha官方API:http://docs.sencha.com/e ...
- reactor线程阻塞引起故障
大致线程模型: jstack打印JVM堆栈,可以看到reactor线程阻塞了,导致它对应的前端连接无法使用.阻塞在了oracle驱动rollback动作,这里其实是因为oracle驱动为了保证串行请求 ...
- SpringMVC源码分析--容器初始化(五)DispatcherServlet
上一篇博客SpringMVC源码分析--容器初始化(四)FrameworkServlet我们已经了解到了SpringMVC容器的初始化,SpringMVC对容器初始化后会进行一系列的其他属性的初始化操 ...