home *** CD-ROM | disk | FTP | other *** search
/ Planet Source Code Jumbo …e CD Visual Basic 1 to 7 / 6_2008-2009.ISO / data / zips / Drag_To_Ex215183582009.psc / modules / mShellNotify.bas < prev    next >
BASIC Source File  |  2009-05-08  |  19KB  |  366 lines

  1. Attribute VB_Name = "mShellNotify"
  2. Option Explicit
  3. ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
  4. ' Copyright ⌐1996-2009 VBnet, Randy Birch, All Rights Reserved.
  5. ' Some pages may also contain other copyrights by the author.
  6. ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
  7. ' Distribution: You can freely use this code in your own
  8. '               applications, but you may not reproduce
  9. '               or publish this code on any web site,
  10. '               online service, or distribute as source
  11. '               on any media without express permission.
  12. ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
  13. 'Brought to you by Brad Martinez
  14. '  http://www.mvps.org/btmtz/
  15. '  http://www.mvps.org/ccrp/
  16. '
  17. 'Demonstrates how to receive shell change
  18. 'notifications (ala "what happens when the
  19. 'SHChangeNotify API is called?")
  20. '
  21. 'Interpretation of the shell's undocumented
  22. 'functions SHChangeNotifyRegister (ordinal 2)
  23. 'and SHChangeNotifyDeregister (ordinal 4) would
  24. 'not have been possible without the assistance of
  25. 'James Holderness. For a complete (and probably
  26. 'more accurate) overview of shell change notifications,
  27. 'please refer to James'"Shell Notifications" page at
  28. 'http://www.geocities.com/SiliconValley/4942/
  29. '------------------------------------------------------
  30. Public Const MAX_PATH As Long = 260
  31. 'Defined as an HRESULT that corresponds to S_OK.
  32. Public Const ERROR_SUCCESS As Long = 0
  33. Public Type SHFILEINFO   'shfi
  34.   hIcon As Long
  35.   iIcon As Long
  36.   dwAttributes As Long
  37.   szDisplayName As String * MAX_PATH
  38.   szTypeName As String * 80
  39. End Type
  40. 'If pidl is invalid, SHGetFileInfoPidl can very easily blow up when filling the szDisplayName and szTypeName string members of the SHFILEINFO struct
  41. Public Type SHFILEINFOBYTE   'sfib
  42.   hIcon As Long
  43.   iIcon As Long
  44.   dwAttributes As Long
  45.   szDisplayName(1 To MAX_PATH) As Byte
  46.   szTypeName(1 To 80) As Byte
  47. End Type
  48. 'Special folder values for
  49. 'SHGetSpecialFolderLocation and
  50. 'SHGetSpecialFolderPath (Shell32.dll v4.71)
  51. Public Enum SHSpecialFolderIDs
  52.   CSIDL_DESKTOP = &H0
  53.   CSIDL_INTERNET = &H1
  54.   CSIDL_PROGRAMS = &H2
  55.   CSIDL_CONTROLS = &H3
  56.   CSIDL_PRINTERS = &H4
  57.   CSIDL_PERSONAL = &H5
  58.   CSIDL_FAVORITES = &H6
  59.   CSIDL_STARTUP = &H7
  60.   CSIDL_RECENT = &H8
  61.   CSIDL_SENDTO = &H9
  62.   CSIDL_BITBUCKET = &HA
  63.   CSIDL_STARTMENU = &HB
  64.   CSIDL_DESKTOPDIRECTORY = &H10
  65.   CSIDL_DRIVES = &H11
  66.   CSIDL_NETWORK = &H12
  67.   CSIDL_NETHOOD = &H13
  68.   CSIDL_FONTS = &H14
  69.   CSIDL_TEMPLATES = &H15
  70.   CSIDL_COMMON_STARTMENU = &H16
  71.   CSIDL_COMMON_PROGRAMS = &H17
  72.   CSIDL_COMMON_STARTUP = &H18
  73.   CSIDL_COMMON_DESKTOPDIRECTORY = &H19
  74.   CSIDL_APPDATA = &H1A
  75.   CSIDL_PRINTHOOD = &H1B
  76.   CSIDL_ALTSTARTUP = &H1D        ''DBCS
  77.   CSIDL_COMMON_ALTSTARTUP = &H1E  ''DBCS
  78.   CSIDL_COMMON_FAVORITES = &H1F
  79.   CSIDL_INTERNET_CACHE = &H20
  80.   CSIDL_COOKIES = &H21
  81.   CSIDL_HISTORY = &H22
  82. End Enum
  83. Enum SHGFI_FLAGS
  84.   SHGFI_LARGEICON = &H0           'sfi.hIcon is large icon
  85.   SHGFI_SMALLICON = &H1           'sfi.hIcon is small icon
  86.   SHGFI_OPENICON = &H2            'sfi.hIcon is open icon
  87.   SHGFI_SHELLICONSIZE = &H4       'sfi.hIcon is shell size (not system size), rtns BOOL
  88.   SHGFI_PIDL = &H8                'pszPath is pidl, rtns BOOL
  89.   SHGFI_USEFILEATTRIBUTES = &H10  'parent pszPath exists, rtns BOOL
  90.   SHGFI_ICON = &H100              'fills sfi.hIcon, rtns BOOL, use DestroyIcon
  91.   SHGFI_DISPLAYNAME = &H200       'isf.szDisplayName is filled, rtns BOOL
  92.   SHGFI_TYPENAME = &H400          'isf.szTypeName is filled, rtns BOOL
  93.   SHGFI_ATTRIBUTES = &H800        'rtns IShellFolder::GetAttributesOf  SFGAO_* flags
  94.   SHGFI_ICONLOCATION = &H1000     'fills sfi.szDisplayName with filename containing the icon, rtns BOOL
  95.   SHGFI_EXETYPE = &H2000          'rtns two ASCII chars of exe type
  96.   SHGFI_SYSICONINDEX = &H4000     'sfi.iIcon is sys il icon index, rtns hImagelist
  97.   SHGFI_LINKOVERLAY = &H8000&     'add shortcut overlay to sfi.hIcon
  98.   SHGFI_SELECTED = &H10000        'sfi.hIcon is selected icon
  99. End Enum
  100. Public Declare Function FlashWindow Lib "user32" (ByVal hwnd As Long, ByVal bInvert As Long) As Long
  101. Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (pDest As Any, pSource As Any, ByVal dwLength As Long)
  102. 'Frees memory allocated by the shell (pidls)
  103. Public Declare Sub CoTaskMemFree Lib "ole32" (ByVal pv As Long)
  104. 'Retrieves the location of a special (system) folder. Returns ERROR_SUCCESS if successful or an OLE-defined error result otherwise.
  105. Public Declare Function SHGetSpecialFolderLocation Lib "shell32" (ByVal hwndOwner As Long, ByVal nFolder As SHSpecialFolderIDs, pidl As Long) As Long
  106. 'Converts an item identifier list to a file system path. Returns TRUE if successful or FALSE if an error occurs, for example, if the location specified by the pidl parameter is not part of the file system.
  107. Public Declare Function SHGetPathFromIDList Lib "shell32" Alias "SHGetPathFromIDListA" (ByVal pidl As Long, ByVal pszPath As String) As Long
  108. 'Retrieves information about an object in the file system, such as a file, a folder, a directory, or a drive root.
  109. Public Declare Function SHGetFileInfoPidl Lib "shell32" Alias "SHGetFileInfoA" (ByVal pidl As Long, ByVal dwFileAttributes As Long, psfib As SHFILEINFOBYTE, ByVal cbFileInfo As Long, ByVal uFlags As SHGFI_FLAGS) As Long
  110. Public Declare Function SHGetFileInfo Lib "shell32" Alias "SHGetFileInfoA" (ByVal pszPath As String, ByVal dwFileAttributes As Long, psfi As SHFILEINFO, ByVal cbFileInfo As Long, ByVal uFlags As SHGFI_FLAGS) As Long
  111. Private Const WM_NCDESTROY As Long = &H82
  112. Private Const GWL_WNDPROC As Long = (-4)
  113. Private Const OLDWNDPROC As String = "OldWndProc"
  114. Private Declare Function GetProp Lib "user32" Alias "GetPropA" (ByVal hwnd As Long, ByVal lpString As String) As Long
  115. Private Declare Function SetProp Lib "user32" Alias "SetPropA" (ByVal hwnd As Long, ByVal lpString As String, ByVal hData As Long) As Long
  116. Private Declare Function RemoveProp Lib "user32" Alias "RemovePropA" (ByVal hwnd As Long, ByVal lpString As String) As Long
  117. Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
  118. Private Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hwnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
  119. 'the one and only shell change notification handle for the desktop folder
  120. Private m_hSHNotify As Long
  121. 'the desktop's pidl
  122. Private m_pidlDesktop As Long
  123. 'User defined notification message sent to the specified window's window proc.
  124. Public Const WM_SHNOTIFY = &H401
  125.  
  126. '------------------------------------------------------
  127. Public Type PIDLSTRUCT
  128.   'Fully qualified pidl (relative to the desktop folder) of the folder to monitor changes in. 0 can also be specified for the desktop folder.
  129.   pidl As Long
  130.   'Value specifying whether changes in the folder's subfolders trigger a change notification event.
  131.   bWatchSubFolders As Long
  132. End Type
  133. Public Declare Function SHChangeNotifyRegister Lib "shell32" Alias "#2" (ByVal hwnd As Long, ByVal uFlags As SHCN_ItemFlags, ByVal dwEventID As SHCN_EventIDs, ByVal uMsg As Long, ByVal cItems As Long, lpps As PIDLSTRUCT) As Long
  134. 'If successful, SHChangeNotifyRegister returns a notification handle which must be passed to SHChangeNotifyDeregister when no longer used. Returns 0 otherwise.
  135. 'Once the specified message is registered with SHChangeNotifyRegister, the specified window's function proc will be notified by the shell of the specified event in (and under) the folder(s) specified in a pidl.
  136. 'On message receipt, wParam points to a SHNOTIFYSTRUCT and lParam contains the event's ID value.
  137. 'The values in dwItem1 and dwItem2 are event specific. See the description of the values for the wEventId parameter of the documented SHChangeNotify API function.
  138. Public Type SHNOTIFYSTRUCT
  139.   dwItem1 As Long
  140.   dwItem2 As Long
  141. End Type
  142. '...?
  143. 'Public Declare Function SHChangeNotifyUpdateEntryList Lib "shell32" Alias "#5" (ByVal hNotify As Long, ByVal Unknown As Long, ByVal cItem As Long, lpps As PIDLSTRUCT) As Boolean
  144. 'Public Declare Function SHChangeNotifyReceive Lib "shell32" Alias "#5" (ByVal hNotify As Long, ByVal uFlags As SHCN_ItemFlags, ByVal dwItem1 As Long, ByVal dwItem2 As Long) As Long
  145. 'Closes the notification handle returned from a call to SHChangeNotifyRegister. Returns True if successful,False otherwise.
  146. Public Declare Function SHChangeNotifyDeregister Lib "shell32" Alias "#4" (ByVal hNotify As Long) As Boolean
  147. '------------------------------------------------------
  148. 'This function should be called by any app that changes anything in the shell. The shell will then notify each "notification registered" window of this action.
  149. Public Declare Sub SHChangeNotify Lib "shell32" (ByVal wEventId As SHCN_EventIDs, ByVal uFlags As SHCN_ItemFlags, ByVal dwItem1 As Long, ByVal dwItem2 As Long)
  150. 'Shell notification event IDs
  151. Public Enum SHCN_EventIDs
  152.   SHCNE_RENAMEITEM = &H1          '(D) A non-folder item has been renamed.
  153.   SHCNE_CREATE = &H2              '(D) A non-folder item has been created.
  154.   SHCNE_DELETE = &H4              '(D) A non-folder item has been deleted.
  155.   SHCNE_MKDIR = &H8               '(D) A folder item has been created.
  156.   SHCNE_RMDIR = &H10              '(D) A folder item has been removed.
  157.   SHCNE_MEDIAINSERTED = &H20      '(G) Storage media has been inserted into a drive.
  158.   SHCNE_MEDIAREMOVED = &H40       '(G) Storage media has been removed from a drive.
  159.   SHCNE_DRIVEREMOVED = &H80       '(G) A drive has been removed.
  160.   SHCNE_DRIVEADD = &H100          '(G) A drive has been added.
  161.   SHCNE_NETSHARE = &H200          'A folder on the local computer is being shared via the network.
  162.   SHCNE_NETUNSHARE = &H400        'A folder on the local computer is no longer being shared via the network.
  163.   SHCNE_ATTRIBUTES = &H800        '(D) The attributes of an item or folder have changed.
  164.   SHCNE_UPDATEDIR = &H1000        '(D) The contents of an existing folder have changed, but the folder still exists and has not been renamed.
  165.   SHCNE_UPDATEITEM = &H2000       '(D) An existing non-folder item has changed, but the item still exists and has not been renamed.
  166.   SHCNE_SERVERDISCONNECT = &H4000  'The computer has disconnected from a server.
  167.   SHCNE_UPDATEIMAGE = &H8000&     '(G) An image in the system image list has changed.
  168.   SHCNE_DRIVEADDGUI = &H10000     '(G) A drive has been added and the shell should create a new window for the drive.
  169.   SHCNE_RENAMEFOLDER = &H20000    '(D) The name of a folder has changed.
  170.   SHCNE_FREESPACE = &H40000       '(G) The amount of free space on a drive has changed.
  171.   #If (WIN32_IE >= &H400) Then
  172.   SHCNE_EXTENDED_EVENT = &H4000000  '(G) Not currently used.
  173.   #End If
  174.   SHCNE_ASSOCCHANGED = &H8000000   '(G) A file type association has changed.
  175.   SHCNE_DISKEVENTS = &H2381F       '(D) Specifies a combination of all of the disk event identifiers.
  176.   SHCNE_GLOBALEVENTS = &HC0581E0   '(G) Specifies a combination of all of the global event identifiers.
  177.   SHCNE_ALLEVENTS = &H7FFFFFFF
  178.   SHCNE_INTERRUPT = &H80000000     'The specified event occurred as a result of a system
  179.   'interrupt. It is stripped out before the clients of SHCNNotify_ see it.
  180. End Enum
  181.  
  182. #If (WIN32_IE >= &H400) Then
  183.   Public Const SHCNEE_ORDERCHANGED = &H2  'dwItem2 is the pidl of the changed folder
  184. #End If
  185.  
  186. 'Notification flags uFlags & SHCNF_TYPE is an ID which indicates what dwItem1 and dwItem2 mean
  187. Public Enum SHCN_ItemFlags
  188.   SHCNF_IDLIST = &H0         'LPITEMIDLIST
  189.   SHCNF_PATHA = &H1          'path name
  190.   SHCNF_PRINTERA = &H2       'printer friendly name
  191.   SHCNF_DWORD = &H3          'DWORD
  192.   SHCNF_PATHW = &H5          'path name
  193.   SHCNF_PRINTERW = &H6       'printer friendly name
  194.   SHCNF_TYPE = &HFF
  195.   'Flushes the system event buffer. The function does not return until the system is finished processing the given event.
  196.   SHCNF_FLUSH = &H1000
  197.   'Flushes the system event buffer. The function returns immediately regardless of whether the system is finished processing the given event.
  198.   SHCNF_FLUSHNOWAIT = &H2000
  199.   #If UNICODE Then
  200.   SHCNF_PATH = SHCNF_PATHW
  201.   SHCNF_PRINTER = SHCNF_PRINTERW
  202.   #Else
  203.   SHCNF_PATH = SHCNF_PATHA
  204.   SHCNF_PRINTER = SHCNF_PRINTERA
  205.   #End If
  206. End Enum
  207.  
  208.  
  209. Public Function SHNotify_Register(hwnd As Long) As Boolean
  210.   'Registers the one and only shell change notification.
  211.   Dim ps As PIDLSTRUCT
  212.  
  213.   'If we don't already have a notification going...
  214.   If (m_hSHNotify = 0) Then
  215.     'Get the pidl for the desktop folder.
  216.     m_pidlDesktop = GetPIDLFromFolderID(0, CSIDL_DESKTOP)
  217.     If m_pidlDesktop Then
  218.       'Fill the one and only PIDLSTRUCT, we're watching desktop and all of the its subfolders, everything...
  219.       ps.pidl = m_pidlDesktop
  220.       ps.bWatchSubFolders = True
  221.       'Register the notification, specifying that we want the dwItem1 and dwItem2 members of the SHNOTIFYSTRUCT to be pidls. We're watching all events.
  222.       m_hSHNotify = SHChangeNotifyRegister(hwnd, SHCNF_TYPE Or SHCNF_IDLIST, SHCNE_ALLEVENTS Or SHCNE_INTERRUPT, WM_SHNOTIFY, 1, ps)
  223.       SHNotify_Register = CBool(m_hSHNotify)
  224.     Else
  225.       'If something went wrong...
  226.       Call CoTaskMemFree(m_pidlDesktop)
  227.     End If
  228.   End If
  229. End Function
  230.  
  231.  
  232. Public Function SHNotify_Unregister() As Boolean
  233.   'Unregisters the one and only shell change notification.
  234.   'If we have a registered notification handle.
  235.   If m_hSHNotify Then
  236.     'Unregster it. If the call is successful, zero the handle's variable, free and zero the the desktop's pidl.
  237.     If SHChangeNotifyDeregister(m_hSHNotify) Then
  238.       m_hSHNotify = 0
  239.       Call CoTaskMemFree(m_pidlDesktop)
  240.       m_pidlDesktop = 0
  241.       SHNotify_Unregister = True
  242.     End If
  243.   End If
  244. End Function
  245.  
  246.  
  247. Public Function SHNotify_GetEventStr(dwEventID As Long) As String
  248.   'Returns the event string associated with the specified event ID value.
  249.   Dim sEvent As String
  250.  
  251.   Select Case dwEventID
  252.     Case SHCNE_RENAMEITEM: sEvent = "SHCNE_RENAMEITEM"  '&H1
  253.     Case SHCNE_CREATE: sEvent = "SHCNE_CREATE"  '&H2
  254.     Case SHCNE_DELETE: sEvent = "SHCNE_DELETE"  '&H4
  255.     Case SHCNE_MKDIR: sEvent = "SHCNE_MKDIR"  '&H8
  256.     Case SHCNE_RMDIR: sEvent = "SHCNE_RMDIR"  '&H10
  257.     Case SHCNE_MEDIAINSERTED: sEvent = "SHCNE_MEDIAINSERTED"  '&H20
  258.     Case SHCNE_MEDIAREMOVED: sEvent = "SHCNE_MEDIAREMOVED"  '&H40
  259.     Case SHCNE_DRIVEREMOVED: sEvent = "SHCNE_DRIVEREMOVED"  '&H80
  260.     Case SHCNE_DRIVEADD: sEvent = "SHCNE_DRIVEADD"  '&H100
  261.     Case SHCNE_NETSHARE: sEvent = "SHCNE_NETSHARE"  '&H200
  262.     Case SHCNE_NETUNSHARE: sEvent = "SHCNE_NETUNSHARE"  '&H400
  263.     Case SHCNE_ATTRIBUTES: sEvent = "SHCNE_ATTRIBUTES"  '&H800
  264.     Case SHCNE_UPDATEDIR: sEvent = "SHCNE_UPDATEDIR"  '&H1000
  265.     Case SHCNE_UPDATEITEM: sEvent = "SHCNE_UPDATEITEM"  '&H2000
  266.     Case SHCNE_SERVERDISCONNECT: sEvent = "SHCNE_SERVERDISCONNECT"  '&H4000
  267.     Case SHCNE_UPDATEIMAGE: sEvent = "SHCNE_UPDATEIMAGE"  '&H8000&
  268.     Case SHCNE_DRIVEADDGUI: sEvent = "SHCNE_DRIVEADDGUI"  '&H10000
  269.     Case SHCNE_RENAMEFOLDER: sEvent = "SHCNE_RENAMEFOLDER"  '&H20000
  270.     Case SHCNE_FREESPACE: sEvent = "SHCNE_FREESPACE"  '&H40000
  271.       #If (WIN32_IE >= &H400) Then
  272.       Case SHCNE_EXTENDED_EVENT: sEvent = "SHCNE_EXTENDED_EVENT"  '&H4000000
  273.       #End If
  274.     Case SHCNE_ASSOCCHANGED: sEvent = "SHCNE_ASSOCCHANGED"  '&H8000000
  275.     Case SHCNE_DISKEVENTS: sEvent = "SHCNE_DISKEVENTS"  '&H2381F
  276.     Case SHCNE_GLOBALEVENTS: sEvent = "SHCNE_GLOBALEVENTS"  '&HC0581E0
  277.     Case SHCNE_ALLEVENTS: sEvent = "SHCNE_ALLEVENTS"  '&H7FFFFFFF
  278.     Case SHCNE_INTERRUPT: sEvent = "SHCNE_INTERRUPT"  '&H80000000
  279.   End Select
  280.   SHNotify_GetEventStr = sEvent
  281. End Function
  282.  
  283. Public Function SubClass(hwnd As Long) As Boolean
  284.   Dim lpfnOld As Long, fSuccess As Boolean
  285.  
  286.   If (GetProp(hwnd, OLDWNDPROC) = 0) Then
  287.     lpfnOld = SetWindowLong(hwnd, GWL_WNDPROC, AddressOf WindowProc)
  288.     If lpfnOld Then
  289.       fSuccess = SetProp(hwnd, OLDWNDPROC, lpfnOld)
  290.     End If
  291.   End If
  292.   If fSuccess Then
  293.     SubClass = True
  294.   Else
  295.     If lpfnOld Then Call UnSubClass(hwnd)
  296.     MsgBox "Unable to successfully subclass &H" & Hex(hwnd), vbCritical
  297.   End If
  298. End Function
  299.  
  300.  
  301. Public Function UnSubClass(hwnd As Long) As Boolean
  302.   Dim lpfnOld As Long
  303.  
  304.   lpfnOld = GetProp(hwnd, OLDWNDPROC)
  305.   If lpfnOld Then
  306.     If RemoveProp(hwnd, OLDWNDPROC) Then
  307.       UnSubClass = SetWindowLong(hwnd, GWL_WNDPROC, lpfnOld)
  308.     End If
  309.   End If
  310. End Function
  311.  
  312. Public Function GetPIDLFromFolderID(hOwner As Long, nFolder As SHSpecialFolderIDs) As Long
  313.   'Returns an absolute pidl (relative to the desktop) from a special folder's ID. (Calling proc is responsible for freeing the pidl)
  314.   'hOwner - handle of window that will own any displayed msg boxes
  315.   'nFolder  - special folder ID
  316.   Dim pidl As Long
  317.  
  318.   If SHGetSpecialFolderLocation(hOwner, nFolder, pidl) = ERROR_SUCCESS Then
  319.     GetPIDLFromFolderID = pidl
  320.   End If
  321. End Function
  322.  
  323.  
  324. Public Function GetDisplayNameFromPIDL(pidl As Long) As String
  325.   'If successful returns the specified absolute pidl's displayname, returns an empty string otherwise.
  326.   Dim sfib As SHFILEINFOBYTE
  327.  
  328.   If SHGetFileInfoPidl(pidl, 0, sfib, Len(sfib), SHGFI_PIDL Or SHGFI_DISPLAYNAME) Then
  329.     GetDisplayNameFromPIDL = GetStrFromBufferA(StrConv(sfib.szDisplayName, vbUnicode))
  330.   End If
  331. End Function
  332.  
  333.  
  334. Public Function GetPathFromPIDL(pidl As Long) As String
  335.   'Returns a path from only an absolute pidl (relative to the desktop).
  336.   Dim sPath As String * MAX_PATH
  337.  
  338.   'SHGetPathFromIDList rtns TRUE (1), if successful, FALSE (0) if not
  339.   If SHGetPathFromIDList(pidl, sPath) Then
  340.     GetPathFromPIDL = GetStrFromBufferA(sPath)
  341.   End If
  342. End Function
  343.  
  344.  
  345. Public Function GetStrFromBufferA(sz As String) As String
  346.   'Return the string before first null char encountered (if any) from an ANSII string. If no null, return the string passed
  347.   If InStr(sz, vbNullChar) Then
  348.     GetStrFromBufferA = Left$(sz, InStr(sz, vbNullChar) - 1)
  349.   Else
  350.     GetStrFromBufferA = sz
  351.   End If
  352. End Function
  353.  
  354.  
  355. Public Function WindowProc(ByVal hwnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
  356.   Select Case uMsg
  357.     Case WM_SHNOTIFY
  358.       Call frmMain.NotificationReceipt(wParam, lParam)
  359.     Case WM_NCDESTROY
  360.       Call UnSubClass(hwnd)
  361.       MsgBox "Unsubclassed &H" & Hex(hwnd), vbCritical, "WindowProc Error"
  362.   End Select
  363.   WindowProc = CallWindowProc(GetProp(hwnd, OLDWNDPROC), hwnd, uMsg, wParam, lParam)
  364. End Function
  365.  
  366.