domingo, 5 de mayo de 2013

Mostrar MsgBox en donde queramos

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