C语言:WindowsAPI个人学习笔记(一)
一、在C语言中,为了使用windowsAPI,需要在源文件开头写上:
#include <windows.h>二、每一个windows窗口的调用都必须有 LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 窗口过程函数和 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) 入口点函数:
三、窗口过程函数是windows编程中的核心概念之一。它是windows操作系统用来与窗口交互的函数,处理发送到窗口的消息。每个窗口都有一个且唯一的窗口过程函数,当窗口接收到消息时,系统会调用这个函数来处理消息。
四、入口点函数 WinMain 是windows应用程序的入口点,它负责初始化应用程序、创建窗口、进入消息循环等。在windows编程中,WinMain 函数是程序的启动点,它接收启动参数,并负责设置应用程序的环境。
五、消息循环是windows编程中的一个核心概念,它负责处理应用程序中的消息。消息是windows操作系统传递给应用程序的通信机制,用于通知应用程序发生了某些事件,如用户输入、窗口状态变化等。
六、消息循环的几个步骤:
1.消息获取:应用程序需要从消息队列中获取消息。这通常是通过调用 GetMessage 函数来实现的。【消息队列是windows操作系统中的一个机制,用于处理应用程序之间的通信。它是一个先进先出(FIFO)的数据结构,用于存储各种消息,这些消息在应用程序之间传递,以通知发生了某些事件或操作。】
2.消息解析:应用程序需要解析消息,确定消息的类型和内容。这通常是通过检查消息的 uMsg 字段来实现的。【消息解析不是解密过程,而是将消息的格式和内容转换为应用程序可以理解和操作的形式。】
3.消息分发:应用程序需要将消息分发给适当的窗口过程函数来处理。这通常是通过调用 TranslateMessage 和 DispatchMessage 函数来实现的。【TranslateMessage 函数负责将虚拟键码转换为物理键码。它通常用于处理键盘消息,因为键盘消息包含虚拟键码,而物理键码与实际的物理按键相关联。 DispatchMessage 函数负责将消息分发给相应的窗口过程函数(WndProc)进行处理。这个函数会检查消息队列中是否有消息,如果有,它会从队列中取出消息,并将其传递给窗口过程函数。】
TranslateMessage函数的声明如下:
BOOL TranslateMessage(const MSG *lpMsg);DispatchMessage函数的声明如下:
LRESULT DispatchMessage(const MSG *lpMsg);4.窗口过程函数处理:窗口过程函数负责处理接收到的消息。它根据消息的类型执行相应的操作,如更新界面、响应用户输入等。【窗口过程函数(WndProc)的具体处理逻辑完全由程序员设定。每个窗口过程函数都需要根据接收到的消息类型来执行相应的操作。 窗口过程函数需要返回一个 LRESULT 值。对于大多数消息,返回 0 表示消息已经被处理,而返回 DefWindowProc 的返回值表示消息没有被处理,应该由操作系统继续处理。】
5.无限循环:应用程序需要重复上述步骤,以处理所有传入的消息。这通常是通过一个无限循环来实现的,直到应用程序接收到退出消息为止。
七:在windows编程中,DefWindowProc 是一个宏,它定义了默认的窗口过程函数。当窗口过程函数没有处理一个消息时,通常会返回 DefWindowProc 的返回值,这告诉操作系统消息没有被处理,应该由操作系统继续处理。
DefWindowProc 对于一些常见消息的返回值:
1.对于 WM_COMMAND 消息,DefWindowProc 通常返回命令ID,这意味着它已经处理了消息。
2.对于 WM_PAINT 消息,DefWindowProc 通常调用系统提供的默认绘制函数,因此它返回 0。
3.对于其他消息,DefWindowProc 通常返回 0,表示它处理了消息。
4.当DefWindowProc没有处理某个特定的消息时,它会返回1,表示消息没有被处理。这种情况通常发生在消息是自定义消息或者是DefWindowProc不认识的消息时。
【这里为了避免混淆作出澄清:WndProc的具体处理逻辑是完全由程序序员设定的,而当WndProc没有编写相应消息类型的处理逻辑时,当然消息就无法被 WndProc 进行处理,于是将消息转移至DefWindowProc,因为DefWindowProc定义了默认的窗口过程函数,所以让DefWindowProc对消息进行处理。DefWindowProc 执行的操作是操作系统定义的默认行为,这些行为是针对每种消息类型预定义的。所以DefWindowProc 处理消息通常被视为由操作系统处理的。】
还是看代码吧,一看便知:
八:以下是一些常见的消息类型及其符号:
1.窗口创建和销毁消息:
WM_CREATE:窗口创建时发送。
WM_DESTROY:窗口销毁时发送。
2.键盘和鼠标消息:
WM_KEYDOWN、WM_KEYUP:与键盘按键相关。
WM_LBUTTONDOWN、WM_LBUTTONUP、WM_RBUTTONDOWN、 WM_RBUTTONUP:与鼠标按钮相关。
WM_MOUSEMOVE:鼠标移动时发送。
WM_MOUSEWHEEL:鼠标滚轮滚动时发送。
3.绘图消息:
WM_PAINT:窗口需要重绘时发送。
WM_ERASEBKGND:背景需要清除时发送。
4.用户输入消息:
WM_CHAR、WM_DEADCHAR:与键盘字符输入相关。
WM_SYSKEYDOWN、WM_SYSKEYUP:与系统键盘按键相关。
WM_MENUCHAR:菜单需要字符输入时发送。
5.窗口状态消息:
WM_GETMINMAXINFO:获取窗口最小化/最大化信息时发送。
WM_GETICON:获取窗口图标时发送。
WM_SETICON:设置窗口图标时发送。
6.用户界面消息:
WM_SETTEXT:设置窗口标题时发送。
WM_GETTEXT、WM_GETTEXTLENGTH:获取窗口标题时发送。
WM_COMMAND:命令消息,与菜单项、按钮等控件相关。
WM_NOTIFY:与控件通知消息相关。
7.其他消息:
WM_TIMER:定时器消息。
九、关于消息队列:
1.消息类型:消息可以是多种类型,包括但不限于键盘和鼠标事件、窗口状态变化、用户界面交互等。
2.消息处理:当一个线程接收到消息时,它会从消息队列中取出消息,并将其传递给相应的窗口过程函数(WndProc)进行处理。
3.消息队列的访问:应用程序可以通过调用 GetMessage 函数来从消息队列中获取消息。当应用程序处理完消息后,可以通过调用 PeekMessage 函数来检查是否有新消息到达,或者通过调用 PostMessage 函数将新消息发送到消息队列。
4.消息队列的关闭:当应用程序接收到退出消息或完成所有消息处理后,它可以通过调用 PostQuitMessage 函数来关闭消息队列。【PostQuitMessage 是一个 windows API 函数,用于在程序的主消息循环中终止消息处理,并启动程序退出过程。当调用 PostQuitMessage 时,它会将一个 WM_QUIT 消息放入线程的消息队列中。这个消息不直接发送给任何窗口,而是由消息循环(通常是在 GetMessage 或 PeekMessage 函数中)检索。】
5.线程独立:每个线程都有自己的消息队列,这使得不同的线程可以独立地处理自己的消息,而不会干扰其他线程。【一个线程可以创建多个窗口,每个窗口都有自己独立的队列。】
十、通常WinMain 函数执行了以下步骤来设置应用程序的环境:
1.初始化应用程序:这个步骤可以包括处理命令行参数、初始化全局变量等。
2.注册窗口类:使用WNDCLASSEX结构来定义窗口类,包括窗口过程函数、实例句柄、窗口风格、光标、背景刷和窗口类名称。然后调用RegisterClassEx函数来注册窗口类。【windows使用窗口句柄(HWND)来标识窗口。】
以下是 WNDCLASSEX 结构的完整定义:
(学习windowsAPI的学生是这样的,windows开发人员只需要专心致志,奋力开发windows系统就可以了,而看沟槽的缩写的学生要考虑的就很多了 )
【在早期的 windows 开发中,匈牙利命名法非常流行,这种命名法由 Microsoft 的查尔斯·西蒙尼(Charles Simonyi)推广。匈牙利命名法通过在变量名前加上一个或多个前缀来指示变量的类型和用途。例如,lpfnWndProc 中的 lpfn 表示这是一个指向函数(fn)的长指针(lp),而 hInstance 中的 h 表示这是一个句柄。一个整型变量用来表示数量,可以命名为 nCount;一个字符型指针变量用来指向字符串,可以命名为 pszName。】
在注册窗口类时,WNDCLASSEX 结构的某些成员是必须定义的,而其他成员则可以根据需要进行定义或忽略。以下是你必须填充的成员:
cbSize:必须设置为 WNDCLASSEX 结构的大小,即 sizeof(WNDCLASSEX)。
style:必须设置窗口类的样式,通常至少包括 CS_HREDRAW 和 CS_VREDRAW。
lpfnWndProc:必须设置指向窗口过程函数的指针。
lpszClassName:必须设置窗口类的名称。
其他成员可以根据你的需求进行设置,如果不需要特殊处理,可以忽略或设置为默认值:
cbClsExtra 和 cbWndExtra:如果你不需要额外的类或窗口数据,可以设置为0。
hIcon、hCursor 和 hbrBackground:如果你不需要自定义图标、光标或背景,可以设置为默认值或 NULL。
lpszMenuName:如果你不需要菜单,可以设置为 NULL。
hIconSm:如果你不需要小图标,可以设置为 NULL。
3.创建窗口:调用CreateWindowEx函数来创建窗口,指定窗口类名称、窗口标题、窗口风格、位置和大小等参数。
以下是 CreateWindowEx 函数的原型:
有关参数:
dwExStyle:如果不使用任何扩展窗口样式,可以设置为 0。
lpClassName:必须指定的参数,因为它确定了窗口类的类型,该类必须已经通 过 RegisterClassEx 注册。
lpWindowName:如果不设置窗口标题,可以传递 NULL 或空字符串。
dwStyle:这是必须指定的参数,因为它确定了窗口的基本样式。至少需要包括 WS_OVERLAPPEDWINDOW 或 WS_POPUP 之一。
x 和 y:如果设置为 CW_USEDEFAULT,系统会根据窗口的样式和屏幕分辨率选择默认位置。
nWidth 和 nHeight:如果设置为 CW_USEDEFAULT,系统会根据窗口的样式选择默认大小。
hWndParent:对于顶级窗口,可以设置为 NULL。对于子窗口,必须指定父窗口的句柄。
hMenu:如果没有菜单,可以设置为 NULL。
hInstance:这是必须指定的参数,通常是 WinMain 函数的 hInstance 参数。
lpParam:如果不使用窗口创建参数,可以设置为 NULL。
4.显示窗口:调用ShowWindow函数来根据nCmdShow参数显示或隐藏窗口。
5.开始消息循环:使用GetMessage、TranslateMessage和DispatchMessage函数来处理窗口消息。
6.清理资源并退出:当GetMessage返回0时,消息循环结束,WinMain函数返回msg.wParam,通常是PostQuitMessage传递的退出代码。
(哥们学累了浅浅放张图休息休息)
Ongwu博客 版权声明:以上内容未经允许不得转载!授权事宜或对内容有异议或投诉,请联系站长,将尽快回复您,谢谢合作!