一. Windows程序内部运行机制--Windows编程课程学习笔记
来源:互联网 发布:flothermal软件下载 编辑:程序博客网 时间:2024/05/22 17:41
1.1 API与SDK
操作系统把它所能够完成的功能以函数的形式提供给应用程序使用,应用程序对这些函数的调用就叫做系统调用,这些函数的集合就是Windows应用程序编程接口(Application ProgrammingInterface),简称Windows API。API大多是意义的单词的组合,其精确的拼写及调用语法可以在MSDN中查询。
SDK全称是Software Development Kit,软件开发包。实际是开发所需资源。
1.2窗口与句柄
利用窗口可以接受用户输入以及显示输入。通常包括标题栏、菜单栏、系统菜单、最小化框、最大化框、滚动条。可以分为客户区与非客户区。客户区用于显示与绘制。窗口可以有父窗口、子窗口。同时对话框、消息框也是窗口。
Windows应用程序中,句柄(HWND)来标识窗口。各种各样的资源系统创建时都会分配内存,并返回一个标识这些资源的标识号即句柄。
1.3消息与消息队列
1)消息
Windows程序设计是一种事件驱动方式的模式,主要基于消息。消息其实由一个结构体MSG表示。
MSG结构定义如下:
typedefstruct tagMSG { HWND hwnd; // 消息所属窗口 UINT message; // 消息的标识符 WPARAMwParam; // 附加消息 LPARAMlParam; // 附加消息 DWORD time; // 投递到消息队列的时间 POINT pt; // 鼠标当前坐标} MSG;
2)消息队列
应用程序开始执行后,系统都会为该程序创建一个消息队列,这个消息队列用来存放该程序创建的窗口的消息(消息通常与窗口相关)。消息队列等待应用程序响应,应用程序对事件作出反应的过程就是消息响应,各种消息响应放在一起组成了窗口过程。这种消息机制就是Windows程序运行的机制。
3)进队消息和不进队消息
进队消息由操作系统放入消息队列,应用程序取出并发送。不进队消息在系统调用窗口过程是直接发送给窗口。最终都由系统调用窗口过程函数对消息进行处理。
1.4 WinMain函数
完整的Win32程序步骤如下:
1)入口函数WinMain
2)创建窗口
3)消息循环与发送消息
4)窗口过程与消息响应
1)入口函数WinMain
intWINAPI WinMain( HINSTANCE hInstance, // 当前应用程序实例句炳 HINSTANCE hPrevInstance, //永远为NULL(当前句柄的前一个句柄) LPSTR lpCmdLine, // 命令行参数 int nCmdShow // 窗口显示时的状态);
2)创建窗口
Step1: 设计一个窗口类;
Step2: 注册窗口类;
Step3: 创建窗口;
Step4: 显示及更新窗口。
Step1. 设计窗口类
typedef struct _WNDCLASS { UINT style; //窗口类样式(CS_XXX) WNDPROC lpfnWndProc; //窗口过程函数指针(*) int cbClsExtra; //窗口类附加内存字节数,通常为0 int cbWndExtra; //窗口附加内存字节数,通常为0 HANDLE hInstance; //应用程序实例句柄 HICON hIcon; //标题栏图标(IDI_XXX, NULL) HCURSOR hCursor; //光标 HBRUSH hbrBackground; //窗口背景颜色 LPCTSTR lpszMenuName; //菜单资源名称 LPCTSTR lpszClassName; //窗口类名称} WNDCLASS;
About lpfnWndProc.指向窗口过程函数(回调函数:特定事件或条件发生受另一方调用)。窗口过程函数被调用过程如下:(1)设计窗口类时,地址复制给lpfnWndProc;(2)调用RegisterClass(&wndclass),系统有了窗口过程函数地址;(3)应用程序接收一个消息时,调用DispatchMessage(&msg)将消息回传给系统。系统利用指针,调用窗口过程函数处理。
About hIcon. 可以调用LoadIcon加载一个图标资源。HICON LOADICON( HINSTANCE hInstance, LPCTSTR lpIconName),加载标准图标第一个参数NULL,也可以加载自定义图标。
About hCursor. 可以调用LoadCursor加载一个光标。同LoadIcon。
About hbrBackground. 调用GetStockObject得到系统标准画刷。
详见MSDN。
Step2. 注册
ATOMRegisterClass(CONST WNDCLASS *lpWndClass)
Step3. 创建
HWND CreateWindow( LPCTSTRlpClassName, // 已注册的窗口类名称 LPCTSTRlpWindowName, // 窗口标题栏中显示的文本 DWORDdwStyle, //窗口样式(WS_XXX | WS_XXX) intx, // 水平坐标 inty, // 垂直坐标 intnWidth, // 宽度 intnHeight, //高度 HWNDhWndParent, //父窗口句柄 HMENUhMenu, //菜单句柄 HINSTANCEhInstance, // 应用程序实例句柄 LPVOIDlpParam // 用于多文档程序的附加参数,单文档为NULL );
Step4. 显示与更新
BOOL ShowWindow(HWNDhWnd, int nCmdShow) // nCmdShow(SW_XXX)BOOL UpdataWindow(HWND hWnd);
3)消息循环与发送消息
MSG msg; while (GetMessage(&msg,NULL,0,0)) // 从消息队列获取消息 { TranslateMessage(&msg); //消息解释 DispatchMessage(&msg); //将消息发送到“窗口过程” }
TranslateMessage函数用于将虚拟键消息转换为字符消息。将WM_KEYDOWN和WM_KEYUP消息的组合转换为一条WM_CHAR消息,该消息的WParam附加参数包含了字符的ASCII码。并将转换后的新消息投递到调用线程的消息队列中。注意,Translate函数并不会修改原有的信息,他只是产生新的消息并投递到消息队列中。
DispatchMessage分派一个消息到窗口过程。由窗口过程函数对消息进行处理。DispatchMessage实际上是将消息回传给操作系统,再由操作系统调用窗口过程函数对消息进行处理。
BOOL GetMessage( LPMSGlpMsg, // 消息结构体指针,返回消息信息 HWND hWnd, //窗口句柄 ,通常设为NULL UINT wMsgFilterMin, //消息过滤最小值 UINT wMsgFilterMax //消息过滤最大值 );
WM_QUIT返回0,错误返回-1。
4)窗口过程与消息响应
LRESULT CALLBACK MyWndProc( HWNDhwnd, // handle to window UINTuMsg, // message identifier WPARAMwParam, //first message parameter LPARAMlParam // second message parameter){ switch(uMsg) { case WM_PAINT: //响应消息 caseWM_KEYDOWN: //响应消息 caseWM_LBUTTONDOWN: //响应消息 … default: returnDefWindowProc(hwnd,uMsg,wParam,lParam); } return0;}
About WM_PAINT. Windows 把一个最小的需要重绘的正方形区域叫做“无效区域”。发现了一个“无效区域“后,它就会向该应用程序发送一个 WM_PAINT 消息,通知应用程序重新绘制窗口。当窗口从无到有、改变尺寸、最小化后再恢复、被其他窗口遮盖后再显示时,窗口的客户区都将变为无效。
About DefWindowProc. 不感兴趣的、不需要我们处理的消息,交还给Windows操作系统由DefWindowProc函数来实现。在销毁窗口后,发送WM_DESTROY(响应方式就是调用PostQuitMessage函数,该函数会在消息队列中添加一个WM_QUIT消息,准备让由消息循环中的GetMessage取得)
1.5 测试程序
VS2015下面测试一下程序。新建Win32 项目,编写代码后调试,发现一堆error2664,解决方法是项目属性,字符集更改为使用多字节字符型。之后出现链接错误,解决方法是添加附加依赖项。
#pragma comment (lib,"User32.lib")#pragma comment(lib, "gdi32.lib")
程序运行界面
#pragma warning (disable:4996)#pragma comment (lib,"User32.lib")#pragma comment(lib, "gdi32.lib")#include <Windows.h>#include <stdio.h> LRESULT CALLBACK MyWinProc( HWND hwnd, //handle to window UINT uMsg, //message identifier WPARAM wParam, //first message parameter LPARAM lParam //second message parameter ); int WINAPI WinMain( HINSTANCE hInstance, // 当前应用程序实例句炳 HINSTANCE hPrevInstance, // 永远为NULL(当前句柄的前一个句柄) LPSTR lpCmdLine, // 命令行参数 int nCmdShow // 窗口显示时的状态 ){ //Step1. 设计窗口类 WNDCLASS wndcls; wndcls.cbClsExtra = 0; wndcls.cbWndExtra = 0; wndcls.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wndcls.hCursor = LoadCursor(NULL, IDC_ARROW); wndcls.hIcon = LoadIcon(NULL, IDI_QUESTION); wndcls.hInstance = hInstance; wndcls.lpfnWndProc = MyWinProc; wndcls.lpszClassName = ("WindowsTest"); wndcls.lpszMenuName = NULL; wndcls.style = CS_HREDRAW | CS_VREDRAW; //Step2. 注册窗口类 RegisterClass(&wndcls); //Step3. 创建窗口类 HWND hwnd; hwnd = CreateWindow("WindowsTest", "MyFirst Windows App", WS_OVERLAPPEDWINDOW, 0, 0, 600, 400, NULL, NULL, hInstance, NULL); //Step4. 显示及刷新窗口 ShowWindow(hwnd, SW_SHOWNORMAL); UpdateWindow(hwnd); // 定义结构体,开始消息循环 MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam;} LRESULT CALLBACK MyWinProc( HWND hwnd, //handle to window UINT uMsg, // message identifier WPARAM wParam, // first message parameter LPARAM lParam //second message parameter ){ switch (uMsg) { case WM_CHAR: charszChar[20]; sprintf(szChar, "char code is %d", wParam); MessageBox(hwnd,szChar, "char", 0); break; case WM_PAINT: HDChDC; PAINTSTRUCT ps; hDC = BeginPaint(hwnd, &ps); TextOut(hDC,0, 0, "HelloWorld!", strlen("Hello World!")); EndPaint(hwnd,&ps); break; case WM_LBUTTONDOWN: MessageBox(hwnd, "mouse clicked", "message", 0); HDChdc; hdc = GetDC(hwnd); TextOut(hdc,0, 50, "HelloWin32!", strlen("Hello Win32!")); ReleaseDC(hwnd,hdc); break; case WM_DESTROY: PostQuitMessage(0); break; case WM_CLOSE: if (IDYES == MessageBox(hwnd, "是否真的结束?", "message", MB_YESNO)) { DestroyWindow(hwnd); } break; default: return DefWindowProc(hwnd, uMsg, wParam, lParam); } return 0;}
- 一. Windows程序内部运行机制--Windows编程课程学习笔记
- 一.Windows程序内部运行机制
- Windows程序内部运行机制笔记
- Windows程序内部运行机制学习
- 孙鑫-MFC笔记一--Windows程序内部运行机制
- 《VC++深入详解》学习笔记 第一章 Windows程序内部运行机制
- VC++深入详解学习笔记之Windows程序内部运行机制
- vc学习笔记之windows程序内部运行机制
- Windows程序内部运行机制
- Windows程序内部运行机制
- Windows程序内部运行机制
- Windows程序内部运行机制
- WINDOWS程序内部运行机制
- Windows程序内部运行机制
- Windows程序内部运行机制
- Windows程序内部运行机制
- windows程序内部运行机制
- Windows 程序内部运行机制
- -source 1.5 中不支持 diamond 运算符
- 技术小黑屋
- CSS Display(显示) 与 Visibility(可见性)
- 关于idea中怎么选择maven项目的profiles
- 广东海洋大学 电子1151 孔yanfei python语言程序设计 第四周
- 一. Windows程序内部运行机制--Windows编程课程学习笔记
- Openstack liberty 创建实例快照源码分析1
- Java Bean、POJO、 Entity、 VO 、PO、DAO
- 关于android Error:Execution failed for task ':app:transformClassesWithJarMergingForDebug'. > com.的解决方法
- Espresso 测试SwipeRefreshLayout 组件,下拉问题记录
- SVN e155004 locked
- java.net.SocketException: Unrecognized Windows Sockets error: 0: JVM_Bind
- 大数据的仓库Hive学习(一)
- 笔记︱金融风险控制基础常识——巴塞尔协议+信用评分卡Fico信用分