第七章 鼠标(CHECKER2)
CHECKER2程序包含一个键盘接口,内容与CHECKER1完全相同。利用←、→、↑、↓四个方向键可以在25个矩形之间移动鼠标指针。Home键把鼠标指针移动到左上角的矩形;End键使鼠标指针落到右下角的矩形。空格键和回车键都可以切换X形标记。
/*---------------------------------------------
CHECKER2.C -- Mouse Hit-Test Demo Program No.2
(c) Charles Petzold, 1998
---------------------------------------------*/ #include <Windows.h> #define DIVISIONS 5 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); int WINAPI WinMain( __in HINSTANCE hInstance
, __in_opt HINSTANCE hPrevInstance
, __in LPSTR lpCmdLine
, __in int nShowCmd )
{
static TCHAR szAppName[] = TEXT("Checker2");
HWND hwnd;
MSG msg;
WNDCLASS wndclass; wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = WndProc;
wndclass.cbClsExtra = ;
wndclass.cbWndExtra = ;
wndclass.hInstance = hInstance;
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = szAppName; if (!RegisterClass(&wndclass))
{
MessageBox(NULL, TEXT("Program requires Windows NT!")
, szAppName, MB_ICONERROR);
return ;
} hwnd = CreateWindow(szAppName, TEXT("Checker2 Mouse Hit-Test Demo")
, WS_OVERLAPPEDWINDOW
, CW_USEDEFAULT, CW_USEDEFAULT
, CW_USEDEFAULT, CW_USEDEFAULT
, NULL, NULL, hInstance, NULL); ShowWindow(hwnd, nShowCmd);
UpdateWindow(hwnd); while (GetMessage(&msg, NULL, , ))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
} return msg.wParam;
} LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static BOOL fState[DIVISIONS][DIVISIONS];
static int cxBlock, cyBlock;
HDC hdc;
int x, y;
PAINTSTRUCT ps;
POINT point;
RECT rect; switch (message)
{
case WM_SIZE:
cxBlock = LOWORD(lParam) / DIVISIONS;
cyBlock = HIWORD(lParam) / DIVISIONS;
return ; case WM_SETFOCUS:
ShowCursor(TRUE);
return ; case WM_KILLFOCUS:
ShowCursor(FALSE);
return ; case WM_KEYDOWN:
GetCursorPos(&point);
ScreenToClient(hwnd, &point); x = max(, min(DIVISIONS - , point.x / cxBlock));
y = max(, min(DIVISIONS - , point.y / cyBlock)); switch (wParam)
{
case VK_UP:
--y;
break; case VK_DOWN:
++y;
break; case VK_LEFT:
--x;
break; case VK_RIGHT:
++x;
break; case VK_HOME:
x = y = ;
break; case VK_END:
x = y = DIVISIONS - ;
break; case VK_RETURN:
case VK_SPACE:
SendMessage(hwnd, WM_LBUTTONDOWN, MK_LBUTTON, MAKELONG(x * cxBlock, y * cyBlock));
break;
} x = (x + DIVISIONS) % DIVISIONS;
y = (y + DIVISIONS) % DIVISIONS; point.x = x * cxBlock + cxBlock / ;
point.y = y * cyBlock + cyBlock / ; ClientToScreen(hwnd, &point);
SetCursorPos(point.x, point.y);
return ; case WM_LBUTTONDOWN:
x = LOWORD(lParam) / cxBlock;
y = HIWORD(lParam) / cyBlock; if (x < DIVISIONS && y < DIVISIONS)
{
fState[x][y] ^= ; rect.left = x * cxBlock;
rect.top = y * cyBlock;
rect.right = (x + ) * cxBlock;
rect.bottom = (y + ) * cyBlock; InvalidateRect(hwnd, &rect, FALSE);
}
else
MessageBeep();
return ; case WM_PAINT:
hdc = BeginPaint(hwnd, &ps); for (x = ; x < DIVISIONS; ++x)
for (y = ; y < DIVISIONS; ++y)
{
Rectangle(hdc, x * cxBlock, y * cyBlock
, (x + ) * cxBlock, (y + ) * cyBlock); if (fState[x][y])
{
MoveToEx(hdc, x * cxBlock, y * cyBlock, NULL);
LineTo(hdc, (x + ) * cxBlock, (y + ) * cyBlock);
MoveToEx(hdc, x * cxBlock, (y + ) * cyBlock, NULL);
LineTo(hdc, (x + ) * cxBlock, y * cyBlock);
}
} EndPaint(hwnd, &ps);
return ; case WM_DESTROY:
PostQuitMessage();
return ;
} return DefWindowProc(hwnd, message, wParam, lParam);
}
CHECKER2.C
在CHECKER2程序中,处理WM_KEYDOWN时利用GetCursorPos判断指针的位置,并利用ScreenToClient将屏幕坐标转换成客户区坐标,然后将坐标值除以矩形块的宽和高,得到x和y。这些x和y的值表示了矩形在5*5数组中的位置。当按下某个键时,鼠标指针可能在客户区也可能不在客户区内,因此x和y必须包含在min和max的宏处理中,保证它们的范围处于0和4之间。
对于方向键,CHECKER2程序相应的增加或减少x和y的值。若按下回车键或空格键,CHECKER2程序调用SendMessage给自己发送一个WM_LBUTTONDOWN消息。最后,WM_KEYDOWN处理逻辑计算得到指向矩形中心的客户区坐标,并调用ClientToScreen将其转换成屏幕坐标,最后调用SetCursorPos设置指针的位置。
第七章 鼠标(CHECKER2)的更多相关文章
- 第七章 鼠标(CHECKER1)
CHECKER1程序将客户区划分成25个矩形,构成一个5*5的数组.如果在其中一个矩形内单击鼠标,就用X形填充该矩形.再次单击,则X形消失. /*--------------------------- ...
- 第七章 鼠标(CHECKER4)
/*--------------------------------------------- CHECKER4.C -- Mouse Hit-Test Demo Program No.4 (c) C ...
- 第七章 鼠标(CHECKER3)
/*--------------------------------------------- CHECKER3.C -- Mouse Hit-Test Demo Program No.3 (c) C ...
- 第七章 鼠标(CONNECT)
/* CONNECT.C -- Connect-the-Dots Mouse Demo Program (c) Charles Petzold,1998 */ #include <Windows ...
- 第七章 探秘Qt的核心机制-信号与槽
第七章 探秘Qt的核心机制-信号与槽 注:要想使用Qt的核心机制信号与槽,就必须在类的私有数据区声明Q_OBJECT宏,然后会有moc编译器负责读取这个宏进行代码转化,从而使Qt这个特有的机制得到使用 ...
- (转)iOS Wow体验 - 第七章 - 操作图例与触屏人机工学
本文是<iOS Wow Factor:Apps and UX Design Techniques for iPhone and iPad>第七章译文精选,其余章节将陆续放出.上一篇:Wow ...
- 【转】第七章、Linux 文件与目录管理
原文网址:http://vbird.dic.ksu.edu.tw/linux_basic/0220filemanager.php 第七章.Linux 文件与目录管理 最近升级日期:2009/08/26 ...
- 【知识强化】第七章 输入/输出系统 7.1 I/O系统基本概念
那么下面,我们将要进入计算机组成原理的最后一章,也就是我们的第七章,输入输出系统的学习.那么这一部分内容呢,我们之前呢一直在提,但是并没有详细地讲解,那么进入到我们第七章输入输出系统这一部分,我们就要 ...
- 精通Web Analytics 2.0 (9) 第七章:失败更快:爆发测试与实验的能量
精通Web Analytics 2.0 : 用户中心科学与在线统计艺术 第七章:失败更快:爆发测试与实验的能量 欢迎来到实验和测试这个棒极了的世界! 如果Web拥有一个超越所有其他渠道的巨大优势,它就 ...
随机推荐
- UFLDL 教程学习笔记(二)反向传导算法
UFLDL(Unsupervised Feature Learning and Deep Learning)Tutorial 是由 Stanford 大学的 Andrew Ng 教授及其团队编写的一套 ...
- Linux编程 5 (目录重命名与移动mv,删除文件rm,目录创建mkdir删除rmdir,查看file,cat,more,tail,head)
一. 文件重命名与移动(mv) 在linux中,重命名文件称为移动(moving).mv命令可以将文件和目录移动到另一个位置或重新命名. 1.1 使用mv重命名 下面在/usr/local下面创建一个 ...
- mysql 开发进阶篇系列 28 数据库二进制包安装(centos系统准备)
1. centos 7安装工作 对于mysql二进制安装,我这里在使用一台新的centos系统.准备好VMware,Xftp-6.0, Xshell-6.0.在VMware中网络使用桥接模式,分配20 ...
- 【OSX】解决编译AOSP时需要10.5/10.6 SDK下载
有人遇到的是需要10.6的sdk. 公司网快下载了xcode, 把里面的10.5sdk和10.6sdk拿出来, 一共才一百多兆…… 下载链接: http://pan.baidu.com/s/1gdxG ...
- 【Java基本功】聊聊抽象类和接口的区别
1 抽象类一般会实现一部分操作,并且留一些抽象方法让子类自己实现,比如Stringbuffer和Stringbuilder的父类abstractStringbuilder. 2 接口一般指一种规定,比 ...
- 今天讲座的感悟--java
发现当你擅长于某一专业,永远那专业上的人才挤挤.倘若你和相邻专业结合,就能更厉害的走在交叉专业上.例如:医学加计算机等 待续...
- Angular2入门:TypeScript的函数 - 剩余参数和箭头函数
- Java设计模式学习记录-解释器模式
前言 这次介绍另一个行为模式,解释器模式,都说解释器模式用的少,其实只是我们在日常的开发中用的少,但是一些开源框架中还是能见到它的影子,例如:spring的spEL表达式在解析时就用到了解释器模式,以 ...
- Linux IPC基础(System V)
简介 IPC 主要有消息队列.信号量和共享内存3种机制.和文件一样,IPC 在使用前必须先创建,使用 ipcs 命令可以查看当前系统正在使用的 IPC 工具: 由以上可以看出,一个 IPC 至少包含 ...
- 动态规划法(四)0-1背包问题(0-1 Knapsack Problem)
继续讲故事~~ 转眼我们的主人公丁丁就要离开自己的家乡,去大城市见世面了.这天晚上,妈妈正在耐心地帮丁丁收拾行李.家里有个最大能承受20kg的袋子,可是妈妈却有很多东西想装袋子里,已知行李的编 ...