02 使用Windows API创建窗口

1、打开Visual Studio 2017,其他Visual Studio版本也可以

2、新建一个Windows桌面向导项目,或者Win32应用程序项目都可以

3、新建项目时,选择Windows应用程序,并勾上空项目

4、新加源文件,注意因为WindowsAPI都是C语言实现,所以,新加文件的后缀要是*.c文件

5、实现功能,源码如下:

必要解释:

  1. WM_PAINT 消息:当窗口客户区的一部分或者全部变为“ 无效” 时, 系统会发送 WM_PAINT 消息,通知应用程序重新绘制窗口。当窗口刚创建的时候, 整个客户区都是无效的。因为这个时候程序还没有在窗口上绘制任何东西,当调用 UpdateWindow 函数时,会发送 WM_PAINT 消息给窗口过程,对窗口进行刷新。当窗口从无到有、改变尺寸、最小化后再恢复、被其他窗口遮盖后再显示时, 窗口的客户区都将变为无效, 时系统会给应用程序发送 WM_PAINT 消息,通知应用程序重新绘制。
  2. WM_CLOSE 消息:对 WM_CLOSE 消息的响应并不是必须的,如果应用程序没有对该消息进行响应, 系统将把这条消息传给 DefWindowProc 函数而 DefWindowProc 函数则调用 DestroyWindow 函数来响应这条 WM_CLOSE 消息。
  3. WM_DESTROY消息:DestroyWindow 函数在销毁窗口后,会给窗口过程发送 WM_DESTROY消息,我们在该消息的响应代码中调用 PostQuitMessage 函数。PostQuitMessage函数向应用程序的消息队列中投递一条 WM_QUIT 消息并返回。我们在前边介绍过,GetMessage 函数只有在收到 WM_QUIT 消息时才返回 0,此时消息循环才结束,程序退出。要想让程序正常退出, 我们必须响应 WM_DESTROY 消息,并在消息响应代码中调用PostQuitMessage,向应用程序的消息队列中投递 WM_QUIT 消息。传递给 PostQuitMessage函数的参数值将作为 WM_QUIT 消息的 wParam 参数,这个值通常用做 WinMain 函数的返回值。
  4. BeginPaintEndPaint 函数:BeginPaint 函数的第 1 个参数是窗口的句柄,第二个参数是 PAINTSTRUCT 结构体的指针,该结构体对象用于接收绘制的信息。在 调 用 BeginPaint 时,如果客户区的背景还没有被擦除, 那么 BeginPaint 会 发 送WM_ERASEBKGND 消息给窗口, 系统就会使用 WNDCLASS 结构体的 hbrBackground 成员指定的画刷来擦除背景。在响应 WM_PAINT 消息的代码中, 要得到窗口的 DC, 必须调用 BeginPaint 函数。BeginPaint 函数也只能在 WM_PAINT 消息的响应代码中使用, 在其他地方, 只能使用GetDC 来得到 DC 的句柄。 另外, BeginPaint 函数得到的 DC, 必须用 EndPaint 函数去释放。
  5. TextOut函数: 调用 TextOut 函数在(300, 300) 的位置输出一个字符串“Hello,MFC!”。当发生重绘时,窗口中的文字和图形都会被擦除。在擦除背景后,TextOut 函数又一次执行,在窗口中再次绘制出 “Hello,MFC!”。 这个过程对用户来说是透明的,用户并不知道程序执行的过程,给用户的感觉就是你在响应 WM_PAINT 消息的代码中输出的文字或图形始终保持在窗口中。换句话说,如果我们想要让某个图形始终在窗口中显示, 就应该将图形的绘制操作放到响应 WM_PAINT 消息的代码中。
  6. DefWindowProc函数:调用默认的窗口过程,对应用程序没有处理的其他消息提供默认处理。对于大多数的消息,应用程序都可以直接调用 DefWindowProc函数进行处理。在编写窗口过程时,应该将 DefWindowProc 函数的调用放到 default 语句中,并将该函数的返回值作为窗口过程函数的返回值。
  7. SendMessage发送“不进队消息”,直接把消息发送给窗口,并调用该窗口的窗口过程函数进行处理。在窗口过程对消息处理完毕后,返回处理结果。
  8. PostMessage发送“进队消息”。将消息放入与创建窗口的线程相关联的消息队列后立即返回。
/* 注意此时必须包含windows.h文件 */
#include <windows.h>

//窗口过程函数
LRESULT CALLBACK DealMessage(HWND hWnd, //窗口句柄,消息所属的窗口
	UINT uMsg,	//消息标志
	WPARAM wParam, //附加信息
	LPARAM lParam
	)
{
	switch (uMsg)
	{
	case WM_LBUTTONDOWN: //鼠标左键按下
		MessageBox(hWnd, TEXT("ABC"), TEXT("鼠标左键按下"), MB_OK);
		break;

	case WM_PAINT:
	{
    		PAINTSTRUCT ps; //绘图结构体

		HDC dc = BeginPaint(hWnd, &ps); //开始绘图
		TCHAR * p = L"aaaaaaa"; //转为宽字节
		TextOutW(dc, 30, 30, p, wcslen(p));//输出

		EndPaint(hWnd, &ps);//结束绘图
		break;
	}

	case WM_DESTROY:
		PostQuitMessage(2); //WM_QUIT, 给主函数 return msg.wParam
		break;
	default:
                /* 该函数对未被处理的消息提供默认响应 */
		return DefWindowProc(hWnd, uMsg, wParam, lParam);
	}


	return 0;
}


//WINAPI: 修饰函数,规定函数参数入栈从右往左,函数调用完毕,自动清理堆栈
//CALLBACK
int WINAPI WinMain(HINSTANCE hInstance, //应用程序实例
	HINSTANCE hPrevInstance, //上一个应用程序实例,不用
	LPSTR lpCmdLine, //命令行参数
	int nCmdShow //窗口显示的样式, 最大化,最小化
	)
{
	/*
	1、定义入口函数WinMain()
	2、创建一个窗口
	a)设计窗口类WNDCLASS(给成员变量赋值)
	b)注册窗口类
	c)创建窗口类
	d)显示和更新窗口
	3、消息循环
	4、窗口过程函数
	*/

	//a)设计窗口类WNDCLASS(给成员变量赋值)
	WNDCLASS wc;
	wc.cbClsExtra = 0; //类的附加信息
	wc.cbWndExtra = 0; //窗口附加信息
						//获取系统默认的白色画刷
	wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); //背景色,必须写

	wc.hCursor = LoadCursor(NULL, IDC_HELP); //加载系统默认光标

	wc.hIcon = LoadIcon(NULL, IDI_WARNING); //加载系统默认图标

	wc.hInstance = hInstance; //应用程序实例
	wc.lpfnWndProc = DealMessage; //窗口过程函数名字,消息处理函数

	wc.lpszClassName = TEXT("abc"); //类的名字
	wc.lpszMenuName = NULL; //菜单名字
	wc.style = nCmdShow; //显示风格

	//b)注册窗口类, 告诉系统窗口过程函数的入口地址
	RegisterClass(&wc);

	//c)创建窗口类
	HWND hWnd = CreateWindow(TEXT("abc"), TEXT("hello, windwos"),                 WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
		NULL, NULL, hInstance, NULL);

	//d)显示和更新窗口
	ShowWindow(hWnd, SW_SHOWNORMAL);
	UpdateWindow(hWnd);

	//消息循环
	MSG msg;
	//如果接受到WM_QUIT, 返回0, 退出
	//如果出错,返回-1,不退出
	while (GetMessage(&msg, NULL, 0, 0))
	{
		//翻译工作
		//虚拟按键转为标准字符WM_CHAR
		TranslateMessage(&msg);

		//给操作系统分发消息
		DispatchMessage(&msg);
	}

	return msg.wParam;

}​​

6、按下左键,效果如下:

  • 4
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Chiang木

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值