Windows桌面应用程序 基础知识

visual studio2019自动生成的代码:

// WindowsProject1.cpp : 定义应用程序的入口点。
//

#include "framework.h"
#include "WindowsProject1.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_WINDOWSPROJECT1, szWindowClass, MAX_LOADSTRING);
    MyRegisterClass(hInstance);

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

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

    MSG msg;

    // 主消息循环:
    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_WINDOWSPROJECT1));
    wcex.hCursor        = LoadCursor(nullptr, IDC_ARROW);
    wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
    wcex.lpszMenuName   = MAKEINTRESOURCEW(IDC_WINDOWSPROJECT1);
    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,
      CW_USEDEFAULT, 0, 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)
            {
            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;
}

文章参考:chatgpt和Windows应用程序基础(详细,简单易懂)_windows编程基础-CSDN博客

加注释后代码:

// WindowsProject1.cpp : 定义应用程序的入口点。
//

#include "framework.h"
#include "WindowsProject1.h"

#define MAX_LOADSTRING 100      /*定义一个宏,表示字符串缓冲区的最大长度为100*/

// 全局变量:
HINSTANCE hInst;                                // 当前实例
WCHAR szTitle[MAX_LOADSTRING];                  // 标题栏文本    /*存储窗口标题的字符串
WCHAR szWindowClass[MAX_LOADSTRING];            // 主窗口类名    /*存储窗口类名,windows系统通过窗口类名识别窗口

// 此代码模块中包含的函数的前向声明:
ATOM                MyRegisterClass(HINSTANCE hInstance);   /*用于注册窗口类,使Windows知道如何创建窗口*/
BOOL                InitInstance(HINSTANCE, int);           /*初始化应用程序实例,创建窗口*/
LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);    /*窗口过程函数,用于处理窗口的各种消息*/
INT_PTR CALLBACK    About(HWND, UINT, WPARAM, LPARAM);      /*关于对话框的消息处理函数*/

/*主函数wWinMain,是程序的入口点*/
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,         /*操作系统使用此值来标识 EXE (加载到) 可执行文件。 某些函数需要实例句柄Windows例如,加载图标或位*/
                     _In_opt_ HINSTANCE hPrevInstance,  /*没有意义。 它用于 16 位Windows,但现在始终为零。*/
                     _In_ LPWSTR    lpCmdLine,          /*用于指定程序的命令行,是指向字符串的指针类型。*/
                     _In_ int       nCmdShow)           /*是一个标志,指示主应用程序窗口是最小化、最大化还是正常显示。*/
{
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);

    // TODO: 在此处放置代码。

    // 初始化全局字符串
    /*LoadStringW: 加载资源文件中的字符串,将应用程序标题和窗口类名存入全局变量*/
    LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); 
    LoadStringW(hInstance, IDC_WINDOWSPROJECT1, szWindowClass, MAX_LOADSTRING);
    MyRegisterClass(hInstance); /*注册窗口类*/

    // 执行应用程序初始化:
    /*InitInstance: 初始化实例并创建主窗口*/
    if (!InitInstance (hInstance, nCmdShow))
    {
        return FALSE;
    }

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

    MSG msg;

    // 主消息循环:
    /*GetMessage: 主消息循环,等待并处理系统消息(如鼠标点击、键盘输入等)*/
    while (GetMessage(&msg, nullptr, 0, 0))
    {
        if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
        {
            /*TranslateMessage 和 DispatchMessage: 将消息翻译并分发给窗口过程函数 WndProc*/
            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;  /*WndProc: 指定窗口的消息处理函数*/
    wcex.cbClsExtra     = 0;    /*指定分配给窗口类结构之后的额外字节数*/
    wcex.cbWndExtra     = 0;    /*指定分配给窗口实例之后的额外字节数*/
    wcex.hInstance      = hInstance;    /*指定窗口过程所对应的实例句柄*/
    wcex.hIcon          = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WINDOWSPROJECT1));    /*指定窗口的图标*/
    wcex.hCursor        = LoadCursor(nullptr, IDC_ARROW);   /*指定窗口的鼠标指针(光标)*/
    wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1); /*窗口背景颜色*/
    wcex.lpszMenuName   = MAKEINTRESOURCEW(IDC_WINDOWSPROJECT1);    /*窗口的菜单资源名称*/
    wcex.lpszClassName  = szWindowClass;    /*窗口类名*/
    wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

    /*虽然我们定义了一个窗口,但是系统并不知道这个窗口的存在,
    所以接下来我们通过RegisterClass()函数来注册窗口类。*/
    return RegisterClassExW(&wcex); /*RegisterClassExW: 注册窗口类*/
}

//
//   函数: InitInstance(HINSTANCE, int)
//
//   目标: 保存实例句柄并创建主窗口
//
//   注释:
//
//        在此函数中,我们在全局变量中保存实例句柄并
//        创建和显示主程序窗口。
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   hInst = hInstance; // 将实例句柄存储在全局变量中

   /*CreateWindowW: 创建主窗口*/
   HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);

   if (!hWnd)
   {
      return FALSE;
   }

   /*ShowWindow: 显示窗口;UpdateWindow: 更新窗口内容*/
   /*参数 hWnd 指定要显示的窗口的句柄,nCmdShow 表示窗口的显示方式,
   可以指定为从函数 WinMain()的nCmdshow 所传递而来的值。*/
   ShowWindow(hWnd, nCmdShow);  
   /*由于函数 Show Window()的执行优先级不高,所以当系统正忙着执行其他任务时,不会立即显示窗口,
   此时,调用函数 Update Window()立即显示窗口*/
   UpdateWindow(hWnd);
   /*同时,函数UpdateWindow()还会给窗口过程发出 WM_ PAINT 消息使窗口客户区重绘。*/

   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)
    {
    /*WM_COMMAND: 菜单和控件的消息*/
    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;
    /*WM_PAINT: 绘制窗口内容*/
    case WM_PAINT:
        {
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint(hWnd, &ps);
            // TODO: 在此处添加使用 hdc 的任何绘图代码...
            EndPaint(hWnd, &ps);
        }
        break;
    /*WM_DESTROY: 销毁窗口时发送退出消息*/
    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;
}

创建窗口类:

在注册窗口后,并没有生成一个窗口实体,我们可以用函数CreateWindows()来创建窗口,其代码为:

	HWND WINAPI CreateWindow(	//返回值是窗口句柄
	LPCTSTR lpClassName,		//窗口类名,要与注册时指定的名称相同
	LPCTSTR lpWindowName,		//窗口标题
	DWORD dwStyle,				//窗口样式
	int X,						//窗口最初的x位置
	int y,						//窗口最初的y位置
	int nWidth,					//窗口最初的x大小
	int nHeight,				//窗口最初的y大小
	HWND hWndParent,			//父窗口句柄
	HMENU hMenu,				//窗口菜单句柄
	HINSTANCE hInstance,		//应用程序实例句柄
	LPVOID lpParam				//指向一个传递给窗口的参数值的指针,以便后续在程序中加以引用
	);

其具体创建实例的代码为:

	hwnd=CreateWindow ( "HelloWin",
						"我的窗口",
						WS_OVERLAPPEDWINDOW,
						CW_USEDEFAULT,
						CW_USEDEFAULT,
						480,
						320,
						NULL,
						NULL,
						hInstance,
						NULL
						);

创建窗口时,我们只需要按照参数的位置给其逐一赋值即可,如果想知道详细内容可以点击下方链接了解。链接:详细内容

实践代码:

更改标题:

HWND hWnd = CreateWindowW(szWindowClass, L"我的新标题", WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT, 480, CW_USEDEFAULT, 320, nullptr, nullptr, hInstance, nullptr);

添加"L"的原因:

  1. ANSI 字符串与 Unicode 字符串

    • 普通的字符串,比如 "Hello",是 ANSI 字符串,它使用 char 类型,一个字符通常占用1个字节。
    • 使用 L"Hello",则是 Unicode 字符串,使用 wchar_t 类型,一个字符占用2个字节(在Windows上),它可以支持更多的字符集(如中文、日文、韩文等)。
  2. Windows API 函数

    • CreateWindowWSetWindowTextW 等函数要求传入 宽字符 类型的字符串,也就是 L"..."
    • 如果不加 L,而使用普通字符串,例如 "Hello",会导致类型不匹配,因为普通字符串是 char*,而这些函数需要 wchar_t* 类型。

示例:

  • "Hello"const char* 类型,适用于 CreateWindowA 等使用ANSI字符串的函数。
  • L"Hello"const wchar_t* 类型,适用于 CreateWindowW 等使用Unicode字符串的函数。

 添加文字代码:

case WM_PAINT:
	{
		PAINTSTRUCT ps;
		HDC hdc = BeginPaint(hWnd, &ps);
		RECT rect;
		// TODO: 在此处添加使用 hdc 的任何绘图代码...
		GetClientRect(hWnd, &rect);
		DrawText(hdc, TEXT("加油!相信你自己!"), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
		EndPaint(hWnd, &ps);
	}
	break;

 其中,获取窗口的客户区 GetClientRect:

RECT rect;
GetClientRect(hWnd, &rect);
  • RECT rect:定义一个矩形结构体,它将保存窗口客户区(显示区域)的大小和位置。
  • GetClientRect:获取窗口客户区的大小,并将结果存储到 rect 结构体中。客户区是窗口标题栏以下可以绘制的区域。

绘制文本 DrawText:

DrawText(hdc, TEXT("加油!相信你自己!"), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
  • DrawText 函数用于在指定的矩形区域内绘制文本。
    • hdc: 用于绘图的设备上下文。
    • TEXT("加油!相信你自己!"): 要绘制的文本。TEXT 宏用于确保字符串的字符集与项目设置一致(ANSI 或 Unicode)。
    • -1: 表示文本长度,由函数自动计算(以 null 结尾)。
    • &rect: 指定绘制文本的矩形区域,这里是窗口的整个客户区。
    • DT_SINGLELINE | DT_CENTER | DT_VCENTER:这几个标志指定了文本的绘制方式:
      • DT_SINGLELINE: 绘制单行文本。
      • DT_CENTER: 将文本水平居中。
      • DT_VCENTER: 将文本垂直居中。

效果:

直接修改按钮

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值