VS创建 Win32 应用程序(实现窗口的创建)

  • Post author:
  • Post category:其他




VS创建 Win32 应用程序(实现窗口的创建)(二)


程序框架如下:


在这里插入图片描述



一、VS演示流程

打开VS—-文件—-新建—-项目—-Windows 桌面应用程序

在这里插入图片描述

在这里插入图片描述



二、生成代码:(大部分函数在上一篇已经解释)

// 第一个窗口.cpp : 定义应用程序的入口点。
#include "stdafx.h"
#include "第一个窗口.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);       // 弹出对话框


主函数 WinMain

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_MY, szWindowClass, MAX_LOADSTRING);
    MyRegisterClass(hInstance);

    // 执行应用程序初始化:
    if (!InitInstance (hInstance, nCmdShow))
    {
        return FALSE;
    }

    HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_MY));

    MSG msg;

    // 主消息循环:
    while (GetMessage(&msg, nullptr, 0, 0))
    {
        if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }

    return (int) msg.wParam;
}


注册窗口类MyRegisterClass()

//  函数: 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_MY));
    wcex.hCursor        = LoadCursor(nullptr, IDC_ARROW);
    wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
    wcex.lpszMenuName   = MAKEINTRESOURCEW(IDC_MY);
    wcex.lpszClassName  = szWindowClass;
    wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

    return RegisterClassExW(&wcex);
}


初始化窗口InitInstance()

//   函数: InitInstance(HINSTANCE, int)
//   目标: 保存实例句柄并创建主窗口
//   注释:
//        在此函数中,我们在全局变量中保存实例句柄并
//        创建和显示主程序窗口。
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   hInst = hInstance; // 将实例句柄存储在全局变量中
//注意:此处的窗口类名szWindowClass要与前面注册窗口类的一样
   HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);

   if (!hWnd)
   {
      return FALSE;
   }

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

   return TRUE;
}


消息处理WndProc

//  函数: 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)
            {
            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 的任何绘图代码...
             LPCWSTR text1 = TEXT("VS Win32 窗口创建");
			TextOut(hdc, 0, 0, text1, lstrlen(text1));
			MessageBox(NULL, TEXT("VS Win32 窗口创建"), TEXT("hoade"), MB_OK);
			![](https://img-blog.csdnimg.cn/20190731143942499.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ1MDIxMTgw,size_16,color_FFFFFF,t_70)
            EndPaint(hWnd, &ps);
        }
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}


框的消息处理About

// “关于”框的消息处理程序。
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;
}



三、代码运行效果:

在这里插入图片描述



四、补充:



4.1 UNREFERENCED_PARAMETER的使用

其目的是避免编译器关于未引用参数的警告,告诉编译器,已经使用了该变量,不必检测警告!在VC编译器下,如果您用最高级别进行编译,编译器就会很苛刻地指出您的非常细小的警告。当你生命了一个变量,而没有使用时,编译器就会报警告:“warning C4100: ‘‘XXXX’’ : unreferenced formal parameter.” 所以,为了让编译器不必检测你的警告,就使UNREFERENCED_PARAMETER语句。



4.2 LoadStringW()


函数原型



对项目文件的资源(这里是指字符串,通过ID号找到)加载到实例的缓存区(通过指针加载,且指定缓存区大小)

LoadStringW( _In_opt_ HINSTANCE hInstance,    // 实例句柄    
             _In_ UINT uID,                   // 已有的资源ID(名字)    
             _Out_writes_to_(cchBufferMax, return + 1) LPWSTR lpBuffer,//存放资源的缓存区指针  
             _In_ int cchBufferMax);          // 存放资源缓存区的大小 

已有的资源就已经在项目文件中了,项目文件会对资源提供ID号(也就是资源名),我们加载的字符串就是这个资源。缓存区指针就是对加载的资源进行存储区域的指针。存放资源缓存区的大小就是对加载的资源进行存储区域的大小。



4.3 调入加速键表LoadAccelerators()


LoadAccelerators函数功能:调入加速键表。该函数调入指定的加速键表。



加速键也称为键盘快捷键


函数原型:

HACCEL LoadAccelerators(HINSTANCE hlnstance,
                         LPCTSTR lpTableName);


参数:

hlnstance:模块的一个实例的句柄,该模块的可执行文件中包含将要调入的加速键表。

IpTableName:指向一个以空结尾的字符串的指针,该字符串包含了即将调入的加速键表的名字。另一种可选的方案是,该参数可以在加速键表资源的低位字中指定资源标识符,而高位字中全零。MADEINTRESOURCE宏可被用于创建该值。


返回值:

返回值:若函数调用成功,则返回所加载的加速键表句柄 [1] 。若函数调用失败,则返回值为NULL。若要获得更多的错误信息,可以调用GetLastError函数。



4.4 MSG 消息结构


结构原型:

MSG msg;
	{
       	HWND        hwnd;     //窗口句柄
    	UINT        message;  //消息id,传递过来的消息
	    WPARAM      wParam;   //消息辅助参数
	    LPARAM      lParam;   //消息辅助参数
    	DWORD       time;     //消息产时间
	    POINT       pt;       //消息产生时鼠标所在的位置
	}



4.5 MAKEINTRESOURCEW的作用

MAKEINTRESOURCE是一个资源名转换的宏,这个宏是把一个数字类型转换成指针类型的宏,它不存在释放的问题。

就是lpName参数需要使用MAKEINTRESOURCE ,因为它需要LPCTSTR类型的参数输入.那么,情况就很清楚了.凡涉及”资源”的API或者MFC类,在参数类型为LPCTSTR时,就应该使用 MAKEINTRESOURCE.这是针对”资源名字”为”数字类型”时的情况.



版权声明:本文为qq_45021180原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。