windows应用程序开发系列五:注册窗口类

开发流程:

1 定义一个窗口处理函数

2 注册窗口类

3 创建窗口

4 显示窗口

5 更新窗口

6 消息循环

窗口类的分类

    -系统窗口类 

    系统已经定义好的窗口类,所有应用程序都可以直接使用。

    -应用程序全局窗口类 

     由用户自己定义,当前应用程序所有模块都可以使用。

    -应用程序局部窗口类 

     由用户自己定义,当前应用程序中本模块可以使用

不需要注册,直接使用窗口类即可。系统
已经定义好相应名称,例如:
    按钮   - BUTTON
    编辑框 - EDIT

应用程序全局窗口类的注册

RegisterClass/RegisterClassEx

ATOM RegisterClass(

CONST WNDCLASS *lpWndClass //窗口类的数据

); 注册成功后,返回一个数字标识。

ATOM RegisterClassEx(

CONST WNDCLASSEX *lpwcx  //窗口类的数据

);

加强版的注册窗口类

typedef struct _WNDCLASSEX { 
    UINT       cbSize; //结构体的大小,之所以有这个成员是因为不同的平台大小不一样,对齐补齐问题造成
    UINT       style;  //窗口类的风格
    WNDPROC    lpfnWndProc; //窗口处理函数,自己定义的窗口处理函数名字
    int        cbClsExtra; //窗口类的附加数据buff的大小
    int        cbWndExtra; //窗口的附加数据buff的大小
    HINSTANCE  hInstance; //当前模块的实例句柄
    HICON      hIcon; //窗口图标句柄
    HCURSOR    hCursor; //鼠标的句柄
    HBRUSH     hbrBackground; //绘制窗口背景的画刷句柄
    LPCTSTR    lpszMenuName; //窗口菜单的资源ID字符串
    LPCTSTR    lpszClassName; //窗口类的名称
    HICON      hIconSm; //窗口的小图标句柄,比WNDCLASS多出来的成员 
} WNDCLASSEX, *PWNDCLASSEX;

应用程序全局窗口类的注册,需要在窗口类的风格中增加 CS_GLOBALCLASS,例如:
    WNDCLASSEX wce = {0};
    wce.style = ….|CS_GLOBALCLASS;
应用程序局部窗口类
    在注册窗口类时,不添加CS_GLOBALCLASS风格。

窗口类的风格

CS_GLOBALCLASS - 应用程序全局窗口类
CS_BYTEALIGNCLIENT - 窗口客户区的水平位置8倍数对齐
CS_BYTEALIGNWINDOW - 窗口的水平位置8倍数对齐
CS_HREDRAW - 当窗口水平变化时,窗口重新绘制
CS_VREDRAW - 当窗口垂直变化时,窗口重新绘制 
CS_CLASSDC - 该类型的窗口,都是有同一个绘图(DC)设备 
CS_PARENTDC - 该类型的窗口,使用它的父窗口的绘图(DC)设备
CS_OWNDC - 该类型的窗口,每个窗口都使用自己的绘图(DC)设备
CS_SAVEBITS - 允许窗口保存成图(位图),提高窗口的绘图效率,但是耗费内存资源
CS_DBLCLKS - 允许窗口接收鼠标双击
CS_NOCLOSE - 窗口没有关闭按钮


void SystemReg()
{
	HWND hWnd = CreateWindow("BUTTON","搜狗",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,g_hInstance,NULL);  //创建一个窗口
	ShowWindow(hWnd,SW_SHOW); // 显示窗口
	UpdateWindow(hWnd);  // 更新窗口
	MSG nMsg = {0};
	while (GetMessage(&nMsg,NULL,0,0)) // GetMessage()函数从操作系统的消息队列中抓取消息
	{
		TranslateMessage(&nMsg); // 翻译消息
		DispatchMessage(&nMsg); // 派发消息
	}
}

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
	g_hInstance = hInstance;
 	SystemReg();
	return 0;
}
窗口的创建

CreateWindow/CreateWindowEx

HWND CreateWindowEx(

DWORD dwExStyle, //窗口的扩展风格

LPCTSTR lpClassName,  //已经注册的窗口类名称

LPCTSTR lpWindowName, //窗口标题栏的名字

DWORD dwStyle, //窗口的基本风格

int x, //窗口左上角水平坐标位置

int y, //窗口左上角垂直坐标位置

int nWidth, //窗口的宽度

int nHeight,//窗口的高度

HWND hWndParent,//窗口的父窗口句柄

HMENU hMenu,//窗口菜单句柄

HINSTANCE hInstance, //应用程序实例句柄

LPVOID lpParam //窗口创建时附加参数   

); 创建成功返回窗口句柄


一个完整的窗口创建代码

#include "stdafx.h"
HINSTANCE g_hInstance = 0;

/*
	1 定义自己的窗口消息处理函数
	* 如果点击了鼠标,鼠标消息首先进入操作系统,操作系统会调用我们定义的消息处理函数
	* CALLBACK是回调,就是我们定义的函数,我们自己并不调用,交给操作系统调用,是一种调用约定
	* APIENTRY和CALLBACK一样都属于回调函数
<span style="white-space:pre">	* 当这个函数收到WM_DESTROY消息时,进程就会终止,否则进程不会终止。也就事点击关闭按钮的时候会发送这个消息</span>
*/
LRESULT CALLBACK WndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)
{
<span style="white-space:pre">	</span>switch(msg)
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>case WM_DESTROY:
<span style="white-space:pre">			</span>PostQuitMessage(0);
<span style="white-space:pre">			</span>break;
<span style="white-space:pre">	</span>}
	return DefWindowProc(hWnd,msg,wParam,lParam);
}


/*
	2 注册窗口类
*/
BOOL Register(LPSTR lpClassName,WNDPROC wndProc)
{
	WNDCLASSEX wce = {0};

	wce.cbSize = sizeof(wce);
	wce.cbClsExtra = 0;
	wce.cbWndExtra = 0;
	wce.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
	wce.hCursor = NULL;
	wce.hIcon = NULL;
	wce.hIconSm = NULL;
	wce.hInstance = g_hInstance;
	wce.lpfnWndProc = wndProc;
	wce.lpszClassName = lpClassName;
	wce.lpszMenuName = NULL;
	wce.style = CS_HREDRAW|CS_VREDRAW;
	
	ATOM nAtom = RegisterClassEx(&wce);
	if(nAtom == 0)
	{
		return FALSE;
	}
	return TRUE;
}


/*
	3 创建主窗口
*/
HWND CreateMain(LPSTR lpClassName,LPSTR lpWndName)
{
	HWND hWnd = CreateWindowEx(0,lpClassName,lpWndName,WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,g_hInstance,NULL);
	return hWnd;
}


/*
	4 显示窗口和更新窗口
*/
void DisplayWindow(HWND hWnd)
{
	ShowWindow(hWnd,SW_SHOW);
	UpdateWindow(hWnd);
}


/*
	5 消息循环
*/
void Message()
{
	MSG nMsg = {0};
	while(GetMessage(&nMsg,NULL,0,0))
	{
		TranslateMessage(&nMsg);
		DispatchMessage(&nMsg);
	}
}
int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
	g_hInstance = hInstance;	 	
	Register("Main",WndProc);
	HWND hwnd = CreateMain("Main","速度与激情");
	DisplayWindow(hwnd);
	Message();
	return 0;
}



二、创建一个子窗口

创建时要设置父窗口句柄(必备)

创建风格要增加 WS_CHILD|WS_VISIBLE(必备)


一个完整的创建子窗口的代码

</pre><pre name="code" class="html">#include "stdafx.h"
HINSTANCE g_hInstance = 0;

/*
	1 定义自己的窗口消息处理函数
	* 如果点击了鼠标,鼠标消息首先进入操作系统,操作系统会调用我们定义的消息处理函数
	* CALLBACK是回调,就是我们定义的函数,我们自己并不调用,交给操作系统调用,是一种调用约定
	* APIENTRY和CALLBACK一样都属于回调函数
	* 当这个函数收到WM_DESTROY消息时,进程就会终止,否则进程不会终止。也就事点击关闭按钮的时候会发送这个消息
*/
LRESULT CALLBACK WndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)
{
	switch(msg)
	{
		case WM_DESTROY:
			PostQuitMessage(0);
			break;
	}
	return DefWindowProc(hWnd,msg,wParam,lParam);
}


/*
	2 注册窗口类
*/
BOOL Register(LPSTR lpClassName,WNDPROC wndProc)
{
	WNDCLASSEX wce = {0};

	wce.cbSize = sizeof(wce);
	wce.cbClsExtra = 0;
	wce.cbWndExtra = 0;
	wce.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
	wce.hCursor = NULL;
	wce.hIcon = NULL;
	wce.hIconSm = NULL;
	wce.hInstance = g_hInstance;
	wce.lpfnWndProc = wndProc;
	wce.lpszClassName = lpClassName;
	wce.lpszMenuName = NULL;
	wce.style = CS_HREDRAW|CS_VREDRAW;
	
	ATOM nAtom = RegisterClassEx(&wce);
	if(nAtom == 0)
	{
		return FALSE;
	}
	return TRUE;
}


/*
	3 创建主窗口
*/
HWND CreateMain(LPSTR lpClassName,LPSTR lpWndName)
{
	HWND hWnd = CreateWindowEx(0,lpClassName,lpWndName,WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,g_hInstance,NULL);
	return hWnd;
}

/*
	3.1 创建一个子窗口
*/
HWND CreateChild(LPSTR lpClassName,LPSTR lpWndName,HWND hParent)
{
	HWND hChild = CreateWindowEx(0,lpClassName,lpWndName,WS_CHILD|WS_VISIBLE|WS_OVERLAPPEDWINDOW,150,150,200,200,hParent,NULL,g_hInstance,NULL);
	return hChild;
}


/*
	4 显示窗口和更新窗口
*/
void DisplayWindow(HWND hWnd)
{
	ShowWindow(hWnd,SW_SHOW);
	UpdateWindow(hWnd);
}


/*
	5 消息循环
*/
void Message()
{
	MSG nMsg = {0};
	while(GetMessage(&nMsg,NULL,0,0))
	{
		TranslateMessage(&nMsg);
		DispatchMessage(&nMsg);
	}
}
int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
	g_hInstance = hInstance;	 	
	Register("Main",WndProc);
	HWND hwnd = CreateMain("Main","速度与激情");
	DisplayWindow(hwnd);
	
	Register("Child",DefWindowProc);
	HWND hChild1 = CreateChild("Child","保尔",hwnd);
	MoveWindow(hChild1,120,120,100,100,TRUE);

	Register("Child2",DefWindowProc);
	HWND hChild2 = CreateChild("Child2","丽萨",hwnd);
	MoveWindow(hChild2,300,120,100,100,TRUE);

	Message();
	return 0;
}

     int cbClsExtra; //窗口类的附加数据BUFF大小
     int cbWndExtra; //窗口的附加数据BUFF大小

窗口类附加数据缓冲区的用法:

int cbClsExtra; //窗口类的附加数据BUFF大小

1 申请缓冲区,赋值就可以申请下来,int cbClsExtra - 一般赋4的倍数

2 写入数据的函数 SetClassLong()

3 读取数据的函数 GetClassLong()

窗口附加数据缓冲区的用法:

1 申请缓冲区,赋值就可以申请下来,int cbWndExtra - 一般为4的倍数

2 写入数据的函数 SetWindowLong()

3 读取数据的函数 GetWindowLong()

两者的区别:

窗口类附加数据缓冲区:是所有基于该窗口类创建出来的共享的缓冲区

窗口附加数据缓冲区:是窗口自己私有的缓冲区,即便是基于同一个窗口类创建出来的窗口,之间不共享


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值