第七章 鼠标(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拥有一个超越所有其他渠道的巨大优势,它就 ...
随机推荐
- package.json文件中dependencies和devDependencies的区别
在工作和学习中,我经常会用的npm 下载各种包,有时就会遇到各种npm 的形式,现在就捋一捋 首先要先了解 package.json文件中dependencies和devDependencies的 ...
- Hadoop服务库与事件库的使用及其工作流程
Hadoop服务库与事件库的使用及其工作流程 Hadoop服务库: YARN采用了基于服务的对象管理模型,主要特点有: 被服务化的对象分4个状态:NOTINITED,INITED,STARTED, ...
- Eclipse常用注释设置
菜单:Window→Preferences→Java→Code Style→Code Template Files /** * @Title: ${file_name} * @Package ${pa ...
- Android应用系列:手把手教你做一个小米通讯录(附图附源码)
前言 最近心血来潮,突然想搞点仿制品玩玩,很不幸小米成为我苦逼的第一个试验品.既然雷布斯的MIUI挺受欢迎的(本人就是其的屌丝用户),所以就拿其中的一些小功能做一些小demo来玩玩.小米的通讯录大家估 ...
- C++中的字符串可以这样换行写
运行结果:
- apache tomcat搭建负载均衡(实现集群中的session同步)
原理:tomcat 做个WEB服务器有它的局限性,处理能力低,效率低.承受并发小(1000左右).但目前有不少网站或者页面是JSP的.并采用了tomcat做为WEB,因此只能在此基础上调优. 目前采取 ...
- css布局------上下高度固定,中间高度自适应容器
HTML <body> <div class="container"> <div class="header"></d ...
- 动态规划法(三)子集和问题(Subset sum problem)
继续讲故事~~ 上次讲到我们的主人公丁丁,用神奇的动态规划法解决了杂货店老板的两个找零钱问题,得到了老板的肯定.之后,他就决心去大城市闯荡了,看一看外面更大的世界. 这天,丁丁刚回到家,他 ...
- 学会4种备份MySQL数据库(基本备份方面没问题了)
前言 我们试着想一想, 在生产环境中什么最重要?如果我们服务器的硬件坏了可以维修或者换新, 软件问题可以修复或重新安装, 但是如果数据没了呢?这可能是最恐怖的事情了吧, 我感觉在生产环境中应该没有什么 ...
- 关于vue,webpack 中 “exports is not defined”报错
vue项目npm run dev 后项目报错 : 提示 “exports is not defined”. 导致这个问题是因为balbel的配置文件.babelrc的问题: { "prese ...