打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
C 如何创建窗口程序?Windows API永不过时

https://m.toutiao.com/is/Btx2j4B/ 


什么是Windows API编程

  • 应用编程接口
  • Application Programming Interface

WinMain函数

当Windows操作系统启动一个程序时,它调用的就是该程序的WinMain函数( 实际是由插入到可执行文件中的启动代码调用的)。 WinMain是Windows程序的入口点函数,与DOS程序的入口点函数main的作用相同,当WinMain 函数结束或返回时,Windows应用程序结束。

int WINAPI WinMain( HINSTANCE hInstance, //应用程序实例 HINSTANCE hPrevInstance, //上一个应用程序实例 LPSTR lpCmdLine, //命令行参数 int nShowCmd //窗口显示的样式);
  • WINAPI:是一个宏,它代表的是__stdcall(注意是两个下划线),表示的是参数传递的顺序:从右往左入栈,同时在函数返回前自动清空堆栈。
  • hInstance:表示该程序当前运行的实例的句柄,这是一个数值。当程序在Windows下运行时,它唯一标识运行中的实例(注意,只有运行中的程序实例, 才有实例句柄)。一个应用程序可以运行多个实例,每运行一个实例,系统都会给该实例分配一个句柄值,并通过hInstance参数传递给 WinMain 函数。
  • hPrevInstance:表示当前实例的前一个实例的句柄。在Win32环境下,这个参数总是NULL,即在Win32环境下,这个参数不再起作用。
  • lpCmdLine:是一个以空终止的字符串, 指定传递给应用程序的命令行参数,相当于C或C++中的main函数中的参数char *argv[]
  • nShowCmd:表示一个窗口的显示,表示它是要最大化显示、最小化显示、正常大小显示还是隐藏显示。
#include <Windows.h>#include <cstdio>#pragma comment(linker, '/subsystem:\'console\' /entry:\'WinMainCRTStartup\'')int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR lpCmdLine, int nCmdShow) {    printf('%p %p %p\n', hInstance, hPrevInstance, GetModuleHandleA(NULL));    printf('%d %d\n', nCmdShow, SW_SHOWNORMAL);    printf('%s\n', lpCmdLine);    MessageBoxA(NULL, TEXT('第一个 Windows API 程序'), TEXT('黑猫编程'), MB_OK);    return 0;}

字符集

#include <Windows.h>#include <cstdio>#include <cstring>#include <clocale>int main() { const char* str1 = 'Abc中国'; printf('%s %d\n', str1, strlen(str1)); _wsetlocale(LC_ALL, L'chs'); const wchar_t* str2 = L'ABC中国文字'; wprintf(L'%s %d\n', str2, wcslen(str2)); MessageBoxW(NULL, TEXT('hello cat.'), L'coding', MB_OK); return 0;}

Windows 编程模型

一个完整的Win32程序(#include <windows.h>),该程序实现的功能是创建一个窗口,并在该窗口中响应键盘及鼠标消息,程序的实现步骤为:

  • WinMain函数的定义
  • 创建一个窗口
  • 进行消息循环
  • 编写窗口过程函数

项目创建

窗口程序模板代码

#include <Windows.h>// 自定义窗口过程回调函数LRESULT CALLBACK MyWindowProc(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam) {    switch (Msg) {    case WM_DESTROY:        PostQuitMessage(0);        return 0;    }    return DefWindowProcA(hwnd, Msg, wParam, lParam);}int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) {    // 注册窗口类    WNDCLASS wnd;    wnd.cbClsExtra = 0;    wnd.cbWndExtra = 0;    wnd.hbrBackground = (HBRUSH)(GetStockObject(WHITE_BRUSH));    wnd.hCursor = LoadIcon(NULL, IDC_ARROW);    wnd.hIcon = LoadIcon(NULL, IDI_APPLICATION);    wnd.lpfnWndProc = MyWindowProc;    wnd.lpszClassName = TEXT('blackcat');    wnd.lpszMenuName = NULL;    wnd.style = CS_HREDRAW;    wnd.hInstance = hInstance;    RegisterClassA(&wnd);    // 创建窗口 返回之前发送 VW_CREATE    HWND hwnd = CreateWindowA(        TEXT('blackcat'),        TEXT('黑猫编程'),        WS_OVERLAPPEDWINDOW,        100, 100, 300, 300, NULL, NULL, hInstance, NULL    );    // 显示窗口    ShowWindow(hwnd, nShowCmd);    // 更新窗口    UpdateWindow(hwnd);    // 消息循环 收到 VM_QUIT 退出    MSG msg;    while (GetMessageA(&msg, hwnd, 0, 0)) {        TranslateMessage(&msg);        DispatchMessageA(&msg);    }    return 0;}

线程和窗口

在WIN32中,消息队列是与线程(Thread)相关的,一个线程只能有一个消息队列(queue)与之相对应。当一个线程里面首次调用User32.dll或GDI32.dll中的函数时,系统会为该线程创建一个消息队列,否则就没有消息队列。

在一个线程中可以产生多个窗口,所以每个窗口课共用一个线程消息队列,所有产生给某个窗口的消息,都先由创建这个窗口的线程处理,窗口在任何线程中都可以创建,但消息循环必须要和创建窗口在同一线程,否则窗口将无法从DispatchMessage()获取任何消息,为了使窗口接受这些消息,线程必须有自己的循环。

消息分类

  • 标准消息:所有以WM_开头的消息,除了WM_COMMAND
  • 命令消息:来自菜单栏、工具栏、按钮或者快捷键的消息。WM_COMMAND
  • 通告消息:由控件产生的消息,例如按钮单击、列表项的选择等,为了向其父窗口通知事件的发生。

SendMessage和PostMessage

PostThreadMessage

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
一个exe可执行程序的生与死
孙鑫VC视频教程笔记之第一课“Windows程序的内部运行原理”
Win32编程基础知识_天空总是蓝色的
用Win32 application建立窗体_入门
VS2010/MFC编程入门之四(MFC应用程序框架分析)
day01
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服