700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > C语言开发windows桌面程序 演练:创建传统的 Windows 桌面应用程序 (c + +)

C语言开发windows桌面程序 演练:创建传统的 Windows 桌面应用程序 (c + +)

时间:2021-05-16 00:22:34

相关推荐

C语言开发windows桌面程序 演练:创建传统的 Windows 桌面应用程序 (c + +)

演练:创建传统的 Windows 桌面应用程序 (c + +)

05/28/

本文内容

本演练演示如何在 Visual Studio 中创建传统的 Windows 桌面应用程序。 要创建的示例应用程序使用 Windows API 显示 "Hello,Windows desktop!" 应用程序。 可以将本演练中开发的代码作为模式来创建其他 Windows 桌面应用程序。

Windows API (也称为 Win32 API、Windows 桌面 API 和 Windows Classic API) 是基于 C 语言的框架,用于创建 Windows 应用程序。 它已存在,因为它已被占用了20% 的时间,用于创建数十年的 Windows 应用程序。 更高级、更易于编程的框架是在 Windows API 之上构建的。 例如,MFC,ATL,.NET framework。 甚至使用 c + +/WinRT 编写的 UWP 和应用商店应用的最新式 Windows 运行时代码也使用下面的 Windows API。 有关 Windows API 的详细信息,请参阅 WINDOWS Api Index。 有多种方法可以创建 Windows 应用程序,但上面的过程是第一个。

重要

为了简洁起见,文本中省略了一些代码语句。 本文档末尾的 " 生成代码" 部分显示了完整的代码。

先决条件

运行 Microsoft Windows 7 或更高版本的计算机。 建议使用 Windows 10 以实现最佳开发体验。

Visual Studio 的副本。 有关如何下载和安装 Visual Studio 的信息,请参阅安装 Visual Studio。 运行安装程序时,请务必选中“使用 C++ 的桌面开发” 工作负载。 如果在安装 Visual Studio 时未安装此工作负载,请不要担心。 可以再次运行安装程序并立即安装。

使用 C++ 的桌面开发

了解使用 Visual Studio IDE 的基础知识。 如果你之前使用过 Windows 桌面应用,可能具备一定的相关知识。 有关简介,请参阅 Visual Studio IDE 功能导览。

了解足够的 C++ 语言基础知识以供继续操作。 别担心,我们不会执行过于复杂的操作。

创建 Windows 桌面项目

按照以下步骤创建您的第一个 Windows 桌面项目。 当你执行此操作时,你将为正在运行的 Windows 桌面应用程序输入代码。 若要查看 Visual Studio 首选项的文档,请使用“版本”选择器控件。 它位于此页面上目录表的顶部。

在 Visual Studio 中创建 Windows 桌面项目

在主菜单中,依次选择“文件”>“新建”>“项目”,以打开“新建项目”对话框。

在对话框顶部,将 " 语言 " 设置为 " c + + ",将 " 平台 " 设置为 " Windows ",将 " 项目类型 " 设置为 " 桌面

从筛选的项目类型列表中,选择 " Windows 桌面向导 ",然后选择 " 下一步 "。 在下一页中,输入项目的名称,例如 " DesktopApp "。

选择“创建” 按钮创建项目。

此时将显示 " Windows 桌面项目 " 对话框。 在 " 应用程序类型 " 下,选择 " 桌面应用程序 ( .exe) 。 在“附加选项” 下,选择“空项目” 。 选择“确定”,创建项目 。

在 解决方案资源管理器 中,右键单击 DesktopApp 项目,选择 " 添加 ",然后选择 " 新建项 "。

在“添加新项” 对话框中选择“C++ 文件(.cpp)” 。 在 " 名称 " 框中,键入文件的名称,例如 " HelloWindowsDesktop "。 选择“添加”。

此时会创建项目,并在编辑器中打开源文件。 若要继续,请跳到 创建代码。

在 Visual Studio 中创建 Windows 桌面项目

在“文件”菜单上选择“新建”,再选择“项目”。

在 " 新建项目 " 对话框的左窗格中,展开 " 已安装 > " Visual C++ ,然后选择 " Windows 桌面 "。 在中间窗格中,选择 " Windows 桌面向导 "。

在 " 名称 " 框中,键入项目的名称,例如 " DesktopApp "。 选择 “确定” 。

在 " Windows 桌面项目 " 对话框中的 " 应用程序类型 " 下,选择 " Windows 应用程序 ( .exe) 。 在“附加选项” 下,选择“空项目” 。 请确保未选择 " 预编译头 "。 选择“确定”,创建项目 。

在 解决方案资源管理器 中,右键单击 DesktopApp 项目,选择 " 添加 ",然后选择 " 新建项 "。

在“添加新项” 对话框中选择“C++ 文件(.cpp)” 。 在 " 名称 " 框中,键入文件的名称,例如 " HelloWindowsDesktop "。 选择“添加”。

此时会创建项目,并在编辑器中打开源文件。 若要继续,请跳到 创建代码。

在 Visual Studio 中创建 Windows 桌面项目

在“文件”菜单上选择“新建”,再选择“项目”。

在 " 新建项目 " 对话框的左窗格中,展开 " 已安装 > 的 模板 " > Visual C++ ,然后选择 " Win32 "。 在中间窗格中,选择“Win32 项目” 。

在 " 名称 " 框中,键入项目的名称,例如 " DesktopApp "。 选择 “确定” 。

在 " Win32 应用程序向导 " 的 " 概述 " 页上,选择 " 下一步 "。

在 " 应用程序设置 " 页的 " 应用程序类型 " 下,选择 " Windows 应用程序 "。 在 其他选项 下,取消选中 " 预编译头 ",然后选择 " 空项目 "。 选择“完成”以创建项目 。

在 解决方案资源管理器 中,右键单击 DesktopApp 项目,选择 " 添加 ",然后选择 " 新建项 "。

在“添加新项” 对话框中选择“C++ 文件(.cpp)” 。 在 " 名称 " 框中,键入文件的名称,例如 " HelloWindowsDesktop "。 选择“添加”。

此时会创建项目,并在编辑器中打开源文件。

创建代码

接下来,你将学习如何在 Visual Studio 中为 Windows 桌面应用程序创建代码。

启动 Windows 桌面应用程序

正如每个 C 应用程序和 c + + 应用程序必须将 main 函数作为其起始点一样,每个 Windows 桌面应用程序都必须具有一个 WinMain 函数。 WinMain 具有以下语法。

int CALLBACK WinMain(

_In_ HINSTANCE hInstance,

_In_opt_ HINSTANCE hPrevInstance,

_In_ LPSTR lpCmdLine,

_In_ int nCmdShow

);

有关此函数的参数和返回值的信息,请参阅 WinMain 入口点。

备注

所有这些额外的词,例如 CALLBACK 、或 HINSTANCE _In_ 。 传统的 Windows API 广泛使用 typedef 和预处理器宏来抽象掉某些类型的详细信息和特定于平台的代码,例如调用约定、 __declspec 声明和编译器杂注。 在 Visual Studio 中,可以使用 IntelliSense 快速信息 功能来查看这些 typedef 和宏定义的内容。 将鼠标悬停在感兴趣的字词上,或选择它, 然后按 ctrl + K , ctrl + I 获取包含定义的小的弹出窗口。 有关详细信息,请参阅使用 IntelliSense。 参数和返回类型通常使用 SAL 批注 来帮助您捕获编程错误。 有关详细信息,请参阅 使用 SAL 注释减少 C/c + + 代码缺陷。

Windows 桌面程序需要 <>。 定义 TCHAR 宏, wchar_t 如果在项目中定义了 UNICODE 符号,则该宏将最终解析为,否则它将解析为 char 。 如果你始终启用了 UNICODE 生成,则无需 TCHAR,只需直接使用即可 wchar_t 。

#include

#include

除了 WinMain 函数,每个 Windows 桌面应用程序还必须具有一个窗口过程函数。 此函数通常名为 WndProc ,但你可以将其命名为你喜欢的任何名称。 WndProc 具有以下语法。

LRESULT CALLBACK WndProc(

_In_ HWND hWnd,

_In_ UINT message,

_In_ WPARAM wParam,

_In_ LPARAM lParam

);

在此函数中,你将编写代码来处理应用程序在发生 事件 时从 Windows 接收的 消息 。 例如,如果用户在您的应用程序中选择了 "确定" 按钮,Windows 将向您发送一条消息,您可以在函数内编写 WndProc 执行任何适当工作的代码。 这称为 处理 事件。 仅处理与应用程序相关的事件。

有关详细信息,请参阅 窗口过程。

向 WinMain 函数添加功能

在 WinMain 函数中,您将填充类型为 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, 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, IDI_APPLICATION);

有关上述结构的字段的信息,请参阅 WNDCLASSEX。

向 Windows 注册, WNDCLASSEX 使其了解你的窗口以及如何向其发送消息。 使用 RegisterClassEx 函数,并将窗口类结构作为参数传递。 使用 _T 宏是因为我们使用的是 TCHAR 类型。

if (!RegisterClassEx(&wcex))

{

MessageBox(NULL,

_T("Call to RegisterClassEx failed!"),

_T("Windows Desktop Guided Tour"),

NULL);

return 1;

}

现在可以创建窗口了。 使用 CreateWindow 函数。

static TCHAR szWindowClass[] = _T("DesktopApp");

static TCHAR szTitle[] = _T("Windows Desktop Guided Tour Application");

// The parameters to CreateWindow explained:

// 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 = 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("Windows Desktop Guided Tour"),

NULL);

return 1;

}

此函数返回一个 HWND ,它是窗口的句柄。 句柄有些类似于 Windows 用来跟踪打开的窗口的指针。 有关详细信息,请参阅 Windows 数据类型。

此时,已创建了窗口,但我们仍需要告知 Windows 使其可见。 这就是此代码的作用:

// The parameters to ShowWindow explained:

// hWnd: the value returned from CreateWindow

// nCmdShow: the fourth parameter from WinMain

ShowWindow(hWnd,

nCmdShow);

UpdateWindow(hWnd);

显示的窗口不包含太多内容,因为您尚未实现 WndProc 函数。 换句话说,应用程序尚未处理 Windows 现在正在向其发送的消息。

为了处理这些消息,我们首先添加一个消息循环来侦听 Windows 发送的消息。 当应用程序收到消息时,此循环会将它调度到要 WndProc 处理的函数。 该消息循环类似于以下代码。

MSG msg;

while (GetMessage(&msg, NULL, 0, 0))

{

TranslateMessage(&msg);

DispatchMessage(&msg);

}

return (int) msg.wParam;

此时, WinMain 函数类似于以下代码。

int WINAPI WinMain(HINSTANCE hInstance,

HINSTANCE hPrevInstance,

LPSTR lpCmdLine,

int nCmdShow)

{

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, 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, IDI_APPLICATION);

if (!RegisterClassEx(&wcex))

{

MessageBox(NULL,

_T("Call to RegisterClassEx failed!"),

_T("Windows Desktop Guided Tour"),

NULL);

return 1;

}

// Store instance handle in our global variable

hInst = hInstance;

// The parameters to CreateWindow explained:

// 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 dows not have a menu bar

// hInstance: the first parameter from WinMain

// NULL: not used in this application

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("Windows Desktop Guided Tour"),

NULL);

return 1;

}

// The parameters to ShowWindow explained:

// hWnd: the value returned from CreateWindow

// nCmdShow: the fourth parameter from WinMain

ShowWindow(hWnd,

nCmdShow);

UpdateWindow(hWnd);

// Main message loop:

MSG msg;

while (GetMessage(&msg, NULL, 0, 0))

{

TranslateMessage(&msg);

DispatchMessage(&msg);

}

return (int) msg.wParam;

}

向 WndProc 函数添加功能

若要启用 WndProc 函数以处理应用程序收到的消息,请实现 switch 语句。

要处理的一项重要消息是 WM_PAINT 消息。 WM_PAINT当必须更新其显示窗口的一部分时,应用程序将接收该消息。 如果用户将窗口移到窗口的前面,则会发生此事件,然后再将其移开。 您的应用程序不知道这些事件发生的时间。 只有 Windows 知道,因此它将使用消息通知您的应用程序 WM_PAINT 。 第一次显示窗口时,必须对其进行更新。

要处理 WM_PAINT 消息,首先应调用 BeginPaint,然后处理所有的逻辑以在窗口中布局文本、按钮和其他控件,然后调用 EndPaint。 对于应用程序,开始调用和结束调用之间的逻辑显示字符串 "Hello,Windows desktop!" “Hello,World!”。 在下面的代码中, TextOut 函数用于显示字符串。

PAINTSTRUCT ps;

HDC hdc;

TCHAR greeting[] = _T("Hello, Windows desktop!");

switch (message)

{

case WM_PAINT:

hdc = BeginPaint(hWnd, &ps);

// Here your application is laid out.

// For this introduction, we just print out "Hello, Windows desktop!"

// in the top left corner.

TextOut(hdc,

5, 5,

greeting, _tcslen(greeting));

// End application-specific layout section.

EndPaint(hWnd, &ps);

break;

}

HDC 在代码中,是用于在窗口的工作区中进行绘制的设备上下文的句柄。 使用 BeginPaint 和 EndPaint 函数来准备并完成工作区中的绘图。 BeginPaint 返回用于在客户端区域中绘制的显示设备上下文的句柄; EndPaint 结束绘制请求并释放设备上下文。

应用程序通常会处理许多其他消息。 例如,在首次创建窗口时 WM_CREATE ,当窗口关闭时 WM_DESTROY 。 以下代码显示基本但完整的 WndProc 函数。

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

{

PAINTSTRUCT ps;

HDC hdc;

TCHAR greeting[] = _T("Hello, Windows desktop!");

switch (message)

{

case WM_PAINT:

hdc = BeginPaint(hWnd, &ps);

// Here your application is laid out.

// For this introduction, we just print out "Hello, Windows desktop!"

// in the top left corner.

TextOut(hdc,

5, 5,

greeting, _tcslen(greeting));

// End application specific layout section.

EndPaint(hWnd, &ps);

break;

case WM_DESTROY:

PostQuitMessage(0);

break;

default:

return DefWindowProc(hWnd, message, wParam, lParam);

break;

}

return 0;

}

生成代码

正如我们所承诺的,以下是适用于工作应用程序的完整代码。

生成此示例

在编辑器中删除在 HelloWindowsDesktop 中输入的任何代码。 复制此示例代码,然后将其粘贴到 HelloWindowsDesktop 中:

// HelloWindowsDesktop.cpp

// compile with: /D_UNICODE /DUNICODE /DWIN32 /D_WINDOWS /c

#include

#include

#include

#include

// Global variables

// The main window class name.

static TCHAR szWindowClass[] = _T("DesktopApp");

// The string that appears in the application's title bar.

static TCHAR szTitle[] = _T("Windows Desktop Guided Tour Application");

HINSTANCE hInst;

// Forward declarations of functions included in this code module:

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

int CALLBACK WinMain(

_In_ HINSTANCE hInstance,

_In_opt_ HINSTANCE hPrevInstance,

_In_ LPSTR lpCmdLine,

_In_ int nCmdShow

)

{

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, 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, IDI_APPLICATION);

if (!RegisterClassEx(&wcex))

{

MessageBox(NULL,

_T("Call to RegisterClassEx failed!"),

_T("Windows Desktop Guided Tour"),

NULL);

return 1;

}

// Store instance handle in our global variable

hInst = hInstance;

// The parameters to CreateWindow explained:

// 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 = 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("Windows Desktop Guided Tour"),

NULL);

return 1;

}

// The parameters to ShowWindow explained:

// hWnd: the value returned from CreateWindow

// nCmdShow: the fourth parameter from WinMain

ShowWindow(hWnd,

nCmdShow);

UpdateWindow(hWnd);

// Main message loop:

MSG msg;

while (GetMessage(&msg, NULL, 0, 0))

{

TranslateMessage(&msg);

DispatchMessage(&msg);

}

return (int) msg.wParam;

}

// FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)

//

// PURPOSE: Processes messages for the main window.

//

// WM_PAINT - Paint the main window

// WM_DESTROY - post a quit message and return

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

{

PAINTSTRUCT ps;

HDC hdc;

TCHAR greeting[] = _T("Hello, Windows desktop!");

switch (message)

{

case WM_PAINT:

hdc = BeginPaint(hWnd, &ps);

// Here your application is laid out.

// For this introduction, we just print out "Hello, Windows desktop!"

// in the top left corner.

TextOut(hdc,

5, 5,

greeting, _tcslen(greeting));

// End application-specific layout section.

EndPaint(hWnd, &ps);

break;

case WM_DESTROY:

PostQuitMessage(0);

break;

default:

return DefWindowProc(hWnd, message, wParam, lParam);

break;

}

return 0;

}

在 “生成” 菜单上,选择 “生成解决方案” 。 编译结果应显示在 Visual Studio 的 " 输出 " 窗口中。

若要运行应用程序,请按 F5 。 包含文本 "Hello,Windows desktop!" 的窗口 文字的窗口。

恭喜! 您已经完成了本演练,并构建了传统的 Windows 桌面应用程序。

请参阅

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。