windows程序设计(二):建立第一个视窗

创建一个视窗的具体步骤如下:
(1)注册窗口类RegisterClassEx
(2)创建窗口CreateWindowEx
(3)在桌面上显示窗口ShowWindow
(4)更新窗口客户区UpdateWindow
(5)进入无限的消息获取和循环处理。首先获取消息GetMessage,若有消息到达,则将消息分派回调函数DispatchMessage处理,如果返回的是WM_QUIT,则GetMessage函数返回FALSE,整个消息循环结束 。消息处理的具体过程在WndProc函数中进行

#include<stdio.h>
#include<Windows.h>

//窗口回调函数
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPreveInstance,
	LPSTR szCmdLine, int nCmdShow) {
	static TCHAR szAppName[] = TEXT("HelloWin");
	HWND hwnd;//窗口句柄
	MSG msg;//消息类型

	WNDCLASSEX wndclass; //用描述主窗口的参数填充WNDCLASSEX结构
	wndclass.cbSize = sizeof(wndclass); //结构的大小(必须定义结构大小)
	wndclass.style = CS_HREDRAW | CS_VREDRAW; //样式
	wndclass.lpfnWndProc = WndProc; //指向窗口过程函数指针
	wndclass.cbClsExtra = 0; //没有额外的类内存
	wndclass.cbWndExtra = 0; //没有额外的窗体内存
	wndclass.hInstance = hInstance;  //包含类的窗口过程的实例的句柄
	wndclass.hIcon = ::LoadIcon(NULL, IDI_APPLICATION);//使用预定义的图标
	wndclass.hCursor = ::LoadCursor(NULL, IDC_ARROW); //使用预定义光标
	wndclass.hbrBackground = (HBRUSH)::GetStockObject(WHITE_BRUSH);//使用白色背景画刷	
	wndclass.lpszMenuName = NULL;  //不指定菜单
	wndclass.lpszClassName = szAppName;  //窗口类的名称
	wndclass.hIconSm = NULL; //没有类的小图标
	::RegisterClassEx(&wndclass);//注册这个窗口类

	//创建主窗口
	hwnd = ::CreateWindowEx(
		0,  //dwExStyle, 扩展样式 
		szAppName, //lpClassName,类名
		"WindowsName",  //lpWindowName
		WS_OVERLAPPEDWINDOW, //dwStyle, 窗口风格
		CW_USEDEFAULT,  //X,初始X坐标
		CW_USEDEFAULT,  //Y,初始Y坐标
		CW_USEDEFAULT,  //nWight, 宽度
		CW_USEDEFAULT,  //nHight, 高度
		NULL,  //hWndParent, 父窗口句柄
		NULL,  //hMenu, 菜单句柄
		hInstance,  //hInstance, 程序实例句柄
		NULL   //ipParam,用户数据
	);
	//若窗口句柄为空,则创建失败
	if (NULL == hwnd) { 
		::MessageBox(NULL, "创建窗口失败", "error", MB_OK);
		return -1;
	}

	//显示窗口
	::ShowWindow(hwnd, nCmdShow);
	//更新窗口
	::UpdateWindow(hwnd);

	//从操作系统的消息队列中不断的捡取消息
	while (::GetMessage(&msg, NULL, 0, 0)) {
		::TranslateMessage(&msg); //软键盘转化消息
		::DispatchMessage(&msg);//将消息发送到窗体中
	}
	return	msg.wParam;//当GetMessage返回0时程序结束
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) {
	HDC hdc;
	PAINTSTRUCT ps;
	RECT rect;

	switch (message) {
	case WM_CREATE:
		return 0;
	case WM_PAINT:
		hdc = BeginPaint(hwnd, &ps);
		GetClientRect(hwnd, &rect);
		DrawText(hdc, TEXT("Hello windows32SDK"), -1, &rect,
			DT_SINGLELINE|DT_CENTER|DT_VCENTER);
		EndPaint(hwnd, &ps);
		return 0;
	case WM_DESTROY:  //正在销毁窗口
	    //向消息序列投递一个WM_QUIT消息,促使GetMessage函数返回0,结束消息循环
		::PostQuitMessage(0);
		return 0;
	}
	return ::DefWindowProc(hwnd, message, wparam, lparam);
}

在程序中WNDCLASSEX 类型是包含窗口信息,其结构是类似于WNDCLASS结构。有两个区别。WNDCLASSEX包括cbSize成员和hIconSm成员,该成员指定结构的大小,而hIconSm成员包含与窗口类关联的小图标的句柄。HWND类型定义窗口,MSG类型定义所传递的消息。通过展示窗口ShowWindow函数将注册的窗体展示在桌面上,通过UpdateWindow函数将消息回调函数中的操作更新,GetMessage函数则负责消息的接收和发送。

对于窗口回调函数WndProc函数的返回值类型为LRESULT,该类型为处理消息值指定的消息的窗口过程的返回值,在其中使用switch—case语句来进行相关消息的处理。进入WM_PAINT分支,意味着调整后的大小要重新画出BeginPaint函数开始绘制视窗,GetClientRect取得视窗区域显示大小,DrawText显示字符,EndPaint结束绘制视窗。

程序运行结果如下所示:
可以拖动改变其大小,但文字仍然显示在中央
在程序中有很多大写的识别字,如CS_HREDRAW 等,一般是前两个或三个字母大写,后面接一个下划线后面再是字母,这些是简单的数值常数。字首指示的是该常数所属的类别,如下表所示:

字首 类别
CS 视窗类别样式
CW 建立视窗
DT 绘制文字
IDI 图示ID
IDC 游标ID
MB 讯息方块
SND 声音
WM 视窗讯息
WS 视窗样式

在代码中我们还用到了很多新的结构体来进行表示,如下表所示:

结构 含义
MSG 讯息结构
WNDCLASS 视窗类别结构
PAINTSTRUCT 绘图结构
RECT 图示ID

除此之外,在程序中我们还使用了很多代号,也可以称之为句柄,如下表所示:

识别字 含义
HINSTANCE 执行实体(程序本身)代号
HWND 视窗代号
HDC 装置内容代号

代号也被称之为句柄,它是一个整数(通常为32元),程序可以通过获得相关物件的代号来对该物件进行相关操作。

参考资料:
[1]《Windows程序设计(第五版)》
[2]windows程序设计应用开发 夏曹俊 丁宋涛
[3]https://docs.microsoft.com/zh-cn/welcome-to-docs

发布了20 篇原创文章 · 获赞 0 · 访问量 762

猜你喜欢

转载自blog.csdn.net/LeavingBook/article/details/104146104
今日推荐