第七章 鼠标(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拥有一个超越所有其他渠道的巨大优势,它就 ...
随机推荐
- 与LINQ有关的语言特性
在说LINQ之前必须先说说几个重要的C#语言特性 一:与LINQ有关的语言特性 1.隐式类型 (1)源起 在隐式类型出现之前, 我们在声明一个变量的时候, 总是要为一个变量指定他的类型 甚至在fore ...
- python虚拟环境 | virtualenv 的简单使用 (图文)
一.创建virtualenv虚拟环境 mkvirtualenv -p 版本号 虚拟名 mkvirtualenv -p python3 env_1 python3:版本号 env_1: 虚拟环境名称 创 ...
- SQL 必知必会·笔记<10>联结表
可伸缩(scale) 能够适应不断增加的工作量而不失败.设计良好的数据库或应用程序 称为可伸缩性好(scale well). 联结(JOIN) 联结(JOIN)是一种机制,用来在一条SELECT 语句 ...
- Quartz.NET的简单任务管理类
昨天使用Quartz.NET做了个定时任务的功能,并实现了多个定时任务的功能 下面这个类实现了如下功能: 1.对定时任务进行管理 2.创建定时任务,需要给定时任务一个job的名称 3.判断给定的job ...
- 声明父类new子类
基本概念 这个实例是子类的,但是因为你声明时是用父类声明的,所以你用正常的办法访问不到子类自己的成员,只能访问到从父类继承来的成员. 在子类中用override重写父类中用virtual申明的虚方法时 ...
- APiCloud学习
端API调用 核心模块在 window.api 对象下,默认提供该模块,不需要单独引用. 扩展模块在相应的模块对象下(例如:文件系统模块在fs对象下),需要require引入(var fs = api ...
- CASE函数
-> 使用类似switch-case与if-else if -> 语法 •case [字段] • when 表达式 then 显示数据 • when 表达式 then 显示数据 ...
- HibernateTemplate的用法以及作用
HibernateTemplate作用:从字面上意思我们就知道他是一个模板,然后我们又知道hibernate是一个对象关系映射的框架,所以我们很容易联想到他的功能就是将Hibernate 的持久层访问 ...
- 本地计算机上的MySQL服务启动后停止。某些服务在未由其他服务或程序使用时将自动
重新安装MySQL数据库,由于安装的时候马虎,一路next(事实上,某些地方需要严格的配置,我忘记注意了),导致现在出了很多麻烦. 错误信息: 本地计算机上的MySQL服务启动后停止.某些服务在未由其 ...
- 【redis】7、redis用法总结
Redis是一个开源的使用ANSI C语言编写.支持网络.可基于内存亦可持久化的日志型.Key-Value数据库,并提供多种语言的API. 一.redis优点 Redis支持数据的持久化,可以将内存中 ...