modSubClasser.bas
上传用户:jnjasmy
上传日期:2015-01-04
资源大小:637k
文件大小:15k
源码类别:

GDI/图象编程

开发平台:

Visual Basic

  1. Attribute VB_Name = "modSubClasser"
  2. Option Explicit
  3. ' APIs used in this module
  4. Private Declare Function GetProp Lib "user32.dll" Alias "GetPropA" (ByVal hWnd As Long, ByVal lpString As String) As Long
  5. Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (pDest As Any, pSource As Any, ByVal ByteLen As Long)
  6. Private Declare Function GetGDIObject Lib "gdi32" Alias "GetObjectA" (ByVal hObject As Long, ByVal nCount As Long, lpObject As Any) As Long
  7. Private Declare Function CreateCompatibleBitmap Lib "gdi32" (ByVal hDC As Long, ByVal nWidth As Long, ByVal nHeight As Long) As Long
  8. Private Declare Function SelectObject Lib "gdi32" (ByVal hDC As Long, ByVal hObject As Long) As Long
  9. ' used to convert VB system color variables to proper long color values
  10. Private Declare Function GetSysColor Lib "user32.dll" (ByVal nIndex As Long) As Long
  11. ' used to create drawing pens/lines & DC movements
  12. Private Declare Function MoveToEx Lib "gdi32" (ByVal hDC As Long, ByVal X As Long, ByVal Y As Long, lpPoint As Any) As Long
  13. Private Declare Function LineTo Lib "gdi32" (ByVal hDC As Long, ByVal X As Long, ByVal Y As Long) As Long
  14. Private Declare Function CreatePen Lib "gdi32.dll" (ByVal nPenStyle As Long, ByVal nWidth As Long, ByVal crColor As Long) As Long
  15. Private Declare Function DeleteObject Lib "gdi32.dll" (ByVal hObject As Long) As Long
  16. ' temporary - all border routines will be moved to a separate class
  17. Private Declare Function DrawEdge Lib "user32" (ByVal hDC As Long, qrc As RECT, ByVal edge As Long, ByVal grfFlags As Long) As Long
  18. Private Declare Function OffsetRect Lib "user32" (lpRect As RECT, ByVal X As Long, ByVal Y As Long) As Long
  19. Private Declare Function SelectClipRgn Lib "gdi32" (ByVal hDC As Long, ByVal hRgn As Long) As Long
  20. Private Declare Function CreateRectRgnIndirect Lib "gdi32" (lpRect As RECT) As Long
  21. Private Declare Function OffsetRgn Lib "gdi32.dll" (ByVal hRgn As Long, ByVal X As Long, ByVal Y As Long) As Long
  22. Private Declare Function CombineRgn Lib "gdi32" (ByVal hDestRgn As Long, ByVal hSrcRgn1 As Long, ByVal hSrcRgn2 As Long, ByVal nCombineMode As Long) As Long
  23. Private Declare Function GetRgnBox Lib "gdi32.dll" (ByVal hRgn As Long, lpRect As RECT) As Long
  24. Private Declare Function UnhookWindowsHookEx Lib "user32.dll" (ByVal hHook As Long) As Long
  25. Private Declare Function CallNextHookEx Lib "user32.dll" (ByVal hHook As Long, ByVal ncode As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
  26. Private Declare Function SetWindowsHookEx Lib "user32.dll" Alias "SetWindowsHookExA" (ByVal idHook As Long, ByVal lpfn As Long, ByVal hmod As Long, ByVal dwThreadId As Long) As Long
  27. Private Declare Function GetCurrentThreadId Lib "kernel32.dll" () As Long
  28. Private Type BITMAP
  29.     bmType As Long
  30.     bmWidth As Long
  31.     bmHeight As Long
  32.     bmWidthBytes As Long
  33.     bmPlanes As Integer
  34.     bmBitsPixel As Integer
  35.     bmBits As Long
  36. End Type
  37. Public Enum ButtonStateConstants
  38.     bsNormal = 0
  39.     bsDown = 1
  40.     bsDisabled = 2
  41. End Enum
  42. Public Enum TitlelBarBtnPosition
  43.     tbPosDefault = 0
  44.     tbPosLockX = 1
  45.     tbPosLockY = 2
  46.     tbPosStatic = 4
  47.     tbNoFrame = 128
  48. End Enum
  49. Public Enum SysMenuItemConstants
  50.     smClose = 2
  51.     smMinimize = 4
  52.     smMaximize = 8
  53.     smSize = 16
  54.     smMove = 32
  55.     smSysIcon = 64
  56. End Enum
  57. Public Enum WindowBorderStyleConstants
  58.     wbBlackEdge = 1
  59.     wbThin = 2
  60.     wbDialog = 3
  61.     wbThick = 4
  62.     wbCustom = 5
  63. End Enum
  64. Public Enum FontStateColorConstants
  65.     fcEnabled = 0
  66.     fcSelected = 1
  67.     fcDisabled = 2
  68.     fcInActive = 3
  69. End Enum
  70. Public Type SystemMenuItems
  71.     ID As Long
  72.     SysIcon As Long
  73.     ItemType As Long
  74.     Caption As String
  75. End Type
  76. Private Type MOUSEHOOKSTRUCT
  77.     pt As POINTAPI
  78.     hWnd As Long
  79.     wHitTestCode As Long
  80.     dwExtraInfo As Long
  81. End Type
  82. Private Type MSG
  83.     hWnd As Long
  84.     message As Long
  85.     wParam As Long
  86.     lParam As Long
  87.     time As Long
  88.     pt As POINTAPI
  89. End Type
  90. Private Const MSGF_MENU As Long = 2
  91. Private Const WH_KEYBOARD As Long = 2
  92. Private Const WH_MSGFILTER As Long = -1
  93. Private Const WH_GETMESSAGE As Long = 3
  94. Private Const WH_MOUSE As Long = 7
  95. Private menuHK_ptr As Long
  96. Private oldMenuHook As Long
  97. Private inputHK_ptr As Long
  98. Private oldKeyBdHook As Long
  99. Private oldMouseHook As Long
  100. Public Sub SetMenuHook(bSet As Boolean, callingClass As clsMenuBarControl)
  101. If oldMenuHook Then UnhookWindowsHookEx oldMenuHook
  102. If bSet Then
  103.     Dim hookAddr As Long
  104.     hookAddr = ReturnAddressOf(AddressOf MenuFilterProc)
  105.     menuHK_ptr = ObjPtr(callingClass)
  106.     oldMenuHook = SetWindowsHookEx(WH_MSGFILTER, hookAddr, 0, GetCurrentThreadId())
  107. Else
  108.     oldMenuHook = 0
  109.     menuHK_ptr = 0
  110. End If
  111. End Sub
  112. Public Sub SetInputHook(bSet As Boolean, callingClass As clsMenuBarControl)
  113. If oldKeyBdHook Then ' currently existing hook; remove it
  114.     UnhookWindowsHookEx oldKeyBdHook
  115.     UnhookWindowsHookEx oldMouseHook
  116. End If
  117. If bSet Then
  118.     Dim hookAddr As Long
  119.     hookAddr = ReturnAddressOf(AddressOf KeybdFilterProc)
  120.     inputHK_ptr = ObjPtr(callingClass)
  121.     oldKeyBdHook = SetWindowsHookEx(WH_KEYBOARD, hookAddr, 0, GetCurrentThreadId())
  122.     hookAddr = ReturnAddressOf(AddressOf MouseFilterProc)
  123.     oldMouseHook = SetWindowsHookEx(WH_MOUSE, hookAddr, 0, GetCurrentThreadId())
  124. Else
  125.     oldKeyBdHook = 0
  126.     oldMouseHook = 0
  127.     inputHK_ptr = 0
  128. End If
  129. End Sub
  130. Private Function ReturnAddressOf(lAddress As Long) As Long
  131. ReturnAddressOf = lAddress
  132. End Function
  133. Private Function MenuFilterProc(ByVal ncode As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
  134. If ncode = MSGF_MENU Then
  135.     Dim tgtClass As clsMenuBarControl
  136.     If GetObjectFromPointer(menuHK_ptr, tgtClass) Then
  137.         If tgtClass.SetMenuAction(lParam) = True Then
  138.             MenuFilterProc = 1
  139.             Exit Function
  140.         End If
  141.     End If
  142. End If
  143. MenuFilterProc = CallNextHookEx(oldMenuHook, ncode, wParam, lParam)
  144. End Function
  145. Private Function MouseFilterProc(ByVal ncode As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
  146. If ncode > -1 Then
  147.     Dim tgtClass As clsMenuBarControl
  148.     If GetObjectFromPointer(inputHK_ptr, tgtClass) Then
  149.         'If tgtClass.SetMessageAction(wParam, lParam) = True Then
  150.         If tgtClass.SetMouseAction(wParam, lParam) = True Then
  151.             MouseFilterProc = 1
  152.             Exit Function
  153.         End If
  154.     End If
  155. End If
  156. MouseFilterProc = CallNextHookEx(oldMouseHook, ncode, wParam, lParam)
  157. End Function
  158. Private Function KeybdFilterProc(ByVal ncode As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
  159. If ncode > -1 Then
  160.     Dim tgtClass As clsMenuBarControl
  161.     If GetObjectFromPointer(inputHK_ptr, tgtClass) Then
  162.         If tgtClass.SetKeyBdAction(wParam, lParam) = True Then
  163.             KeybdFilterProc = 1
  164.             Exit Function
  165.         End If
  166.     End If
  167. End If
  168. KeybdFilterProc = CallNextHookEx(oldKeyBdHook, ncode, wParam, lParam)
  169. End Function
  170. Public Function GetObjectFromPointer(oPtr As Long, outClass As Object) As Boolean
  171. If oPtr Then
  172.     Dim tgtClass As Object
  173.     CopyMemory tgtClass, oPtr, &H4
  174.     Set outClass = tgtClass
  175.     CopyMemory tgtClass, 0&, &H4
  176.     GetObjectFromPointer = True
  177. End If
  178. End Function
  179. Public Function LoWord(DWord As Long) As Long
  180. ' =====================================================================
  181. ' function to return the LoWord of a Long value
  182. ' =====================================================================
  183.      If DWord And &H8000& Then
  184.         LoWord = DWord Or &HFFFF0000
  185.      Else
  186.         LoWord = DWord And &HFFFF&
  187.      End If
  188. End Function
  189. Public Function HiWord(DWord As Long) As Long
  190. ' =====================================================================
  191. ' function to return the HiWord of a Long value
  192. ' =====================================================================
  193.      HiWord = (DWord And &HFFFF0000)  &H10000
  194. End Function
  195. Public Function MakeDWord(LoWord As Integer, HiWord As Integer) As Long
  196. ' =====================================================================
  197. ' function combines 2 Integers into a Long value
  198. ' =====================================================================
  199.      MakeDWord = (HiWord * &H10000) Or (LoWord And &HFFFF&)
  200. End Function
  201. Public Sub TempDrawBorders(hDC As Long, wRgn As Long, cRgn As Long)
  202. Const BDR_RAISEDINNER As Long = &H4
  203. Const BDR_RAISEDOUTER As Long = &H1
  204. Const BDR_SUNKENINNER As Long = &H8
  205. Const BDR_SUNKENOUTER As Long = &H2
  206. Const BF_MIDDLE As Long = &H800
  207. Const BF_LEFT As Long = &H1
  208. Const BF_TOP As Long = &H2
  209. Const BF_RIGHT As Long = &H4
  210. Const BF_BOTTOM As Long = &H8
  211. Dim eRect As RECT
  212. Dim edgeRgn As Long
  213. GetRgnBox wRgn, eRect
  214. edgeRgn = CreateRectRgnIndirect(eRect) '  copy the overall window region
  215. OffsetRgn edgeRgn, -eRect.Left, -eRect.Top  ' offset to 0,0
  216. 'OffsetRgn cRgn, -eRect.Left, -eRect.Top     ' offset client area to 0,0
  217. CombineRgn edgeRgn, edgeRgn, cRgn, 4   ' exclude the client region
  218. ' use it for clipping region to prevent painting over client area
  219. SelectClipRgn hDC, edgeRgn
  220. DeleteObject edgeRgn
  221. ' draw the rectangular borders
  222. OffsetRect eRect, -eRect.Left, -eRect.Top
  223. DrawEdge hDC, eRect, BDR_RAISEDINNER Or BDR_RAISEDOUTER, BF_BOTTOM Or BF_LEFT Or BF_RIGHT Or BF_TOP Or BF_MIDDLE
  224. SelectClipRgn hDC, 0
  225. 'DeleteObject cRgn
  226. End Sub
  227. Public Function ResizeBitmap(cDC As Long, hBmp As Long, _
  228.         newCx As Long, newCy As Long, _
  229.         selectInto As Long, bResized As Boolean) As Long
  230.         
  231. Dim bmpInfo As BITMAP
  232. If hBmp Then GetGDIObject hBmp, Len(bmpInfo), bmpInfo
  233. If bmpInfo.bmHeight <> newCy Or bmpInfo.bmWidth <> newCx Then
  234.     If hBmp Then DeleteObject hBmp
  235.     hBmp = CreateCompatibleBitmap(cDC, newCx, newCy)
  236.     bResized = True
  237. End If
  238. If selectInto Then ResizeBitmap = SelectObject(selectInto, hBmp)
  239. End Function
  240. Public Function ConvertVBSysColor(inColor As Long) As Long
  241. ' converts a vbSystemColor variable to a long color variable
  242. ' I've never seen the GetSysColor API return an error, but just in case...
  243. On Error GoTo ExitRoutine
  244. If inColor < 0 Then
  245.     ConvertVBSysColor = GetSysColor(inColor And &HFF&)
  246. Else
  247.     ConvertVBSysColor = inColor
  248. End If
  249. ExitRoutine:
  250. End Function
  251. Public Sub GradientFill(ByVal FromColor As Long, ByVal ToColor As Long, _
  252.     hDC As Long, ByVal X As Long, ByVal Y As Long, ByVal Cx As Long, Cy As Long, _
  253.     Optional ByVal Roughness As Byte)
  254. ' FromColor :: any valid RGB color or system color (i.e vbActiveTitleBar)
  255. ' ToColor :: any valid RGB color or system color (i.e vbInactiveTitleBar)
  256. ' hDC :: the DC to draw gradient on
  257. ' X :: left edge of gradient rectangle
  258. ' Y :: top edge of gradient rectangle
  259. ' to determine direction of gradient, pass Cx and/or Cy as follows
  260. ' Left>Right :: Cx is positive and right edge of gradient rectangle (i.e., Right)
  261. ' Right>Left :: Cx is negative and right edge of gradient rectangle (i.e., -Right)
  262. ' Bottom>Top :: Cy is negative and bottom edge of gradient rectangle (i.e., -Bottom)
  263. ' Top>Bottom :: Cx is negative & Cy is negative (i.e., -Right & -Bottom)
  264. ' Roughness :: 0=fine detail, 1-4 is lesser quality for larger rectangles
  265. '               determines line thickness of 1,3,5,7 or 9
  266. Dim bColor(0 To 3) As Byte, eColor(0 To 3) As Byte
  267. 'convert values like vbButtonFace to a proper RGB value
  268. FromColor = ConvertVBSysColor(FromColor)
  269. ToColor = ConvertVBSysColor(ToColor)
  270. ' quick easy way to convert long to RGB values
  271. CopyMemory bColor(0), FromColor, &H3
  272. CopyMemory eColor(0), ToColor, &H3
  273. Dim lPtIncr As Long ' counter in positive values only
  274. Dim lPenSize As Long ' size of drawing pen
  275. Dim lWxHx As Long   ' adjusted width/height of gradient rectangle
  276. Dim lPoint As Long  ' loop variables
  277. Dim lPtStart As Long, lPtEnd As Long, lPtStep As Long
  278. ' values to add/subtracted from RGB to show next gradient color
  279. Dim ratioRed As Single, ratioGreen As Single, ratioBlue As Single
  280. ' memory DC variables
  281. Dim hPen As Long, hOldPen As Long
  282. ' set a maximum value. I think CreatePen API tends to max out around 10
  283. ' This value will help determine the line width/size
  284. If Roughness > 4 Then Roughness = 4
  285. ' ensure an odd number; even number sizes may not step right in a loop
  286. Roughness = Roughness * 2 + 1
  287. ' Setup the loop variables
  288. If Cy < 0 Then ' vertical
  289.     If Cx < 0 Then ' vertical top to bottom
  290.         lPtStart = Y
  291.         lPtEnd = Abs(Cy)
  292.         lPtStep = Roughness
  293.     Else            ' vertical bottom to top
  294.         lPtStart = Abs(Cy)
  295.         lPtEnd = Y
  296.         lPtStep = -Roughness
  297.     End If
  298. Else        ' horizontal
  299.     If Cx < 0 Then ' horizontal right to left
  300.         lPtStep = -Roughness
  301.         lPtStart = Abs(Cx)
  302.         lPtEnd = X
  303.     Else                ' horizontal left to right
  304.         lPtStep = Roughness
  305.         lPtStart = X
  306.         lPtEnd = Cx
  307.     End If
  308. End If
  309. ' calculate the width & add a buffer of 1 to prevent RGB overflow possibility
  310. lWxHx = Abs(lPtEnd - lPtStart) + 1
  311. ' ensure we can draw at least a minimum amount of lines
  312. If lWxHx < Roughness Then
  313.     ' if not, make the step value either +1 or -1 depending on current pos/neg sign
  314.     lPtStep = lPtStep / Abs(lPtStep)
  315. Else
  316. ' tweak to prevent situation where last line may not be drawn
  317. ' To combat this, we simply add an extra loop
  318.     lPtEnd = lPtEnd - lPtStep * (Abs(lPtStep) > 1)
  319. End If
  320. ' calculate color step value
  321. ratioRed = ((eColor(0) + 0 - bColor(0)) / lWxHx)
  322. ratioGreen = ((eColor(1) + 0 - bColor(1)) / lWxHx)
  323. ratioBlue = ((eColor(2) + 0 - bColor(2)) / lWxHx)
  324. ' cache vs using the ABS function in the loop -- less calculations
  325. Cx = Abs(Cx)
  326. lPenSize = Abs(lPtStep)
  327. ' It is faster to have 2 separate loops (1 for vertical & 1 for horizontal)
  328. ' than to use one loop and put an IF statement in there to identify
  329. ' direction of drawing. Difference could be 100's of "IFs" processed.
  330. ' select the first color; then enter loop.
  331. hOldPen = SelectObject(hDC, CreatePen(0, lPenSize, FromColor))
  332. ' these loops are pretty much identical with the only big difference
  333. ' of shifting X,Y coords to draw a vertical line or a horizontal line
  334. If Cy < 0 Then  ' vertical loop
  335.     For lPoint = lPtStart To lPtEnd Step lPtStep
  336.         MoveToEx hDC, X, lPoint, ByVal 0&
  337.         LineTo hDC, Cx, lPoint
  338.         DeleteObject SelectObject(hDC, CreatePen(0, lPenSize, RGB( _
  339.             bColor(0) + lPtIncr * ratioRed, _
  340.             bColor(1) + lPtIncr * ratioGreen, _
  341.             bColor(2) + lPtIncr * ratioBlue)))
  342.         lPtIncr = lPtIncr + lPenSize
  343.     Next
  344. Else        ' horizontal loop
  345.     For lPoint = lPtStart To lPtEnd Step lPtStep
  346.         MoveToEx hDC, lPoint, Y, ByVal 0&
  347.         LineTo hDC, lPoint, Cy
  348.         DeleteObject SelectObject(hDC, CreatePen(0, lPenSize, RGB( _
  349.             bColor(0) + lPtIncr * ratioRed, _
  350.             bColor(1) + lPtIncr * ratioGreen, _
  351.             bColor(2) + lPtIncr * ratioBlue)))
  352.         lPtIncr = lPtIncr + lPenSize
  353.     Next
  354. End If
  355. ' destroy the last pen created & replace with original DC pen
  356. DeleteObject SelectObject(hDC, hOldPen)
  357. End Sub