第七章 鼠标(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拥有一个超越所有其他渠道的巨大优势,它就 ...
随机推荐
- 课程四(Convolutional Neural Networks),第二 周(Deep convolutional models: case studies) —— 1.Practice questions
[解释] 应该是same padding 而不是 valid padding . [解释] 卷积操作用的应该是adding additional layers to the network ,而是应该 ...
- .NET内存管理、垃圾回收
1. Stack和Heap 每个线程对应一个stack,线程创建的时候CLR为其创建这个stack,stack主要作用是记录函数的执行情况.值类型变量(函数的参数.局部变量 等非成员变量)都分配 ...
- SSH, 整合分页功能,连带DAO经典封装
任何一个封装讲究的是,使用,多状态.Action: 任何一个Action继承分页有关参数类PageManage,自然考虑的到分页效果,我们必须定义下几个分页的参数.并根据这个参数进行查值. 然 ...
- 从零开始学 Web 之 移动Web(六)响应式布局
大家好,这里是「 从零开始学 Web 系列教程 」,并在下列地址同步更新...... github:https://github.com/Daotin/Web 微信公众号:Web前端之巅 博客园:ht ...
- Postgres绿色版本安装 windows
虽然PostgreSQL是为类UNIX平台开发的,但它却是可以移植的.从7.1版本开始,PostgreSQL可以编译安装和作为一个PostgreSQL服务器运行在Windows NT 4,2000,X ...
- 开源网站流量统计系统Piwik源码分析——参数统计(一)
Piwik现已改名为Matomo,这是一套国外著名的开源网站统计系统,类似于百度统计.Google Analytics等系统.最大的区别就是可以看到其中的源码,这正合我意.因为我一直对统计的系统很好奇 ...
- Go命令行参数解析flag包
go语言提供的flag包可以解析命令行的参数,代码: package main import ( "flag" "fmt" ) func main() { // ...
- python解析处理snmp回显----snmp
查看服务端配置:https://www.cnblogs.com/dpf-10/p/9175409.html 查看内容示例: D:\python>snmpwalk -v 2c -c public ...
- Freemarker教程1(基本使用)
简介 FreeMarker是一款模板引擎: 即一种基于模板和要改变的数据, 并用来生成输出文本(HTML网页.电子邮件.配置文件.源代码等)的通用工具. 它不是面向最终用户的,而是一个Java类库,是 ...
- Apache RocketMQ在linux上的常用命令
Apache RocketMQ在linux上的常用命令 进入maven安装后的rocketmq的bin目录 1.启动Name Server 2.启动Broker 3.关闭Name Server 4 ...