2013.8.3 学习笔记《windows核心编程》(七) 窗口类,窗口显示更新与消息

《windows核心编程》(七)-----------2013.8.3

一、概念


窗口类和窗口的附加数据
• 作用
    注册窗口时,可以设置这两个数据内存空间 的大小。
     int cbClsExtra; //窗口类的附加数据大小
     int cbWndExtra; //窗口的附加数据大小
     可以提供窗口类和窗口存放自己的数据的空间。

窗口类附加数据缓冲区的使用
1. 开缓冲区
   int cbClsExtra - 以字节为单位,一般为4的倍数
2. 存入数据
利用SetClassLong函数往缓冲区存入数据
  DWORD SetClassLong(
    HWND hWnd,//窗口句柄
    int nIndex,//字节索引号(从哪个字节开始存)
    LONG dwNewLong//存入的数据(因为long占4个字节,所以开缓冲区的字节数一般为4的倍数)
  );
3. 读取数据
  DWORD GetClassLong(
    HWND hWnd,//窗口句柄
    int nIndex//字节索引号(从哪个字节开始读)
  );//返回 读取到的数据


窗口附加数据缓冲区的使用
1. 开缓冲区
   int cbWndExtra - 以字节为单位,一般为4的倍数
2. 存入数据
  LONG SetWindowLong(
    HWND hWnd,//窗口句柄
    int nIndex,//字节索引号(从哪个字节开始存)
    LONG dwNewLong//存入的数据
  );
3. 读取数据
  LONG GetWindowLong(
    HWND hWnd,//窗口句柄
    int nIndex//字节索引号(从哪个字节开始读)
  );//返回 读取到的数据


区别:
   窗口类附加数据缓冲区: 基于该窗口类,创建的所有窗口共享的缓冲区。
   窗口附加数据缓冲区: 窗口自己私有的缓冲区,即便基于同一窗口类,创建的窗口也不共享。

窗口类缓冲区与窗口缓冲区的用法示例:

// WinCreate.cpp : 定义应用程序的入口点。
//

#include "stdafx.h"
#include "stdio.h"
#include "WinCreate.h"
#include "windows.h"
HINSTANCE g_hInstance = 0;

//窗口处理函数
LRESULT CALLBACK WindowProc(HWND hWnd,UINT nMsg,WPARAM wParam,LPARAM lParam)
{
	switch(nMsg)
	{
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	}
	return DefWindowProc(hWnd,nMsg,wParam,lParam);
}
//注册窗口类
BOOL Register(LPTSTR lpClassName,WNDPROC wndproc)
{
	WNDCLASSEX wce = {0};
	wce.cbSize = sizeof(wce);
	wce.cbClsExtra = 200;
	wce.cbWndExtra = 200;
	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;
}

//创建主窗口
HWND CreateMain(LPTSTR lpClassName,LPTSTR lpWndName)
{
	HWND hWnd = CreateWindowEx(0,lpClassName,lpWndName,WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,
		NULL,NULL,g_hInstance,NULL);
	return hWnd;
}

//创建子窗口
HWND CreateChild(LPTSTR lpClassName,LPTSTR lpWndName,HWND hParent)
{
	HWND hChild = CreateWindowEx(0,lpClassName,lpWndName,
		WS_CHILD | WS_VISIBLE | WS_OVERLAPPEDWINDOW,100,100,200,200,
		hParent,NULL,g_hInstance,NULL);
	return hChild;
}

//存入数据
void SetExtra(HWND hWnd)
{
	SetClassLong(hWnd,0,50);
	SetWindowLong(hWnd,0,50);
}

//读取数据
void GetExtra(HWND hWnd)
{
	DWORD nCalssExtra = GetClassLong(hWnd,0);
	DWORD nWndExtra = GetWindowLong(hWnd,0);
	char szText[256] = {0};
	sprintf(szText,"窗口类:%d,窗口:%d",nCalssExtra,nWndExtra);
	MessageBox(NULL,szText,"Infor",MB_OK);
}
//显示窗口
void Display(HWND hWnd)
{
	ShowWindow(hWnd,SW_SHOW);
	UpdateWindow(hWnd);
}

//消息循环
void Message()
{
	MSG nMsg = {0};
	while (GetMessage(&nMsg,NULL,0,0))
	{
		TranslateMessage(&nMsg);
		DispatchMessage(&nMsg);
	}
}
int APIENTRY _tWinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPTSTR    lpCmdLine,
                     int       nCmdShow)
{
	g_hInstance = hInstance;
	Register("Main",WindowProc);
	HWND hWnd = CreateMain("Main","Window");
	HWND hChile1 = CreateChild("Main","C1",hWnd);
	HWND hChile2 = CreateChild("Main","C2",hWnd);
	SetExtra(hChile1);
	GetExtra(hChile2);
	Display(hWnd);
	MoveWindow(hChile1,300,100,200,200,TRUE);
	MoveWindow(hChile2,500,100,200,200,TRUE);
	Message();
	return 0;
}

结果:


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

所以调用SetClassLong函数可以读取数据50,

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

所以调用SetWindowLong函数时不能读取缓冲区中的数据。


因为LONG型数据占用内存为4位,而指针占用内存也为4位,所以可以讲指针传入缓冲区,这样就可以存取不同类型的数据。


将指针传入缓冲区读取数据示例:

// WinCreate.cpp : 定义应用程序的入口点。
//

#include "stdafx.h"
#include "stdio.h"
#include "WinCreate.h"
#include "windows.h"
HINSTANCE g_hInstance = 0;

//窗口处理函数
LRESULT CALLBACK WindowProc(HWND hWnd,UINT nMsg,WPARAM wParam,LPARAM lParam)
{
	switch(nMsg)
	{
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	}
	return DefWindowProc(hWnd,nMsg,wParam,lParam);
}
//注册窗口类
BOOL Register(LPTSTR lpClassName,WNDPROC wndproc)
{
	WNDCLASSEX wce = {0};
	wce.cbSize = sizeof(wce);
	wce.cbClsExtra = 200;
	wce.cbWndExtra = 200;
	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;
}

//创建主窗口
HWND CreateMain(LPTSTR lpClassName,LPTSTR lpWndName)
{
	HWND hWnd = CreateWindowEx(0,lpClassName,lpWndName,WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,
		NULL,NULL,g_hInstance,NULL);
	return hWnd;
}

//创建子窗口
HWND CreateChild(LPTSTR lpClassName,LPTSTR lpWndName,HWND hParent)
{
	HWND hChild = CreateWindowEx(0,lpClassName,lpWndName,
		WS_CHILD | WS_VISIBLE | WS_OVERLAPPEDWINDOW,100,100,200,200,
		hParent,NULL,g_hInstance,NULL);
	return hChild;
}

//存入数据
void SetExtra(HWND hWnd)
{
	char *pszText = "Hello Extra";
	SetClassLong(hWnd,0,(LONG)pszText);
	SetWindowLong(hWnd,0,50);
}

//读取数据
void GetExtra(HWND hWnd)
{
	DWORD nCalssExtra = GetClassLong(hWnd,0);
	DWORD nWndExtra = GetWindowLong(hWnd,0);
	char * pszText = (char *)nCalssExtra;
	char szText[256] = {0};
	sprintf(szText,"窗口类:%s,窗口:%d",pszText,nWndExtra);
	MessageBox(NULL,szText,"Infor",MB_OK);
}
//显示窗口
void Display(HWND hWnd)
{
	ShowWindow(hWnd,SW_SHOW);
	UpdateWindow(hWnd);
}

//消息循环
void Message()
{
	MSG nMsg = {0};
	while (GetMessage(&nMsg,NULL,0,0))
	{
		TranslateMessage(&nMsg);
		DispatchMessage(&nMsg);
	}
}
int APIENTRY _tWinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPTSTR    lpCmdLine,
                     int       nCmdShow)
{
	g_hInstance = hInstance;
	Register("Main",WindowProc);
	HWND hWnd = CreateMain("Main","Window");
	HWND hChile1 = CreateChild("Main","C1",hWnd);
	HWND hChile2 = CreateChild("Main","C2",hWnd);
	SetExtra(hChile1);
	GetExtra(hChile2);
	Display(hWnd);
	MoveWindow(hChile1,300,100,200,200,TRUE);
	MoveWindow(hChile2,500,100,200,200,TRUE);
	Message();
	return 0;
}

运行结果:


显示窗口:
ShowWindow(hWnd,.....)
{
   根据hWnd,可以获取某块内存中保存的关于光口的各项数据
   根据获取的数据,将窗口在显示器(显卡)中绘制出来
}

更新窗口:
UpdateWindow(hWnd);


消息和消息机制

Windows消息机制
•程序执行机制
   过程驱动 - 程序的执行过程是按照预定好的顺序执行。
   事件驱动 - 程序的执行是无序,用户可以根据需要随机触发相应的事件。
•Win32窗口程序就是采用 事件驱动 方式执行,也就是 消息机制。

什么是消息?
•当系统通知窗口工作时,就采用消息的方式派发给窗口。
•消息组成:
窗口句柄
消息ID
消息的两个参数
消息产生的时间
消息产生时的鼠标位置
typedef struct { HWND hwnd; //窗口句柄
             UINT message;//消息ID
            WPARAM wParam;//消息附加参数1
            LPARAM lParam; //消息附加参数2
            DWORD time; //消息产生时的系统时间
            POINT pt;//消息产生时鼠标的位置
} MSG, *PMSG;

窗口处理函数和消息
•每个窗口都必须具有窗口处理函数。
LRESULT CALLBACK WindowProc(
    HWND hwnd, //窗口句柄
    UINT uMsg, //消息ID
    WPARAM wParam, //消息参数
    LPARAM lParam  //消息参数
);
•当系统通知窗口时,会调用窗口处理函数同时,将消息ID和消息参数传递给窗口处理函数。
•在窗口处理函数中,不处理的消息,使用缺省窗口处理函数,例如DefWindowProc(默认处理)。
(CALLBACK为回调,回调是指申明一个函数让操作系统自己调用,例如WinMain函数与WindowProc函数)

消息相关函数

获取消息:
只抓取本进程的消息。
BOOL GetMessage(
    LPMSG lpMsg,//存放获取到的消息buff
    HWND hWnd,//窗口句柄
    UINT wMsgFilterMin,//获取消息的最小ID
    UINT wMsgFilterMax//获取消息的最大ID
);
lpMsg - 当获取到消息后,将消息的参数存放到MSG结构中。
hWnd - 获取到hWnd所指定窗口的消息。
wMsgFilterMin和wMsgFilterMax -只能获取到由它们指定的消息范围内的消息, 如果都为0,表示没有范围


翻译消息:
TranslateMessage - 只翻译按键消息
    BOOL TranslateMessage(
    CONST MSG *lpMsg //要翻译的消息地址
    );
    检查消息是否是按键的消息,如果不是按键消息,不做任何处理,继续执行。

消息派发:
•DispatchMessage - 派发消息。将消息派发到该消息所属窗口的窗口处理函数上。
DispatchMessage(&nMsg)
{
   根据nMsg.hWnd --> 内存 --> "Main" --> 匹配窗口类名
   一旦匹配成功,调用这个窗口类中保存的函数WndProc回到自己的代码

   WndProc(nMsg.hWnd,nMsg.message,nMsg.wParam,nMsg.lParam);
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值