Windows窗口程序的开发1_20190913

一、Windows第一个窗口程序开发:入口函数WinMain。

1、注册窗口类

2、创建窗口

3、显示窗口

4、更新窗口

5、消息循环

6、窗口过程函数

二、了解窗口类WNDCLASS

窗口类是系统用作创建窗口的模板的一组属性。每个窗口都是窗口类的成员。所有窗口类都是特定于进程的。

//WNDCLASS结构体包含一个窗口类的全部信息,定义一个窗口类确定窗口的属性:
typedef struct tagWNDCLASSA 
{
  UINT      style;//窗口类的风格 CS_HREDRAW CS_VREDRAW CS_NOCLOSE CS_DBLCKS
  WNDPROC   lpfnWndProc;//函数指针,指向窗口过程函数,处理窗口消息
  int       cbClsExtra;//指定窗口类结构之后要分配的额外字节数。系统将字节数初始化为零。
  int       cbWndExtra;//指定窗口实例之后要分配的额外字节数。系统将字节数初始化为零。
  HINSTANCE hInstance;//窗口实例句柄。
  HICON     hIcon;//该窗口类所用的图标。
  HCURSOR   hCursor;//该窗口类所用的光标。
  HBRUSH    hbrBackground;//该窗口类所用的背景。
  LPCSTR    lpszMenuName;//该窗口类所用的菜单资源名称。
  LPCSTR    lpszClassName;//该窗口类的名称。
} WNDCLASSA, *PWNDCLASSA, *NPWNDCLASSA, *LPWNDCLASSA;

步骤1、使用RegisterClass该函数注册一个窗口类:

ATOM RegisterClassA(const WNDCLASSA *lpWndClass);
//const WNDCLASSA *:指向WNDCLASS结构的指针。
//如果函数成功,则返回值是一个唯一标识正在注册的类的类原子。
//如果函数失败,则返回值为零。要获取扩展错误信息,请调用GetLastError。
//ATOM:unsigned short 无符号短整型

步骤2、创建窗口:

WNDCLASS结构体包含一个窗口类的全部信息,定义一个窗口类确定窗口属性。

HWND CreateWindowExA(
  DWORD     dwExStyle,
  LPCSTR    lpClassName,//RegisterClass注册的窗口名称.
  LPCSTR    lpWindowName,//窗口名称
  DWORD     dwStyle,//窗口的样式 WS_CHILD WS_VISIBLE WS_MAXIMIZEBOX WS_OVERLAPPED
  int       X,//初始X坐标
  int       Y,//初始Y坐标
  int       nWidth,//窗口的宽度 CW_USEDEFAULT
  int       nHeight,//窗口的高度 CW_USEDEFAULT
  HWND      hWndParent,//父窗的句柄
  HMENU     hMenu,//窗口菜单句柄
  HINSTANCE hInstance,//模块实例句柄
  LPVOID    lpParam//通过发送WM_CREATE消息的lParam参数指向的CREATESTRUCT结构
);
//在函数返回之前,CreateWindow发送WM_CREATE消息给窗口过程。对于重叠窗口,弹出窗口和子窗口,
//如果函数成功,则返回值是新窗口的句柄。如果函数失败,则返回值为NULL。

步骤3、显示窗口

BOOL ShowWindow(HWND hWnd,int  nCmdShow);

 

步骤4、更新窗口
//如果窗口的更新区域不为空,则UpdateWindow函数通过向窗口发送WM_PAINT消息来更新指定窗口的客户区域。
//该函数将WM_PAINT消息直接发送到指定窗口的窗口过程,绕过应用程序队列。
//如果更新区域为空,则不发送任何消息。
BOOL UpdateWindow(HWND hWnd);

一、//WNDCLASS结构体包含一个窗口类的全部信息,定义一个窗口类确定窗口的属性:
typedef struct tagWNDCLASSA 
{
  UINT      style;//窗口类的风格 CS_HREDRAW CS_VREDRAW CS_NOCLOSE CS_DBLCKS
  WNDPROC   lpfnWndProc;//函数指针,指向窗口过程函数,处理窗口消息
  int       cbClsExtra;//指定窗口类结构之后要分配的额外字节数。系统将字节数初始化为零。
  int       cbWndExtra;//指定窗口实例之后要分配的额外字节数。系统将字节数初始化为零。
  HINSTANCE hInstance;//窗口实例句柄。
  HICON     hIcon;//该窗口类所用的图标。
  HCURSOR   hCursor;//该窗口类所用的光标。
  HBRUSH    hbrBackground;//该窗口类所用的背景。
  LPCSTR    lpszMenuName;//该窗口类所用的菜单资源名称。
  LPCSTR    lpszClassName;//该窗口类的名称。
} WNDCLASSA, *PWNDCLASSA, *NPWNDCLASSA, *LPWNDCLASSA;

1、RegisterClass函数
ATOM RegisterClassA(const WNDCLASSA *lpWndClass);
//const WNDCLASSA *:指向WNDCLASS结构的指针。
//如果函数成功,则返回值是一个唯一标识正在注册的类的类原子。
//如果函数失败,则返回值为零。要获取扩展错误信息,请调用GetLastError。
//ATOM:unsigned short 无符号短整型

2、CreateWindow函数
HWND CreateWindowExA(
  DWORD     dwExStyle,
  LPCSTR    lpClassName,//RegisterClass注册的窗口名称.
  LPCSTR    lpWindowName,//窗口名称
  DWORD     dwStyle,//窗口的样式 WS_CHILD WS_VISIBLE WS_MAXIMIZEBOX WS_OVERLAPPED
  int       X,//初始X坐标
  int       Y,//初始Y坐标
  int       nWidth,//窗口的宽度 CW_USEDEFAULT
  int       nHeight,//窗口的高度 CW_USEDEFAULT
  HWND      hWndParent,//父窗的句柄
  HMENU     hMenu,//窗口菜单句柄
  HINSTANCE hInstance,//模块实例句柄
  LPVOID    lpParam//通过发送WM_CREATE消息的lParam参数指向的CREATESTRUCT结构
);
//在函数返回之前,CreateWindow发送WM_CREATE消息给窗口过程。对于重叠窗口,弹出窗口和子窗口,
//如果函数成功,则返回值是新窗口的句柄。如果函数失败,则返回值为NULL。

3、显示窗口
BOOL ShowWindow(HWND hWnd,int  nCmdShow);

4、更新窗口
//如果窗口的更新区域不为空,则UpdateWindow函数通过向窗口发送WM_PAINT消息来更新指定窗口的客户区域。
//该函数将WM_PAINT消息直接发送到指定窗口的窗口过程,绕过应用程序队列。
//如果更新区域为空,则不发送任何消息。
BOOL UpdateWindow(HWND hWnd);

5、窗口过程函数 WNDPROC
WNDPROC是一个函数指针,指向窗口过程函数,定义如下:
typedef LRESULT (CALLBACK* WNDPROC)(HWND,UINT,WPARAM,LPARAM)
备注:
这个函数指向窗口过程函数:
第一个参数为窗口的句柄;
第二个参数为消息ID;
第三个参数为附加消息信息,取决于uMsg参数的值。
第四个参数为附加消息信息,取决于uMsg参数的值。
返回值为LRESULT类型(typedef long LRSEULT);

默认窗口过程函数:
在Windows操作系统里,当窗口显示之后,用户再在窗口上操作
比如移动鼠标,单击鼠标、关闭窗口,系统会向该窗口源源不断的发送消息
然后窗口就需要处理这些消息
因此就需要一个函数来处理这些消息。WIN32API里面定义了一个系统默认处理函数
DefWindowProc,我们可以把不关系的消息都丢给他处理,
如果我们需要自定义处理相关的消息,则需要实现自己的窗口过程函数。

LRESULT WINAPI DefWindowProc(HWND hwnd,UINT Msg,WPARAM wParam,LPARAM lParam)
返回消息处理的结果并取决于消息

//自定义窗口过程函数
如果我们需要自定义处理函数,则需要实现自己的窗口过程函数,
它被系统自动调用
LRESULT CALLBACK MyWndProc(HWND hwnd,UINT uMsg,
 WPARAM wParam,LPARAM lParam)
 {
	 switch(uMsg)
	 {
		 case WM_CREATE:
		 //Initialize the window.
		 return 0;
		 
		 case WM_DESTROY:
		 //Clean up window-specific data object.
		 return 0;
		 
		 default:
		 return DefWindowProc(hwnd,uMsg,wParam,lParam);
		 
	 }
	 return 0;
	 
 }

6、消息循环
Windows 中有一个系统消息队列,对于每一个正在执行的Windows应用程序,
系统为其建立一个“消息队列”,即应用程序队列,用来存放该程序可能创建的
各种窗口的消息。窗口程序想要一直捕获消息,则必须不停循环读取消息队列。

MSG msg;
while(GetMessage(&msg,NULL,0,0))//从消息队列中获取消息
{
	TranslateMessage(&msg);//消息的翻译(将虚拟键的消息转化为字符消息)
	DispatchMessage(&msg);//消息的分发给窗口过程
}
#include <windows.h>

//自定义窗口过程函数
LRESULT CALLBACK MyWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
	switch (Msg)
	{
	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;
	default:
		return DefWindowProc(hWnd, Msg, wParam, lParam);
	}
	return 0;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
	LPSTR lpCmdLine, int nShowCmd)
{
	//使用窗口类结构体
	WNDCLASS wnd;
	//指定窗口类实例属性
	wnd.cbClsExtra = 0;//指定窗口类之后要分配的额外字节数,系统默认为0
	wnd.cbWndExtra = 0;//指定窗口实例之后要分配的额外字节数,系统默认为0
	wnd.hbrBackground = (HBRUSH)(GetStockObject(WHITE_BRUSH));//指定窗口背景色
	wnd.hCursor = LoadCursor(NULL, IDC_ARROW);//鼠标光标
	wnd.hIcon = LoadIcon(NULL, IDI_APPLICATION);//图标
	wnd.hInstance = hInstance;//窗口实例句柄
	wnd.lpfnWndProc = MyWindowProc;//默认窗口过程函数,用于处理消息
	wnd.lpszClassName = L"good";//创建的窗口类名
	wnd.lpszMenuName = NULL;//该窗口类所用的菜单资源名称
	wnd.style = CS_HREDRAW;//窗口风格
	//1、注册窗口类
	RegisterClass(&wnd);
	//2、创建窗口(返回之前发送WM_CREATE)
	HWND hwnd = CreateWindow(L"good", L"Tip", WS_OVERLAPPEDWINDOW,
		700, 300, 400, 300, NULL, NULL, hInstance, NULL);
	//3、显示窗口
	ShowWindow(hwnd, nShowCmd);
	//4、更新窗口(发送WM_PAINT)
	UpdateWindow(hwnd);
	//5、消息循环(收到WM_QUIT)
	MSG msg;
	while (GetMessage(&msg, NULL, 0, 0))
	{
		TranslateMessage(&msg);//消息的翻译(将虚拟键的消息转化为字符消息)
		DispatchMessage(&msg);//消息分发给窗口过程
	}
	return 0;
}

 

发布了140 篇原创文章 · 获赞 26 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/weixin_41211961/article/details/100795098