ToolTips Usando un Form en Access
Para hacerlo he usado varias APIs
Me comenta un amigo.... Es posible crear tooltips usando un Form en Access...?
Si, la respuesta es que si... Un poco laborioso pero posible.
Ya sabemos (y para los que no sabian) que para crear tooltips, tendriamos que recurrir a la Api
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
Pero para hacerlo usando un form, que nos sirva como ToolTips y que Ademas no sea como el predeterminado de Access (que solo acepta hasta 255 caracteres y ademas que solo nos presenta el Tips de forma lineal) Ojo el del "API CreateWindowEx" tambien hace lo mismo
** EL CODIGO **
Option Compare Database
Option Explicit
'***************************************************************
'& &*
'& &*
'& &*
'& &*
'& Jefferson Jimenez (JJJT) &*
'& Cabimas - Venezuela &*
'& Junio - 2010 &*
'& &*
'& &*
'& &*
'& &*
'& &*
'***************************************************************
Private Type RECT
Left As Long
Top As Long
Right As Long
Bottom As Long
End Type
Private Type LOGFONT
lfHeight As Long
lfWidth As Long
lfEscapement As Long
lfOrientation As Long
lfWeight As Long
lfItalic As Byte
lfUnderline As Byte
lfStrikeOut As Byte
lfCharSet As Byte
lfOutPrecision As Byte
lfClipPrecision As Byte
lfQuality As Byte
lfPitchAndFamily As Byte
lfFaceName As String * 32
End Type
Private Type TEXTMETRIC
tmHeight As Long
tmAscent As Long
tmDescent As Long
tmInternalLeading As Long
tmExternalLeading As Long
tmAveCharWidth As Long
tmMaxCharWidth As Long
tmWeight As Long
tmOverhang As Long
tmDigitizedAspectX As Long
tmDigitizedAspectY As Long
tmFirstChar As Byte
tmLastChar As Byte
tmDefaultChar As Byte
tmBreakChar As Byte
tmItalic As Byte
tmUnderlined As Byte
tmStruckOut As Byte
tmPitchAndFamily As Byte
tmCharSet As Byte
End Type
Private Type POINTAPI
X_Pos As Long
Y_Pos As Long
End Type
'Declaramos las APIs necesarias para crear estos tooltips con Form
Private Declare Function GetTextMetrics Lib "gdi32" Alias "GetTextMetricsA" _
(ByVal hDC As Long, _
lpMetrics As TEXTMETRIC) As Long
Private Declare Function apiCreateFontIndirect Lib "gdi32" Alias "CreateFontIndirectA" _
(lpLogFont As LOGFONT) As Long
Private Declare Function apiSelectObject Lib "gdi32" Alias "SelectObject" _
(ByVal hDC As Long, _
ByVal hObject As Long) As Long
Private Declare Function apiDeleteObject Lib "gdi32" Alias "DeleteObject" _
(ByVal hObject 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 apiGetDC Lib "user32" Alias "GetDC" _
(ByVal hwnd As Long) As Long
Private Declare Function apiReleaseDC Lib "user32" Alias "ReleaseDC" _
(ByVal hwnd As Long, _
ByVal hDC As Long) As Long
Private Declare Function apiDrawText Lib "user32" Alias "DrawTextA" _
(ByVal hDC As Long, _
ByVal lpStr As String, _
ByVal nCount As Long, _
lpRect As RECT, _
ByVal wFormat As Long) As Long
Private Declare Function GetCursorPos Lib "user32" _
(lpPoint As POINTAPI) As Long
Private Declare Function AbreFrmTool Lib "user32" Alias "MoveWindow" _
(ByVal hwnd As Long, _
ByVal X As Long, _
ByVal Y As Long, _
ByVal nWidth As Long, _
ByVal nHeight As Long, _
ByVal bRepaint As Long) As Long
Private Declare Function SetTimer Lib "user32" (ByVal hwnd As Long, _
ByVal nIDEvent As Long, _
ByVal uElapse As Long, _
ByVal lpTimerFunc As Long) As Long
Private Declare Function KillTimer Lib "user32" (ByVal hwnd As Long, _
ByVal nIDEvent As Long) As Long
'Declaramos las variables
Dim VarTools As String
Dim CtlHeight As Long
Dim CtlWidth As Long
Dim frmHwnD1 As Long
Dim ImgTool As String
Dim Color As Long
Dim CtLSet As Control
Dim frmX As Long
Dim frmY As Long
Dim FrmTools As Form
Const Ico As String = "C:\WINDOWS\Web\*.gif"
Function AbreTool(frm As Form, _
ctl As Control, _
StrTool As String, _
Optional Duracion As Long = 3, _
Optional FTools As String = "ToolTips", _
Optional ImgIcono As String = Ico _
)
'Asigno valor a ciertas variables
VarTools = StrTool: Color = frm.Detalle.BackColor: ImgTool = ImgIcono
'Busco las coordenadas del mouse
Dim mouse As POINTAPI
GetCursorPos mouse
frmX = mouse.X_Pos + 1
frmY = mouse.Y_Pos + 1
On Error Resume Next
'Cargo el coontrol del MouseMove
Set CtLSet = ctl
'Al hacer click sobre el campo llamo la funcion que cierra el form ToolTips
DestroyedFocus
'Creo la variable estatica del control sobre el que pasa el mouse
Static CtlViejo As String
'Si vuelvo a pasar el mouse sobre el mismo campo detengo la funcion
If CtlViejo = CtLSet.Name Then Exit Function
'Si todo esta bien abro el form
DoCmd.OpenForm FTools
'Establezco el activo del ToolTips
Set FrmTools = Forms.Item(FTools)
'Cargo al campo TxtTools segun la cantidad del texto que le agregemos el ancho y alto del mismo
CargaTextHeightFrm
'Usando la API MoveWindow abro el form ToolTips situandolo segun las coordenadas del Mouse
Call AbreFrmTool(frmHwnD1, frmX, frmY, CtlWidth, CtlHeight, 1)
'Activo el Timer segun la duracion que le coloquemos, para cerrar el form ToolTips
SetTimer frmHwnD1, 0, Duracion * 1000, AddressOf TimerProc
'Le cargo a la variable el control activo
CtlViejo = CtLSet.Name
'Asesino la Altura del control
CtlHeight = 0
'Asesino el Ancho del control
CtlWidth = 0
'Desactivo el control
ctl = Nothing
End Function
Function DestroyedFocus()
Dim CtlFocus As Control
Set CtlFocus = Screen.ActiveControl 'Al activar (Click) el control del form hijo
'detengo la funcion al comparar que se trate del mismo del CtlSet del form ToolTips
If CtlFocus.Name = CtLSet.Name Then DoCmd.Close acForm, FrmTools.Name: Exit Function
CtlFocus = Nothing 'Lo desactivo
End Function
Sub TimerProc(ByVal hwnd As Long, ByVal nIDEvent As Long, _
ByVal uElapse As Long, ByVal lpTimerFunc As Long)
KillTimer frmHwnD1, 0 'Al cumplir el tiempo asesino el timer
DoCmd.Close acForm, FrmTools.Name 'Y de paso cierro el form ToolTips
End Sub
'Esta es una funcion de Stephen Lebans
'Donde nos devuelve la Altura y Ahcho de un Control TextBox, segun los caracteres
'incluidos en él
'Claro la funcion original no es esta, pues la he depurado y ajustado a mis nececidades
'si deseas ver la funcion original en la pagina de Lebans puedes descargartela
'http://www.lebans.com/textwidth-height.htm
Public Function fTextHeight(ctl As Control, _
Optional ByVal sText As String = "", _
Optional HeightTwips As Long = 0, _
Optional WidthTwips As Long = 0, _
Optional TotalLines As Long = 0, _
Optional TwipsPerPixel As Long = 0 _
) As Long
Dim hDC, lngDPI, newfont, oldfont, lngRet, lngLineSpacing, numLines, sngTemp1, sngTemp2 As Long
Dim sRect As RECT: Dim myfont As LOGFONT: Dim tm As TEXTMETRIC: Dim strName As String
hDC = apiGetDC(0&)
If TypeOf ctl Is TextBox Then
sText = Nz(ctl.Value, vbNullString)
End If
lngDPI = apiGetDeviceCaps(hDC, 90)
TwipsPerPixel = 1440 / lngDPI
myfont.lfClipPrecision = 16
myfont.lfOutPrecision = 7
myfont.lfEscapement = 0
myfont.lfFaceName = ctl.FontName & Chr$(0)
myfont.lfWeight = ctl.FontWeight
myfont.lfItalic = ctl.FontItalic
myfont.lfUnderline = ctl.FontUnderline
myfont.lfHeight = (ctl.FontSize / 72) * -lngDPI
newfont = apiCreateFontIndirect(myfont)
oldfont = apiSelectObject(hDC, newfont)
sRect.Left = 0
sRect.Top = 0
sRect.Bottom = 0
sRect.Right = (ctl.Width / (1440 / lngDPI)) - 10
lngRet = apiDrawText(hDC, sText, -1, sRect, &H400 Or &H0 Or &H0 Or &H10 Or &H200 Or &H2000& Or &H100)
lngRet = GetTextMetrics(hDC, tm)
lngRet = apiSelectObject(hDC, oldfont)
apiDeleteObject (newfont)
lngRet = apiReleaseDC(0&, hDC)
TotalLines = sRect.Bottom / (tm.tmHeight + tm.tmExternalLeading)
numLines = TotalLines
sRect.Bottom = (sRect.Bottom) * (1440 / lngDPI)
HeightTwips = sRect.Bottom
WidthTwips = sRect.Right * (1440 / lngDPI)
fTextHeight = HeightTwips
End Function
'Ya esta es Vieja (verifico que algun archivo nombrado exista)
Function JJJT_ExisteDir(ByVal Ruta As String) As Boolean
On Error Resume Next
JJJT_ExisteDir = (GetAttr(Ruta) And vbNormal) = vbNormal
Err.Clear
End Function
'Con esta funcion lo que hice fue asignarle la altura y ancho del textbox al form ToolTips
Sub CargaTextHeightFrm()
'Cargo las variables y busco el Hwnd del Form ToolTips
FrmTools.TxtTools = VarTools: frmHwnD1 = FrmTools.hwnd
'Comprueba exista el archivo imagen
If JJJT_ExisteDir(ImgTool) = True Then
FrmTools.Img.Picture = ImgTool
ElseIf JJJT_ExisteDir("C:\WINDOWS\Web\" & Dir(Ico)) = True Then
FrmTools.Img.Picture = "C:\WINDOWS\Web\" & Dir(Ico)
Else
FrmTools.Img.Picture = ""
End If
'Le doy el color de fondo al toolTips, segun se lo pase el Form Hijo
FrmTools.Detalle.BackColor = Color
'Establezco las variables para usar la funcion de Lebans
Dim lngWidth As Long, lngHeight As Long, lngTotalLines As Long, lngRet As Long
Dim lngTopMargin As Long
lngTopMargin = 60
'Segun la cantidad de caracteres busco abrir el form ToolTips que mas se le asemeje
Select Case Len(VarTools)
Case Is < 10
lngRet = fTextHeight(FrmTools.TxtTools, , lngHeight, lngWidth, lngTotalLines)
FrmTools.TxtTools.Height = lngHeight + lngTopMargin
FrmTools.TxtTools.Width = 150 * Len(VarTools)
CtlHeight = FrmTools.TxtTools.Height / 7.5
CtlWidth = FrmTools.TxtTools.Width / 7.5
Case Is < 30
lngRet = fTextHeight(FrmTools.TxtTools, , lngHeight, lngWidth, lngTotalLines)
FrmTools.TxtTools.Height = lngHeight + lngTopMargin
FrmTools.TxtTools.Width = 120 * Len(VarTools)
CtlHeight = FrmTools.TxtTools.Height / 7.5
CtlWidth = FrmTools.TxtTools.Width / 7.5
Case Is < 50
lngRet = fTextHeight(FrmTools.TxtTools, , lngHeight, lngWidth, lngTotalLines)
FrmTools.TxtTools.Height = lngHeight + lngTopMargin
FrmTools.TxtTools.Width = 3500
CtlHeight = FrmTools.TxtTools.Height / 10.5
CtlWidth = FrmTools.TxtTools.Width / 10
Case Is < 150
lngRet = fTextHeight(FrmTools.TxtTools, , lngHeight, lngWidth, lngTotalLines)
FrmTools.TxtTools.Height = lngHeight + lngTopMargin
FrmTools.TxtTools.Width = 3500
CtlHeight = FrmTools.TxtTools.Height / 12.3
CtlWidth = FrmTools.TxtTools.Width / 11.85
Case Is < 250
lngRet = fTextHeight(FrmTools.TxtTools, , lngHeight, lngWidth, lngTotalLines)
FrmTools.TxtTools.Height = lngHeight + lngTopMargin
FrmTools.TxtTools.Width = 3500
CtlHeight = FrmTools.TxtTools.Height / 13.6
CtlWidth = FrmTools.TxtTools.Width / 11.85
Case Is < 500
lngRet = fTextHeight(FrmTools.TxtTools, , lngHeight, lngWidth, lngTotalLines)
FrmTools.TxtTools.Height = lngHeight + lngTopMargin
FrmTools.TxtTools.Width = 3500
CtlHeight = FrmTools.TxtTools.Height / 14.6
CtlWidth = FrmTools.TxtTools.Width / 11.85
End Select
End Sub