• win32概述及框架


    系列文章目录


    在这里插入图片描述


    前言

    在互联网发展迅速的今天,计算机已经深入到每个人的生活中,windows系统也成了用户最多的系统,对于程序员而言,windows编程也是非常重要的内容,对于软件开发的用户而言,更是必须要学习的。


    一、windows编程概述

    Windows是一个具有可视化图形用户界面的多任务操作系统,它为用户提供了风格统一的由窗口,菜单,工具栏等界面元素所构成的多任务环境。
    可以把windows看成一个软件,对其进行编程就是去调用其接口去实现功能。一个软件由两部分组成,一个是逻辑,一个是绘制。
    窗口是Windows编程实现的基础,大多数Windows程序都是以窗口的方式运行的,Windows程序设计是一种事件驱动方式的程序设计模式,主要是基于消息机制。当用户或对应的程序(窗口)的某种操作会调用操作系统中的某种支持,操作系统会将用户的操作包装成消息,并发送到一个应用程序可以访问的消息队列中,最后应用程序从消息队列中取走消息,并进行响应。

    二.Windows操作系统的特点

    1.直观,高效,统一的面向对象的图形用户界面,易学易用。
    2.丰富的设备无关的图形操作。
    3.多任务多进程
    各个应用程序共享系统提供的资源。

    三.资源使用的步骤

    1.向windows系统请示资源。
    2.使用该资源
    3.释放资源给windows以供别的程序使用。

    四.windows程序模块

    1.控制台应用程序
    2.窗口应用程序
    3.动态库
    4.静态库
    win32的学习主要为“窗口应用程序”模块。

    五.win32数据类型

    windows是基于c/c++,然后发展出自己特有的数据类型,在c/c++的基础上作出类型重定义。
    1.去区别c/c++语言。
    2.见名思义
    3.封装信息

    特性

    1.大写H开头,在win32里面叫句柄。
    2.P,LP开头,在win32里面表示指针
    3.windows数据类型全是大写(和c++中的类型意思基本一样,除了BOOL型,返回数据为数字,不再为布尔类型数据)。

    win32应用程序入口函数

    1.需要导入windows头文件
    2.入口函数是winmain

    int WINAPI winmain(HINSTANCE hinstance,    //应用程序实例句柄
    HINSTANCE hPrevInstance ,  //父应用程序实例句柄
    LPSTR lpCmdLine,   //命令行参数
    int nShowCmd        //窗口显示方式;
    )
    
    • 1
    • 2
    • 3
    • 4
    • 5

    注册窗口类

    ATOM MyRegisterClass(HINSTANCE hInstance)
    {
        WNDCLASSEXW wcex; //表示一个窗口类型的结构体变量;
    
        wcex.cbSize = sizeof(WNDCLASSEX);  //表示的是自身这个类型的大小;
    
        wcex.style          = CS_HREDRAW | CS_VREDRAW;  //风格;
        wcex.lpfnWndProc    = WndProc; //**非常重要(窗口消息处理函数)
        wcex.cbClsExtra     = 0;   //类的额外信息;
        wcex.cbWndExtra     = 0;   //窗口的额外信息;
        wcex.hInstance      = hInstance; //当前实例句柄;
        wcex.hIcon          = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WINDOWSPROJECT2)); //图标,菜单栏图标;
        wcex.hCursor        = LoadCursor(0, nullptr); //光标;
        wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);  // 背景,一般不需要改变;
        wcex.lpszMenuName   = MAKEINTRESOURCEW(IDC_WINDOWSPROJECT2); // 菜单;
        wcex.lpszClassName  = szWindowClass;  // 窗口类名;
        wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));  //图标,窗口左上角的图标;
    
        return RegisterClassExW(&wcex);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    创建窗口

    BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
    {
       hInst = hInstance; // 将实例句柄存储在全局变量中
    
       HWND hWnd = CreateWindowW(szWindowClass,  //窗口类名,注意,必须是已经注册的窗口类名;
           szTitle, //窗口标题名;
           WS_OVERLAPPEDWINDOW| WS_VSCROLL, // 窗口风格;
    
          CW_USEDEFAULT,   //窗口的坐标x
           0,  // 窗口的y坐标
           CW_USEDEFAULT, //窗口的宽度
           0, //窗口的高度
           nullptr,  //父窗口菜单句柄
           nullptr, // 窗口菜单句柄
           hInstance, //当前实例句柄
           nullptr); // 保留参数;
    
       if (!hWnd)
       {
          return FALSE;
       }
    
       ShowWindow(hWnd, nCmdShow);
       UpdateWindow(hWnd);
    
       return TRUE;
    }
    
    • 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

    显示&更新窗口

    ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd);

    消息结构体

    typedef struct tagMSG {
        HWND        hwnd;
        UINT        message;
        WPARAM      wParam;
        LPARAM      lParam;
        DWORD       time;
        POINT       pt;
    #ifdef _MAC
        DWORD       lPrivate;
    #endif
    } MSG, *PMSG, NEAR *NPMSG, FAR *LPMSG;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    消息循环

    //主消息循环
     while (GetMessage(&msg, nullptr, 0, 0))
        {
            if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
            {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    六、win32框架流程

    1.入口函数
    2.窗口注册函数
    3.窗口创建函数
    4.窗口显示
    5.窗口更新
    6.消息循环
    7.入口函数返回

    窗口消息处理函数

    CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)

    默认窗口消息处理函数

    DefWindowProc(hWnd, message, wParam, lParam)

    字符集

    在计算机中字符通常并不是保存为图像,每个字符都是用一个编码来表示。二两个字符究竟用哪个编码表示,取决于使用哪个字符集(charset)。
    字符编码:
    ascii,gb_2312
    win32经常使用:多字节字符集,宽字节字符集。
    字符集示例:
    char c='a'; //多字节字符的存储; char *pc="ab中cd"; //多字节字符集的存储; strlen(pc); wchar_t wc='a';// 宽字节字符的存储; wchar_t *pwc="L abc 中cd“; //宽字节字符集的存储; wcslen(pwc);

    TCHAR通配符

    TCHAR tc='a';  //会受到字符集的影响,如果是多字节tchar=char,如果是宽字节,tchar=wchar_t;
    TCHAR *ptc=&tc;
    ptc=_T("abd");  //通配符字符集的字符串赋值_T()通配符 带参宏 字符串的拼接;
    _tcslen(ptc);
    
    • 1
    • 2
    • 3
    • 4

    字符集的选择

    1.自行设定用固定的类型去表现字符或字符串,char或wchar_t;
    2.统一使用字符的通配符(_tcslen()),不管是什么字节,都可以计算。
    3.win32函数中如果在后缀上有大写的A或W,那么A对应多字节,W对应宽字节,通常情况下也会有一个设有后缀为A或W的同名函数,根据字符不同的设定来通配。

    七.代码示例(轰炸消息)

    1.创建项目

    写win32项目的时候,创建项目不再是创建空项目,而是选择win32桌面应用程序;
    在这里插入图片描述

    2.代码

    我们在创建好项目的时候,程序本身就包含了win32框架;所以在使用的时候就只需要在原程序中写就可。

    // WindowsProject2.cpp : 定义应用程序的入口点。
    //
    
    /*
    1.入口函数;
    2.窗口注册函数
    3.窗口创建函数
    4.显示窗口
    5.更新窗口
    6.主消息循环
    7.入口函数返回;
    */
    
    #include "framework.h"
    #include "WindowsProject2.h"
    
    #define MAX_LOADSTRING 100
    
    // 全局变量:
    HINSTANCE hInst;                                // 当前实例
    WCHAR szTitle[MAX_LOADSTRING];                  // 标题栏文本
    WCHAR szWindowClass[MAX_LOADSTRING];            // 主窗口类名
    
    // 此代码模块中包含的函数的前向声明:
    ATOM                MyRegisterClass(HINSTANCE hInstance);
    BOOL                InitInstance(HINSTANCE, int);
    LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
    INT_PTR CALLBACK    About(HWND, UINT, WPARAM, LPARAM);
    
    int APIENTRY wWinMain(_In_ HINSTANCE hInstance,      //入口函数;
                         _In_opt_ HINSTANCE hPrevInstance,
                         _In_ LPWSTR    lpCmdLine,
                         _In_ int       nCmdShow)
    {
        UNREFERENCED_PARAMETER(hPrevInstance);
        UNREFERENCED_PARAMETER(lpCmdLine);
       
        
    
    
        // TODO: 在此处放置代码。
    
        // 初始化全局字符串
        LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
        LoadStringW(hInstance, IDC_WINDOWSPROJECT2, szWindowClass, MAX_LOADSTRING);
        MyRegisterClass(hInstance);
    
        // 执行应用程序初始化:
        if (!InitInstance (hInstance, nCmdShow))
        {
            return FALSE;
        }
    
        HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_WINDOWSPROJECT2));
    
        MSG msg;
      /*  //窗口示例,如果需要就可以去掉;  
      if (MessageBox(0, _T("你是否要选择轰炸"), _T("提示"), MB_ABORTRETRYIGNORE) == IDABORT)
        {
            MessageBoxW(0, _T("对你要轰炸的对象操作"), _T("选择按钮"), 0);
        }*/
            //自己添加的消息提示
        // 主消息循环:
        while (GetMessage(&msg, nullptr, 0, 0))
        {
            if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
            {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }
        }
    
        return (int) msg.wParam;
    }
    
    
    
    //
    //  函数: MyRegisterClass()
    //
    //  目标: 注册窗口类。
    //
    ATOM MyRegisterClass(HINSTANCE hInstance)
    {
        WNDCLASSEXW wcex; //表示一个窗口类型的结构体变量;
    
        wcex.cbSize = sizeof(WNDCLASSEX);  //表示的是自身这个类型的大小;
    
        wcex.style          = CS_HREDRAW | CS_VREDRAW;  //风格;
        wcex.lpfnWndProc    = WndProc; //**非常重要(窗口消息处理函数)
        wcex.cbClsExtra     = 0;   //类的额外信息;
        wcex.cbWndExtra     = 0;   //窗口的额外信息;
        wcex.hInstance      = hInstance; //当前实例句柄;
        wcex.hIcon          = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WINDOWSPROJECT2)); //图标,菜单栏图标;
        wcex.hCursor        = LoadCursor(0, nullptr); //光标;
        wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);  // 背景,一般不需要改变;
        wcex.lpszMenuName   = MAKEINTRESOURCEW(IDC_WINDOWSPROJECT2); // 菜单;
        wcex.lpszClassName  = szWindowClass;  // 窗口类名;
        wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));  //图标,窗口左上角的图标;
    
        return RegisterClassExW(&wcex);
    }
    
    //
    //   函数: InitInstance(HINSTANCE, int)
    //
    //   目标: 保存实例句柄并创建主窗口
    //
    //   注释:
    //
    //        在此函数中,我们在全局变量中保存实例句柄并
    //        创建和显示主程序窗口。
    //
    //创建窗口函数;
    BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
    {
       hInst = hInstance; // 将实例句柄存储在全局变量中
    
       HWND hWnd = CreateWindowW(szWindowClass,  //窗口类名,注意,必须是已经注册的窗口类名;
           szTitle, //窗口标题名;
           WS_OVERLAPPEDWINDOW| WS_VSCROLL, // 窗口风格;
    
          CW_USEDEFAULT,   //窗口的坐标x
           0,  // 窗口的y坐标
           CW_USEDEFAULT, //窗口的宽度
           0, //窗口的高度
           nullptr,  //父窗口菜单句柄
           nullptr, // 窗口菜单句柄
           hInstance, //当前实例句柄
           nullptr); // 保留参数;
    
       if (!hWnd)
       {
          return FALSE;
       }
    
       ShowWindow(hWnd, nCmdShow);
       UpdateWindow(hWnd);
    
       return TRUE;
    }
    
    //
    //  函数: WndProc(HWND, UINT, WPARAM, LPARAM)
    //
    //  目标: 处理主窗口的消息。
    //
    //  WM_COMMAND  - 处理应用程序菜单
    //  WM_PAINT    - 绘制主窗口
    //  WM_DESTROY  - 发送退出消息并返回
    //
    //
    LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        switch (message)
        {
        case WM_COMMAND:      //菜单命令;
            {
                int wmId = LOWORD(wParam);
                // 分析菜单选择:
                switch (wmId)
                {
                
                break;
                case ID_32774:
                {
                    int i = 0;
                    HWND hwnd = FindWindowA(0, "轰炸窗口的昵称");  //查找窗口;
                    for (i = 0; i < 10; i++)
                    {
                        SendMessage(hwnd, WM_PASTE, 0, 0);
                        SendMessage(hwnd, WM_KEYDOWN, VK_RETURN, 0);
                    }
                }
                case IDB_BITMAP1:
                    MessageBox(0, 0, 0, 0);
                    break;
                case IDM_ABOUT:
               
                    DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
                    break;
                case IDM_EXIT:
                    DestroyWindow(hWnd);
                    break;
                default:
                    return DefWindowProc(hWnd, message, wParam, lParam);  //消息默认处理函数;
                }
            }
            break;
        case WM_PAINT:
            {
                PAINTSTRUCT ps;
                HDC hdc = BeginPaint(hWnd, &ps);
                // TODO: 在此处添加使用 hdc 的任何绘图代码...
                EndPaint(hWnd, &ps);
            }
            break;
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
        }
        return 0;
    }
    
    // “关于”框的消息处理程序。
    INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
    {
        UNREFERENCED_PARAMETER(lParam);
        switch (message)
        {
        case WM_INITDIALOG:
            return (INT_PTR)TRUE;
    
        case WM_COMMAND:
            if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
            {
                EndDialog(hDlg, LOWORD(wParam));
                return (INT_PTR)TRUE;
            }
            break;
        }
        return (INT_PTR)FALSE;
    }
    
    
    • 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
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226

    代码运行演示

    代码演示

    总结

    win32程序开发作为c++软件开发中重要的部分,而win32程序框架又作为win32中重要的知识点,能够理解win32的基础知识。win32框架函数的具体操作在下一节的消息机制中会讲到,这里提供的代码只是为了让大家认识窗口程序。

  • 相关阅读:
    SQL优化之深分页
    Spring IoC、容器初始化、对象
    MySQL数据库备份与还原批处理脚本
    科尔伯格道德发展阶段论:重点识记,比皮亚杰考频更高。
    【洛谷 P3654】First Step (ファーストステップ) 题解(模拟+循环枚举)
    【2023年11月第四版教材】第19章《配置与变更管理》(合集篇)
    0719~分布式锁
    Pytorch 多卡并行(2)—— 使用 torchrun 进行容错处理
    ElementUI之首页导航+左侧菜单
    【实习】Mockito + JUnit5 单元测试学习
  • 原文地址:https://blog.csdn.net/qq_59931372/article/details/126111219