1.鼠标输入
1.用户移动鼠标时,系统在屏幕上移动一个称为鼠标光标的小位图
2.鼠标光标含有一个叫做热点的像素点,系统用它来跟踪和识别光标的位置
3.如果发生了鼠标事件,热点所在位置下的窗口通常会接收到相关的鼠标消息
4.能够接收鼠标消息的窗口并不一定是活动窗口或具有键盘输入焦点
2.鼠标消息
3.鼠标捕获
接收鼠标消息的窗口
1.窗口过程通常只在鼠标光标位于窗口的客户区或非客户区上时才接收鼠标消息,也就是说,系统只向光标热点之下的窗口发
送鼠标消息 ------ 这种是客户区坐标
2.但是某些时候应用程序可能需要接收鼠标消息,即使光标热点在它的窗口范围之外,这种情况下,我们可以使用 SetCapture函数来使某个窗口捕获鼠标,在应用程序调用 ReleaseCapture 恢复正常的鼠标处理方式之前,这个窗口将接收所有的鼠标消息 ----- 这种是屏幕坐标
HWND GUIAPI SetCapture(HWND hWnd);
void GUIAPI ReleaseCapture(void);
HWND GUIAPI GetCapture(void);
例程
#include <minigui/common.h>
#include <minigui/minigui.h>
#include <minigui/gdi.h>
#include <minigui/window.h>
#include <minigui/control.h>
#define IDC_MYBUTTON 100
/* 简单按钮控件类的回调函数 */
static int MybuttonWindowProc (HWND hWnd, int message, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
static int status = 0;//用于保存按钮控件的状态。注意,在实际的控件类中,不应该使用静态变量来保存控件实例的信息
switch (message) {
case MSG_LBUTTONDOWN:
status = 1; //设置按下状态
SetCapture (hWnd); //捕获鼠标
InvalidateRect (hWnd, NULL, TRUE); //使控件无效,导致重绘按钮
break;
case MSG_LBUTTONUP:
if (GetCapture() != hWnd)
break;
status = 0; //设置释放状态
ReleaseCapture (); //释放鼠标
InvalidateRect (hWnd, NULL, TRUE);//使控件无效,导致重绘按钮
break;
case MSG_PAINT:
hdc = BeginPaint (hWnd);
if (status) {
SetBkMode(hdc, BM_TRANSPARENT); //根据按下或释放的状态进行不同的绘制
TextOut(hdc, 0, 0, "pressed");
}
EndPaint(hWnd, hdc);
return 0;
case MSG_DESTROY:
return 0;
}
return DefaultControlProc (hWnd, message, wParam, lParam);
}
/* 该函数注册简单按钮控件 */
BOOL RegisterMybutton (void)
{
WNDCLASS WndClass;
WndClass.spClassName = "mybutton";
WndClass.dwStyle = 0;
WndClass.dwExStyle = 0;
WndClass.hCursor = GetSystemCursor(0);
WndClass.iBkColor = PIXEL_lightgray;
WndClass.WinProc = MybuttonWindowProc;
return RegisterWindowClass (&WndClass);
}
static int CaptureWinProc(HWND hWnd, int message, WPARAM wParam, LPARAM lParam)
{
switch (message) {
case MSG_CREATE:
/* 注册简单按钮控件类 */
RegisterMybutton();
/* 创建简单按钮控件类的一个实例 */
CreateWindow ("mybutton", "", WS_VISIBLE | WS_CHILD, IDC_MYBUTTON,
30, 50, 60, 20, hWnd, 0);
break;
case MSG_CLOSE:
/* 销毁控件及主窗口 */
DestroyAllControls (hWnd);
DestroyMainWindow (hWnd);
PostQuitMessage (hWnd);
return 0;
}
return DefaultMainWinProc(hWnd, message, wParam, lParam);
}
/* 以下创建主窗口的代码从略 */
4.跟踪鼠标一个demo
#include <minigui/common.h>
#include <minigui/minigui.h>
#include <minigui/gdi.h>
#include <minigui/window.h>
#include <minigui/control.h>
static int PainterWinProc(HWND hWnd, int message, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
static BOOL bdraw = FALSE;
static int pre_x, pre_y;/* 设定静态变量保存运行状态以及鼠标按下的位置 */
switch (message) {
case MSG_LBUTTONDOWN:
/* 进入绘制状态;捕获鼠标并记录鼠标按下的位置 */
bdraw = TRUE;
SetCapture(hWnd);
pre_x = LOWORD (lParam);
pre_y = HIWORD (lParam);
break;
case MSG_MOUSEMOVE:
{
int x = LOWORD (lParam);
int y = HIWORD (lParam);
if (bdraw) {
ScreenToClient(hWnd, &x, &y);//如果是绘制状态,则表明鼠标被捕获,因此需要将鼠标坐标从屏幕坐标转换为客户区坐标
hdc = GetClientDC(hWnd); //获取客户区设备上下文并开始绘制
SetPenColor(hdc, PIXEL_red);
MoveTo(hdc, pre_x, pre_y); //从先前的位置画直线到当前鼠标位置
LineTo(hdc, x, y);
ReleaseDC(hdc);
pre_x = x; //已当前鼠标位置更新先前的位置
pre_y = y;
}
break;
}
case MSG_LBUTTONUP:
/* 退出绘图状态,并释放鼠标 */
bdraw = FALSE;
ReleaseCapture();
break;
case MSG_RBUTTONDOWN:
/* 按鼠标右键将清除窗口 */
InvalidateRect(hWnd, NULL, TRUE);
break;
case MSG_CLOSE:
DestroyAllControls (hWnd);
DestroyMainWindow (hWnd);
PostQuitMessage (hWnd);
return 0;
}
return DefaultMainWinProc (hWnd, message, wParam, lParam);
}
/* 以下创建窗口的代码从略 */