热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

创建Win32应用程序(C++)

本演练演示如何创建基于Win32的简单基本应用程序,该应用程序在窗口中显示“Hello,World!”。您可以使用在此演练中开发的代码作为创建其他基于Win32的应用

本演练演示如何创建基于 Win32 的简单基本应用程序,该应用程序在窗口中显示“Hello, World!”。 您可以使用在此演练中开发的代码作为创建其他基于 Win32 的应用程序的模式。

Win32 API(也称为 Windows API)是用于创建 Windows 应用程序的基于 C 的框架。 有关 Win32 API 的更多信息,请参见 Windows API。

重要说明 重要事项

为了可以更加清楚地说明本文档内各步骤中的特定代码段,我们可能会省略一个有效应用程序所必需的某些代码语句,例如 include 指令和全局变量声明。 本文档末尾的示例一节显示了完整代码。



系统必备

若要完成本演练,你必须了解 C++ 语言的基础知识。

有关视频演示,请参见 Visual Studio 2008 文档中的 Video How to: Creating Win32 Applications (C++)(视频帮助:创建 Win32 应用程序 (C++))。



创建基于 Win32 的项目


  1. “文件”菜单上,单击“新建”,然后单击“项目”

  2. “新建项目”对话框的左侧窗格中,单击“已安装的模板”,单击“Visual C++”,然后选择“Win32”在中间窗格中,选择“Win32 项目”

    “名称”框中,键入项目名称,例如 win32app。 单击“确定”

  3. “Win32 应用程序向导”的“欢迎”页上,单击“下一步”

  4. 在“应用程序设置”页上的在“应用程序类型”下,选择“Windows 应用程序”。 “附加选项”下,选择“空项目” 单击“完成”创建项目。

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



启动基于 Win32 的应用程序


  1. 就像每个 C 应用程序和 C++ 应用程序都以 main 函数作为起点那样,每个基于 Win32 的应用程序同样必须要有WinMain 函数。 WinMain 具有以下语法。

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

    有关此函数的参数和返回值的信息,请参见 WinMain 函数。

  2. 由于应用程序代码必须使用现有定义,因此应将 include 语句添加到文件中。

    #include
    #include
    #include
    #include

  3. 除 WinMain 函数外,每个基于 Win32 的应用程序还必须具有一个窗口过程函数。 此函数通常名为WndProc WndProc 具有以下语法。

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

    此函数处理应用程序从操作系统接收的许多消息。 例如,在具有对话框(该对话框中有一个“确定”按钮)的应用程序中,如果用户单击该按钮,操作系统就会向该应用程序发送一条消息,告知已单击该按钮。 WndProc 负责响应该事件。 在此示例中,相应的响应可能是关闭该对话框。

    有关更多信息,请参见窗口过程。



向 WinMain 函数添加功能


  1. 在 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, 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));

    有关此结构的各字段的信息,请参见 WNDCLASSEX。

  2. 现在您已经创建一个窗口类,接下来必须将其注册。 使用 RegisterClassEx 函数,并将窗口类结构作为参数进行传递。

    if (!RegisterClassEx(&wcex)){MessageBox(NULL,_T("Call to RegisterClassEx failed!"),_T("Win32 Guided Tour"),NULL);return 1;}

  3. 现在可以创建一个窗口。 使用 CreateWindow 函数。

    static TCHAR szWindowClass[] = _T("win32app");
    static TCHAR szTitle[] = _T("Win32 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("Win32 Guided Tour"),NULL);return 1;
    }

    此函数返回 HWND,它是某个窗口的句柄。 有关更多信息,请参见 Windows 数据类型。

  4. 现在,使用下列代码来显示窗口。

    // The parameters to ShowWindow explained:
    // hWnd: the value returned from CreateWindow
    // nCmdShow: the fourth parameter from WinMain
    ShowWindow(hWnd,nCmdShow);
    UpdateWindow(hWnd);

    此时,所显示的窗口不会有太多内容,因为您尚未实现 WndProc 函数。

  5. 现在添加一个消息循环以侦听操作系统发送的消息。 如果应用程序收到一条消息,则此循环会将该消息调度至WndProc 函数以接受处理。 消息循环类似于下列代码。

    MSG msg;while (GetMessage(&msg, NULL, 0, 0)){TranslateMessage(&msg);DispatchMessage(&msg);}return (int) msg.wParam;

    有关消息循环中各结构和函数的更多信息,请参见 MSG、GetMessage、TranslateMessage 和DispatchMessage。

    此时,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, 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));if (!RegisterClassEx(&wcex)){MessageBox(NULL,_T("Call to RegisterClassEx failed!"),_T("Win32 Guided Tour"),NULL);return 1;}hInst = hInstance; // Store instance handle in our global variable// 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 applicationHWND 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;}// The parameters to ShowWindow explained:// hWnd: the value returned from CreateWindow// nCmdShow: the fourth parameter from WinMainShowWindow(hWnd,nCmdShow);UpdateWindow(hWnd);// Main message loop:MSG msg;while (GetMessage(&msg, NULL, 0, 0)){TranslateMessage(&msg);DispatchMessage(&msg);}return (int) msg.wParam;
    }



向 WndProc 函数添加功能


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

    要处理的第一条消息是 WM_PAINT 消息。 如果必须更新所显示的应用程序窗口的一部分,该应用程序就会收到此消息。(首次显示该窗口时,必须将其全部更新。)

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

    PAINTSTRUCT ps;
    HDC hdc;
    TCHAR greeting[] = _T("Hello, World!");switch (message)
    {
    case WM_PAINT:hdc = BeginPaint(hWnd, &ps);// Here your application is laid out.// For this introduction, we just print out "Hello, World!"// in the top left corner.TextOut(hdc,5, 5,greeting, _tcslen(greeting));// End application-specific layout section.EndPaint(hWnd, &ps);break;
    }

  2. 应用程序通常会处理许多其他消息,例如 WM_CREATE 和 WM_DESTROY。 下列代码展示了一个基本但完整的WndProc 函数。

    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:hdc = BeginPaint(hWnd, &ps);// Here your application is laid out.// For this introduction, we just print out "Hello, World!"// 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;
    }




示例

生成此示例

  1. 创建本演练中之前“创建基于 Win32 的项目”中的基于 Win32 的项目。

  2. 复制这些步骤之后的代码,然后将其粘贴到 GT_HelloWorldWin32.cpp 源文件中。

  3. “生成”菜单上,单击“生成解决方案”

  4. 若要运行该应用程序,请按 F5。 在显示屏的左上角应出现一个窗口,窗口中含有文本“Hello World!”。

Bb384843.collapse_all(zh-cn,VS.140).gif代码

// GT_HelloWorldWin32.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("win32app");// The string that appears in the application's title bar.
static TCHAR szTitle[] = _T("Win32 Guided Tour Application");HINSTANCE hInst;// Forward declarations of functions included in this code module:
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);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, 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));if (!RegisterClassEx(&wcex)){MessageBox(NULL,_T("Call to RegisterClassEx failed!"),_T("Win32 Guided Tour"),NULL);return 1;}hInst = hInstance; // Store instance handle in our global variable// 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 applicationHWND 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;}// The parameters to ShowWindow explained:// hWnd: the value returned from CreateWindow// nCmdShow: the fourth parameter from WinMainShowWindow(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, World!");switch (message){case WM_PAINT:hdc = BeginPaint(hWnd, &ps);// Here your application is laid out.// For this introduction, we just print out "Hello, World!"// 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;
}



请参见

任务

Win32 Windows 应用程序 (C++)


推荐阅读
  • 本文详细解析了使用C++实现的键盘输入记录程序的源代码,该程序在Windows应用程序开发中具有很高的实用价值。键盘记录功能不仅在远程控制软件中广泛应用,还为开发者提供了强大的调试和监控工具。通过具体实例,本文深入探讨了C++键盘记录程序的设计与实现,适合需要相关技术的开发者参考。 ... [详细]
  • NOIP2000的单词接龙问题与常见的成语接龙游戏有异曲同工之妙。题目要求在给定的一组单词中,从指定的起始字母开始,构建最长的“单词链”。每个单词在链中最多可出现两次。本文将详细解析该题目的解法,并分享学习过程中的心得体会。 ... [详细]
  • 开发笔记:实现1353表达式中的括号匹配(栈的应用) ... [详细]
  • Java Socket 关键参数详解与优化建议
    Java Socket 的 API 虽然被广泛使用,但其关键参数的用途却鲜为人知。本文详细解析了 Java Socket 中的重要参数,如 backlog 参数,它用于控制服务器等待连接请求的队列长度。此外,还探讨了其他参数如 SO_TIMEOUT、SO_REUSEADDR 等的配置方法及其对性能的影响,并提供了优化建议,帮助开发者提升网络通信的稳定性和效率。 ... [详细]
  • 题目解析给定 n 个人和 n 种书籍,每个人都有一个包含自己喜好的书籍列表。目标是计算出满足以下条件的分配方案数量:1. 每个人都必须获得他们喜欢的书籍;2. 每本书只能分配给一个人。通过使用深度优先搜索算法,可以系统地探索所有可能的分配组合,确保每个分配方案都符合上述条件。该方法能够有效地处理这类组合优化问题,找到所有可行的解。 ... [详细]
  • 在C语言中,指针的高级应用及其实例分析具有重要意义。通过使用 `&` 符号可以获取变量的内存地址,而 `*` 符号则用于定义指针变量。例如,`int *p;` 定义了一个指向整型的指针变量 `p`。其中,`p` 代表指针变量本身,而 `*p` 则表示指针所指向的内存地址中的内容。此外,指针在不同函数中可以具有相同的变量名,但其作用域和生命周期会有所不同。指针的灵活运用能够有效提升程序的效率和可维护性。 ... [详细]
  • 使用 ListView 浏览安卓系统中的回收站文件 ... [详细]
  • 在使用 Qt 进行 YUV420 图像渲染时,由于 Qt 本身不支持直接绘制 YUV 数据,因此需要借助 QOpenGLWidget 和 OpenGL 技术来实现。通过继承 QOpenGLWidget 类并重写其绘图方法,可以利用 GPU 的高效渲染能力,实现高质量的 YUV420 图像显示。此外,这种方法还能显著提高图像处理的性能和流畅性。 ... [详细]
  • 题目要求维护一个数列,并支持两种操作:一是查询操作,语法为QL,用于查询数列末尾L个数中的最大值;二是更新操作,用于修改数列中的某个元素。本文通过ST表(Sparse Table)优化查询效率,确保在O(1)时间内完成查询,同时保持较低的预处理时间复杂度。 ... [详细]
  • PHP预处理常量详解:如何定义与使用常量 ... [详细]
  • 本文深入解析了 Kuangbin 数学训练营中的经典问题——Ekka Dokka,并通过详细的代码示例和数学推导,探讨了该问题的多种解法及其应用场景。通过对算法的优化和扩展,本文旨在为读者提供全面的理解和实用的参考。 ... [详细]
  • 经过两天的努力,终于成功解决了半平面交模板题POJ3335的问题。原来是在`OnLeft`函数中漏掉了关键的等于号。通过这次训练,不仅加深了对半平面交算法的理解,还提升了调试和代码实现的能力。未来将继续深入研究计算几何的其他核心问题,进一步巩固和拓展相关知识。 ... [详细]
  • 洛谷 P4035 [JSOI2008] 球形空间生成器(高斯消元法 / 模拟退火算法)
    本文介绍了洛谷 P4035 [JSOI2008] 球形空间生成器问题的解决方案,主要使用了高斯消元法和模拟退火算法。通过这两种方法,可以高效地求解多维空间中的球心位置。文章提供了详细的算法模板和实现代码,适用于 ACM 竞赛和其他相关应用场景。数据范围限制在 10 以内,确保了算法的高效性和准确性。 ... [详细]
  • 解题心得:UVA1339(逻辑分析与字符串处理+排序算法)
    解题心得:UVA1339(逻辑分析与字符串处理+排序算法) ... [详细]
  • 深入剖析Java中SimpleDateFormat在多线程环境下的潜在风险与解决方案
    深入剖析Java中SimpleDateFormat在多线程环境下的潜在风险与解决方案 ... [详细]
author-avatar
爱智孝的蛋清汤
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有