⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄

📁 VB的文本资料,需要时有帮助
💻
字号:

让VB应用程序支持鼠标滚轮  
 
    一、提出问题  
    自从1996年微软推出Intellimouse鼠标后,带滚轮的鼠标开始大行其道,支持鼠标滚轮的应用软件也越来越多。但我感到奇怪,为什么VB到6.0本身仍然不支持鼠标滚轮,VF可是从5.0就提供MouseWheel事件了。  
    如何让VB应用程序支持鼠标滚轮?MSDN上有一篇解决VB下应用Intellimouse鼠标的文章,它解决这一问题的方法是通过一个几十K的第三方控件实现的,可惜该控件没有源代码。况且为了支持鼠标滚轮使用一个第三方控件,好像有点得不偿失。本文给出用纯VB实现这一功能的方法。  
    二、解决问题  
    我们知道VB应用程序响应的Windows传来的消息,需要通过VB解释。可是很不幸,虽然VB解释所有得消息,却只让用户程序在事件中处理部分消息,VB自己处理其他的消息,或者忽略这些消息。  
    在VB5.0以前应用程序无法越过VB直接处理消息,微软从VB5.0开始提供AddressOf  运算符,该运算符可以让用户程序将函数或者过程的地址传递给一个API函数。这样我们就可以在VB应用程序中编写自己的窗口处理函数,通过AddressOf  运算符将在VB中定义的窗口地址传递给窗口处理函数,从而绕过VB的解释器,自己处理消息。事实上,该方法可用于在VB中处理任何消息。  
    实现应用程序支持鼠标滚轮的关键是,捕获鼠标滚轮的消息  MSH_MOUSEWHEEL、WM_MOUSEWHEEL。其中MSH_MOUSEWHEEL是为95准备的,需要Intellimouse驱动程序,而WM_MOUSEWHEEL是目前各版本Windows(98/NT40/2000)内置的消息。本文主要处理WM_MOUSEWHEEL消息。下面是WM_MOUSEWHEEL的语法。  
 
WM_MOUSEWHEEL  
 
fwKeys  =  LOWORD(wParam);  /*  key  flags  */  
 
zDelta  =  (short)  HIWORD(wParam);  
 
/*  wheel  rotation  */  
 
xPos  =  (short)  LOWORD(lParam);  
 
/*  horizontal  position  of  pointer  */  
 
yPos  =  (short)  HIWORD(lParam);  
 
/*  vertical  position  of  pointer  */  
 
    其中:fwKeys指出是否有CTRL、SHIFT、鼠标键(左、中、右、附加)按下,允许复合。zDelta传递滚轮滚动的快慢,该值小于零表示滚轮向后滚动(朝用户方向),大于零表示滚轮向前滚动(朝显示器方向)。lParam指出鼠标指针相对屏幕左上的x、y轴坐标。  
    滚轮按钮相当于普通的三键鼠标的中键,根据滚轮按钮的动作,Windows分别发出WM_MBUTTONUP、WM_MBUTTONDOWN、WM_MBUTTONDBLCLK消息,这些消息VB已经在鼠标事件中支持。  
 
    三、实际应用  
    根据上述原理,给出一个数据库应用的典型例子。  
    1.用户界面班级和学生一对多的查询,当用户在学生网格以外滚动鼠标滚轮,班级主表前后移动;用户在网格以内滚动鼠标学生明细表垂直移动;如果在网格以内按住鼠标滚轮键并且滚动鼠标,学生明细表水平移动。  
    2.Form1上ADO  Data  控件对象datPrimaryRS的  ConnectionString为"PROVIDER=MSDataShape;Data  PROVIDER=MSDASQL;dsn=SCHOOL;uid=;pwd=;",  RecordSelectors  属性的SQL命令文本为"SHAPE  {select  *  from  班级}  AS  ParentCMD  APPEND  ({select  *  from  学生  }  AS  ChildCMD  RELATE  班级名称  TO  班级名称)  AS  ChildCMD"。  
    3.TextBox的DataSource均为datPrimaryRS,DataFiled如图所示。  
    4.窗口下部的网格是DataGrid控件,名称为grdDataGrid。  
    5.表单From1.frm的清单如下:  
 
Private  Sub  Form_Load()  
 
Set  grdDataGrid.DataSource  =datPrimaryRS.Recordset("ChildCMD").UnderlyingValue  
Hook  Me.hWnd  
 
End  Sub  
 
Private  Sub  Form_Unload(Cancel  As  Integer)  
 
UnHook  Me.hWnd  
 
End  Sub  
 
 
    6.标准模块Module1.bas清单如下:  
 
Option  Explicit  
Public  Type  POINTL  
x  As  Long  
y  As  Long  
End  Type  
 
Declare  Function  CallWindowProc  _  
Lib  "USER32"  Alias  "CallWindowProcA"  _  
(ByVal  lpPrevWndFunc  As  Long,  _  
ByVal  hWnd  As  Long,  _  
ByVal  Msg  As  Long,  _  
ByVal  wParam  As  Long,  _  
ByVal  lParam  As  Long)  As  Long  
 
 
Declare  Function  SetWindowLong  _  
Lib  "USER32"  Alias  "SetWindowLongA"  _  
(ByVal  hWnd  As  Long,  _  
ByVal  nIndex  As  Long,  _  
ByVal  dwNewLong  As  Long)  As  Long  
 
Declare  Function  SystemParametersInfo  _  
Lib  "USER32"  Alias  "SystemParametersInfoA"  _  
(ByVal  uAction  As  Long,  _  
ByVal  uParam  As  Long,  _  
lpvParam  As  Any,  _  
ByVal  fuWinIni  As  Long)  As  Long  
 
 
Declare  Function  ScreenToClient  Lib  "USER32"  _  
(ByVal  hWnd  As  Long,  xyPoint  As  POINTL)  As  Long  
Public  Const  GWL_WNDPROC  =  -4  
Public  Const  SPI_GETWHEELSCROLLLINES  =  104  
Public  Const  WM_MOUSEWHEEL  =  &H20A  
Public  WHEEL_SCROLL_LINES  As  Long  
 
Global  lpPrevWndProc  As  Long  
 
Public  Sub  Hook(ByVal  hWnd  As  Long)  
lpPrevWndProc  =  SetWindowLong(hWnd,  GWL_WNDPROC,  AddressOf  WindowProc)  
 
’获取"控制面板"中的滚动行数值  
Call  SystemParametersInfo(SPI_GETWHEELSCROLLLINES,  0,  WHEEL_SCROLL_LINES,  0)  
 
If  WHEEL_SCROLL_LINES  >  Form1.grdDataGrid.VisibleRows  Then  
WHEEL_SCROLL_LINES  =  Form1.grdDataGrid.VisibleRows  
End  If  
 
End  Sub  
 
 
Public  Sub  UnHook(ByVal  hWnd  As  Long)  
 
Dim  lngReturnValue  As  Long  
 
lngReturnValue  =  SetWindowLong(hWnd,GWL_WNDPROC,  lpPrevWndProc)  
 
End  Sub  
 
 
Function  WindowProc(ByVal  hw  As  Long,  _  
ByVal  uMsg  As  Long,  _  
ByVal  wParam  As  Long,  _  
ByVal  lParam  As  Long)  As  Long  
 
Dim  pt  As  POINTL  
Select  Case  uMsg  
  Case  WM_MOUSEWHEEL  
     Dim  wzDelta,  wKeys  As  Integer  
     wzDelta  =  HIWORD(wParam)  
     wKeys  =  LOWORD(wParam)  
     pt.x  =  LOWORD(lParam)  
     pt.y  =  HIWORD(lParam)  
    ’将屏幕坐标转换为Form1.窗口坐标  
    ScreenToClient  Form1.hWnd,  pt  
      With  Form1.grdDataGrid  
       ’判断坐标是否在Form1.grdDataGrid窗口内  
       If  pt.x  >  .Left  /  Screen.TwipsPerPixelX  And  _  
       pt.x  <  (.Left  +  .Width)  /  Screen.TwipsPerPixelX  And  _  
       pt.y  >  .Top  /  Screen.TwipsPerPixelY  And  _  
       pt.y  <  (.Top  +  .Height)  /  Screen.TwipsPerPixelY  Then  
 
      ’滚动明细数据库  
   If  wKeys  =  16  Then  
  ’滚动键按下,水平滚动grdDataGrid  
      If  Sgn(wzDelta)  =  1  Then  
          Form1.grdDataGrid.Scroll  -1,  0  
      Else  
          Form1.grdDataGrid.Scroll  1,  0  
      End  If  
    Else  
 
   ’垂直滚动grdDataGrid  
  If  Sgn(wzDelta)  =  1  Then  
   Form1.grdDataGrid.Scroll  0,  0  -  WHEEL_SCROLL_LINES  
    Else  
   Form1.grdDataGrid.Scroll  0,  WHEEL_SCROLL_LINES  
  End  If  
   End  If  
 
Else  
 
’鼠标不在grdDataGrid区域,滚动主数据库  
 
With  Form1.datPrimaryRS.Recordset  
 
If  Sgn(wzDelta)  =  1  Then  
 
If  .BOF  =  False  Then  
 
.MovePrevious  
 
If  .BOF  =  True  Then  
 
.MoveFirst  
 
End  If  
 
End  If  
 
Else  
 
If  .EOF  =  False  Then  
 
.MoveNext  
 
If  .EOF  =  True  Then  
 
.MoveLast  
 
End  If  
 
End  If  
 
End  If  
 
End  With  
 
   End  If  
 
   End  With  
 
Case  Else  
 
   WindowProc  =  CallWindowProc(lpPrevWndProc,  hw,  uMsg,  wParam,  lParam)  
 
End  Select  
 
End  Function  
 
 
Public  Function  HIWORD(LongIn  As  Long)  As  Integer  
 
’  取出32位值的高16位  
 
HIWORD  =  (LongIn  And  &HFFFF0000)  \  &H10000  
 
End  Function  
 
 
Public  Function  LOWORD(LongIn  As  Long)  As  Integer  
 
’  取出32位值的低16位  
 
LOWORD  =  LongIn  And  &HFFFF&  
 
End  Function  
 
 
当然也可以找找控件。听说有个控件封装了这个鼠标功能,用起来省心多了。  

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -