Windows编程---使用C/C++语言创建一个窗口

序言

记得刚学习C语言的时候,我还只能写出在“小黑框”里面运行的控制台程序。后来我了解到这种控制台程序属于命令行界面(CLI,Command-Line Interface),而我们经常看到的比如QQ、酷我音乐、各种浏览器软件都是图形用户界面(GUI,Graphical User Interface)。我当时就很好奇那些漂亮的桌面软件是如何创建出来的。但是苦于课业的繁忙,我只能利用课余的时间来了解一些关于GUI的编程信息,也就渐渐地接触到了Windows编程。
Windows编程历史悠久,从上个世纪八十年代DOS系统诞生以来,它的编程范式随着Windows的进化而进化。最初,我们只是编写简单的bat脚本命令来操作电脑。Windows的诞生,让DOS程序员见识到了GUI的魅力,越来越多的人都加入进来。

什么是窗口

我们要进行Windows编程,首先要明白什么是窗口。简单来讲,窗口就是一块区域,我们可以在上面进行绘制显示操作,将我们的UI逻辑显示出来。Windows本身就是一个窗口管理系统,桌面本身就是一个窗口。我们进行界面编程的第一步就是创建一个窗口。

创建窗口

编写主函数

首先,我们需要定义wWinMain函数作为入口点

int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
    ......
    return 0;
}

注册窗口类

第一步,我们需要注册窗口类。首先填写WNDCLASS或者WNDCLASSEX结构。这个结构体配置了窗口的全局属性,比如ICON图标,鼠标的样式,窗口背景色、窗口的过程函数等等。它的成员不必要全部填写。

WNDCLASSEX wc = { sizeof(WNDCLASSEX) };
wc.style = CS_VREDRAW | CS_HREDRAW;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(nullptr, IDI_APPLICATION);
wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
wc.hbrBackground = CreateSolidBrush(RGB(255, 255, 255));
wc.lpszMenuName = nullptr;
wc.lpszClassName = TEXT("MainWindow");

RegisterClassEx(&wc);

然后调用RegisterClassEx函数,完成窗口类的注册

创建窗口

窗口类注册完成以后我们就可以调用CreateWindow(Ex)函数来创建窗口了

HWND hWnd = CreateWindowEx(
    0,                        //扩展窗口风格,暂时设为0
    wc.lpszClassName,         //已注册的窗口类名称
    TEXT("Hello Windows"),    //窗口的标题
    dwStyle,                  //窗口的风格
    CW_USEDEFAULT, 
    CW_USEDEFAULT,
    CW_USEDEFAULT,
    CW_USEDEFAULT,            //窗口的位置信息
    nullptr, 
    nullptr, 
    nullptr, 
    nullptr);
    
ShowWindow(hWnd, SW_SHOWDEFAULT);//显示窗口

进入消息循环

MSG msg = {};
while(GetMessage(&msg, nullptr, 0, 0))
{
    TranslateMessage(&msg);
    DispatchMessage(&msg);
}

return static_cast<int>(msg.wParam);

这样窗口就成功创建了。

完整代码

#include <Windows.h>

// 如果创建的项目类型是“控制台应用程序”,可以添加下面两条预编译指令
// 第一条的意思是程序入口点是wWinMainCRTStartup函数,这样我们就可以使用wWinMain函数替代常见的main函数
// 第二条的意思是生成Windows程序,就是不带小黑框的图形界面程序
#pragma comment(linker, "/ENTRY:wWinMainCRTStartup")
#pragma comment(linker, "/SUBSYSTEM:WINDOWS")

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	// 在这里处理所有窗口消息
	switch (msg)
	{
	case WM_DESTROY:
		// 当窗口销毁时退出应用程序
		PostQuitMessage(0);
		break;
	default:
		return DefWindowProc(hWnd, msg, wParam, lParam);
	}
	return 0;
}

int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
	// 初始化窗口类结构体
	WNDCLASSEX wc = { sizeof(WNDCLASSEX) };
	wc.style = CS_VREDRAW | CS_HREDRAW;
	wc.lpfnWndProc = WndProc;
	wc.cbClsExtra = 0;
	wc.cbWndExtra = 0;
	wc.hInstance = hInstance;
	wc.hIcon = LoadIcon(nullptr, IDI_APPLICATION);
	wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
	wc.hbrBackground = CreateSolidBrush(RGB(255, 255, 255));
	wc.lpszMenuName = nullptr;
	wc.lpszClassName = TEXT("MainWindow");

	// 注册窗口类
	RegisterClassEx(&wc);

	// 创建窗口并显示窗口
	HWND hWnd = CreateWindowEx(0, wc.lpszClassName, TEXT("标题"), WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, nullptr, nullptr, nullptr, nullptr);
	ShowWindow(hWnd, SW_SHOWDEFAULT);

	// 进入消息循环
	MSG msg = {};
	while (GetMessage(&msg, nullptr, 0, 0))
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	return static_cast<int>(msg.wParam);
}

备注

2021年7月27日:完善示例代码。

  • 17
    点赞
  • 88
    收藏
    觉得还不错? 一键收藏
  • 9
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值