本节课我们将用C++ 写一个最简单的Windows 程序。

目录:

创建一个窗口

窗口消息

编写窗口过程

绘制窗口

关闭窗口

管理应用程序状态

代码如下:

#ifndef UNICODE
#define UNICODE
#endif #include <windows.h> LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR pCmdLine, int nCmdShow)
{
// Register the window class.
const wchar_t CLASS_NAME[] = L"Sample Window Class"; WNDCLASS wc = { }; wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = CLASS_NAME; RegisterClass(&wc); // Create the window. HWND hwnd = CreateWindowEx(
, // Optional window styles.
CLASS_NAME, // Window class
L"Learn to Program Windows", // Window text
WS_OVERLAPPEDWINDOW, // Window style // Size and position
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, // Parent window
NULL, // Menu
hInstance, // Instance handle
NULL // Additional application data
); if (hwnd == NULL)
{
return ;
} ShowWindow(hwnd, nCmdShow); // Run the message loop. MSG msg = { };
while (GetMessage(&msg, NULL, , ))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
} return ;
} LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_DESTROY:
PostQuitMessage();
return ; case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps); FillRect(hdc, &ps.rcPaint, (HBRUSH) (COLOR_WINDOW+)); EndPaint(hwnd, &ps);
}
return ; }
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

 1. wWinMain  是程序的入口点,当程序开始的时候,它注册一些信息关于窗口的一些行为,其中最重要的是函数的地址,

在这个Demo中名字叫做 WindowProc,这个函数中定义了这个窗口的一些行为,比如它的外观,它如何与用户交互,等等。

2. 接下来程序创建了一个window窗口以及接受一个句柄 handler来识别窗口。

3. 如果这个窗口创建成功,程序将会进入一个循环,直到用户关闭这个窗口和退出这个应用程序。

Tips:

尽管我们说这个应用程序的大多数逻辑被定义了,但是这个程序没有很明显地调用这个windowProc 函数。

Windows通过传递一系列消息与您的程序通信。while循环中的代码驱动此进程。

每次程序调用DispatchMessage函数,它间接地使每一次的消息调用WindowProc函数。

创建一个窗口

window Classes

一个窗口类定义了一些行为的设置和一些窗口公用的方法。

例如:一个组合中的这些按钮,当用户单击某个按钮的时候每一个按钮都有一个简单的行为。

当然,按钮并不是完全相同的,每个按钮显示自己的文本字符串,并且有自己的屏幕坐标。

对于每个窗口来说唯一的数据称为实例数据。

每个窗口都必须与一个窗口类相关联,即使您的程序只创建该类的一个实例。

重要的是要明白,一个窗口类是不是在C++意义上的一个类。

相反,它是由操作系统内部使用的数据结构。窗口类在运行时注册到系统中。

登记一个新的窗口类,先填一个WNDCLASS数据结构:

 // Register the window class.
const wchar_t CLASS_NAME[] = L"Sample Window Class"; WNDCLASS wc = { }; wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = CLASS_NAME;

你必须设置这些结构成员:

lpfnWndProc:是指向一个应用程序定义的函数称为窗口程序或“window proc.”这个窗口程序定义了大部分的窗口行为。稍后我们将详细检查窗口过程。现在,把这个当作一个前向参考。

hInstance:是应用程序实例句柄。从wWinMain的程序参数得到这个值

lpszClassName:是一个字符串,标识窗口类

类名对当前进程是局部的,因此名称只在进程中是惟一的。但是,标准Windows控件也有类。如果使用这些控件中的任何一个,则必须选择与控件类名不冲突的类名。例如,按钮控件的窗口类被命名为“按钮”。

WNDCLASS 结构的其他成员不在这里。您可以将它们设置为零,如本例所示,或填充它们。MSDN文档的结构进行了详细描述。

其次,通过RegisterClass函数的WNDCLASS结构的地址。这个函数用操作系统注册窗口类。

RegisterClass(&wc);

创建窗口

要创建一个新的实例化窗口,调用CreateWindowEx 函数

HWND hwnd = CreateWindowEx(
, // Optional window styles.
CLASS_NAME, // Window class
L"Learn to Program Windows", // Window text
WS_OVERLAPPEDWINDOW, // Window style // Size and position
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, // Parent window
NULL, // Menu
hInstance, // Instance handle
NULL // Additional application data
); if (hwnd == NULL)
{
return ;
}

Tips:

第一个参数:让你对这个窗口指定一些行为选项,设置为0指定默认的行为

第二个参数:CLASS_NAME 是这个窗口的类,当你创建窗口的时候定义

第三个参数:窗口文本使用不同类型的窗口以不同的方式使用。如果窗口有标题栏,则文本将显示在标题栏中。

第四个参数:窗口样式是定义窗口外观的一组标志。静态不变的 WS_OVERLAPPEDWINDOW 实际上是几个标记结合位或。

这些标志一起给窗口一个标题栏,一个边界,一个系统菜单,最小化和最大化按钮。这组标志是顶级应用程序窗口最常用的样式。

第五个参数:位置和大小,CW_USEDEFAULT 表示使用默认位置和大小。

第六个参数:下一个参数为新窗口设置父窗口或所有者窗口。如果您正在创建子窗口,则设置父级。对于顶级窗口,将此设置为null。

第七个参数:对于一个应用程序窗口来说,下个参数为窗口定义菜单。这个例子中没有使用菜单,所以这个值是NULL

第八个参数:hInstance 是程序的实例句柄,前面描述的

第九个参数:最后一个参数是一个空类型的任意数据指针。你可以使用此值将数据结构传递给窗口过程。在管理应用程序状态的部分中,我们将展示一种可能的方法来使用这个参数。

CreateWindowEx函数返回一个句柄到新窗口,如果函数失败则返回0。

要使窗口可见通过窗口句柄的ShowWindow函数:

ShowWindow(hwnd, nCmdShow);

hwnd 参数是CreateWindowEx 函数返回的窗口句柄, 这个nCmdShow参数可用于最小化和最大化一个窗口。

操作系统将该值传递给程序通过wWinMain函数

下面是创建窗口的一个完整例子:

记住,WindowProc 仍然只是一个函数声明。

// Register the window class.
const wchar_t CLASS_NAME[] = L"Sample Window Class"; WNDCLASS wc = { }; wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = CLASS_NAME; RegisterClass(&wc); // Create the window. HWND hwnd = CreateWindowEx(
, // Optional window styles.
CLASS_NAME, // Window class
L"Learn to Program Windows", // Window text
WS_OVERLAPPEDWINDOW, // Window style // Size and position
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, // Parent window
NULL, // Menu
hInstance, // Instance handle
NULL // Additional application data
); if (hwnd == NULL)
{
return ;
} ShowWindow(hwnd, nCmdShow);

恭喜你现在已经创建了一个窗口,这个窗口不包含任何内容也不包括任何用户交互。

在真正的GUI应用程序中,窗口一般会响应来自用户和操作系统的事件。

下一节将介绍窗口消息是如何提供这话总共交互的。

0x02 译文:Windows桌面应用Win32第一个程序的更多相关文章

  1. 0x01 译文:Windows桌面应用Win32开发简介

    本节课将简单介绍下使用C++开发Windows桌面应用的一些基础知识 目录: 准备你的开发环境 Windows 代码规范 操作字符串 什么是一个Window? WinMain:程序的入口点 1. 准备 ...

  2. 0x00 译文:Windows桌面应用入门选择

    当你想要创建一个新的桌面应用的时候,第一个你需要做的决定是使用Win32 和COM 还是使用.NET两个选项. C++ 和 Win32 使你“离奖牌更近”,并使你可以获得最佳的应用性能..NET 使你 ...

  3. Windows创建Sciter的第一个程序.HelloWorld

    介绍什么的就免了.直接进入正题 平台: Windows 10 IDE : Visual studio 2017 首先从官网下载最新的SDK,https://sciter.com/download/ 创 ...

  4. Win32++:可替代MFC的Windows桌面应用开发框架

    写在前面 有过Win32编程经验的朋友都知道,使用Windows提供的API开发桌面应用是相当繁琐的,创建一个功能简单能接收并处理消息的窗口至少也得几百行代码.创建一个可视化的窗口一般要以下几个步骤: ...

  5. 不管服不服 Windows仍是全球第一大桌面系统

    不管服不服 Windows仍是全球第一大桌面系统 近日,根据来自市场调研机构 Net Applications 公布的统计数据显示,Windows 依然是世界上排名第一的操作系统,而且未来将很难被打破 ...

  6. 完美脱离Windows!! Linux发行版第一系统 Manjaro 开箱教程 :)

    没兴趣? 来几张图敌敌畏(kai kai wei) !! 0x00 预览(zhuangbi) 0x01 引言(feihua) 当我们想用ssh工具时,不像telnet那样是系统自带的软件,需要额外安装 ...

  7. Flutter Windows 桌面端支持进入稳定版

    Flutter 创建伊始,我们就致力于打造一个能够构建精美的.可高度定制的.并且可以编译为机器码的跨平台应用解决方案,以充分发挥设备底层硬件的全部图形渲染能力.今天,Flutter 对 Windows ...

  8. Cocos2dx集成于windows桌面窗口程序的步骤

    2D游戏需要做编辑器,而编辑器总是希望可以复用游戏中的逻辑来运行场景试看效果. 对于cocos2dx开发的程序,这个需求可以描述为: 实现一种方法,在桌面窗口程序中的某个控件上显示cocos2dx的场 ...

  9. Linux系统VPS/服务器安装WINDOWS桌面环境可以采用的几个方法

    我们公司的几个项目需要在WINDOWS桌面类型的界面操作,哪怕仅有一个浏览器远程操作也是可以的,我们运维部门得到的任务就是需要能在已有的Linux系统的VPS.服务器环境中能够远程操作,至少需要能可以 ...

随机推荐

  1. mysql常用基础操作语法(十一)~~字符串函数【命令行模式】

    注:sql的移植性比较强,函数的移植性不强,一般为数据库软件特有,例如mysql有mysql的函数,oracle有oracle的函数. 1.concat连接字符串: 从上图中可以看出,直接使用sele ...

  2. 硬盘分区表格式GUID和MBR知识普及

    我们的电脑硬盘分区格式一共有两种,一种是GUID(GPT),一种是MBR 如果你的电脑原装系统是win8或者以上的,那么他的硬盘分区表格式为GUID(GPT)格式的:如果是win7以下的,那么一般就是 ...

  3. Netty未来展望

    作为<Netty权威指南(第2版)>的结尾章节,和读者朋友们一起展望下Netty的未来. 1应用范围 随着大数据.互联网和云计算的发展,传统的垂直架构逐渐将被分布式.弹性伸缩的新架构替代. ...

  4. freemarker中的left_pad和right_pad

    freemarker中的left_pad和right_pad 1.简易说明 (1)left_pad 距左边 (2)right_pad 距右边 (3)当仅仅只有一个参数时,插入的是空白:当有两个参数时, ...

  5. 使用VLC和live555MediaServer搭建RTSP服务器

    一.使用VLC搭建 服务端 1.打开"媒体--流"选项,如图所示:  2.点击"添加"按钮选择流媒体文件,然后点击"串流"按钮  3.点击& ...

  6. 芝麻HTTP:Python爬虫入门之正则表达式

    1.了解正则表达式 正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符.及这些特定字符的组合,组成一个"规则字符串",这个"规则字符串"用来 ...

  7. 如何通过java反射的方式对java私有方法进行单元测试

    待测试的私有方法: import org.testng.Assert;import org.testng.annotations.BeforeClass;import org.testng.annot ...

  8. Qtree3题解(树链剖分(伪)+线段树+set)

    外话:最近洛谷加了好多好题啊...原题入口 这题好像是SPOJ的题,挺不错的.看没有题解还是来一篇... 题意: 很明显吧.. 题解: 我的做法十分的暴力:树链剖分(伪)+线段树+\(set\)... ...

  9. [HDU5799]This world need more Zhu

    题面戳我 题意: 给定一棵树,m次操作,每次询问某一棵子树中,或者是某一条路径上,出现次数为a的所有数字之和与出现次数为b的所有数字之和的gcd 原题表述:the \(\gcd\) of the su ...

  10. C#利用substring按指定长度分割字符串

    这几天学习分析声音的波形数据,接收到的是十六进制的数据,需要将数据转换成十进制再绘图,这个过程涉及到字符串的分割,正好可以促进自己对C#相关知识的学习.说到分割字符串,我首先想到的是Split,但根据 ...