Windows API 程序设计入门
- 1. Windows 程序内部运行原理简述
- 2. 创建文件
- 3. 开始编写程序
- 3.1 头文件
- 3.2 WinMain函数(程序入口函数)
- 3.3 窗口过程函数
- 4. 运行结果截图
- 5. 总结
学习目的:
- 了解 windows操作系统应用程序开发的基本概念,win32 API函数、消息与事件驱动
- 掌握WinMain函数的基本框架,窗口定义、窗口创建、消息循环及窗口过程函数
1. Windows 程序内部运行原理简述
下面简单讲述一下Windows程序内部运行机制。一个Windows程序,是以消息为基础,事务来推进程序的运行,这里贴出一份Windows应用程序、操作系统、计算机硬件相互驱动的关系图。
操作系统→输出设备:操作系统能操控计算机输出设备执行相应的功能,比如让声卡发生、显示动画等;
输入设备→操作系统:操作系统收到输入设备,如鼠标、键盘发出的指令消息;
应用程序→操作系统:应用程序可以通过一些函数调用的形式通知操作系统让声卡发出何种声音、显示怎样的画面;
操作系统→应用程序:操作系统收到输入设备的指令后,将把指令压入消息队列中,应用程序从消息队列中顺序读取并做处理。
这里我们简单了解一下就行了,我们Windows程序设计主要在应用程序上。
2. 创建文件
实验工具:Visual C++ 6.0
编译环境:Windows 10
首先新建一个APP文件。
然后在Projects目录下选择Win32 Application。
创建一个空文件。
点击OK。
接下来就进入程序编写界面了。
3. 开始编写程序
一个简单的Windows API 程序就只有两个函数,一个是程序入口函数,一个是窗口过程函数,下面我们来简单阐述一下。
3.1 头文件
1
2
3#include <windows.h> #include <stdio.h>
3.2 WinMain函数(程序入口函数)
3.2.1 函数申明及参数
所有的C语言都会有一个函数入口,WinMain()函数有四个参数。
1
2
3
4
5
6
7int WINAPI WinMain( HINSTANCE hInstance, //当前窗口实例的句柄 HINSTANCE hPrevInstance, //先前窗口实例的句柄 LPSTR lpCmdLine, //指向字符串首地址的指针 int nCmdShow //表示指定窗口显示状态(最大、最小、隐藏显示) )
(注:固定格式,可以直接引用)
3.2.2 函数体
一个主函数内主要由五个部分。
- 设计一个窗口类
更改窗口的样式可在该部分进行修改。
1
2
3
4
5
6
7
8
9
10
11
12WNDCLASS wndcls; //窗口类申明变量wndcls wndcls.style = CS_HREDRAW | CS_VREDRAW; //指定窗口类的类型:CS_HREDRAW(水平重画)、CS_VREDRAW(垂直重画)以达到窗口拉伸效果 wndcls.lpfnWndProc = WinSunProc; //将窗口过程函数赋值给lpfnWndProc,让操作系统来调用窗口过程函数,而不用我们自己调用 wndcls.cbClsExtra = 0; //给窗口设定额外的字节,通常情况下设定为0 wndcls.cbWndExtra = 0; //给窗口设定附加内存,通常情况下设定为0 wndcls.hInstance = hInstance; //操作系统通过WinMain函数的形参hInstance,将窗口实例号赋值给它 wndcls.hIcon = LoadIcon(NULL,IDI_APPLICATION); //图标的句柄(窗口左上角的图标),例:IDI_APPLICATION是一个标准的应用图标 wndcls.hCursor = LoadCursor(NULL,IDC_ARROW); //光标的句柄(鼠标),例:IDC_ARROW是一个标准箭头光标 wndcls.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); //画刷的句柄,例:WHITE_BRUSH设定了白色的背景图 wndcls.lpszMenuName = NULL; //设定菜单的名字,本程序无菜单,所以设定为空 wndcls.lpszClassName = "Zcj2020"; //给窗口类设定名称
- 注册窗口类
1
2RegisterClass(&wndcls); //向操作系统注册窗口类
- 创建窗口
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16HWND hwnd; //定义一个窗口句柄(标识) hwnd = CreateWindow("Zcj2020","重庆交通大学",WS_OVERLAPPEDWINDOW, 0,10,600,400,NULL,NULL,hInstance,NULL); //CreateWindow函数参数解析(顺序不可变): //"Zcj2020":窗口类名(基于注册后的窗口类名) //"重庆交通大学":窗口标题栏的名称 //WS_OVERLAPPEDWINDOW:窗口的类型 //0:窗口初始位置的横坐标 //10:窗口初始位置的纵坐标 //600:窗口初始化后的宽 //400:窗口初始化后的高 //NULL:指定父窗口的句柄,本程序只有一个窗口,所以设定为NULL //NULL:菜单的句柄,本程序无菜单,所以设定为NULL //hInstance:实例号 //NULL:WM_CREATE消息的附加参数指针,本程序用不上,所以设定为NULL
- 显示及更新窗口
1
2
3ShowWindow(hwnd,SW_SHOWNORMAL); //SW_SHOWNORMAL指的窗口初始正常显示,此外还有最大化、最小化显示,这里不做赘述 UpdateWindow(hwnd); //更新窗口
- 消息循环体
GetMessage()函数从消息队列中取出消息
1
2
3
4
5
6
7
8MSG msg; while(GetMessage(&msg,NULL,0,0)) { TranslateMessage(&msg); //转换(翻译)消息并压入消息队列中 DispatchMessage(&msg); //将消息路由给操作系统,操作系统再调用窗口过程函数 } return 0;
3.3 窗口过程函数
函数申明及参数
程序作出反应的函数,共4个参数。
1
2
3
4
5
6
7
8//格式一定,参数类型不能更改,函数名、参数名可更改 LRESULT CALLBACK WinSunProc( HWND hwnd, //窗口的句柄 UINT uMsg, //消息的标识 WPARAM wParam, //附加参数 LPARAM lParam //附加参数 )
(注:格式一定,可直接引用)
函数体
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37{ switch(uMsg) { case WM_CHAR: //用户按下键盘上的某个按键,并弹窗提示 char szChar[20]; sprintf(szChar,"char is %d",wParam); MessageBox(hwnd,szChar,"提示",MB_OK); break; case WM_LBUTTONDOWN: //用户按下鼠标左键,弹窗提示并打印在窗口内 MessageBox(hwnd,"mouse clicked","提示",MB_OK); HDC hdc; hdc = GetDC(hwnd); TextOut(hdc,0,50,"计算机左键已按下",strlen("计算机左键已按下")); //0和50是基于窗口而打印的位置 ReleaseDC(hwnd,hdc); //若不释放,则会造成内存泄露! break; case WM_PAINT: //窗口重绘(窗口水平、竖直发生变化时都会发生窗口重绘) HDC hDC; PAINTSTRUCT ps; hDC = BeginPaint(hwnd,&ps); TextOut(hDC,0,0,"窗口重绘",strlen("窗口重绘")); //打印文本 EndPaint(hwnd,&ps); //注意及时结束重绘! break; case WM_CLOSE: //点击关闭按钮时,做出反应 if(IDYES == MessageBox(hwnd,"是否真的结束?","提示",MB_YESNO)) { DestroyWindow(hwnd); //销毁窗口 } break; case WM_DESTROY: //窗口销毁时,接收到销毁消息 PostQuitMessage(0); //结束程序 break; default: return DefWindowProc(hwnd,uMsg,wParam,lParam); //对不感兴趣的消息进行缺省处理(注:该部分不可以删除,否则窗口不能正常显示) } return 0; }
4. 运行结果截图
最后直接贴上完整的代码。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90#include <windows.h> #include <stdio.h> LRESULT CALLBACK WinSunProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ); int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { WNDCLASS wndcls; wndcls.style = CS_HREDRAW | CS_VREDRAW; wndcls.lpfnWndProc = WinSunProc; wndcls.cbClsExtra = 0; wndcls.cbWndExtra = 0; wndcls.hInstance = hInstance; wndcls.hIcon = LoadIcon(NULL,IDI_APPLICATION); wndcls.hCursor = LoadCursor(NULL,IDC_ARROW); wndcls.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wndcls.lpszMenuName = NULL; wndcls.lpszClassName = "Zcj2020"; RegisterClass(&wndcls); HWND hwnd; hwnd = CreateWindow("Zcj2020","重庆交通大学",WS_OVERLAPPEDWINDOW, 0,10,600,400,NULL,NULL,hInstance,NULL); ShowWindow(hwnd,SW_SHOWNORMAL); UpdateWindow(hwnd); MSG msg; while(GetMessage(&msg,NULL,0,0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return 0; } LRESULT CALLBACK WinSunProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { switch(uMsg) { case WM_CHAR: char szChar[20]; sprintf(szChar,"char is %d",wParam); MessageBox(hwnd,szChar,"提示",MB_OK); break; case WM_LBUTTONDOWN: MessageBox(hwnd,"mouse clicked","提示",MB_OK); HDC hdc; hdc = GetDC(hwnd); TextOut(hdc,0,50,"计算机左键已按下",strlen("计算机左键已按下")); ReleaseDC(hwnd,hdc); break; case WM_PAINT: HDC hDC; PAINTSTRUCT ps; hDC = BeginPaint(hwnd,&ps); TextOut(hDC,0,0,"窗口重绘",strlen("窗口重绘")); EndPaint(hwnd,&ps); break; case WM_CLOSE: if(IDYES == MessageBox(hwnd,"是否真的结束?","提示",MB_YESNO)) { DestroyWindow(hwnd); } break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hwnd,uMsg,wParam,lParam); } return 0; }
程序运行开始
按下键盘的字母,显示出的数字是字母的ASCLL码
点击鼠标左键
结束程序
最后程序关闭。
5. 总结
第一次写博客,有什么不足可以赐教一下,如有帮到您的地方,不胜荣幸。
最后我推荐一本书——《深入浅出MFC_简体版》,里面第一章讲述的就是Windows API程序设计,以下是书的电子书链接地址。
链接:https://pan.baidu.com/s/1PIzRAuG0EKN6tAlyAY2LyQ
提取码:fjbo
最后
以上就是冷静高山最近收集整理的关于Windows API程序开发入门的全部内容,更多相关Windows内容请搜索靠谱客的其他文章。
发表评论 取消回复