Windows程序设计--创建第一个窗口
2015-12-08 20:23
309 查看
本篇文章讲如何创建一个基本的窗口。
MessageBox弹出来的消息框就是一个窗口,但是窗口是怎样创建的呢?其实很简单,只要几个固定的步骤就行。而只要我们的窗口创建出来之后,只要把需要的函数填进去就能得到一个有功能的窗口。所以我觉得学习Windows就是学习API函数而已,懂得如何调用,各个参数的意思就行。说到参数,其类型都是从C语言的基本数据类型演变而来的,并不难。
现在开始创建第一个窗口,该窗口并无功能,只是一个空的框架。
代码如下:
总结一下创建窗口的步骤:
1.创建并初始化窗口类
看过很多好文章,里面都会把创建窗口类比作一个品牌汽车的模板
2.注册窗口类
然后去为这个品牌注册登记
3.创建窗口
再然后用这个模板来创建同样品牌不同样式的汽车
4.显示、更新窗口
造好车后就要拿出去展示,并时不时的更新车辆信息
5.从消息循环队列中获取消息
把车卖出去后(显示窗口),会有客户把用户体验或者车辆问题反馈回来(消息),这肯定是需要排队的(队列),如果很紧急也可以插队。然后公司就会获取他们反馈的信息(系统),然后叫各种部门处理(窗口过程).
如此循环就是窗口了
HWND hwnd;//窗口句柄
UINT message;//一个无符号整形消息
WPARAM wParam;//16位(双字节(在16位系统的时间))的消息参数。
//值的款式和意思取决于重要的事件消息类型。
//注:在我的VS2008编译器中定义是64位的。
LPARAM lParam;//32位(长整型)的消息参数。这个参数的值和意思取决于主事件消息类型。
//注:在我的VS2008编译器中定义是64位的。
其在头文件中的定义如下:
typedef UINT_PTR WPARAM;
typedef LONG_PTR LPARAM;
typedef LONG_PTR LRESULT;
typedef _W64 unsigned int UINT_PTR, *PUINT_PTR;
typedef _W64 long LONG_PTR, *PLONG_PTR;
DefWindowProc:(解释转自百科)
函数功能:该函数调用缺省的窗口过程来为应用程序没有处理的任何窗口
消息提供缺省的处理。该函数确保每一个消息得到处理。
调用DefWindowProc函数时使用窗口过程接收的相同参数。
函数原型:LRESULT DefWindowProc(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM IParam);
参数:
hWnd:指向接收消息的窗口过程的句柄。
Msg:指定消息类型。
wParam:指定其余的、消息特定的信息。该参数的内容与Msg参数值有关。
IParam:指定其余的、消息特定的信息。该参数的内容与Msg参数值有关。
返回值:返回值就是消息处理结果,它与发送的消息有关。
现在窗口已经创建好了,骨架搭好了就剩下五脏六腑了,只要一步步完善这个骨架,最后就能写出一个界面程序了。
这里不详细解释每个结构体的参数是什么意思,因为没用到说了也白说,用了再去了解它,这样学习负担就不会很大。
看了这个那么长的代码也只是创建出一个空白的窗口,心里可能会有些失望,感觉好像很难,这是刚开始学习Windows程序设计都会遇到的坎坷。但是以后你写多了这个框架,你就会对里面各个参数有一点的理解,并且不之不觉中闭着眼睛都能写出这100多行代码。正所谓,都没有会走怎么可能会跑?所以还是慢慢走吧,总有一天会跑得飞起。
注释1:
lpParam:
指向一个值的指针,该值传递给窗口WM_CREATE消息。该值通过在IParam参数中的CREATESTRUCT结构传递。如果应用程序调用CreateWindow创建一个MDI客户窗口,则lpParam必须指向一个CLIENTCREATESTRUCT结构。
MessageBox弹出来的消息框就是一个窗口,但是窗口是怎样创建的呢?其实很简单,只要几个固定的步骤就行。而只要我们的窗口创建出来之后,只要把需要的函数填进去就能得到一个有功能的窗口。所以我觉得学习Windows就是学习API函数而已,懂得如何调用,各个参数的意思就行。说到参数,其类型都是从C语言的基本数据类型演变而来的,并不难。
现在开始创建第一个窗口,该窗口并无功能,只是一个空的框架。
代码如下:
#include <windows.h> //声明窗口过程函数 LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ; int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { static TCHAR szAppName[] = TEXT ("MyClass") ; HWND hwnd ; //窗口句柄 MSG msg ; //消息结构 WNDCLASS wndclass ;//窗口类结构 //类风格 wndclass.style = CS_HREDRAW | CS_VREDRAW ; wndclass.lpfnWndProc = WndProc ;//窗口过程函数指针 wndclass.cbClsExtra = 0 ;//窗口类需要的额外空间 wndclass.cbWndExtra = 0 ;//窗口实例需要的额外空间 wndclass.hInstance = hInstance ;//程序应用实例句柄 wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;//加载图标供程序使用。 wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;//加载鼠标光标供程序使用。 wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;//取得一个图形对象 //(在这个例子中,是取得绘制窗口背景的画刷对象)。 wndclass.lpszMenuName = NULL ; //窗口菜单 wndclass.lpszClassName = szAppName ;//窗口类名 //注册窗口类 if (!RegisterClass (&wndclass)) { //显示消息框。 MessageBox (NULL, TEXT ("This program requires Windows NT!"), szAppName, MB_ICONERROR) ; return 0 ; } //根据窗口类别建立一个窗口。 hwnd = CreateWindow (szAppName, // 窗口类名 TEXT ("MyWin"), // 窗口标题 WS_OVERLAPPEDWINDOW|WS_VSCROLL|WS_HSCROLL,//窗口风格 CW_USEDEFAULT, // 窗口的x坐标,相对于屏幕左上角 CW_USEDEFAULT, // 窗口的x坐标,相对于屏幕左上角 CW_USEDEFAULT, // 窗口宽度(像素为单位) CW_USEDEFAULT, // 窗口高度(像素为单位) NULL, // 父窗口句柄 NULL, // 窗口菜单 hInstance, // 程序实例句柄 NULL) ; // (请看注释1) //在屏幕上显示窗口 ShowWindow (hwnd, iCmdShow) ; //指示窗口自我更新。 UpdateWindow (hwnd) ; //从消息队列中取得消息 while (GetMessage (&msg, NULL, 0, 0)) { //转译某些键盘消息。 TranslateMessage (&msg) ; //将消息发送给系统,系统再将消息发送给窗口过程处理消息。 DispatchMessage (&msg) ; } // msg.wParam 来自一条表示退出的消息,返回这个值给系统,从而退出。 return msg.wParam ; } //窗口过程函数 //窗口句柄 //窗口消息 //第一个额外附加消息 //第二个额外附加消息 LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { HDC hdc ;//设备环境 PAINTSTRUCT ps ;//绘画结构 //通常定义为静态变量是为了在不断的调用这个函数时该值不会改变 static int cxClient,cyClient;//客户区宽和高 //筛选消息,如果没有需要关注的消息,则有系统自动处理 switch (message) { //窗口创建消息,创建窗口时会有此消息 //注:创建窗口之前还会有很多消息进来,可以自己在 //switc中加断点调试看看有哪些消息进来 case WM_CREATE: return 0; //当客户区改变的时候,也就是发生大小变化 //就会传进来这个消息,然后两个参数会被改变 case WM_SIZE: cxClient=LOWORD(lParam); cyClient=HIWORD(lParam); return 0; //垂直滚动条信息 //记得在窗口风格中添加这两个风格 case WM_VSCROLL: return 0 ; //水平滚动条信息 case WM_HSCROLL: return 0; //重绘窗口消息 //每当窗口改变大小或者移动时都会发送重绘 case WM_PAINT: //开始绘制窗口。 hdc = BeginPaint (hwnd, &ps) ; //获取设备环境的方法不只这一种 //结束绘制窗口。 EndPaint (hwnd, &ps) ; return 0 ; case WM_DESTROY: //在消息队列中插入一个「退出程序」消息 //该消息是WM_QUIT PostQuitMessage (0) ; return 0 ; } //除了需要关注的消息,其它消息都经由系统自动处理。 return DefWindowProc (hwnd, message, wParam, lParam) ; }
总结一下创建窗口的步骤:
1.创建并初始化窗口类
看过很多好文章,里面都会把创建窗口类比作一个品牌汽车的模板
2.注册窗口类
然后去为这个品牌注册登记
3.创建窗口
再然后用这个模板来创建同样品牌不同样式的汽车
4.显示、更新窗口
造好车后就要拿出去展示,并时不时的更新车辆信息
5.从消息循环队列中获取消息
把车卖出去后(显示窗口),会有客户把用户体验或者车辆问题反馈回来(消息),这肯定是需要排队的(队列),如果很紧急也可以插队。然后公司就会获取他们反馈的信息(系统),然后叫各种部门处理(窗口过程).
如此循环就是窗口了
HWND hwnd;//窗口句柄
UINT message;//一个无符号整形消息
WPARAM wParam;//16位(双字节(在16位系统的时间))的消息参数。
//值的款式和意思取决于重要的事件消息类型。
//注:在我的VS2008编译器中定义是64位的。
LPARAM lParam;//32位(长整型)的消息参数。这个参数的值和意思取决于主事件消息类型。
//注:在我的VS2008编译器中定义是64位的。
其在头文件中的定义如下:
typedef UINT_PTR WPARAM;
typedef LONG_PTR LPARAM;
typedef LONG_PTR LRESULT;
typedef _W64 unsigned int UINT_PTR, *PUINT_PTR;
typedef _W64 long LONG_PTR, *PLONG_PTR;
DefWindowProc:(解释转自百科)
函数功能:该函数调用缺省的窗口过程来为应用程序没有处理的任何窗口
消息提供缺省的处理。该函数确保每一个消息得到处理。
调用DefWindowProc函数时使用窗口过程接收的相同参数。
函数原型:LRESULT DefWindowProc(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM IParam);
参数:
hWnd:指向接收消息的窗口过程的句柄。
Msg:指定消息类型。
wParam:指定其余的、消息特定的信息。该参数的内容与Msg参数值有关。
IParam:指定其余的、消息特定的信息。该参数的内容与Msg参数值有关。
返回值:返回值就是消息处理结果,它与发送的消息有关。
现在窗口已经创建好了,骨架搭好了就剩下五脏六腑了,只要一步步完善这个骨架,最后就能写出一个界面程序了。
这里不详细解释每个结构体的参数是什么意思,因为没用到说了也白说,用了再去了解它,这样学习负担就不会很大。
看了这个那么长的代码也只是创建出一个空白的窗口,心里可能会有些失望,感觉好像很难,这是刚开始学习Windows程序设计都会遇到的坎坷。但是以后你写多了这个框架,你就会对里面各个参数有一点的理解,并且不之不觉中闭着眼睛都能写出这100多行代码。正所谓,都没有会走怎么可能会跑?所以还是慢慢走吧,总有一天会跑得飞起。
注释1:
lpParam:
指向一个值的指针,该值传递给窗口WM_CREATE消息。该值通过在IParam参数中的CREATESTRUCT结构传递。如果应用程序调用CreateWindow创建一个MDI客户窗口,则lpParam必须指向一个CLIENTCREATESTRUCT结构。
相关文章推荐
- Java实现从数据库导出大量数据记录并保存到文件的方法(转)
- Sqlite3
- 北大OJ1001
- c++侵入式对象计数设计技术
- Codeforces Round #302 (Div. 2) A. Set of Strings
- Multi-Exemplar Affinity Propagation
- 使用Decision Tree对MNIST数据集进行实验
- JavaScript 系列笔记(一)数据类型
- servlet容器的URL映射知识
- 如何在Linux中查看所有正在运行的进程
- [Android]本地广播的好处
- print float as int 的分析
- 简易的 WebView 拦截事件等
- QQl聊天消息
- LeetCode OJ:Number of Islands(孤岛计数)
- 数组链表下标指针map list
- Centos root权限的变化
- Codeforces Round #105 (Div. 2) 148C Terse princess(脑洞)
- 一些算法书籍
- fs_initcall、early_initcall、__init宏