Win32开发(1):01_Windows 创建窗体与消息机制

前段时间忙着找工作,好久没有更新了,现在准备开一个Win32学习的简单教程。教会大家快速入门。之所以不直接做MFC的教程,主要是因为MFC的封装比较高,不能比较深入的理解win编程的细节。而且学完WIN32的开发会发现MFC其实已经会了80%了。所以请跟我一起进入学习吧。

===============================================================================

基本概念

窗口和句柄

窗口是屏幕上的一块矩形区域,是 Windows 应用程序与用户进行交互的接口。 利用窗口可以接收用户的输入、以及显示输出。一个应用程序窗口通常都包含标题栏、菜单栏、系统菜单、最小化框、最大化框、 可调边框,有的还有滚动条。
窗口可以分为客户区和非客户区,客户区是窗口的一部分, 应用程序通常在客户区中显示文字或者绘制图形。 标题栏、 菜单栏、 系统菜单、 最小化框和最大化框、 可调边框统称为窗口的非客户区, 它们由 Windows 系统来管理, 而应用程序则主要管理客户区的外观及操作。
在 Windows 应用程序中, 窗口是通过窗口句柄( HWND) 来标识的。 我们要对某个窗口进行操作, 首先就要得到这个窗口的句柄。 句柄( HANDLE) 是 Windows 程序中一个重要的概念, 使用也非常频繁。 在 Windows 程序中, 有各种各样的资源( 窗口、 图标、光标,画刷等), 系统在创建这些资源时会为它们分配内存, 并返回标识这些资源的标识号, 即句柄。

消息与消息队列

操作系统感知事件,将事件包装成一个消息,投递到应用程序的消息队列中,然后应用程序从消息队列中取出消息并进行响应。
下面是消息的结构体

	typedef struct tagMSG {
    HWND        hwnd; 主窗口句柄
    UINT        message; 具体消息名称
    WPARAM      wParam; 附加消息 键盘消息
    LPARAM      lParam; 附加消息 鼠标消息 左右键
    DWORD       time; 消息产生时间
    POINT       pt; 附加消息 鼠标消息 x y 
	#ifdef _MAC
		DWORD       lPrivate;
	#endif
	} MSG, *PMSG, NEAR *NPMSG, FAR *LPMSG;

每一个 Windows 应用程序开始执行后, 系统都会为该程序创建一个消息队列, 这个消息队列用来存放该程序创建的窗口的消息。
Windows 将产生的消息依次放到消息队列中, 而应用程序则通过一个消息循环不断地从消息队列中取出消息, 并进行响应。 这种消息机制, 就是 Windows程序运行的机制。

WinMain函数

WinMain 是 Windows程序的入口点函数,与 DOS 程序的入口点函数 main 的作用相同,当 WinMain 函数结束或返回时,Windows 应用程序结束。

WinMain函数声明:

int WINAPI WinMain(
	HINSTANCE hINstance,//应用程序的实例句柄
	HINSTANCE hPreINSTANCE,//上一个应用程序句柄,在win32环境下,参数一般为NULL,不起作用了
	LPSTR lpCmdLine,//char * argv[]
	int nCmdShow//显示命令 最大化 最小化 正常
	);

Windows 编程模型

  1. 设计窗口
  2. 注册窗口类
  3. 创建窗口
  4. 显示和更新
  5. 通过循环取消息
  6. 窗口过程(处理消息)

常用消息

关闭程序

  1. 在取消息时判断是否为FALSE
if(GetMessage(&msg,NULL,0,0)== FALSE)
		{
			break ;
		}
  1. 窗口过程中接收WM_CLOSE消息,并调用DestroyWindow(hwnd);DestroyWindow发送另一个消息 WM__DESTROY
case WM_CLOSE:
	    {
		//所有以Window结尾的方法,都不会进入消息队列,而是直接直接执行
		DestroyWindow(hwnd); //DestroyWindow发送另一个消息 WM__DESTROY
		break;
		}
  1. 窗口过程中接收WM_DESTROY消息,并调用PostQuitMessage(0);此时GetMessage()的值为FALSE,窗口才会被关掉
	case WM_DESTROY:
		PostQuitMessage(0); //此时GetMessage()的值为FALSE,窗口才会被关掉

鼠标左键按下

窗口过程中接收WM_LBUTTONDOWN消息,调用int xPos = LOWORD(lparam); int yPos = HIWORD(lparam);获取坐标值,MessageBox可弹出一个消息窗口

case WM_LBUTTONDOWN: //鼠标左键按下
		{
		int xPos = LOWORD(lparam);//获取鼠标按下的坐标
		int yPos = HIWORD(lparam);

		wchar_t buf[1024];
		wsprintf(buf,TEXT("x = %d,y = %d"),xPos,yPos);

		MessageBox(hwnd,buf,TEXT("鼠标左键按下"),MB_OK);
		break;
		}

MessageBox

MessageBox(hwnd,//消息框属于的父窗口,若为NULL表示无父窗口
buf,//消息框的内容
TEXT("鼠标左键按下"),//消息框的标题
MB_OK);//决定对话框的内容和行为的位标志集

按钮

按钮参数 含义
MB_OK 默认值。有一个确认按钮在里面。
row 2 col 1 row 2 col 2
MB_YESNO 有是和否在里面。
MB_ABORTRETRYIGNORE 有Abort(放弃),Retry(重试)和Ignore(跳过)
MB_YESNOCANCEL 消息框含有三个按钮:Yes,No和Cancel
MB_RETRYCANCEL 有Retry(重试)和Cancel(取消)
MB_OKCANCEL 消息框含有两个按钮:OK和Cancel

图标

参数 含义
MB_ICONEXCLAMATION 一个惊叹号出现在消息框
MB_ICONWARNING 一个惊叹号出现在消息框
MB_ICONINFORMATION 一个圆圈中小写字母i组成的图标出现在消息框
MB_ICONASTERISK 一个圆圈中小写字母i组成的图标出现在消息框
MB_ICONQUESTION 一个问题标记图标出现在消息框
MB_ICONSTOP 一个停止消息图标出现在消息框
MB_ICONERROR 一个停止消息图标出现在消息框
MB_ICONHAND 一个停止消息图标出现在消息框

键盘按下

窗口过程中接收WM_KEYDOWN消息

case WM_KEYDOWN:
		MessageBox(hwnd,TEXT("键盘按下"),TEXT("键盘按下"),MB_OK);
		break;

重绘

当窗口重新显现或改变大小时会发生重绘。窗口过程中接收WM_PAINT消息

	case WM_PAINT: //绘图
		{
		PAINTSTRUCT ps;//绘图结构体
		HDC hdc = BeginPaint(hwnd,&ps);
		//绘制文本
		SetTextColor(hdc,RGB(10,0,255));//文本颜色
		TextOut(hdc,100,100,TEXT("HELLO"),strlen("HELLO"));//文本位置和内容
		//绘制图形
		HBRUSH hb = CreateSolidBrush(RGB(0,255,0));  //创建画刷
		HBRUSH orgBrs = (HBRUSH)SelectObject(hdc, hb);  // 画刷选择到当前DC中  
		Ellipse(hdc,235,35,202,170);  // 填充图形  
		SelectObject(hdc, orgBrs);  // 选回原先的画刷    
		EndPaint(hwnd,&ps);
		break;
		}

代码实例:

#include //底层实现窗口的有文件

//窗口过程函数声明
LRESULT CALLBACK WindowProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam);

//程序入口函数
//WINAPI 代表__stdcall 参数的传递顺序:从右到左依次入栈,并且在函数返回前清空栈
int WINAPI WinMain(
	HINSTANCE hINstance,//应用程序的实例句柄
	HINSTANCE hPreINSTANCE,//上一个应用程序句柄,在win32环境下,参数一般为NULL,不起作用了
	LPSTR lpCmdLine,//char * argv[]
	int nCmdShow//显示命令 最大化 最小化 正常
	)
{
	//1、 设计窗口
	WNDCLASS wc;
	wc.cbClsExtra = 0;//类的额外的内存
	wc.cbWndExtra = 0;//窗口的额外内存
	wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);//设置背景
	wc.hCursor = LoadCursor(NULL,IDC_ARROW);//设置光标,如果第一个参数为NULL,代表使用的是系统自带的光标
	wc.hIcon = NULL; //设置图标
	wc.hInstance = hINstance;//应用程序实例句柄,传入WinMain中的形参即可
	wc.lpfnWndProc = WindowProc;//窗口过程的函数名
	wc.lpszClassName = TEXT("WIN"); //指定窗口类名称
	wc.lpszMenuName = NULL;//菜单名称
	wc.style = 0;//显示风格,0代表默认风格

	//2、 注册窗口类
	RegisterClass(&wc);

	//3、 创建窗口
	HWND WINAPI hwnd = CreateWindow(wc.lpszClassName,TEXT("WINDOWS"),WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,hINstance,NULL);
	/*lpClassName, 类名
	lpWindowName, 标题名
	dwStyle, 风格 一般用WS_OVERLAPPEDWINDOW,是一种混合风格
	x, y, 坐标	nWidth, nHeight, 窗口的大小 都可以使用默认值CW_USEDEFAULT
	hWndParent, 父窗口
	hMenu, 菜单
	hInstance, 实例句柄
	lpParam, 附加值 NULL
	*/

	//4、 显示和更新
	ShowWindow(hwnd,SW_SHOWNORMAL);
	UpdateWindow(hwnd);

	//5、 通过循环取消息
	MSG msg;
	/*
	typedef struct tagMSG {
    HWND        hwnd; 主窗口句柄
    UINT        message; 具体消息名称
    WPARAM      wParam; 附加消息 键盘消息
    LPARAM      lParam; 附加消息 鼠标消息 左右键
    DWORD       time; 消息产生时间
    POINT       pt; 附加消息 鼠标消息 x y 
	#ifdef _MAC
		DWORD       lPrivate;
	#endif
	} MSG, *PMSG, NEAR *NPMSG, FAR *LPMSG;
	*/
	while(1)
	{
		/*
		_Out_ LPMSG lpMsg, 消息
		_In_opt_ HWND hWnd, 捕获窗口 填NULL代表捕获所有窗口
		_In_ UINT wMsgFilterMin, 最小过滤消息 一般填0 捕获所有消息
		 _In_ UINT wMsgFilterMax 最大过滤消息 一般填0 捕获所有消息
		*/
		if(GetMessage(&msg,NULL,0,0)== FALSE)
		{
			break ;
		}

		//在分发前翻译消息
		TranslateMessage(&msg);//组合按键是需要翻译的,翻译好的消息重新排队

		//其他消息,分发
		DispatchMessage(&msg);
	}

	//6、 窗口过程(处理消息)
	return 0;
}

//窗口处理函数定义
//CALLBACK 代表__stdcall 参数的传递顺序:从右到左依次入栈,并且在函数返回前清空栈
LRESULT CALLBACK WindowProc(
	HWND hwnd, //消息所属的窗口句柄
	UINT message, //具体的消息名称
	WPARAM wparam, // 键盘附加消息
	LPARAM lparam) // 鼠标附加消息
{
	switch(message)
	{
	case WM_CLOSE:
	    {
		//所有以Window结尾的方法,都不会进入消息队列,而是直接直接执行
		DestroyWindow(hwnd); //DestroyWindow发送另一个夏溪 WM__DESTROY
		break;
		}
	case WM_DESTROY:
		PostQuitMessage(0); //此时GetMessage()的值为FALSE,窗口才会被关掉
	case WM_LBUTTONDOWN: //鼠标左键按下
		{
		int xPos = LOWORD(lparam);//获取鼠标按下的坐标
		int yPos = HIWORD(lparam);

		wchar_t buf[1024];
		wsprintf(buf,TEXT("x = %d,y = %d"),xPos,yPos);

		MessageBox(hwnd,buf,TEXT("鼠标左键按下"),MB_OK);
		break;
		}
	case WM_KEYDOWN:
		MessageBox(hwnd,TEXT("键盘按下"),TEXT("键盘按下"),MB_OK);
		break;

	case WM_PAINT: //绘图
		{
		PAINTSTRUCT ps;//绘图结构体
		HDC hdc = BeginPaint(hwnd,&ps);
		//绘制文本
		SetTextColor(hdc,RGB(10,0,255));//文本颜色
		TextOut(hdc,100,100,TEXT("HELLO"),strlen("HELLO"));//文本位置和内容
		//绘制图形
		HBRUSH hb = CreateSolidBrush(RGB(0,255,0));  //创建画刷
		HBRUSH orgBrs = (HBRUSH)SelectObject(hdc, hb);  // 画刷选择到当前DC中  
		Ellipse(hdc,235,35,202,170);  // 填充图形  
		SelectObject(hdc, orgBrs);  // 选回原先的画刷    
		EndPaint(hwnd,&ps);
		break;
		}
	}

	//返回默认值处理方式
	return DefWindowProc(hwnd, message, wparam, lparam);
}

你可能感兴趣的:(Win32)