对于鼠标的状态,我专门用了一个全局的变量存放,变量结构体如下:
static struct MOUSE_EVENT_STRUCT
{
// 缓冲状态
BOOL DblClicked; // 有效双击次数
BOOL LButtonWasUp; // 左键曾经松开
BOOL RButtonWasUp; // 右键曾经松开
BOOL LButtonWasDown; // 左键曾经按下
BOOL RButtonWasDown; // 右键曾经按下
short nMouseWheel; // 滚轮偏移量
// 当前状态
int x; // 当前鼠标X坐标
int y; // 当前鼠标Y坐标
BOOL LButton; // 左键状态
BOOL RButton; // 右键状态
BOOL MButton; // 中键状态
};
而按键消息,则直接从消息循环的 WM_CHAR 获取。因为我打算做的RPG网游对键盘的实时状态并不关心,只需要知道曾经按下过什么键即可。WM_CHAR 从 WndProc 过程获取 keyCode, 传递给 CGame,再由 CGame 传递给 CDesktop 当前的焦点控件 。
然后开始窗口对鼠标的相应问题。
窗口自身有属性: IsMove(); 这个属性决定窗口是否可以移动,并响应鼠标的拖拽。当它返回为True 的时候,窗体进行鼠标坐标判断。
if (窗体是标准矩形)
{
if (鼠标在拖动响应区)
开始拖拽窗体
}else{
if (鼠标不处于子控件之上 && 鼠标处于窗体非透明区域之内)
开始拖拽窗体。
}
关于拖动响应区
看下图:
可以看到一个窗体,标题栏写着:调试状态。如果我定义鼠标在红色矩形之内响应拖拽动作,则需要判断鼠标坐标是否在这个矩形之内并且鼠标左键是否按下状态。
这个红色矩形是由CSkin读取皮肤的时候定义的。它的 Left, Top, Right 分别是对应于窗体实际 Left、Top、Right的一个偏移量,而Height则是一个固定值,表示矩形的高度。
首先由CDesktop传入一个响应消息结构的变量指针,再由响应到鼠标、键盘信息的窗体返回,CDesktop再根据返回的信息处理掉一些操作(焦点变换,坐标变换等等),再将最终消息结果返回给CGame处理游戏逻辑事件。
CDesktop关心的信息如下:
响应的窗口:(如果不是当前窗口,设置为当前窗口, 如果为NULL, 则忽略.)
响应的控件:(如果不是当前激活控件, 设置为激活控件, 如果为NULL, 则忽略.)
响应的事件ID:(例如 M_CLICK, M_LBTNDOWN, M_RBTNDOWN..等)
响应的处理函数: 一个函数指针
我的想法是用函数指针去处理响应的消息。每个CWin都保存一个自身的消息处理函数指针地址,如果不是空地址,则接收到响应之后调用其自身的响应处理函数去执行游戏的逻辑事件。把游戏的逻辑事件处理函数都放在一个类里面,声明为static,供CGame调用,这样看起来会比较清晰。
我想这种做法应该比较贴近Windows的事件驱动机制,有点回调函数的味道。
static struct MOUSE_EVENT_STRUCT
{
// 缓冲状态
BOOL DblClicked; // 有效双击次数
BOOL LButtonWasUp; // 左键曾经松开
BOOL RButtonWasUp; // 右键曾经松开
BOOL LButtonWasDown; // 左键曾经按下
BOOL RButtonWasDown; // 右键曾经按下
short nMouseWheel; // 滚轮偏移量
// 当前状态
int x; // 当前鼠标X坐标
int y; // 当前鼠标Y坐标
BOOL LButton; // 左键状态
BOOL RButton; // 右键状态
BOOL MButton; // 中键状态
};
而按键消息,则直接从消息循环的 WM_CHAR 获取。因为我打算做的RPG网游对键盘的实时状态并不关心,只需要知道曾经按下过什么键即可。WM_CHAR 从 WndProc 过程获取 keyCode, 传递给 CGame,再由 CGame 传递给 CDesktop 当前的焦点控件 。
然后开始窗口对鼠标的相应问题。
窗口自身有属性: IsMove(); 这个属性决定窗口是否可以移动,并响应鼠标的拖拽。当它返回为True 的时候,窗体进行鼠标坐标判断。
if (窗体是标准矩形)
{
if (鼠标在拖动响应区)
开始拖拽窗体
}else{
if (鼠标不处于子控件之上 && 鼠标处于窗体非透明区域之内)
开始拖拽窗体。
}
关于拖动响应区
看下图:
可以看到一个窗体,标题栏写着:调试状态。如果我定义鼠标在红色矩形之内响应拖拽动作,则需要判断鼠标坐标是否在这个矩形之内并且鼠标左键是否按下状态。
这个红色矩形是由CSkin读取皮肤的时候定义的。它的 Left, Top, Right 分别是对应于窗体实际 Left、Top、Right的一个偏移量,而Height则是一个固定值,表示矩形的高度。
首先由CDesktop传入一个响应消息结构的变量指针,再由响应到鼠标、键盘信息的窗体返回,CDesktop再根据返回的信息处理掉一些操作(焦点变换,坐标变换等等),再将最终消息结果返回给CGame处理游戏逻辑事件。
CDesktop关心的信息如下:
响应的窗口:(如果不是当前窗口,设置为当前窗口, 如果为NULL, 则忽略.)
响应的控件:(如果不是当前激活控件, 设置为激活控件, 如果为NULL, 则忽略.)
响应的事件ID:(例如 M_CLICK, M_LBTNDOWN, M_RBTNDOWN..等)
响应的处理函数: 一个函数指针
我的想法是用函数指针去处理响应的消息。每个CWin都保存一个自身的消息处理函数指针地址,如果不是空地址,则接收到响应之后调用其自身的响应处理函数去执行游戏的逻辑事件。把游戏的逻辑事件处理函数都放在一个类里面,声明为static,供CGame调用,这样看起来会比较清晰。
我想这种做法应该比较贴近Windows的事件驱动机制,有点回调函数的味道。