ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

创建传统的Windows桌面应用程序

2021-03-15 09:32:30  阅读:223  来源: 互联网

标签:窗口 Windows 句柄 应用程序 消息 wcex 桌面 NULL


文章目录

前言

目标:创建的示例应用程序,使用 Windows API 显示 “Hello,Windows desktop!” 应用程序。

教学资料:【SDK开发】《Windows程序设计》 – 小甲鱼 – p4~p8 | 视频中的代码

下面代码来源:演练:创建传统的 Windows 桌面应用程序 (c + +) – windows官网


代码

代码内容可以分为两部分:

  • 填充窗口的有关信息(WNDCLASSEX) -> 注册窗口类(RegisterClassEx) -> 创建窗口(CreateWindow) -> 显示窗口(ShowWindow) -> 更新窗口(UpdateWindow)

  • 消息循环(GetMessage -> TranslateMessage ->DispatchMessage)

/**
 * 编译的时候,链接gdi32库:gcc -o windows -lgdi32 windows
 * kernel32.dll:主要处理内存管理和进程调度;user32.dll:主要控制用户界面;gdi32.dll:负责图形方面的操作
 * */
#include <windows.h>

// 主窗口的名称
static TCHAR szWindowClass[] = TEXT("DesktopApp");
// 出现在应用的title bar
static TCHAR szTitle[] = TEXT("Windows Desktop Guided Tour Application");

// 声明消息处理函数
LRESULT CALLBACK WndPRoc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPreInstance,LPSTR lpCmdLine,int nShowCmd){

    // 填充窗口的有关信息。填充类型为WNDCLASSEX结构
    // 该WNDCLASSEX结构是类似于WNDCLASS结构。有两个区别。WNDCLASSEX包括cbSize成员和hIconSm成员,该成员指定结构的大小,而hIconSm成员包含与窗口类关联的小图标的句柄。
    WNDCLASSEX wcex;

    wcex.cbSize        = sizeof(WNDCLASSEX); //此结构的大小(以字节为单位)。将此成员设置为sizeof(WNDCLASSEX)。在调用GetClassInfoEx函数之前,请确保设置此成员。
    wcex.style         = CS_HREDRAW | CS_VREDRAW; //只要窗口更改大小,就可以让应用程序重绘工作区的全部内容
    wcex.lpfnWndProc   = WndPRoc; //指向窗口过程的指针。您必须使用CallWindowProc函数来调用窗口过程。有关更多信息,请参见WindowProc。
    wcex.cbClsExtra    = 0; // 根据窗口类结构分配的额外字节数。系统将字节初始化为零。
    wcex.cbWndExtra    = 0; // 窗口实例后要分配的额外字节数。系统将字节初始化为零。如果应用程序使用WNDCLASSEX在资源文件中注册使用CLASS指令创建的对话框 ,则必须将此成员设置为DLGWINDOWEXTRA。
    wcex.hInstance     = hInstance; // 包含类的窗口过程的实例的句柄。
    wcex.hIcon         = LoadIcon(hInstance,IDI_APPLICATION); // 类图标的句柄。该成员必须是图标资源的句柄。如果此成员为NULL,则系统提供默认图标。[IDI_APPLICATION:默认应用程序图标]
    wcex.hCursor       = LoadCursor(NULL, IDC_ARROW); // IDC_ARROW:标准箭头
    wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); // 类背景画笔的句柄;颜色值必须是以下标准系统颜色之一(必须将值1添加到所选颜色中)。如果指定了颜色值,则必须将其转换为以下 HBRUSH类型之一
    wcex.lpszMenuName  = NULL; // 该字符串指定类菜单的资源名称;如果此成员为NULL,则属于此类的Windows没有默认菜单。
    wcex.lpszClassName = szWindowClass; // 如果lpszClassName是一个字符串,则它指定窗口类名称
    wcex.hIconSm       = LoadIcon(wcex.hInstance, IDI_APPLICATION); // 与窗口类关联的小图标的句柄


    // 向 Windows 注册, WNDCLASSEX 使其了解你的窗口以及如何向其发送消息
    if(!RegisterClassEx(&wcex)){
        MessageBox(NULL,TEXT("Call to RegisterClassEx failed!"),TEXT("Windows Desktop Guided Tour"),0);
        return 1;
    }

    // 创建窗口
    HWND hWnd = CreateWindow(
        szWindowClass, //如果lpClassName是一个字符串,则它指定窗口类名称
        szTitle,       // 窗口名称
        WS_OVERLAPPEDWINDOW, // 正在创建的窗口的样式,该窗口是一个重叠的窗口[是个组合]
        CW_USEDEFAULT, CW_USEDEFAULT, // 窗口的初始水平位置,窗口的初始垂直位置
        CW_USEDEFAULT, CW_USEDEFAULT, // 窗口的宽度,窗口的高度
        NULL, // 要创建的窗口的父窗口或所有者窗口的句柄
        NULL, // 菜单的句柄
        hInstance, // 与窗口关联的模块实例的句柄
        NULL // 如果不需要其他数据,则lpParam可以为NULL。
    );

    if(!hWnd){
        MessageBox(NULL,TEXT("Call to CreateWindow failed!"),TEXT("Windows Desktop Guided Tour"),0);
        return 1;
    }

    //此时,已创建了窗口,但我们仍需要告知 Windows 使其可见
    ShowWindow(hWnd,nShowCmd);
    UpdateWindow(hWnd);

    // 为了处理 Windows 现在正在向其发送的消息,我们首先添加一个消息循环来侦听 Windows 发送的消息。 
    // 当应用程序收到消息时,此循环会将它调度到要 WndProc 处理的函数

    MSG msg;
    // 从调用线程的消息队列中检索消息
    // 参数含义:
    // 第一个参数:指向MSG结构的指针,该结构从线程的消息队列接收消息信息;
    // 第二个参数:要获取其消息的窗口的句柄。为NULL,则GetMessage检索属于当前线程的任何窗口的消息
    // 第三和第四个参数,均为零,则GetMessage返回所有可用消息(即,不执行范围过滤)。
    while(GetMessage(&msg,NULL,0,0)){
        TranslateMessage(&msg); // 将虚拟键消息转换为字符消息。字符消息将发布到调用线程的消息队列中,以在线程下次调用GetMessage或PeekMessage函数时读取。
        DispatchMessage(&msg); // 将消息调度到窗口过程。它通常用于调度由GetMessage函数检索的消息。
    }

    return (int) msg.wParam;
}


// 启用 WndProc 函数以处理应用程序收到的消息
// 函数的参数分别为:窗口的句柄,消息,附加消息信息,附加消息信息
LRESULT CALLBACK WndPRoc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){
    PAINTSTRUCT ps;
    HDC hdc;
    TCHAR greeting[] = TEXT("Hello, Windows destop!");

    switch (message){
        case WM_PAINT: //显示窗口消息(当对窗口进行更新的时候)

            // BeginPaint函数向指定的窗口绘画,将绘画的信息填充到PAINTSTRUCT结构中
            // hWnd:处理要重绘的窗口;ps:指向将接收绘画信息的PAINTSTRUCT结构的指针
            // 如果函数成功,则返回值是指定窗口的显示设备上下文的句柄
            // 如果函数失败,则返回值为NULL,指示没有显示设备上下文可用
            hdc = BeginPaint(hWnd,&ps);

            // 所述的TextOut函数在指定位置写入的字符串,利用当前选择的字体,背景颜色和文本颜色。
            // 参数分别是:设备上下文的句柄、系统用来对齐字符串的参考点的x坐标、系统用来对齐字符串的参考点的y坐标、指向要绘制的字符串的指针、指向的字符串的长度,以字符为单位
            // 如果函数成功,则返回值为非零。如果函数失败,则返回值为零。
            TextOut(hdc,TA_CENTER,TA_CENTER,greeting,lstrlen(greeting));

            //调用EndPaint函数标记指定窗口画的结束。每次调用BeginPaint函数都需要此函数,但是仅在绘制完成之后才需要。
            // 参数分别是:处理已重新粉刷的窗口,由BeginPaint检索的绘画信息的PAINTSTRUCT结构的指针
            // 返回值始终为非零
            EndPaint(hWnd,&ps);
            break;

        case WM_DESTROY: // 销毁窗口消息
            // 向系统指示线程已请求终止(退出)。通常用于响应WM_DESTROY消息
            // 参数为应用程序退出代码。此值用作WM_QUIT消息的wParam参数
            PostQuitMessage(0);
            break;
        
        default:
            // 继续执行默认处理
            return DefWindowProc(hWnd,message,wParam,lParam);
            break;
    }

    return 0;
}

运行结果

比较讨厌的是,我不知道如何使用vscode 创建桌面程序。[vs可以创建桌面程序,但是我不想下载TA]

这里编译生成的是命令台程序,所以它总是出现命令台。

在这里插入图片描述

标签:窗口,Windows,句柄,应用程序,消息,wcex,桌面,NULL
来源: https://blog.csdn.net/sinat_38816924/article/details/114818786

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有