《Windows编程之鼠标滑轮.pdf》由会员分享,可在线阅读,更多相关《Windows编程之鼠标滑轮.pdf(17页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、WindowsWindows 编程之鼠标滑轮编程之鼠标滑轮与传统的鼠标相比,Microsoft IntelliMouse 的特点是在两个键之间多了一个小滑轮。您可以按下这个滑轮,这时它的功能相当于鼠标按键的中键;或者您也可以用食指来转动它,这会产生一条特殊的消息,叫做 WM_MOUSEWHEEL。使用鼠标滑轮的程序通过滚动或放大文件来响应此消息。它最初听起来像一个不必要的隐藏机关,但我必须承认,我很快就习惯于使用鼠标滑轮来滚动 Microsoft Word 和 Microsoft Internet Explorer 了。我不想讨论鼠标滑轮的所有使用方法。实际上,我只是想告诉您如何在现有的程序(
2、例如程序 SYSMETS4)中添加鼠标滑轮处理程序,以便在显示区域中卷动数据。最终的 SYSMETS 程序如程序7-8所示。程序7-8 SYSMETS4SYSMETS.C/*-SYSMETS.C-Final System Metrics Display Program(c)Charles Petzold,1998-*/#include#include sysmets.hLRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,P
3、STR szCmdLine,intiCmdShow)static TCHAR szAppName=TEXT(SysMets);HWNDhwnd;MSGmsg;WNDCLASSwndclass;wndclass.style=CS_HREDRAW|CS_VREDRAW;wndclass.lpfnWndProc=WndProc;wndclass.cbClsExtra=0;wndclass.cbWndExtra=0;wndclass.hInstance=hInstance;wndclass.hIcon=LoadIcon(NULL,IDI_APPLICATION);wndclass.hCursor=Lo
4、adCursor(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 0;hwnd=CreateWindow(szAppName,TEXT(Get System
5、Metrics),WS_OVERLAPPEDWINDOW|WS_VSCROLL|WS_HSCROLL,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,hInstance,NULL);ShowWindow(hwnd,iCmdShow);UpdateWindow(hwnd);while(GetMessage(&msg,NULL,0,0)TranslateMessage(&msg);DispatchMessage(&msg);return msg.wParam;LRESULT CALLBACK WndProc(HWN
6、D hwnd,UINT message,WPARAM wParam,LPARAM lParam)static intcxChar,cxCaps,cyChar,cxClient,cyClient,iMaxWidth;staticintiDeltaPerLine,iAccumDelta;/for mousewheel logicHDChdc;inti,x,y,iVertPos,iHorzPos,iPaintBeg,iPaintEnd;PAINTSTRUCTps;SCROLLINFOsi;TCHARszBuffer10;TEXTMETRICtm;ULONGulScrollLines;/formous
7、e wheel logicswitch(message)caseWM_CREATE:hdc=GetDC(hwnd);GetTextMetrics(hdc,&tm);cxChar=tm.tmAveCharWidth;cxCaps=(tm.tmPitchAndFamily&1?3:2)*cxChar/2;cyChar=tm.tmHeight+tm.tmExternalLeading;ReleaseDC(hwnd,hdc);/Save the width of the threecolumnsiMaxWidth=40*cxChar+22*cxCaps;/Fall through for mouse
8、wheelinformationcaseWM_SETTINGCHANGE:SystemParametersInfo(SPI_GETWHEELSCROLLLINES,0,&ulScrollLines,0);/ulScrollLines usually equals 3 or 0(for no scrolling)/WHEEL_DELTA equals 120,so iDeltaPerLine will be 40if(ulScrollLines)iDeltaPerLine=WHEEL_DELTA/ulScrollLines;elseiDeltaPerLine=0;return 0;caseWM_
9、SIZE:cxClient=LOWORD(lParam);cyClient=HIWORD(lParam);/Set vertical scroll bar rangeand page sizesi.cbSize=sizeof(si);si.fMask=SIF_RANGE|SIF_PAGE;si.nMin=0;si.nMax=NUMLINES-1;si.nPage=cyClient/cyChar;SetScrollInfo(hwnd,SB_VERT,&si,TRUE);/Set horizontal scroll barrange and page sizesi.cbSize=sizeof(si
10、);si.fMask=SIF_RANGE|SIF_PAGE;si.nMin=0;si.nMax=2+iMaxWidth/cxChar;si.nPage=cxClient/cxChar;SetScrollInfo(hwnd,SB_HORZ,&si,TRUE);return 0;case WM_VSCROLL:/Get all the vertical scrollbar informationsi.cbSize=sizeof(si);si.fMask=SIF_ALL;GetScrollInfo(hwnd,SB_VERT,&si);/Save the position forcomparison
11、later oniVertPos=si.nPos;switch(LOWORD(wParam)caseSB_TOP:si.nPos=si.nMin;break;caseSB_BOTTOM:si.nPos=si.nMax;break;case SB_LINEUP:si.nPos-=1;break;caseSB_LINEDOWN:si.nPos+=1;break;case SB_PAGEUP:si.nPos-=si.nPage;break;caseSB_PAGEDOWN:si.nPos+=si.nPage;break;caseSB_THUMBTRACK:si.nPos=si.nTrackPos;br
12、eak;default:break;/Set the position and then retrieve it.Due to adjustments/by Windows it may not be the same as the value set.si.fMask=SIF_POS;SetScrollInfo(hwnd,SB_VERT,&si,TRUE);GetScrollInfo(hwnd,SB_VERT,&si);/If the position has changed,scrollthe window and update itif(si.nPos!=iVertPos)ScrollW
13、indow(hwnd,0,cyChar*(iVertPos-si.nPos),NULL,NULL);UpdateWindow(hwnd);return 0;caseWM_HSCROLL:/Get all the vertical scroll barinformationsi.cbSize=sizeof(si);si.fMask=SIF_ALL;/Save the position for comparison lateronGetScrollInfo(hwnd,SB_HORZ,&si);iHorzPos=si.nPos;switch(LOWORD(wParam)caseSB_LINELEFT
14、:si.nPos-=1;break;caseSB_LINERIGHT:si.nPos+=1;break;caseSB_PAGELEFT:si.nPos-=si.nPage;break;caseSB_PAGERIGHT:si.nPos+=si.nPage;break;caseSB_THUMBPOSITION:si.nPos=si.nTrackPos;break;default:break;/Set the position and then retrieve it.Due toadjustments/by Windows it may not be the same as the value s
15、et.si.fMask=SIF_POS;SetScrollInfo(hwnd,SB_HORZ,&si,TRUE);GetScrollInfo(hwnd,SB_HORZ,&si);/If the position has changed,scroll the windowif(si.nPos!=iHorzPos)ScrollWindow(hwnd,cxChar*(iHorzPos-si.nPos),0,NULL,NULL);return 0;caseWM_KEYDOWN:switch(wParam)caseVK_HOME:SendMessage(hwnd,WM_VSCROLL,SB_TOP,0)
16、;break;caseVK_END:SendMessage(hwnd,WM_VSCROLL,SB_BOTTOM,0);break;caseVK_PRIOR:SendMessage(hwnd,WM_VSCROLL,SB_PAGEUP,0);break;caseVK_NEXT:SendMessage(hwnd,WM_VSCROLL,SB_PAGEDOWN,0);break;caseVK_UP:SendMessage(hwnd,WM_VSCROLL,SB_LINEUP,0);break;caseVK_DOWN:SendMessage(hwnd,WM_VSCROLL,SB_LINEDOWN,0);br
17、eak;caseVK_LEFT:SendMessage(hwnd,WM_HSCROLL,SB_PAGEUP,0);break;caseVK_RIGHT:SendMessage(hwnd,WM_HSCROLL,SB_PAGEDOWN,0);break;return 0;caseWM_MOUSEWHEEL:if(iDeltaPerLine=0)break;iAccumDelta+=(short)HIWORD(wParam);/120 or-120while(iAccumDelta=iDeltaPerLine)SendMessage(hwnd,WM_VSCROLL,SB_LINEUP,0);iAcc
18、umDelta-=iDeltaPerLine;while(iAccumDelta=-iDeltaPerLine)SendMessage(hwnd,WM_VSCROLL,SB_LINEDOWN,0);iAccumDelta+=iDeltaPerLine;return 0;caseWM_PAINT:hdc=BeginPaint(hwnd,&ps);/Get vertical scroll bar positionsi.cbSize=sizeof(si);si.fMask=SIF_POS;GetScrollInfo(hwnd,SB_VERT,&si);iVertPos=si.nPos;/Get ho
19、rizontal scroll bar positionGetScrollInfo(hwnd,SB_HORZ,&si);iHorzPos=si.nPos;/Find painting limitsiPaintBeg=max(0,iVertPos+ps.rcPaint.top/cyChar);iPaintEnd=min(NUMLINES-1,iVertPos+ps.rcPaint.bottom/cyChar);for(i=iPaintBeg;i=iPaintEnd;i+)x=cxChar*(1-iHorzPos);y=cyChar*(i-iVertPos);TextOut(hdc,x,y,sys
20、metricsi.szLabel,lstrlen(sysmetricsi.szLabel);TextOut(hdc,x+22*cxCaps,y,sysmetricsi.szDesc,lstrlen(sysmetricsi.szDesc);SetTextAlign(hdc,TA_RIGHT|TA_TOP);TextOut(hdc,x+22*cxCaps+40*cxChar,y,szBuffer,wsprintf(szBuffer,TEXT(%5d),GetSystemMetrics(sysmetricsi.iIndex);SetTextAlign(hdc,TA_LEFT|TA_TOP);EndP
21、aint(hwnd,&ps);return 0;caseWM_DESTROY:PostQuitMessage(0);return 0;return DefWindowProc(hwnd,message,wParam,lParam);转动滑轮会导致 Windows 在有输入焦点的窗口(不是鼠标光标下面的窗口)产生WM_MOUSEWHEEL 消息。与平常一样,lParam 将获得鼠标的位置,当然坐标是相对于屏幕左上角的,而不是显示区域的。另外,wParam 的低字组包含一系列的旗标,用于表示鼠标按键、Shift 与 Ctrl 键的状态。新的信息保存在 wParam 的高字组。其中有一个delta值
22、,该值目前可以是120或-120,这取决于滑轮的向前转动(也就是说,向鼠标的前面,即带有按钮与电缆的一端)还是向后转动。值120或-120表示文件将分别向上或向下卷动三行。这里的构想是,以后版本的鼠标滑轮能有比现在的鼠标产生更精确的移动速度信息,并且用 delta 值,例如40和-40,来产生 WM_MOUSEWHEEL 消息。这些值能使文件只向上或向下卷动一行。为使程序能在一般化环境执行,SYSMETS 将在 WM_CREATE 和 WM_SETTINGCHANGE 消息处理时,以 SPI_GETWHEELSCROLLLINES 作为参数来呼叫 SystemParametersInfo。此值
23、说明WHEEL_DELTA 的 delta 值将滚动多少行,WHEEL_DELTA 在 WINUSER.H 中定义。WHEEL_DELTA等于120,并且,在内定情况下 SystemParametersInfo传回3,因此与卷动一行相联系的 delta值就是40。SYSMETS 将此值保存在 iDeltaPerLine。在 WM_MOUSEWHEEL 消息处理期间,SYSMETS 将 delta 值给静态变量 iAccumDelta。然后,如果 iAccumDelta 大于或等于 iDeltaPerLine(或者是小于或等于-iDeltaPerLin),SYSMETS用 SB_LINEUP 或 SB_LINEDOWN 值产生 WM_VSCROLL 消息。对于每一个 WM_VSCROLL 消息,iAccumDelta 由 iDeltaPerLine 增加(或减少)。此代码允许 delta 值大于、小于或等于滚动一行所需要的 delta 值。下面还有下面还有还有一个引人注目的鼠标问题:建立自订鼠标光标。来自:谷融网址:
限制150内