Hauptseite >Tips zu VB5/6 >  MessageBox und CommonDialog platzieren     view this document in English view this document in English
 
Die MessageBox wird bekanntlich standardmässig in der Bildschirmmitte angezeigt. Manchmal ist es jedoch notwendig, sie selbst zu platzieren. Nur: Wie?

Ein Hook hilft hier weiter. Zur Erklärung: einen Hook setzten bedeutet, dem Betriebssystem mitzuteilen: "Ruf doch bis auf weiteres bei jeder Windows-Nachricht, die meinen Thread betrifft, folgende Routine von mir auf: ..." und in dieser Routine dann zu reagieren, wenn das Erzeugen des MsgBox-Fensters bekanntgegeben wird. Da mit dieser Nachricht auch das Fensterhandle der MsgBox mitgegeben wird, kann man nun diesem Fenster eine Nachricht schicken, es möge sich bitte an den Koordinaten x und y platzieren. Danach sollte der Hook sofort aufgehoben werden.

Das Erzeugen eines Fensters (nebenbei: auch Buttons usw. sind Fenster!) wird mit der Nachricht WM_CREATE bekanntgegeben. Nun muss herausgefunden werden, ob es das gewünschte Fenster ist; mit GetClassName kriegt man den Klassennamen heraus, und wenn das Fenster der Klasse #32770 (das ist das Dialogfenster!) angehört, greifen wir ein.

In ein Standard-Modul muss Folgendes:

Option Explicit

Private X32770&, Y32770&, MyHook&

  Type CWPSTRUCT
    lParam As Long
    wParam As Long
    Message As Long
    hwnd As Long
  End Type

Public Const WH_CALLWNDPROC& = 4
Public Const SWP_NOSIZE = &H1
Public Const SWP_NOZORDER = &H4

Declare Function SetWindowsHookEx& Lib "user32" Alias _
  "SetWindowsHookExA" (ByVal idHook&, ByVal lpfn&, ByVal _
  hmod&, ByVal dwThreadId&)
Declare Function UnhookWindowsHookEx& Lib "user32" (ByVal hHook&)
Declare Function GetClassName& Lib "user32" Alias _
  "GetClassNameA" (ByVal hwnd&, ByVal lpClassName$, _
  ByVal nMaxCount&)
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 Sub Position32770(ByVal x As Long, ByVal y As Long) 'Angaben in Pixeln!
X32770 = x
Y32770 = y
MyHook = SetWindowsHookEx(WH_CALLWNDPROC, AddressOf Hook32770, 0&, App.ThreadID)
End Sub
            

Private Function Hook32770&(ByVal nCode&, ByVal wParam&, MyStruct As CWPSTRUCT)
Const WM_CREATE& = &H1
Dim PosFlag&
  With MyStruct
    If .Message = WM_CREATE Then 'es wird ein "Objekt" ... erzeugt
    Dim s$, i%
    s = String$(255, 0)
    GetClassName .hwnd, s, 256   'Klassennamen des Objekts feststellen
    i = InStr(s, vbNullChar)
    If i Then s = Left$(s, i - 1)
      If s = "#32770" Then  'das ist das Dialogfenster!
      Call UnhookWindowsHookEx(MyHook)
      'Hook abstellen, wird nicht mehr gebraucht; Fenster positionieren
      PosFlag = SWP_NOZORDER Or SWP_NOSIZE    'Nur x und y ändern
      SetWindowPos .hwnd, 0&, X32770, Y32770, 0&, 0&, PosFlag
      End If
    End If
  End With
End Function

            
Der Aufruf erfolgt jetzt ganz einfach:

Private Sub Command1_Click()
Position32770 0, 0
MsgBox "Ich erscheine im linken oberen Eck"
End Sub
            
Übrigens: Da das CommonDialog-Fenster ebenfalls der Fensterklasse #32770 angehört, kann es mit dem vorherigen Aufruf von Position32770 ebenso platziert werden.
Hauptseite >  Tips zu VB5/6 >  diese Seite