三.窗口和消息
1.窗口系统(基于事件驱动和树层次)
(桌面窗口/根窗口) ---------- 占满整个桌面,没有父窗口 桌面 疑问:桌面窗口是编程需要用户编,还是就是HWND_DESKTOP
框架窗口 框架窗口 ---------- 分为客户区和非客户区
子窗口 子窗口
2.窗口和屏幕绘制区的关系
3.消息队列 每创建一个窗口其托管窗口为桌面的话,就会创建一个消息队列
但文档上说:1.创建的第一个主窗口的托管窗口必须是桌面,其它窗口用已有的主窗口做托管窗口,确保每个线程共用一个消息队列
4.窗口风格
WS_VISIBLE 可见
WS_EX_TRANSPARENT 透明窗口风格 仅用于控件
5.销毁一个主窗口
MSG_CLOSE -----> DestroyMainWindow(主窗口句柄) ---> MSG_DESTROY 销毁被托管窗口
PostQuitMessage(主窗口句柄) ----> 消息队列 -----> MSG_QUIT 终止消息队列
MainWindowCleanup(主窗口句柄) ----> 销毁主窗口本身以及其消息队列
6.对话框
6.1 创建一个对话框
模态对话框 DialogBoxIndirectParam(对话框模板,托管窗口,过程函数,传递参数)
DialogBoxIndirectParamEx(对话框模板,托管窗口,过程函数,传递参数,渲染器名称,渲染器参数,NULL,NULL)
7.控件
typedef struct _WNDCLASS
{
char* spClassName;//控件名
DWORD opMask;
DWORD dwStyle;//风格
DWORD dwExStyle;//扩展风格
HCURSOR hCursor;//鼠标
int iBkColor;//背景颜色
int (*WinProc) (HWND, int, WPARAM, LPARAM);//过程函数
DWORD dwAddData;//额外数据
} WNDCLASS;
typedef WNDCLASS* PWNDCLASS;
注册一个控件类:BOOL GUIAPI RegisterWindowClass (PWNDCLASS pWndClass);
注销一个控件类:BOOL GUIAPI UnregisterWindowClass (const char *szClassName);
获取指定控件的类名:const char* GUIAPI GetClassName (HWND hWnd);
获取指定类的类信息:BOOL GUIAPI GetWindowClassInfo (PWNDCLASS pWndClass);
该函数设置指定控件类的类信息:BOOL GUIAPI SetWindowClassInfo (const WNDCLASS *pWndClass) ;
创建控件 控件句柄 = CreateWindow(控件名,标题,风格,在父窗口的ID,x,y,w,h,托管窗口,附加数据);
销毁控件 DestroyWindow (控件句柄);
8.消息
8.1消息结构体
typedef struct _MSG
{
HWND hwnd; //消息接收者的窗口句柄
int message; //消息的标识符
WPARAM wParam; //消息参数(32)
LPARAM lParam; //消息参数(32)
unsigned int time;//加入消息队列的时间
#ifndef _LITE_VERSION
void* pAdd;
#endif
}MSG;
typedef MSG* PMSG;
消息产生来源:事件(点击,键盘),应用程序
8.2消息队列
发送消息有两种方式: (排队消息):消息产生者 ----> 消息队列(存储消息的内存区域,每个消息存储在一个消息结构中,先进先出) ---> 过程处理函数
(非排队消息):消息产生者 --------> 过程处理函数 立即处理的消息
消息队列的消息:键盘和鼠标输入的鼠标和键盘消息,定时器消息,绘制消息和退出消息
int GUIAPI GetMessage (PMSG pMsg, HWND hWnd); ----> PostQuitMessage ----> MSG_QUIT
BOOL GUIAPI HavePendingMessage (HWND hMainWnd); //检查消息队列中是否有消息,而不取出消息 在等待消息时立即返回以便处理其他事务
例:
do {
ReadMasterPty (pConInfo);
break;
while (HavePendingMessage (hMainWnd)) {
if (!GetMessage (&Msg, hMainWnd))
break;
DispatchMessage (&Msg);
}
} while (TRUE);
8.3 每个线程有一个消息队列,进程共享一个消息队列,
窗口过程是一个特定类型的函数,用来接收和处理所有发送到该窗口的消息。
每个控件类有一个窗口过程,属于同一控件类的所有控件共用同一个窗口过程来处理消息。
突然发现窗口类型的hwnd就是来标识同一控件类型的不同窗口句柄
默认的窗口处理函数: 主窗口 --- DefaultMainWinProc --- int PreDefMainWinProc (HWND hWnd, int message, WPARAM wParam, LPARAM lParam);
对话框 --- DefaultDialogProc --- int PreDefDialogProc (HWND hWnd, int message, WPARAM wParam, LPARAM lParam);
控件 --- DefaultControlProc --- int PreDefControlProc (HWND hWnd, int message, WPARAM wParam, LPARAM lParam);
8.4 发送和投递消息
PostMessage 消息队列 异步(投递到消息队列会立即返回) 缓冲区满会丢失 鼠标和键盘消息
SendMessage 过程处理函数 同步(会等返回结果再返回,如果是投递到不同线程,会阻塞那个线程)
SendNotifyMessage 消息队列 异步(投递到消息队列会立即返回) 以链表的形式链接在后面
PostQuitMessage QS_QUIT标志 停止消息循环 MSG_QUIT
int GUIAPI BroadcastMessage ( int iMsg, WPARAM wParam, LPARAM lParam ); 在所有窗口广播消息
int GUIAPI ThrowAwayMessages ( HWND pMainWnd ); 丢弃指定窗口的消息
BOOL GUIAPI WaitMessage ( PMSG pMsg, HWND hMainWnd ); 有消息就返回,不从消息队列中取走消息
8.5常用消息
MSG_NCCREATE : 建立主窗口过程中发送的消息(此时主窗口没有建立,不能建立子窗口)
case MSG_NCCREATE: //对于输入法窗口来说,必须在次窗口注册输入法
if (hz_input_init())
SendMessage (HWND_DESKTOP, MSG_IME_REGISTER, (WPARAM)hWnd, 0);
else
return -1;
break;
MSG_SIZECHANGING:建立窗口过程 或 窗口尺寸发生变化 wParam(预期尺寸值) lParam(结果尺寸值) PRECT(指针类型,即可以当传入参数,又可以当传出参数)
MSG_SIZECHANGED 和 MSG_CSIZECHANGED :消息在窗口尺寸发生变化后 wParam 参数包含窗口大小信息, lParam 参数是用来保存窗口客户区大小的 RECT 指针
MSG_CREATE :窗口成功创建
MSG_FONTCHANGING :字体发生改变时 SetWindowFont 不允许改变默认字体
MSG_FONTCHANGED: 字体发生改变后
MSG_ERASEBKGND:清除窗口背景 事件产生者:InvalidateRect 或者 UpdateWindow 等函数并为 bErase 参数传递 TRUE 时
MSG_PAINT: 绘制消息 事件产生者:判断窗口是否含有无效区域,当窗口在初始显示、从隐藏状态变化为显示状态、从部分不可见到可见状态,或者应用程序调用 InvalidateRect 函数使某个矩形区域变成
无效时,窗口将具有特定的无效区域。
MSG_CLOSE: 处理事件 DestroyMainWindow 销毁主窗口
MSG_DESTROY:DestroyMainWindow 或者 DestroyWindow
四.对话框编程基础
1.主窗口和对话框:对话框被称为子类化后的主窗口类
2.typedef struct _CTRLDATA
{
const char* class_name;
DWORD dwStyle;
int x, y, w, h;
int id;
const char* caption;
DWORD dwAddData;
DWORD dwExStyle;
const char* werdr_name;
const WINDOW_ELEMENT_ATTR* we_attrs;
} CTRLDATA;//控件
typedef CTRLDATA* PCTRLDATA;
//对话框模板
typedef struct _DLGTEMPLATE
{
DWORD dwStyle;
DWORD dwExStyle;
int x, y, w, h;
const char* caption;
HICON hIcon;
HMENU hMenu;
int controlnr;
PCTRLDATA controls;
DWORD dwAddData;
} DLGTEMPLATE;
typedef DLGTEMPLATE* PDLGTEMPLATE;
3.对话框回调函数
创建模态对话框
int GUIAPI DialogBoxIndirectParamEx (PDLGTEMPLATE pDlgTemplate,HWND hOwner, WNDPROC DlgProc, LPARAM lParam,const char* werdr_name, WINDOW_ELEMENT_ATTR* we_attrs,const char* window_name, const char* layer_name);
static inline int GUIAPI DialogBoxIndirectParam (PDLGTEMPLATE pDlgTemplate,HWND hOwner, WNDPROC DlgProc, LPARAM lParam)
{
return DialogBoxIndirectParamEx (pDlgTemplate, hOwner, DlgProc, lParam,NULL, NULL, NULL, NULL);
}
结束模态对话框
BOOL GUIAPI EndDialog (HWND hDlg, int endCode);
销毁模态对话框的所有子控件
void GUIAPI DestroyAllControls (HWND hDlg);
4.MSG_INITDIALOG消息 产生事件:根据对话框模板建立对话框以及控件之后 -----> 是创建时第四个消息lParam ----> lParam(消息传进来)
SetWindowAdditionalData (hDlg, (DWORD)lParam);//设置额外数据
info = (struct _DepInfo*) GetWindowAdditionalData (hDlg); //获取额外数据
5.非模态对话框
模态对话框
DialogBoxIndirectParam ---> 根据模板建立对话框 ----> 禁止其托管主窗口 MSG_CREATE -----> 创建控件 -----> MSG_INITDIALOG -----> 新的消息循环 ----> EndDialog
非模态对话框
MG_EXPORT HWND GUIAPI CreateMainWindowIndirectParamEx (PDLGTEMPLATE pDlgTemplate,HWND hOwner, WNDPROC WndProc, LPARAM lParam,const char* werdr_name, WINDOW_ELEMENT_ATTR* we_attrs,const char* window_name, const char* layer_name);
static inline HWND GUIAPICreateMainWindowIndirectParam (PDLGTEMPLATE pDlgTemplate,HWND hOwner, WNDPROC WndProc, LPARAM lParam)
{
return CreateMainWindowIndirectParamEx (pDlgTemplate, hOwner,WndProc, lParam, NULL, NULL, NULL, NULL);
}
#define CreateMainWindowIndirect(pDlgTemplate, hOwner, WndProc) CreateMainWindowIndirectParam(pDlgTemplate, hOwner, WndProc, 0)
销毁非模态对话框
BOOL GUIAPI DestroyMainWindowIndirect (HWND hMainWin);

6550

被折叠的 条评论
为什么被折叠?



