沙朗镇做网站公司,企业策划营销中心,兰州市一地发布提醒,制作简历的免费网站文章转载于#xff1a;https://blog.csdn.net/u011583927/article/details/54896961 如何创建一个最简单的Windows桌面应用程序 (C) 最近刚开始学习C/C开发Windows应用程序#xff0c;这里将会以零基础的视角把学习过程完全记录下来。如果你也刚刚起步#xff0c;那本文一定…文章转载于https://blog.csdn.net/u011583927/article/details/54896961 如何创建一个最简单的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。单击“添加”。 添加引用 我们的应用程序需要使用许多现有定义才能完成所需功能针对我们的需求添加引用如下其中前两个是必须的 [cpp] view plain copy #include windows.h #include stdlib.h #include string.h #include tchar.h WinMain函数 正如每个 C/C控制台应用程序在起始点必须具有 main 函数每个基于 Win32 的应用程序的函数也必须具有 WinMain 函数。WinMain就相当于是入口函数并且具有固定的语法 [cpp] view plain copy int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow); 实现WinMain函数时内部逻辑大体相同主要有以下几部分 1.创建描述窗体信息的窗口类结构WNDCLASSEX 如何创建一个 WNDCLASSEX 类型的窗口类结构下面的代码演示了一个典型的窗口类结构WNDCLASSEX 的定义 [cpp] view plain copy //创建 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_WINDOW1); wcex.lpszMenuName NULL; wcex.lpszClassName szWindowClass; wcex.hIconSm LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_APPLICATION)); 对于初学者我们不用过分纠结代码的细节暂时从宏观上把控。我们需要知道此结构包含关于窗口的信息例如应用程序图标、窗口背景色、标题栏中显示的名称、窗口过程函数的名称等。 2.对窗口类进行注册 现在已创建了窗口类必须进行注册。 使用 RegisterClassEx 函数并将窗口类结构作为参数传递。 [cpp] view plain copy RegisterClassEx(wcex); 3.创建并显示窗口 现在需要使用CreateWindow函数创建窗口 使用ShowWindow函数显示窗口 这部分也很好理解详见文末的代码 4.侦听消息 添加用于侦听操作系统所发送消息的消息循环。 当应用程序收到一条消息时此循环将该消息调度到 WndProc 函数。WndProc 函数用于对接收的消息进行处理我们下面会介绍到。 该消息循环类似于以下代码 [cpp] view plain copy // 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。 对于此应用程序开始调用和结束调用之间的逻辑是在窗口中显示字符串 “HelloWorld!”。 在以下代码中TextOut 函数用于显示字符串。 [cpp] view plain copy 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); // -----------------在这段代码对应用程序进行布局------------------------ // 对于此应用程序开始调用和结束调用之间的逻辑是在窗口中显示字符串 “HelloWorld!”。 // 请注意 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桌面应用程序 对于更多的细节代码中给出了详细注释。 [cpp] view plain copy // 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_WINDOW1); 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); // -----------------在这段代码对应用程序进行布局------------------------ // 对于此应用程序开始调用和结束调用之间的逻辑是在窗口中显示字符串 “HelloWorld!”。 // 请注意 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; }