EasyX图形化学习(二)
peekmessage函数会将消息保存到 ExMessage 结构体中,只需查看 msg.message (一个成员变量)的内容即可知道按了什么键。filter:默认 -1 获取所有类别的消息。removemsg:在 peekmessage 处理完消息后,是否将其从消息队列中移除。如果获取到了消息,返回 true,如果当前没有消息,返回 false。msg.y 中保存了按键时鼠标的位置坐标。ExM
1.消息处理---鼠标消息:
1.ExMessage结构体:
ExMessage---这个结构体用于保存鼠标消息。
//定义消息结构体变量
ExMessage msg = { 0 };
2.获取消息:
(1)peekmessage函数:
用于获取一个消息,并立即返回。
bool peekmessage(ExMessage *msg, BYTE filter = -1, bool removemsg = true);
参数:
msg:指向消息结构体 ExMessage 的指针,用来保存获取到的消息。
filter:默认 -1 获取所有类别的消息。可以用以下值或值的组合获取指定类别的消息:

removemsg:在 peekmessage 处理完消息后,是否将其从消息队列中移除。
返回值:
如果获取到了消息,返回 true,如果当前没有消息,返回 false。
(2)获取鼠标按键情况:
peekmessage函数会将消息保存到 ExMessage 结构体中,只需查看 msg.message (一个成员变量)的内容即可知道按了什么键。
msg.message 可以成为以下值:

//获取消息
while (1)
{
if (peekmessage(&msg, EX_MOUSE))
{
switch (msg.message)
{
case WM_LBUTTONDOWN :
cout << "鼠标左键按下\n" << endl;
break;
case WM_RBUTTONDOWN :
cout << "鼠标右键按下\n" << endl;
break;
case WM_MBUTTONDOWN :
cout << "鼠标中键按下\n" << endl;
break;
case WM_MOUSEWHEEL: :
cout << "鼠标滚轮滚动\n" << endl;
break;
case WM_LBUTTONDBLCLK :
cout << "鼠标左键双击" << endl;
break;
}
}
}
注:检测鼠标双击必须在 initgraph 函数参数中传入 EX_DBLCLKS(详见上篇)。
(3)获取按键时鼠标位置:
msg.x ; msg.y 中保存了按键时鼠标的位置坐标。
例:将上面代码改为:
case WM_LBUTTONDOWN :
cout << "鼠标左键按下 pos("<<msg.x<<","<<msg.y<<")" << endl;

(4)获取滚轮时滚动方向:
msg.wheel 中保存了滚轮时滚动方向:
向屏幕滚动为120 ,向自己为 -120。
2.消息处理---按钮:
1.封装按钮函数:
//鼠标处于按钮区域
bool inArea(int mx, int my, int x, int y, int w, int h)
{
if (msg.x > x && msg.x < x + w && msg.y > y && msg.y < y + h)
{
return true;
}
return false;
}
//按钮绘制且判断是否点击
bool button(int x, int y, int w, int h, const char* text)
{
//绘制按钮
setfillcolor(RGB(230, 231, 232));
fillroundrect(x, y, x + w, y + h, 5, 5);
//绘制文本
int hSpace = (w - textwidth(text)) / 2;
int vSpace = (h - textheight(text)) / 2;
outtextxy(x + hSpace, y + vSpace, text);
//判断按钮是否被点击
if (msg.message == WM_LBUTTONDOWN&&inArea(msg.x,msg.y,x,y,w,h))
{
return true;
}
return false;
}
2.双缓冲绘图:
所有的绘图代码必须放在BeginBatchDraw和EndBatchDraw之间,否则会发生闪烁现象。
两个函数用途:BeginBatchDraw函数将绘图操作保存不输出,直至遇到EndBatchDraw才输出。
BeginBatchDraw();
if (button(20, 20, 150, 35, "Start Game"))
{
printf("Start Game!");
}
EndBatchDraw();
3.按钮可点击时变色:
只需当鼠标在按钮区域时更换填充颜色即可:
//绘制按钮
if (inArea(msg.x, msg.y, x, y, w, h))
{
setfillcolor(RGB(93, 107, 153));
}
else setfillcolor(RGB(230, 231, 232));
fillroundrect(x, y, x + w, y + h, 5, 5);
4.每次循环重置msg的消息:
在循环结尾加
msg.message = 0;
作用:保证每次点击只执行一次内容。
原因:将msg设置为全局变量后,除非鼠标再发生变化(移动,松开),否则msg中message始终为左键点击状态,导致不断执行点击后的内容。
3.消息处理---按键消息:
1.msg.message的可为值:

(也可见上面的图)
2.具体判断是哪个键按下:
msg中有一个变量为 vkcode 保存具体按键的虚拟键值:
常用键值:
(1)上下左右键:

(2)空格键:
![]()
(3)字母键:
大写的相应字母加单引号:如键A 即为 ‘A’
在微软网站上列出有所有的虚拟键码:Virtual-Key Codes (Winuser.h) - Win32 apps | Microsoft Learn
例:
if (msg.message == WM_KEYDOWN)
{
printf("keydown");
//具体判断是哪个键按下
switch (msg.vkcode)
{
case VK_UP:
printf("上箭头");
case VK_DOWN:
printf("下箭头");
case VK_LEFT:
printf("左箭头");
case VK_RIGHT:
printf("右箭头");
case 'A':
printf("A键");
default:
break;
}
}
更多推荐


所有评论(0)