如何创建一个最简单的Windows桌面应用程序 (C++)


如何创建一个最简单的Windows桌面应用程序 (C++)


     最近刚开始学习C/C++开发Windows应用程序,这里将会以零基础的视角把学习过程完全记录下来。如果你也刚刚起步,那本文一定非常适合你。

     进入正题,本文讨论如何使用Visual Studio生成一个最简单的C窗体应用程序,并向用户显示Hello~

     下面我们一步步来介绍,对于涉及代码的地方,我们只介绍大体的框架,完整的代码会在文章最后给出。   

     创建基于 Win32 的项目

     1.在文件菜单上,单击新建,然后单击项目。

     2.在“新建项目”对话框的左窗格中,依次单击“已安装模板”和“Visual C++”,然后选择“Win32”。在中间窗格中,选择“Win32 项目”。在“名称”框中,键入项目名称,例如HelloApp。单击“确定”。

     3.在“Win32 应用程序向导”的欢迎页面中,单击“下一步”。在“应用程序设置”页的“应用程序类型”下,选择“Windows 应用程序”。 在“附加选项”下,选择“空项目”。 单击“完成”以创建项目。

     4.在“解决方案资源管理器”中,右键单击 HelloApp项目,然后依次单击“添加”和“新建项”。 在“添加新项”对话框中选择“C++ 文件(.cpp)”。 在“名称”框中,键入文件名,例如GT_HelloWorldWin32.cpp。单击“添加”。

     添加引用

     我们的应用程序需要使用许多现有定义才能完成所需功能,针对我们的需求,添加引用如下(其中前两个是必须的):

#include <windows.h> 
#include <stdlib.h> 
#include <string.h> 
#include <tchar.h> 

     WinMain函数     

     正如每个 C/C++控制台应用程序在起始点必须具有 main 函数,每个基于 Win32 的应用程序的函数也必须具有 WinMain 函数。WinMain就相当于是入口函数,并且具有固定的语法:

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow); 

     实现WinMain函数时内部逻辑大体相同,主要有以下几部分:

     1.创建描述窗体信息的窗口类结构WNDCLASSEX 

     如何创建一个 WNDCLASSEX 类型的窗口类结构?下面的代码演示了一个典型的窗口类结构WNDCLASSEX 的定义:

//创建 WNDCLASSEX 类型的窗口类结构。 此结构包含关于窗口的信息
	//例如应用程序图标、窗口背景色、标题栏中显示的名称、窗口过程函数的名称等。
	WNDCLASSEX 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_APPLICATION)); 
	wcex.hCursor        = LoadCursor(NULL, IDC_ARROW); 
	wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1); 
	wcex.lpszMenuName   = NULL; 
	wcex.lpszClassName  = szWindowClass; 
	wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_APPLICATION)); 

     对于初学者,我们不用过分纠结代码的细节,暂时从宏观上把控。我们需要知道,此结构包含关于窗口的信息,例如应用程序图标、窗口背景色、标题栏中显示的名称、窗口过程函数的名称等。
     2.对窗口类进行注册

     现在已创建了窗口类,必须进行注册。

     使用 RegisterClassEx 函数,并将窗口类结构作为参数传递。

   RegisterClassEx(&wcex);

     3.创建并显示窗口

     现在需要使用CreateWindow函数创建窗口

     使用ShowWindow函数显示窗口

     这部分也很好理解,详见文末的代码

     4.侦听消息

     添加用于侦听操作系统所发送消息的消息循环。

     当应用程序收到一条消息时,此循环将该消息调度到 WndProc 函数。WndProc 函数用于对接收的消息进行处理,我们下面会介绍到。 

     该消息循环类似于以下代码:

// Main message loop: 
	// 添加用于侦听操作系统所发送消息的消息循环。 
	// 当应用程序收到一条消息时,此循环将该消息调度到 WndProc 函数以进行处理。 
	MSG msg; 
	while (GetMessage(&msg, NULL, 0, 0)) { 
		TranslateMessage(&msg); //翻译消息
		DispatchMessage(&msg);  //派遣消息
	} 

     WndProc 函数

     WndProc 函数用以处理应用程序收到的消息。

     首先需要判断收到的消息类型进而做出不同的处理,这需要使用 switch 语句。
     系统提供了众多的消息命令,例如 WM_PAINT 代表收到了绘图消息,而收到鼠标点击消息的标识是WM_LBUTTONDOWN...

     这里以处理 WM_PAINT 消息为例进行说明。

     要处理 WM_PAINT 消息,首先应调用 BeginPaint,然后处理所有的绘图逻辑,例如在窗口中布局文本、按钮和其他控件,然后调用 EndPaint。 

     对于此应用程序,开始调用和结束调用之间的逻辑是在窗口中显示字符串 “Hello,World!”。 在以下代码中,TextOut 函数用于显示字符串。

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { 
	PAINTSTRUCT ps;
	HDC hdc; 
	TCHAR greeting[] = _T("Hello, World!"); 
	switch (message) { 
		case WM_PAINT: 
			//要处理 WM_PAINT 消息,首先应调用 BeginPaint
			//然后处理所有的逻辑以及在窗口中布局文本、按钮和其他控件等
			//然后调用 EndPaint。 
			hdc = BeginPaint(hWnd, &ps); 

			// -----------------在这段代码对应用程序进行布局------------------------ 
			// 对于此应用程序,开始调用和结束调用之间的逻辑是在窗口中显示字符串 “Hello,World!”。
			// 请注意 TextOut 函数用于显示字符串。
			TextOut(hdc, 50, 5, greeting, _tcslen(greeting)); 
			// -----------------------布局模块结束----------------------------------

			EndPaint(hWnd, &ps);
			break; 
		case WM_DESTROY: 
			PostQuitMessage(0); 
			break;
		default: 
			//DefWindowProc缺省窗口处理函数
			//这个函数是默认的窗口处理函数,我们可以把不关心的消息都丢给它来处理
			return DefWindowProc(hWnd, message, wParam, lParam); 
			break; 
	} 
	return 0; 
} 

     程序运行的结果为:


     完整代码

     到此我已经理清了写一个Windows应用程序的主要逻辑

     我是按照Microsoft官方文档进行的学习,详见创建Windows桌面应用程序

     对于更多的细节,代码中给出了详细注释。

// GT_HelloWorldWin32.cpp 
// compile with: /D_UNICODE /DUNICODE /DWIN32 /D_WINDOWS /c 
// 这是一个最简单的Win32程序,亦可作为开发桌面应用程序的模板

#include <windows.h> 
#include <stdlib.h> 
#include <string.h> 
#include <tchar.h> 

// ------------------------Global variables---------------------------------
// 主窗体类名
static TCHAR szWindowClass[] = _T("win32app"); 
// 应用程序标题栏处出现的字符串
static TCHAR szTitle[] = _T("Win32 Guided Tour Application"); 

//HINSTANCE 是Windows里的一中数据类型,是用于标示(记录)一个程序的实例。
//它与HMODULE是一样的(通用的,这两种类型最终就是32位无符号长整形)。
//HINSTANCE,分开看就是 HANDLE(句柄) + INSTANCE(实例)
//实例就是一个程序。用qq来举例:你可以开同时开2个qq号,但是你电脑里的qq软件只有一份。
//这2个qq号就是qq的2个实例
HINSTANCE hInst; 

// -------------------------需要预定义的函数放置在此代码块种:---------------------------- 


//每个 Windows 桌面应用程序必须具有一个窗口过程函数
//此函数处理应用程序从操作系统中接收的大量消息。 
//例如,如果应用程序的对话框中有“确定”按钮,那么用户单击该按钮时,
//操作系统会向应用程序发送一条消息,通知按钮已被单击。WndProc 负责对该事件作出响应。
//在本例中,相应的响应可能是关闭对话框。
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); 

//-------------------------------------正式内容-----------------------------------------

//主窗体函数(入口过程)
//每个基于 Win32 的应用程序的函数必须具有 WinMain 函数
//正如每个 C 应用程序和 C++ 控制台应用程序在起始点必须具有 main 函数
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { 
	//创建 WNDCLASSEX 类型的窗口类结构。 此结构包含关于窗口的信息
	//例如应用程序图标、窗口背景色、标题栏中显示的名称、窗口过程函数的名称等。
	WNDCLASSEX 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_APPLICATION)); 
	wcex.hCursor        = LoadCursor(NULL, IDC_ARROW); 
	wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1); 
	wcex.lpszMenuName   = NULL; 
	wcex.lpszClassName  = szWindowClass; 
	wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_APPLICATION)); 
	
	//对已创建的窗口类进行注册。 使用 RegisterClassEx 函数,并将窗口类结构作为参数传递。
	if (!RegisterClassEx(&wcex)) { 
		MessageBox(NULL, _T("Call to RegisterClassEx failed!"), _T("Win32 Guided Tour"), NULL); 
		return 1; 
	} 

	// Store instance handle in our global variable 
	// 将句柄实例存储于全局变量中
	hInst = hInstance; 
	
	// CreateWindow 函数的参数解释: 
	// szWindowClass: the name of the application 
	// szTitle: the text that appears in the title bar 
	// WS_OVERLAPPEDWINDOW: the type of window to create 
	// CW_USEDEFAULT, CW_USEDEFAULT: initial position (x, y) 
	// 500, 100: initial size (width, length) 
	// NULL: the parent of this window 
	// NULL: this application does not have a menu bar 
	// hInstance: the first parameter from WinMain 
	// NULL: not used in this application 
	// 返回的HWND是一个窗口的句柄
	HWND hWnd = CreateWindow( szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 500, 100, NULL, NULL, hInstance, NULL ); 
	if (!hWnd) { 
		MessageBox(NULL, _T("Call to CreateWindow failed!"), _T("Win32 Guided Tour"), NULL); 
		return 1; 
	} 


	// ShowWindow 函数的参数解释: 
	// hWnd: CreateWindow函数返回的窗口句柄 
	// nCmdShow: the fourth parameter from WinMain 
	ShowWindow(hWnd, nCmdShow);
	// UpdateWindow函数用于更新窗口指定的区域
	// 如果窗口更新的区域不为空,UpdateWindow函数就发送一个WM_PAINT消息来更新指定窗口的客户区。
	// 函数绕过应用程序的消息队列,直接发送WM_PAINT消息给指定窗口的窗口过程
	// 如果更新区域为空,则不发送消息。
	UpdateWindow(hWnd); 

	// Main message loop: 
	// 添加用于侦听操作系统所发送消息的消息循环。 
	// 当应用程序收到一条消息时,此循环将该消息调度到 WndProc 函数以进行处理。 
	MSG msg; 
	while (GetMessage(&msg, NULL, 0, 0)) { 
		TranslateMessage(&msg); //翻译消息
		DispatchMessage(&msg);  //派遣消息
	} 
	return (int) msg.wParam; 
} 

// //  函数: WndProc(HWND, UINT, WPARAM, LPARAM) 
// //  目标:  处理主窗体产生的信息
// //  WM_PAINT消息代表绘制主窗体 
// //  WM_DESTROY消息代表投递一个退出消息并返回 
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { 
	PAINTSTRUCT ps;
	HDC hdc; 
	TCHAR greeting[] = _T("Hello, World!"); 
	switch (message) { 
		case WM_PAINT: 
			//要处理 WM_PAINT 消息,首先应调用 BeginPaint
			//然后处理所有的逻辑以及在窗口中布局文本、按钮和其他控件等
			//然后调用 EndPaint。 
			hdc = BeginPaint(hWnd, &ps); 

			// -----------------在这段代码对应用程序进行布局------------------------ 
			// 对于此应用程序,开始调用和结束调用之间的逻辑是在窗口中显示字符串 “Hello,World!”。
			// 请注意 TextOut 函数用于显示字符串。
			TextOut(hdc, 50, 5, greeting, _tcslen(greeting)); 
			// -----------------------布局模块结束----------------------------------

			EndPaint(hWnd, &ps);
			break; 
		case WM_DESTROY: 
			PostQuitMessage(0); 
			break;
		default: 
			//DefWindowProc缺省窗口处理函数
			//这个函数是默认的窗口处理函数,我们可以把不关心的消息都丢给它来处理
			return DefWindowProc(hWnd, message, wParam, lParam); 
			break; 
	} 
	return 0; 
} 



  • 98
    点赞
  • 391
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 11
    评论
### 回答1: vswindows桌面应用程序是一种使用C++编写的桌面应用程序开发工具,它可以帮助开发者快速构建高效、稳定的Windows桌面应用程序。该工具集成了丰富的开发工具和库,包括代码编辑器、调试器、图形界面设计工具、数据库连接器等,可以大大提高开发效率和代码质量。同时,vswindows桌面应用程序还支持多种编程语言,如C++、C#、VB等,可以满足不同开发者的需求。 ### 回答2: VsWindows桌面应用程序C是指使用Microsoft Visual Studio集成开发环境(IDE)和C编程语言,创建基于Windows操作系统的桌面应用程序。C语言是一种高级编程语言,被广泛用于系统级编程和硬件编程,因此非常适用于开发Windows应用程序。 VsWindows桌面应用程序C的开发过程涉及到程序设计、编码、编译和调试。使用Visual Studio可以轻松创建Windows窗体应用程序、控制台应用程序和DLL库等各种类型的应用程序。Visual Studio提供了丰富的工具和功能,包括代码编辑器、调试器、自动完成、代码分析和测试工具等,使开发任务变得更加简单快捷。 C语言在Windows应用程序开发中扮演着非常重要的角色。对于Windows操作系统来说,C语言是固有的编程语言,许多核心功能都是使用C语言编写的,因此使用C语言编写Windows应用程序能够更好地利用操作系统的底层资源和API,从而实现更加高效和优质的应用程序。此外,C语言还具备良好的可移植性,可用于不同平台和操作系统中的应用程序开发。 总之,VsWindows桌面应用程序C是一种基于Visual Studio和C语言的Windows应用程序开发方法,其优点包括强大的功能和工具库、操作系统底层资源的利用、高效和可移植性等等。对于需要开发Windows桌面应用程序开发者来说,使用VsWindows桌面应用程序C将会是一种非常可行和有趣的选择。 ### 回答3: VS(Visual Studio)是一款由微软公司开发的软件开发环境,它可以用于开发各种类型的应用程序,包括桌面应用程序。其中,C是一种高级程序设计语言,具有语法简洁、运行快速、可通用于多种操作系统等优点。因此,使用VS进行C语言桌面应用程序开发是非常常见的。 首先,VS提供了非常完善的C语言编译环境和调试工具,使得开发者能够方便地进行代码编写、编译和运行调试等工作。VS还包含一些预置的代码模板和代码段,可以加速开发者的开发进程。同时VS还提供了丰富的库函数,可以在开发过程中调用,使得开发者能够快速地实现各种功能需求。 其次,VS提供了非常友好的界面开发工具,使得C语言桌面应用程序的界面设计变得异常简单开发者只需要在VS提供的拖拽式界面设计器中按照自己的需求进行界面设计,就可以快速地生成出美观、易用的桌面应用程序。 最后,在开发C语言桌面应用程序时,VS还包含了丰富的调试工具和性能分析工具,可以帮助开发者在开发过程中快速发现和解决各种程序缺陷和性能问题。 综上所述,VS为C语言桌面应用程序开发提供了非常完善和便捷的工具支持,可以帮助开发者快速高效地完成开发工作,快速地实现功能需求,为用户提供更佳的用户体验。因此,VS是开发C语言桌面应用程序不可或缺的必备工具之一。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

随煜而安

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值