To All:
Ok - hopefully this will make some sense.. I module "modToolTipsForm" from:
The load event on the main form (shown below) is where it calls the popup form "frmToolTipDataSheet".
The only functions are:
Private Sub Form_Timer()
ShowToolTips Me
End Sub
Private Sub txtToolTip_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
HideToolTips
End Sub
On the main form Load and Unload events...
the line where it states "SetToolText" is the only place it to "pre-type" the tool tip... I would to get rid of this to show a the form with the aiport info based on the caption name of the control....
Private Sub Form_Load()
' Create an instance of our Tooltip class
Set TTip = New clsToolTip
' We must SetFocus to any control that can
' accept the focus in order to force Access to
' create the inplace editing Window.
Me!ParkCsr.SetFocus
With TTip
' Creat the tooltip window
Call .Create(Me)
' Set the tooltip window to show for 5 secs
.DelayTime = 5000
.SetToolTipTitle " GTWY Profile", 0
' ToolTip text colors
.ForeColor = vbBlue
.BackColor = RGB(192, 192, 192)
' Set the text for the txtCustomerID label.
.SetToolText Me.ANC1, "I am the ANC Label." & vbCrLf & "This is the second line!"
.SetToolText Me.SDF1, "I am the SDF Label." & vbCrLf & "This is the second line!"
.SetToolText Me.ONT1, "I am the ONT Label." & vbCrLf & "This is the second line!"
.SetToolText Me.DFW1, "I am the DFW Label." & vbCrLf & "This is the second line!"
.SetToolText Me.MIA1, "I am the MIA Label." & vbCrLf & "This is the second line!"
End With
End Sub
Private Sub Form_Unload(Cancel As Integer)
' Because of reference issues you must invoke
' the Cleanup sub prior to releasing the
' reference to the TTip class.
TTip.Cleanup
' Release our reference to our class
Set TTip = Nothing
End Sub
From the Class Module "clsToolTip""
Option Compare Database
Option Explicit
Private Type POINTAPI
X As Long
y As Long
End Type
Private Type RECT
Left As Long
Top As Long
Right As Long
Bottom As Long
End Type
Private Type TOOLINFO
cbSize As Long
uFlags As Long
hWnd As Long
uId As Long
RECT As RECT
hinst As Long
lpszText As String
lParam As Long
End Type
Private Type SCROLLINFO
cbSize As Long
fMask As Long
nMin As Long
nMax As Long
nPage As Long
nPos As Long
nTrackPos As Long
End Type
Private Declare Function apiGetScrollInfo _
Lib "user32" Alias "GetScrollInfo" (ByVal hWnd As Long, _
ByVal n As Long, lpScrollInfo As SCROLLINFO) As Long
Private Declare Function GetWindowRect Lib "user32" _
(ByVal hWnd As Long, lpRect As RECT) As Long
Private Declare Function ClientToScreen Lib "user32" _
(ByVal hWnd As Long, lpPoint As POINTAPI) As Long
Private Declare Function ScreenToClient Lib "user32" _
(ByVal hWnd As Long, lpPoint As POINTAPI) As Long
Private Declare Function apiGetWindowLong Lib "user32" _
Alias "GetWindowLongA" _
(ByVal hWnd As Long, _
ByVal nIndex As Long) As Long
Private Declare Function GetDC Lib "user32" (ByVal hWnd As Long) As Long
Private Declare Function DeleteDC Lib "gdi32" (ByVal hDC As Long) As Long
Private Declare Function apiGetDeviceCaps Lib "gdi32" _
Alias "GetDeviceCaps" (ByVal hDC As Long, ByVal nIndex As Long) As Long
Private Declare Function ReleaseDC Lib "user32" _
(ByVal hWnd As Long, ByVal hDC As Long) As Long
Private Declare Sub InitCommonControls Lib "comctl32.dll" ()
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" _
(ByVal hWnd As Long, _
ByVal wMsg As Long, _
ByVal wParam As Long, _
lParam As Any) As Long ' <---
Private Declare Function CreateWindowEx Lib "user32" Alias "CreateWindowExA" _
(ByVal dwExStyle As Long, ByVal lpClassName As String, _
ByVal lpWindowName As String, ByVal dwStyle As Long, _
ByVal X As Long, ByVal y As Long, _
ByVal nWidth As Long, ByVal nHeight As Long, _
ByVal hwndParent As Long, ByVal hMenu As Long, _
ByVal hInstance As Long, lpParam As Any) As Long
Private Declare Function DestroyWindow Lib "user32" (ByVal hWnd As Long) As Long
Private Declare Function apiGetWindow Lib "user32" _
Alias "GetWindow" _
(ByVal hWnd As Long, _
ByVal wCmd As Long) _
As Long
Private Declare Function apiGetClassName Lib "user32" _
Alias "GetClassNameA" _
(ByVal hWnd As Long, _
ByVal lpClassName As String, _
ByVal nMaxCount As Long) _
As Long
Private Const TOOLTIPS_CLASS = "tooltips_class32"
'Private Enum TT_DelayTime
Private Const TTDT_AUTOMATIC = 0
Private Const TTDT_RESHOW = 1
Private Const TTDT_AUTOPOP = 2
Private Const TTDT_INITIAL = 3
'Private Enum ttDelayTimeConstants
Private Const ttDelayDefault = TTDT_AUTOMATIC '= 0
Private Const ttDelayInitial = TTDT_INITIAL '= 3
Private Const ttDelayShow = TTDT_AUTOPOP '= 2
Private Const ttDelayReshow = TTDT_RESHOW '= 1
Private Const ttDelayMask = 3
'Private Enum ttMarginConstants
Private Const ttMarginLeft = 0
Private Const ttMarginTop = 1
Private Const ttMarginRight = 2
Private Const ttMarginBottom = 3
Private Const TTS_ALWAYSTIP = &H1
Private Const TTS_NOPREFIX = &H2
Private Const TTS_BALLOON = &H40
'Private Enum TT_Flags
Private Const TTF_IDISHWND = &H1
Private Const TTF_CENTERTIP = &H2
Private Const TTF_RTLREADING = &H4
Private Const TTF_SUBCLASS = &H10
Private Const TTF_TRACK = &H20
Private Const TTF_ABSOLUTE = &H80
Private Const TTF_TRANSPARENT = &H100
Private Const TTF_DI_SETITEM = &H8000&
'* Private Window Messages Start Here:
Private Const WM_USER = &H400&
'Private Enum TT_Msgs
Private Const TTM_ACTIVATE = (WM_USER + 1)
Private Const TTM_SETDELAYTIME = (WM_USER + 3)
Private Const TTM_RELAYEVENT = (WM_USER + 7)
Private Const TTM_GETTOOLCOUNT = (WM_USER + 13)
Private Const TTM_WINDOWFROMPOINT = (WM_USER + 16)
Private Const TTM_ADDTOOL = (WM_USER + 4)
Private Const TTM_DELTOOL = (WM_USER + 5)
Private Const TTM_NEWTOOLRECT = (WM_USER + 6)
Private Const TTM_GETTOOLINFO = (WM_USER + 8)
Private Const TTM_SETTOOLINFO = (WM_USER + 9)
Private Const TTM_HITTEST = (WM_USER + 10)
Private Const TTM_GETTEXT = (WM_USER + 11)
Private Const TTM_UPDATETIPTEXT = (WM_USER + 12)
Private Const TTM_ENUMTOOLS = (WM_USER + 14)
Private Const TTM_GETCURRENTTOOL = (WM_USER + 15)
Private Const TTM_TRACKACTIVATE = (WM_USER + 17)
Private Const TTM_TRACKPOSITION = (WM_USER + 18)
Private Const TTM_SETTIPBKCOLOR = (WM_USER + 19)
Private Const TTM_SETTIPTEXTCOLOR = (WM_USER + 20)
Private Const TTM_GETDELAYTIME = (WM_USER + 21)
Private Const TTM_GETTIPBKCOLOR = (WM_USER + 22)
Private Const TTM_GETTIPTEXTCOLOR = (WM_USER + 23)
Private Const TTM_SETMAXTIPWIDTH = (WM_USER + 24)
Private Const TTM_GETMAXTIPWIDTH = (WM_USER + 25)
Private Const TTM_SETMARGIN = (WM_USER + 26)
Private Const TTM_GETMARGIN = (WM_USER + 27)
Private Const TTM_POP = (WM_USER + 28)
Private Const TTM_UPDATE = (WM_USER + 29)
Private Const TTM_SETTITLE = (WM_USER + 32) '// wParam = TTI_*, lParam = char* szTitle
'Private Enum TT_Notifications
Private Const TTN_FIRST = -520& ' (0U-520U)
Private Const TTN_LAST = -549& ' (0U-549U)
Private Const TTN_NEEDTEXT = (TTN_FIRST - 0)
Private Const TTN_SHOW = (TTN_FIRST - 1)
Private Const TTN_POP = (TTN_FIRST - 2)
'// ToolTip Icons (Set with TTM_SETTITLE)
Private Const TTI_NONE = 0
Private Const TTI_INFO = 1
Private Const TTI_WARNING = 2
Private Const TTI_ERROR = 3
' GetWindow() Constants
Private Const GW_HWNDFIRST = 0
Private Const GW_HWNDLAST = 1
Private Const GW_HWNDNEXT = 2
Private Const GW_HWNDPREV = 3
Private Const GW_OWNER = 4
Private Const GW_CHILD = 5
Private Const GW_MAX = 5
' ScrollInfo fMask's
Private Const SIF_RANGE = &H1
Private Const SIF_PAGE = &H2
Private Const SIF_POS = &H4
Private Const SIF_DISABLENOSCROLL = &H8
Private Const SIF_TRACKPOS = &H10
Private Const SIF_ALL = (SIF_RANGE Or SIF_PAGE Or SIF_POS Or SIF_TRACKPOS)
' Scroll Bar Constants
Private Const SB_HORZ = 0
Private Const SB_CTL = 2
Private Const SB_VERT = 1
' App instance
Private Const GWL_HINSTANCE = (-6)
' Twips per inch
Private Const TWIPSPERINCH = 1440&
' Device Parameters for GetDeviceCaps()
Private Const LOGPIXELSX = 88 ' Logical pixels/inch in X
Private Const LOGPIXELSY = 90 ' Logical pixels/inch in Y
Private Const BITSPIXEL = 12 ' Number of bits per pixel
' WIndow handle to our Tooltip control
Private m_hwndTT As Long
' Window handle to our Form's Detail Section
Private m_hWndDetail As Long
' Window handle to our Detail Section's
' in place editing control. Access activates and
' resizes this window whenever an editing
' control receives the focus.
Private m_hWndOKttbx As Long
' The Form containing the controls
Private m_Form As Form
' Max length of Tooltip
Private m_cMaxTip As Long
' Instance of our App
Private hInstance As Long
' Horizontal and Vertical Screen resolution
Private m_ScreenXdpi As Long
Private m_ScreenYdpi As Long
' Collection for our control classes
Private colControls As New Collection
' Our TextBox class
Private cTBox As clsTextBox
' Our Combo class
Private cCBO As clsCombo
' Our ListBox class
Private cLB As clsListBox
' Junk return vars
Private lngRet As Long
Private blRet As Boolean
Public Function Create(frm As Form) As Boolean
' Grab a reference to the Form
Set m_Form = frm
If (m_hwndTT = 0) Then
Call InitCommonControls
' Get instance of this App
hInstance = apiGetWindowLong(Application.hWndAccessApp, GWL_HINSTANCE)
' Filling the hwndParent param below allows the tooltip window to
' be owned by the specified form and be destroyed along with it,
' but we'll cleanup in Class_Terminate anyway.
' Turn off Balloon if prior to Explorer 5.0
m_hwndTT = CreateWindowEx(0, TOOLTIPS_CLASS, _
vbNullString, TTS_ALWAYSTIP Or TTS_BALLOON, _
0, 0, _
0, 0, _
m_Form.hWnd, 0, _
hInstance, ByVal 0)
End If
' Grab our Detail Section Window handle
m_hWndDetail = FindDetailWindow(m_Form.hWnd)
' Grab our Detail Section's inplace editing window
m_hWndOKttbx = FindOKttbxWindow(m_hWndDetail)
' Set the tooltip's width so that it displays multiline text,
' and that no tool's line length exceeds roughly 240 pixels.
MaxTipWidth = 240
' Now setup a ToolTip entry for every control in the Form.
Dim ctrl As Control
For Each ctrl In m_Form.Controls
Select Case ctrl.ControlType
Case acTextBox
Set cTBox = New clsTextBox
Set cTBox.FormControl = ctrl
Set cTBox.ToolTip = Me
colControls.Add cTBox, ctrl.Name
Set cTBox = Nothing
Case acComboBox
Set cCBO = New clsCombo
Set cCBO.FormControl = ctrl
Set cCBO.ToolTip = Me
colControls.Add cCBO, ctrl.Name
Set cCBO = Nothing
Case acListBox
Set cLB = New clsListBox
Set cLB.FormControl = ctrl
Set cLB.ToolTip = Me
Let cLB.hWndLB = fFindListBoxhWnd(ctrl)
colControls.Add cLB, ctrl.Name
Set cLB = Nothing
Case Else
End Select
Next ctrl
' Now add a ToolTip for every control on the Form
For Each ctrl In m_Form.Controls
Select Case ctrl.ControlType
Case acListBox
AddToolLightWeight colControls(ctrl.Name).hWndLB
Case Else
AddTool ctrl
End Select
Next
' Add a ToolTip for the Detail Section's inplace Editing window
AddToolLightWeight m_hWndOKttbx
' Return
Create = CBool(m_hwndTT)
End Function
Public Function AddTool(ctrl As Control, Optional sText As String) As Boolean
Dim ti As TOOLINFO
Dim lHeight As Long
' Allow for Form Header if visible
' and this control does not reside in the Header!
' Remember if the Form Header section does not exist
' then we will generate a runtime error therefore me MUST:
On Error Resume Next
' Reset temp var
lHeight = 0
' Do we have a valid handle to the ToolTip window
If (m_hwndTT = 0) Then Exit Function
If (GetToolInfo(ctrl, ti) = False) Then
With ti
.cbSize = Len(ti)
' We do not use the TTF_IDISHWND Flag because we are specifying
' rectangular areas of the Window. We have to do this because
' on an Access Form, the TextBox and Label controls are
' "lightweight". They do not exist as seperate Windows. Access uses
' one common shared editing window that it activates as you set the focus to
' each control.
.uFlags = TTF_SUBCLASS
.hWnd = m_Form.hWnd
' On failure use Form's WIndow
'If .hWnd = 0 Then .hWnd = frm.hWnd
' We need a method of identifying each control's rectangular area.
' Normally you could simply fill in the hWnd for the control
' but since we are working with lightweight, non window'd controls
' we require another method. We will assume that no two controls
' will have the exact same Left and Top properties. I realize that this will
' fail for identical controls stacked on top of each other
' but you have been warned!!!
' So we create a unique uId member by putting the control's Left prop
' in the High word and the Top prop in the Lo word.
.uId = MakeDWord(CInt(ctrl.Top), CInt(ctrl.Left))
If Len(sText) Then
.lpszText = sText
Else
.lpszText = ""
End If
' Maintain the maximun tip text length for GetToolInfo
m_cMaxTip = Max(m_cMaxTip, Len(.lpszText) + 1)
' Fill in our bounding rectangle for this control.
' Does not matter which section the control is in as
' we have to add the offsets of the control in this particular section
.RECT.Left = (ctrl.Left / TWIPSPERINCH) * m_ScreenXdpi
.RECT.Right = ((ctrl.Left + ctrl.Width) / TWIPSPERINCH) * m_ScreenXdpi
.RECT.Top = (ctrl.Top / TWIPSPERINCH) * m_ScreenYdpi
.RECT.Bottom = ((ctrl.Top + ctrl.Height) / TWIPSPERINCH) * m_ScreenYdpi
' Allow for Form Header if visible
' and this control does not reside in the Header!
' Remember if the Form Header section does not exist
' then we will generate a runtime error
If m_Form.Section(acHeader).Visible = True Then
If ctrl.Section <> acHeader Then
.RECT.Top = .RECT.Top + (m_Form.Section(acHeader).Height / TWIPSPERINCH) * m_ScreenYdpi
.RECT.Bottom = .RECT.Bottom + ((m_Form.Section(acHeader).Height) / TWIPSPERINCH) * m_ScreenYdpi
End If
End If
' Are we in Form Footer?
If ctrl.Section = acFooter Then
' Add Detail Section Height
If m_Form.Section(acDetail).Visible = True Then
' We have to add the Height of not just the Detail Section
' But the InsideHeight - (acHeader + acFooter) the Form
' This method allows for when the Form is taller than the
' combined Section Heights.
' Grab Header Height
If m_Form.Section(acHeader).Visible = True Then
lHeight = m_Form.Section(acHeader).Height
End If
' Add Footer height
If m_Form.Section(acFooter).Visible = True Then
lHeight = lHeight + m_Form.Section(acFooter).Height
End If
' Calculate true Detail section height
lHeight = m_Form.InsideHeight - lHeight
.RECT.Top = .RECT.Top + (lHeight / TWIPSPERINCH) * m_ScreenYdpi
.RECT.Bottom = .RECT.Bottom + (lHeight / TWIPSPERINCH) * m_ScreenYdpi
End If
End If
End With
' Returns 1 on success, 0 on failure
AddTool = SendMessage(m_hwndTT, TTM_ADDTOOL, 0, ti)
End If
End Function
Public Function AddToolLightWeight(hWnd As Long, Optional sText As String = "") As Boolean
Dim ti As TOOLINFO
Dim ctrl As Control
' Do we have a valid handle to the ToolTip window
If (m_hwndTT = 0) Then Exit Function
If (GetToolInfo(ctrl, ti, hWnd) = False) Then
With ti
.cbSize = Len(ti)
' This is the shared TextBox window Access activates for in place editing
' as we activate each lightweight editing control
.uFlags = TTF_SUBCLASS Or TTF_IDISHWND
.hWnd = hWnd
' On failure use Form's WIndow
'If .hWnd = 0 Then .hWnd = frm.hWnd
' We use the Window Handle to identify this ToolTip.
.uId = .hWnd
If Len(sText) Then
.lpszText = sText
Else
.lpszText = ""
End If
' Maintain the maximun tip text length for GetToolInfo
m_cMaxTip = Max(m_cMaxTip, Len(.lpszText) + 1)
End With
' Returns 1 on success, 0 on failure
AddToolLightWeight = SendMessage(m_hwndTT, TTM_ADDTOOL, 0, ti)
End If
End Function
Public Function RemoveTool(ctrl As Control, Optional hWnd As Long = 0) As Boolean
Dim ti As TOOLINFO
' Do we have a valid handle to the ToolTip window
If (m_hwndTT = 0) Then Exit Function
If GetToolInfo(ctrl, ti, hWnd) Then
Call SendMessage(m_hwndTT, TTM_DELTOOL, 0, ti) ' no rtn val
RemoveTool = True
End If
End Function
' public properties
Public Property Get BackColor() As Long
If (m_hwndTT = 0) Then Exit Property
BackColor = SendMessage(m_hwndTT, TTM_GETTIPBKCOLOR, 0, 0)
End Property
Public Property Let BackColor(clr As Long)
If (m_hwndTT = 0) Then Exit Property
Call SendMessage(m_hwndTT, TTM_SETTIPBKCOLOR, clr, 0) ' no rtn val
End Property
Public Property Get DelayTime() As Long
If (m_hwndTT = 0) Then Exit Property
DelayTime = SendMessage(m_hwndTT, TTM_GETDELAYTIME, (ttDelayShow And ttDelayMask), 0&)
End Property
Public Property Let DelayTime(dwMilliSecs As Long)
If (m_hwndTT = 0) Then Exit Property
Call SendMessage(m_hwndTT, TTM_SETDELAYTIME, (ttDelayShow And ttDelayMask), ByVal dwMilliSecs)
End Property
Public Property Get ForeColor() As Long
If (m_hwndTT = 0) Then Exit Property
ForeColor = SendMessage(m_hwndTT, TTM_SETTIPTEXTCOLOR, 0, 0)
End Property
Public Property Let ForeColor(clr As Long)
If (m_hwndTT = 0) Then Exit Property
Call SendMessage(m_hwndTT, TTM_SETTIPTEXTCOLOR, clr, 0) ' no rtn val
End Property
Public Property Get ScreenXdpi() As Long
ScreenXdpi = m_ScreenXdpi
End Property
Public Property Get ScreenYdpi() As Long
ScreenYdpi = m_ScreenYdpi
End Property
Public Property Get hWnd() As Long ' read-only
hWnd = m_hwndTT
End Property
Public Property Get hWndOKttbx() As Long ' read-only
hWndOKttbx = m_hWndOKttbx
End Property
Public Property Get Margin(dwType As Long) As Long
Dim rc As RECT
' Do we have a valid handle to the ToolTip window
If (m_hwndTT = 0) Then Exit Property
Call SendMessage(m_hwndTT, TTM_GETMARGIN, 0, rc) ' no rtn val
Select Case dwType
Case ttMarginLeft: Margin = rc.Left
Case ttMarginTop: Margin = rc.Top
Case ttMarginRight: Margin = rc.Right
Case ttMarginBottom: Margin = rc.Bottom
End Select
End Property
Public Property Let Margin(dwType As Long, cPixels As Long)
Dim rc As RECT
' Do we have a valid handle to the ToolTip window
If (m_hwndTT = 0) Then Exit Property
Call SendMessage(m_hwndTT, TTM_GETMARGIN, 0, rc) ' no rtn val
Select Case dwType
Case ttMarginLeft: rc.Left = cPixels
Case ttMarginTop: rc.Top = cPixels
Case ttMarginRight: rc.Right = cPixels
Case ttMarginBottom: rc.Bottom = cPixels
End Select
Call SendMessage(m_hwndTT, TTM_SETMARGIN, 0, rc) ' no rtn val
End Property
' If MaxTipWidth is -1, there's no word wrapping and text controls chars
' in lpszText are printed and not evaluated (i.e. a vbCrLf shows up as "||")
Public Property Get MaxTipWidth() As Integer
If (m_hwndTT = 0) Then Exit Property
MaxTipWidth = LoWord(SendMessage(m_hwndTT, TTM_GETMAXTIPWIDTH, 0, 0))
End Property
Public Property Let MaxTipWidth(ByVal cx As Integer)
If (m_hwndTT = 0) Then Exit Property
If (cx < 1) Then cx = -1
Call SendMessage(m_hwndTT, TTM_SETMAXTIPWIDTH, 0, ByVal CLng(cx))
End Property
Public Property Get ToolCount() As Integer ' read-only
If (m_hwndTT = 0) Then Exit Property
ToolCount = SendMessage(m_hwndTT, TTM_GETTOOLCOUNT, 0, 0)
End Property
' For the life of me I couldn't get TTM_GETTEXT to work. So
' we'll use the TTM_ENUMTOOLS message in GetToolInfo
' instead, which does retrieve the specifed tool's text... (?)
Public Property Get ToolText(ctrl As Control, Optional hWnd As Long = 0) As String
Dim ti As TOOLINFO
' Do we have a valid handle to the ToolTip window
If (m_hwndTT = 0) Then Exit Property
If GetToolInfo(ctrl, ti, hWnd, True) Then
ToolText = GetStrFromBufferA(ti.lpszText)
End If
End Property
Public Sub SetToolText(ctrl As Control, sText As String, Optional ByVal hWnd As Long = 0)
Dim ti As TOOLINFO
' Do we have a valid handle to the ToolTip window
If (m_hwndTT = 0) Then Exit Sub
' Is control a ListBox?
If ctrl.ControlType = acListBox Then
hWnd = colControls(ctrl.Name).hWndLB
End If
If GetToolInfo(ctrl, ti, hWnd) Then
ti.lpszText = sText
m_cMaxTip = Max(m_cMaxTip, Len(sText) + 1)
' The tooltip won't appear for the control if lpszText is an empty string
Call SendMessage(m_hwndTT, TTM_UPDATETIPTEXT, 0, ti) ' no rtn val
End If
' Update our private control collection
' We need to extend this to handle List, Combo, OLE Frame controls etc.
' Any other controls that can have the focus.
Select Case ctrl.ControlType
Case acTextBox, acComboBox, acListBox
colControls(ctrl.Name).ToolTipText = sText
'Case ????
' Will add support for the rest of the
' window'd controls in the next release
Case Else
End Select
End Sub
Public Sub SetToolTipTitle(ByVal sText As String, ByVal IcType As Long)
If Len(sText & vbNullString) = 0 Then Exit Sub
lngRet = SendMessage(m_hwndTT, TTM_SETTITLE, IcType, ByVal sText)
End Sub
Private Function GetToolInfo(ctrl As Control, _
ti As TOOLINFO, _
Optional ByVal hWnd As Long = 0, _
Optional fGetText As Boolean = False) As Boolean
Dim nItems As Integer
Dim i As Integer
Dim intLeft As Integer
Dim intTop As Integer
ti.cbSize = Len(ti)
If fGetText Then ti.lpszText = String$(m_cMaxTip, 0)
nItems = ToolCount
For i = 0 To nItems - 1
' call returns 1 on success, 0 on failure...
If SendMessage(m_hwndTT, TTM_ENUMTOOLS, (i), ti) Then
' Check and see if we are requesting our only
' Tooltip that is an actual hWnd not a lighweight control.
If hWnd <> 0 Then
If hWnd = ti.uId Then
GetToolInfo = True
Exit Function
End If
End If
If hWnd = 0 Then
' All other Tooltips are lightweight controls with no hWnd.
' break out uId into its 2 composite values
' that are the control's Left and Top properties.
' We created the value in this uId member by putting the Left prop in
' the High word and the Top prop in the Lo word.
intTop = LoWord(ti.uId)
intLeft = HiWord(ti.uId)
If ctrl.Left = intLeft Then
If ctrl.Top = intTop Then
GetToolInfo = True
Exit Function
End If
End If
End If
End If
Next
End Function
Private Sub GetScreenDPI()
Dim lngDC As Long
Dim lngPixelsPerInch As Long
Const nTwipsPerInch = 1440
lngDC = GetDC(0)
'Horizontal
m_ScreenXdpi = apiGetDeviceCaps(lngDC, LOGPIXELSX)
'Vertical
m_ScreenYdpi = apiGetDeviceCaps(lngDC, LOGPIXELSY)
lngDC = ReleaseDC(0, lngDC)
End Sub
Private Function LoWord(ByVal DWord As Long) As Integer
If DWord And &H8000& Then ' &H8000& = &H00008000
LoWord = DWord Or &HFFFF0000
Else
LoWord = DWord And &HFFFF&
End If
End Function
Private Function HiWord(ByVal DWord As Long) As Integer
HiWord = (DWord And &HFFFF0000) \ &H10000
End Function
Private Function MakeDWord(LoWord As Integer, HiWord As Integer) As Long
MakeDWord = (HiWord * &H10000) Or (LoWord And &HFFFF&)
End Function
Public Function Max(param1 As Long, param2 As Long) As Long
If param1 > param2 Then Max = param1 Else Max = param2
End Function
Public Function GetStrFromBufferA(szA As String) As String
If InStr(szA, vbNullChar) Then
GetStrFromBufferA = Left$(szA, InStr(szA, vbNullChar) - 1)
Else
' If sz had no null char, the Left$ function
' above would rtn a zero length string ("").
GetStrFromBufferA = szA
End If
End Function
Private Function FindDetailWindow(ByVal frmhWnd As Long) As Long
' The Detail Window is always the second of three
' windows of class OFormSub.
' 1) Form Header
' 2) Detail
' 3) Footer
Dim hWnd_VSB As Long
Dim hWnd As Long
Dim ctr As Long
ctr = 0
hWnd = frmhWnd
' Let's get first Child Window of the FORM
hWnd_VSB = apiGetWindow(hWnd, GW_CHILD)
' Let's walk through every sibling window of the Form
Do
' Thanks to Terry Kreft for explaining
' why the apiGetParent acll is not required.
' Terry is in a Class by himself!

'If apiGetParent(hWnd_VSB) <> hWnd Then Exit Do
If fGetClassName(hWnd_VSB) = "OFormSub" Then
ctr = ctr + 1
If ctr = 2 Then
FindDetailWindow = hWnd_VSB
Exit Function
End If
End If
' Let's get the NEXT SIBLING Window
hWnd_VSB = apiGetWindow(hWnd_VSB, GW_HWNDNEXT)
' Let's Start the process from the Top again
' Really just an error check
Loop While hWnd_VSB <> 0
' SORRY - This is impossible but there is no Detail Window!
FindDetailWindow = 0
End Function
Private Function FindOKttbxWindow(ByVal frmhWnd As Long) As Long
' The Detail Window always contains
' one window of class OKttbx.
Dim hWnd_VSB As Long
Dim hWnd As Long
Dim ctr As Long
ctr = 0
hWnd = frmhWnd
' Let's get first Child Window of the FORM
hWnd_VSB = apiGetWindow(hWnd, GW_CHILD)
' Let's walk through every sibling window of the Form
Do
If fGetClassName(hWnd_VSB) = "OKttbx" Then
FindOKttbxWindow = hWnd_VSB
Exit Function
End If
' Let's get the NEXT SIBLING Window
hWnd_VSB = apiGetWindow(hWnd_VSB, GW_HWNDNEXT)
' Let's Start the process from the Top again
' Really just an error check
Loop While hWnd_VSB <> 0
' SORRY - This is impossible but there is no TextBox Window!
FindOKttbxWindow = 0
End Function
Private Function fFindListBoxhWnd(ctl As Access.ListBox) As Long
' Get ListBox's hWnd
Dim hWnd_LSB As Long
Dim hWnd_Temp As Long
' Window RECT
Dim rc As RECT
Dim pt As POINTAPI
'Dim lngIC As Long
'Dim lngYdpi As Long
' Temp vars to calculate Window/Control positions
Dim lngCtlWidth As Long
Dim lngCtlHeight As Long
' Loop Counters
Dim SectionCounter As Long
Dim ctr As Long
' Which Section contains the Control?
Select Case ctl.Section
Case acDetail
'0
SectionCounter = 2
Case acHeader
'1
SectionCounter = 1
Case acFooter
'2
SectionCounter = 3
Case Else
' **** NEED ERROR HANDLING! ****
End Select
' Setup SectionCounter
' Form Header, Detail and then Footer
ctr = 1
' Let's get first Child Window of the FORM
hWnd_LSB = apiGetWindow(m_Form.hWnd, GW_CHILD)
' Let's walk through every sibling window of the Form
Do
If fGetClassName(hWnd_LSB) = "OFormSub" Then
' First OFormSub is the Form's Header. We want the next next one
' which is the detail section
If ctr = SectionCounter Then
' Search for Child Windows of Class "OGrid"
' Let's get first Child Window of the FORM
hWnd_Temp = apiGetWindow(hWnd_LSB, GW_CHILD)
Do
If fGetClassName(hWnd_Temp) = "OGrid" Then '
lngCtlWidth = (ctl.Width / TWIPSPERINCH) * m_ScreenXdpi
lngCtlHeight = (ctl.Height / TWIPSPERINCH) * m_ScreenYdpi
lngRet = GetWindowRect(hWnd_Temp, rc)
' Let's match our X and Y coordinates to make sure we
' have the correct ListBox
pt.X = (ctl.Left / TWIPSPERINCH) * m_ScreenXdpi
pt.y = (ctl.Top / TWIPSPERINCH) * m_ScreenXdpi
' Convert to Screen Coords
lngRet = ClientToScreen(hWnd_LSB, pt)
If Abs(pt.X - rc.Left) <= 2 Then
If Abs(pt.y - rc.Top) <= 2 Then
If Abs(lngCtlWidth - (rc.Right - rc.Left)) <= 3 Then
fFindListBoxhWnd = hWnd_Temp
Exit Function
End If
End If
End If
End If
' Let's get the NEXT SIBLING Window
hWnd_Temp = apiGetWindow(hWnd_Temp, GW_HWNDNEXT)
' Let's Start the process from the Top again
' Really just an error check
Loop While hWnd_Temp <> 0
End If
' Increment our Section Counter
ctr = ctr + 1
End If
' Let's get the NEXT SIBLING Window
hWnd_LSB = apiGetWindow(hWnd_LSB, GW_HWNDNEXT)
' Let's Start the process from the Top again
' Really just an error check
Loop While hWnd_LSB <> 0
' SORRY - NO ListBox hWnd is available
fFindListBoxhWnd = 0
End Function
Public Function fGetScrollBarPos(hWnd) As Long
' Return ScrollBar Thumb position
' for the Vertical Scrollbar attached to the
' Window passed to this Function.
Dim lngRet As Long
Dim sInfo As SCROLLINFO
' Init SCROLLINFO structure
sInfo.fMask = SIF_ALL
sInfo.cbSize = Len(sInfo)
sInfo.nPos = 0
sInfo.nTrackPos = 0
' Get the window's ScrollBar position
lngRet = apiGetScrollInfo(hWnd, SB_VERT, sInfo)
'Debug.Print "nPos:" & sInfo.nPos & " nPage:" & sInfo.nPage & " nMax:" & sInfo.nMax
fGetScrollBarPos = sInfo.nPos ' + 1
End Function
'******* Code Start *********
Private Function fGetClassName(hWnd As Long)
Dim strBuffer As String
Dim lngLen As Long
Const MAX_LEN = 255
strBuffer = Space$(MAX_LEN)
lngLen = apiGetClassName(hWnd, strBuffer, MAX_LEN)
If lngLen > 0 Then fGetClassName = Left$(strBuffer, lngLen)
End Function
'******* Code End *********
Private Sub Class_Initialize()
' Get the current screen resolution
GetScreenDPI
' Defaults:
' DelayInitial = 500 (1/2 sec)
' DelayAutoPopup = 5000 (5 secs)
' DelayReshow = 100 (1/10 sec)
' MaxTipWidth = 0
' all Margins = 0
End Sub
Public Sub Cleanup()
' I obviously have a reference problem. When I release the reference to
' this class from the calling Form the Class_Terminate event
' is not called.
' I have checked for memory/resource leaks and have found none
' by calling this cleanup sub prior to releasing the
' reference to this class.
Dim ctrl As Control
' Remove each tooltip tool we previously added to our Tooltip control
For Each ctrl In m_Form.Controls
Select Case ctrl.ControlType
Case acListBox
blRet = RemoveTool(ctrl, colControls(ctrl.Name).hWndLB)
Case Else
RemoveTool ctrl
End Select
Next
' Now release our ToolTip for the Access in place editing
' window - OKttbx window
blRet = RemoveTool(ctrl, m_hWndOKttbx)
' Free up our collection
Set colControls = Nothing
' Release our private control classes
Set cTBox = Nothing
Set cCBO = Nothing
Set cLB = Nothing
End Sub
Private Sub Class_Terminate()
If m_hwndTT <> 0 Then
lngRet = DestroyWindow(m_hwndTT)
End If
Set m_Form = Nothing
End Sub
I'm pretty certain this will work, just don't know where to put the code to show the "tool-tip form" with the airport info...
Thanks for all the help!!!
jw5107