home *** CD-ROM | disk | FTP | other *** search
/ Planet Source Code Jumbo …e CD Visual Basic 1 to 7 / 3_2004-2005.ISO / Data / Zips / Advanced_S1855972212005.psc / Subclass / Dll / mSubclass.bas < prev    next >
BASIC Source File  |  2005-02-18  |  12KB  |  347 lines

  1. Attribute VB_Name = "mSubclass"
  2. Option Explicit
  3.  
  4. '==================================================================================================
  5. 'mSubclass.bas                          7/5/04
  6. '
  7. '           PURPOSE:
  8. '               Uses a separate cSubclassHub object for each window that is subclassed.  The
  9. '               cSubclassHub object is responsible for delivering the messages to the requesting objects.
  10. '
  11. '           CLASSES CREATED BY THIS MODULE:
  12. '               pcSubclassHub
  13. '
  14. '               cSubclass
  15. '
  16. '==================================================================================================
  17.  
  18. '1.  Private Interface      - Utility procedures
  19. '2.  cSubclass Interface    - Procedures called by cSubclass
  20. '3.  cSubclasses Interface  - Procedures called by cSubclasses
  21.  
  22. #Const bVBVMTypeLib = False      'Toggles between using the MSVBVM type library
  23.  
  24. Private Type tSubclassClient    'store one record for each object requesting subclasses
  25.     hWnd() As Long              'store the hWnds being subclassed
  26.     hWndCount As Long           'store the count of the hWnds
  27.     Ptr As Long                 'store the pointer to the object
  28.     iControl As Long            'keep track of changes for enumeration
  29. End Type
  30.  
  31. Private mtClients() As tSubclassClient  'one record for each object requesting subclasses
  32. Private miClientCount As Long           'current record count
  33.  
  34. Public mCollSubclasses As Collection    'collection of pcSubclass objects to relay the messages
  35.  
  36. '<Private Interface>
  37. Public Property Get MsgHubObject( _
  38.                 ByVal hWnd As Long, _
  39.        Optional ByVal bForce As Boolean) _
  40.                     As pcSubclassHub
  41.     
  42.     On Error GoTo NotThere
  43.     Set MsgHubObject = mCollSubclasses("h" & hWnd)  'return the collection item for this hWnd
  44.     Exit Property
  45. NotThere:
  46.     If bForce Then
  47.         If mCollSubclasses Is Nothing Then Set mCollSubclasses = New Collection
  48.         Set MsgHubObject = New pcSubclassHub
  49.         mCollSubclasses.Add MsgHubObject, "h" & hWnd
  50.         If Not MsgHubObject.Subclass(hWnd) Then gErr vbbApiError, "cSubclasses.Add"
  51.     Else
  52.         gErr vbbItemDetached, "cSubclass"
  53.     End If
  54. End Property
  55.  
  56. Private Sub RemoveHub( _
  57.             ByVal hWnd As Long)
  58.     On Error Resume Next
  59.     mCollSubclasses.Remove "h" & hWnd        'Remove the object from the collection
  60. End Sub
  61.  
  62. Private Function FindClient( _
  63.             ByVal iPtr As Long, _
  64.    Optional ByRef iFirstAvailable As Long) _
  65.                 As Long
  66.     Dim liTemp As Long
  67.     iFirstAvailable = Undefined                         'Initialize the first available slot to nothing
  68.     For FindClient = 0& To miClientCount - 1&           'loop through each client
  69.         liTemp = mtClients(FindClient).Ptr              'store the client's pointer
  70.         If Not (liTemp = 0& Or liTemp = Undefined) Then 'if this pointer is valid
  71.             If iPtr = liTemp Then Exit Function         'if the pointer matches then bail
  72.         Else                                            'if the pointer is invalid
  73.             If iFirstAvailable = Undefined Then _
  74.                 iFirstAvailable = FindClient            'it may be the first available slot
  75.         End If
  76.     Next
  77.     FindClient = Undefined                              'if we made it out here, then the client was not found
  78. End Function
  79.  
  80. 'private implementation of ArrRedim to allow strong typing
  81. Private Sub ArrRedimT( _
  82.             ByRef tArray() As tSubclassClient, _
  83.             ByVal iElements As Long, _
  84.    Optional ByVal bPreserve As Boolean = True)
  85.     'Adjust from elements to zero-based upper bound
  86.     'iElements is now a zero-based array bound
  87.     iElements = iElements - 1&
  88.  
  89.     Dim liNewUbound As Long: liNewUbound = ArrAdjustUbound(iElements)
  90.  
  91.     'If we don't have enough room already, then redim the array
  92.     If liNewUbound > ArrUboundT(tArray) Then
  93.         If bPreserve Then _
  94.             ReDim Preserve tArray(0 To liNewUbound) _
  95.         Else _
  96.             ReDim tArray(0 To liNewUbound)
  97.     End If
  98. End Sub
  99.  
  100. Private Function ArrUboundT( _
  101.             ByRef tArray() As tSubclassClient) _
  102.                 As Long
  103.     On Error Resume Next
  104.     ArrUboundT = UBound(tArray)
  105.     If Err.Number <> 0& Then ArrUboundT = Undefined
  106. End Function
  107. '</Private Interface>
  108.  
  109. '<Public Interface>
  110. '<cSubclasses Interface>
  111. Public Function Subclasses_Add( _
  112.             ByVal iWho As Long, _
  113.             ByVal hWnd As Long _
  114.     ) As cSubclass
  115.     
  116.     If Not MsgHubObject(hWnd, True).AddClient(iWho) Then gErr vbbKeyAlreadyExists, "cSubclasses.Add"
  117.  
  118.     Dim liIndex As Long
  119.     Dim liFirst As Long
  120.     liIndex = FindClient(iWho, liFirst) 'get the index of the client if it exists, and get the first available slot
  121.  
  122.     If liIndex = Undefined Then         'if the client was not already there then
  123.         If liFirst = Undefined Then     'if there was an open slot then
  124.             liFirst = miClientCount     'next index is current count
  125.             miClientCount = miClientCount + 1&  'inc the count
  126.             ArrRedimT mtClients, miClientCount, True    'resize the array
  127.         End If
  128.         With mtClients(liFirst)         'with this array index
  129.             .Ptr = iWho                 'set the pointer to this object
  130.             .hWndCount = 0              'initialize the hWnd count
  131.         End With
  132.         liIndex = liFirst               'store this index
  133.     End If
  134.     Incr mtClients(liIndex).iControl
  135.                                         'add the hWnd to the table
  136.     ArrAddInt mtClients(liIndex).hWnd, mtClients(liIndex).hWndCount, hWnd
  137.     
  138.     Set Subclasses_Add = New cSubclass
  139.     Subclasses_Add.fInit iWho, hWnd
  140.  
  141. End Function
  142.  
  143. Public Sub Subclasses_Remove( _
  144.                     ByVal iWho As Long, _
  145.                     ByVal hWnd As Long)
  146.  
  147.     On Error GoTo NotThere
  148.         
  149.     Dim loHub As pcSubclassHub
  150.     Set loHub = MsgHubObject(hWnd)
  151.     If Not loHub.DelClient(iWho) Then
  152. NotThere:
  153.         gErr vbbKeyNotFound, "cSubclasses.Remove"
  154.     End If
  155.     
  156.  
  157.     If Not loHub.Active Then            'If there's nobody left to notify then destroy the object
  158.         
  159.         Dim liIndex As Long
  160.         liIndex = FindClient(iWho)      'get the index of the client in our array
  161.         If liIndex <> Undefined Then    'if the index was found
  162.             With mtClients(liIndex)     'remove the hWnd from the table
  163.                 ArrDelInt .hWnd, .hWndCount, hWnd
  164.                 If .hWndCount = 0& Then 'if that was the last hWnd
  165.                     .Ptr = 0&           'remove the client from the table
  166.                 End If
  167.                 Incr .iControl
  168.             End With
  169.         Else
  170.             'This would be bad!
  171.             'client wasn't found!!
  172.             Debug.Assert False
  173.         End If
  174.  
  175.         Set loHub = Nothing             'destroy our reference to the object
  176.         RemoveHub hWnd                  'remove the object from the collection
  177.     End If
  178.  
  179. End Sub
  180.  
  181. Public Function Subclasses_Item( _
  182.             ByVal hWnd As Long, _
  183.             ByVal iWho As Long) _
  184.                 As cSubclass
  185.     On Error GoTo NoHub
  186.     If MsgHubObject(hWnd).ClientExists(iWho) Then
  187.         Set Subclasses_Item = New cSubclass
  188.         Subclasses_Item.fInit iWho, hWnd
  189.     Else
  190. NoHub:
  191.         gErr vbbKeyNotFound, "cSubclasses.Item"
  192.     End If
  193.  
  194. End Function
  195.  
  196. Public Function Subclasses_Exists( _
  197.             ByVal hWnd As Long, _
  198.             ByVal iWho As Long _
  199.         ) As Boolean
  200.         
  201.     On Error GoTo NoHub
  202.     Subclasses_Exists = MsgHubObject(hWnd).ClientExists(iWho)
  203.     Exit Function
  204. NoHub:
  205.     Err.Clear
  206. End Function
  207.  
  208. Public Function Subclasses_Count( _
  209.             ByVal iWho As Long) _
  210.                 As Long
  211.         
  212.     Dim liIndex As Long
  213.     liIndex = FindClient(iWho)      'find the index of the client
  214.                                     'if the index was found, return the hWnd count
  215.                                     
  216.     If liIndex > Undefined Then
  217.         With mtClients(liIndex)
  218.             Subclasses_Count = .hWndCount
  219.             For liIndex = 0& To .hWndCount - 1&
  220.                 If .hWnd(liIndex) = 0& Or .hWnd(liIndex) = Undefined _
  221.                 Then Subclasses_Count = Subclasses_Count - 1&
  222.             Next
  223.         End With
  224.     End If
  225.     
  226. End Function
  227.  
  228. Public Function Subclasses_Clear( _
  229.             ByVal iWho As Long) _
  230.                 As Long
  231.     
  232.     Dim liIndex As Long
  233.     Dim i       As Long
  234.     Dim loHub   As pcSubclassHub
  235.     
  236.     liIndex = FindClient(iWho)                          'Find the index of the client
  237.     
  238.     If liIndex <> Undefined Then                        'If the index was found
  239.         With mtClients(liIndex)
  240.             For i = 0 To .hWndCount - 1&                'loop through each hWnd
  241.                 If .hWnd(i) <> Undefined Then
  242.                     Set loHub = MsgHubObject(.hWnd(i))  'Retrieve the subclasser associated with this hwnd
  243.                     If Not loHub Is Nothing Then
  244.                                                         'Tell the object to cease notifications for this client
  245.                         If loHub.DelClient(iWho) Then _
  246.                             Subclasses_Clear = Subclasses_Clear + 1&
  247.                         
  248.                         If Not loHub.Active Then        'If there's nobody left to notify then destroy the object
  249.                             Set loHub = Nothing
  250.                             RemoveHub .hWnd(i)
  251.                         End If
  252.                     Else
  253.                         'hWnd is not subclassed???
  254.                         Debug.Assert False 'this would be bad!
  255.                     End If
  256.                 End If
  257.             Next
  258.             .hWndCount = 0&                             'remove the hWnd
  259.             .Ptr = 0&                                   'remove the ptr
  260.             Incr .iControl
  261.         End With
  262.     End If
  263.     
  264. End Function
  265.  
  266. 'Public Sub Subclasses_NextItem( _
  267. '            ByVal iWho As Long, _
  268. '            ByRef tEnum As tEnum, _
  269. '            ByRef vNextItem As Variant, _
  270. '            ByRef bNoMore As Boolean)
  271. '
  272. '    Dim loSub As cSubclass
  273. '    Dim liIndex As Long
  274. '    Dim liClient As Long
  275. '    Dim i As Long
  276. '
  277. '    liClient = FindClient(iWho)
  278. '    If liClient <> Undefined Then
  279. '
  280. '        liIndex = tEnum.iIndex
  281. '        liIndex = liIndex + 1&
  282. '
  283. '        With mtClients(liClient)
  284. '
  285. '            If .iControl <> tEnum.iControl Then gErr vbbCollChangedDuringEnum, "cSubclasses.NewEnum"
  286. '
  287. '            For i = liIndex To .hWndCount - 1&
  288. '                If .hWnd(i) <> Undefined Then       'if the hWnd exists
  289. '                    Set loSub = New cSubclass       'create a new subclass object
  290. '                    loSub.fInit iWho, .hWnd(i)      'initialize it
  291. '                    Set vNextItem = loSub
  292. '                    Exit For
  293. '                End If
  294. '            Next
  295. '            If i = .hWndCount Then bNoMore = True
  296. '        End With
  297. '
  298. '        tEnum.iIndex = i
  299. '    Else
  300. '        bNoMore = True
  301. '    End If
  302. 'End Sub
  303. '
  304. 'Public Function Subclasses_Skip( _
  305. '            ByVal iWho As Long, _
  306. '            ByRef tEnum As tEnum, _
  307. '            ByVal iSkipCount As Long, _
  308. '            ByRef bSkippedAll As Boolean)
  309. '
  310. '    Dim liSkipped As Long
  311. '    Dim liClient As Long
  312. '
  313. '    liClient = FindClient(iWho)
  314. '    If liClient <> Undefined Then
  315. '
  316. '
  317. '        With mtClients(liClient)
  318. '
  319. '            If .iControl <> tEnum.iControl Then gErr vbbCollChangedDuringEnum, "cSubclasses.NewEnum"
  320. '
  321. '            For tEnum.iIndex = tEnum.iIndex + 1& To .hWndCount - 1&
  322. '                If .hWnd(tEnum.iIndex) <> Undefined Then liSkipped = liSkipped + 1&
  323. '                If liSkipped = iSkipCount Then Exit For
  324. '            Next
  325. '            bSkippedAll = CBool(liSkipped = iSkipCount)
  326. '
  327. '        End With
  328. '    Else
  329. '        bSkippedAll = False
  330. '
  331. '    End If
  332. '
  333. 'End Function
  334. '
  335. 'Public Function Subclasses_Control(ByVal iWho As Long) As Long
  336. '    Subclasses_Control = FindClient(iWho)
  337. '    If Subclasses_Control <> Undefined Then
  338. '        Subclasses_Control = mtClients(Subclasses_Control).iControl
  339. '    Else
  340. '        'client not there!
  341. '        'Debug.Assert False
  342. '    End If
  343. 'End Function
  344. '</cSubclasses Interface>
  345. '</Public Interface>
  346.  
  347.