第八章 滑鼠-2
程式中的命中测试
我在前面讨论了Windows Explorer如何回应滑鼠的单击和双击。显然,程式(或者更精确的说,如同Windows Explorer般使用list view control)必须确定使用者滑鼠所指向的是哪一个档案。
这叫做「命中测试」。正如DefWindowProc在处理WM_NCHITTEST讯息时做一些命中测试一样,视窗讯息处理程式经常必须在显示区域中进行一些命中测试。一般来说,命中测试中会使用x和y座标值,它们由传到视窗讯息处理程式的滑鼠讯息的lParam参数给出。
一个假想的例子
有这样一个例子。假设您的程式需要显示几列按字母排列的档案。通常,您可以使用list view control,他会帮您由於要做全部的命中测试工作。但我们假设您由於某种原因而不能使用,这时就需要自己来做了。让我们假定档案名保存在称为szFileNames的已排序字串指标阵列中。
让我们也假定档案列表开始於显示区域的顶端,显示区域为cxClient图素宽, cyClient图素高,每列为cxColWidth图素宽,每个字元高度为cyChar图素高。那么每栏可填入的档案数就是:
iNumInCol = cyClient / cyChar ;
接收到一个滑鼠单击讯息後,您就能从lParam获得cxMouse和cyMouse座标。然後可以用下面的公式来计算使用者所指的是哪一列的档案名:
iColumn = cxMouse / cxColWidth ;
相对於列顶端的档案名位置为:
iFromTop = cyMouse / cyChar ;
现在您就可以计算szFileNames阵列的下标:
iIndex = iColumn * iNumInCol + iFromTop ;
如果iIndex超过了阵列中的档案数,则表示使用者是在显示器的空白区域内按滑鼠按键。
在许多情况下,命中测试要比本例更加复杂。在显示一幅包含许多小图形的图像时,您必须决定要显示的每个小图形的座标。在命中计算中,您必须从座标找到物件。但这将在使用不确定字体大小的字处理程式中变得非常凌乱,因为您必须找到字元在字串中的位置。
范例程式
程式7-2所示的CHECKER1程式展示了一些简单的命中测试,此程式把显示区域分为5×5的25个矩形。如果您在某个矩形中按下滑鼠按键,那么在该矩形中将出现一个「X」。如果您再按一次,那么「X」将被删除。
程式7-2 CHECKER1
CHECKER1.C
/*-------------------------------------------------------------------------
CHECKER1.C -- Mouse Hit-Test Demo Program No. 1
(c) Charles Petzold, 1998
--------------------------------------------------------------------------*/
#include <windows.h>
#define DIVISIONS 5
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,PSTR szCmdLine, int iCmdShow)
{ static TCHAR szAppName[] = TEXT ("Checker1") ;
HWND hwnd ;
MSG msg ;
WNDCLASS wndclass ;
wndclass.style = CS_HREDRAW | CS_VREDRAW ;











文章评论
共有 0 位网友发表了评论 此处只显示部分留言 点击查看完整评论页面