Por defecto nuestros MsgBox inician centrados en la pantalla de manera modal, lo que veremos es como manejar ese funcionamiento y así cambiarle la posición a nuestro gusto.
Hay que añadir a nuestro proyecto un módulo y declaramos:
Option Explicit
Type RECT
Left As Long
Top As Long
Right As Long
Bottom As Long
End Type
Public Declare Function UnhookWindowsHookEx Lib "user32" _
(ByVal hHook As Long) As Long
Public Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" _
(ByVal hwnd As Long, ByVal nIndex As Long) As Long
Public Declare Function GetCurrentThreadId Lib "kernel32" () As Long
Public Declare Function SetWindowsHookEx Lib "user32" Alias "SetWindowsHookExA" _
(ByVal idHook As Long, ByVal lpfn As Long, _
ByVal hmod As Long, ByVal dwThreadId As Long) As Long
Public Declare Function SetWindowPos Lib "user32" _
(ByVal hwnd As Long, ByVal hWndInsertAfter As Long, _
ByVal x As Long, ByVal y As Long, ByVal cx As Long, _
ByVal cy As Long, ByVal wFlags As Long) As Long
Public Declare Function GetWindowRect Lib "user32" _
(ByVal hwnd As Long, lpRect As RECT) As Long
Public Const GWL_HINSTANCE = (-6)
Public Const SWP_NOSIZE = &H1
Public Const SWP_NOZORDER = &H4
Public Const SWP_NOACTIVATE = &H10
Public Const HCBT_ACTIVATE = 5
Public Const WH_CBT = 5
Public hHook As Long
Las declaraciones de Apis, constantes y tipos de datos las colocamos en un mismo lugar para no generar entreveros, les recomiendo incluir este código en un módulo solo para el, por si hay algún error al cambiar valores, fácilmente podrán detectarlos depurandolo.
Primer proceso (dentro de módulo) para obtener el mensaje y determinar la posición de la caja de mensaje:
Function ProcesoUbicUser(ByVal lMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
If lMsg = HCBT_ACTIVATE Then
SetWindowPos wParam, 4, 0, 0, 0, 0, SWP_NOSIZE Or SWP_NOZORDER Or SWP_NOACTIVATE
UnhookWindowsHookEx hHook
End If
ProcesoUbicUser = False
End Function
Segundo proceso, ubicación predeterminada (centrado al formulario)
Function ProcesoCentrado(ByVal lMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Dim rectForm As RECT, rectMsg As RECT
Dim x As Long, y As Long
If lMsg = HCBT_ACTIVATE Then
GetWindowRect Form1.hwnd, rectForm
GetWindowRect wParam, rectMsg
x = (rectForm.Left + (rectForm.Right - rectForm.Left) / 2) - ((rectMsg.Right - rectMsg.Left) / 2)
y = (rectForm.Top + (rectForm.Bottom - rectForm.Top) / 2) - ((rectMsg.Bottom - rectMsg.Top) / 2)
SetWindowPos wParam, 0, x, y, 0, 0, _
SWP_NOSIZE Or SWP_NOZORDER Or SWP_NOACTIVATE
UnhookWindowsHookEx hHook
End If
ProcesoCentrado = False
End Function
Donde x,y determinan el posicionamiento del mensaje, en este caso, el centrado.
Código en Formulario (luego de añadir 2 botones de comando, uno muestra el msgbox centrado al formulario, esté donde esté y el otro donde le digamos luego de establecer algunos parámetros)
Option Explicit
Private Sub Command1_Click()
Dim hInst As Long
Dim Thread As Long
hInst = GetWindowLong(Me.hwnd, GWL_HINSTANCE)
Thread = GetCurrentThreadId()
hHook = SetWindowsHookEx(WH_CBT, AddressOf ProcesoUbicUser, hInst, Thread)
MsgBox "msgbox en posición determinada por el usuario"
End Sub
Private Sub Command2_Click()
Dim hInst As Long
Dim Thread As Long
hInst = GetWindowLong(Me.hwnd, GWL_HINSTANCE)
Thread = GetCurrentThreadId()
hHook = SetWindowsHookEx(WH_CBT, AddressOf ProcesoCentrado, hInst, Thread)
MsgBox "msgbox centrado al form"
End Sub
Cualquier duda consulten por aca o via mail.
Saludos.
No hay comentarios:
Publicar un comentario