ABOUT Visual Basic Programmieren Programmierung Download Downloads Tips & Tricks Tipps & Tricks Know-How Praxis VB VBA Visual Basic for Applications VBS VBScript Scripting Windows ActiveX COM OLE API ComputerPC Microsoft Office Microsoft Office 97 Office 2000 Access Word Winword Excel Outlook Addins ASP Active Server Pages COMAddIns ActiveX-Controls OCX UserControl UserDocument Komponenten DLL EXE
Diese Seite wurde zuletzt aktualisiert am 10.04.2000

Diese Seite wurde zuletzt aktualisiert am 10.04.2000
Aktuell im ABOUT Visual Basic-MagazinGrundlagenwissen und TechnologienKnow How, Tipps und Tricks rund um Visual BasicActiveX-Komponenten, Controls, Klassen und mehr...AddIns für die Visual Basic-IDE und die VBA-IDEVBA-Programmierung in MS-Office und anderen AnwendungenScripting-Praxis für den Windows Scripting Host und das Scripting-ControlTools, Komponenten und Dienstleistungen des MarktesRessourcen für Programmierer (Bücher, Job-Börse)Dies&Das...

Themen und Stichwörter im ABOUT Visual Basic-Magazin
Code, Beispiele, Komponenten, Tools im Überblick, Shareware, Freeware
Ihre Service-Seite, Termine, Job-Börse
Melden Sie sich an, um in den vollen Genuss des ABOUT Visual Basic-Magazins zu kommen!
Informationen zum ABOUT Visual Basic-Magazin, Kontakt und Impressum

Zurück...

Punktlandungen

Zurück...


Anzeige

(-hg) mailto:hg_setarea@aboutvb.de

Eine Visual Basic-MessageBox oder eine InputBox wird von Windows automatisch etwa in der Mitte des Arbeitsbereichs des Desktops angezeigt. Mit einem kleinen Trick können Sie jedoch eine MessageBox (oder InputBox) recht genau an eine beliebige Position bugsieren - indem Sie eben diesen Arbeitsbereich kurzzeitig ändern. Sie können nämlich Windows über die API-Funktion MSDN Library - API SystemParametersInfoSystemParametersInfo einen neuen aktuellen Arbeitsbereich angeben und diesen sofort nach dem Erscheinen der MessageBox wieder auf seine vorherige Größe zurücksetzen.

Einen kleinen Haken hat dieser Trick allerdings: Sollte Ihre Anwendung gerade in diesem Moment abstürzen, bevor die Rücksetzung erfolgen konnte, bleibt der Arbeitsbereich auch für alle anderen Anwendungen verändert - alle Fenster können dann nur noch in diesem Bereich bewegt werden und maximierte Fenster erhalten lediglich die Größe des veränderten Arbeitsbereichs.

Wenn Sie jedoch nicht warten, bis der modale Aufruf der MessageBox zurückkehrt, ist die Wahrscheinlichkeit eines Absturzes gerade in diesem Moment sehr gering. Das sofortige Rücksetzen können Sie einem Timer mit einem extrem kurzen Intervall (1) überlassen, der vor dem Aufruf der MessageBox gestartet (Enabled = True) wird. Beim Bearbeiten des Timer-Ereignisses stoppt er sich wieder selbst (Enabled = False) und sorgt für die Wiederherstellung des Arbeitsbereichs. Natürlich müssen Sie letzteren ebenfalls vor dem Aufruf der MessageBox erst einmal sichern. Hier tritt übrigens ein interessanter Unterschied zwischen der Laufzeit einer Anwendung in der Entwicklungsumgebung und der Laufzeit als kompilierte, ausführbare Datei (EXE) zutage: Im IDE-Lauf ist die MessageBox 100%ig modal - das Timer-Ereignis wird erst nach der Rückkehr des MessageBox-Aufrufs ausgelöst. Zur Laufzeit als EXE bleibt der Timer jedoch auch während der Anzeige der MessageBox aktiv: Das Timer-Ereignis wird daher unmittelbar nach dem Aufruf der MessageBox ausgelöst, während diese selbst weiterhin modal zu der Anwendung bleibt.

Wenn Sie ganz sicher gehen wollen, sichern Sie den originalen Arbeitsbereich mit SaveSetting-Aufrufen in der Registrierung und lesen die Werte anschließend zum Wiederherstellen von dort aus. Damit nicht nach einem Absturz falsche Werte gesichert und wiederhergestellt werden, koppeln Sie die Sicherung mit einem Flag: Die Werte dürfen nur dann ausgelesen werden, wenn das Flag gesetzt ist. Nach dem Auslesen löschen Sie das Flag wieder. Nur wenn das Flag nicht gesetzt ist, können die aktuellen Werte gesichert werden, d.h. vorhandene, mit dem Flag "geschützte" Werte können nicht überschrieben werden.

Das kleine Beispiel-Projekt zeigt Ihnen, wie die Aufruffolge aussehen sollte. Die Beep-Anweisung im Timer-Ereignis dient nur zur Verdeutlichung, dass das Ereignis tatsächlich zur EXE-Laufzeit sofort nach dem MessageBox-Aufruf ausgelöst wird.

Private Sub cmdShowMsgBox_Click()
  StoreArea
  SetArea -Me.Width \ 2, -Me.Height \ 2, Me.Width, _
   Me.Height * 0.85, True
  tmr.Enabled = True
  MsgBox "Platzierte MsgBox"
End Sub

Private Sub tmr_Timer()
  tmr.Enabled = False
  RestoreArea
  Beep
End Sub

Das Sichern des Arbeitsbereichs erfolgt mit der Prozedur StoreArea. Ihr können Sie optional die Angaben für AppName und Section für die SaveSetting-Aufrufe übergeben. Fehlen diese, wird der Titel der Anwendung als AppName und "WorkArea" für Section angenommen.

Public Sub StoreArea(Optional AppName As String, _
 Optional Section As String)

  Dim nAppName As String
  Dim nSection As String
  Dim nSaved As Boolean
  
  nAppName = Trim$(AppName)
  If Len(AppName) = 0 Then
    nAppName = App.Title
  End If
  nSection = Trim$(Section)
  If Len(nSection) = 0 Then
    nSection = "WorkArea"
  End If
  nSaved = CBool(GetSetting(nAppName, nSection, "AreaSaved", 0))
  If Not nSaved Then
    SystemParametersInfoArea SPI_GETWORKAREA, 0, mSavedArea, 0
    With mSavedArea
      SaveSetting nAppName, nSection, "AreaLeft", .Left
      SaveSetting nAppName, nSection, "AreaTop", .Top
      SaveSetting nAppName, nSection, "AreaRight", .Right
      SaveSetting nAppName, nSection, "AreaBottom", .Bottom
      SaveSetting nAppName, nSection, "AreaSaved", -1
    End With
  End If
End Sub
Die Wiederherstellung erfolgt mit RestoreArea - auch hier können Sie wieder AppName und Section angeben:
Public Sub RestoreArea(Optional AppName As String, _
 Optional Section As String)

  Dim nAppName As String
  Dim nSection As String
  Dim nSaved As Boolean
  
  nAppName = Trim$(AppName)
  If Len(AppName) = 0 Then
    nAppName = App.Title
  End If
  nSection = Trim$(Section)
  If Len(nSection) = 0 Then
    nSection = "WorkArea"
  End If
  nSaved = CBool(GetSetting(nAppName, nSection, "AreaSaved", 0))
  If nSaved Then
    On Error Resume Next
    With mSavedArea
      .Left = GetSetting(nAppName, nSection, "AreaLeft")
      .Top = GetSetting(nAppName, nSection, "AreaTop")
      .Right = GetSetting(nAppName, nSection, "AreaRight")
      .Bottom = GetSetting(nAppName, nSection, "AreaBottom")
    End With
    If Err.Number = 0 Then
      If SystemParametersInfoArea(SPI_SETWORKAREA, 0, _
       mSavedArea, 0) Then
        SaveSetting nAppName, nSection, "AreaSaved", 0
      End If
    End If
  End If
End Sub

Über die Prozedur ClearStoredArea können Sie das Flag gegebenenfalls separat löschen:

Public Sub ClearStoredArea(Optional AppName As String, _
 Optional Section As String)

  Dim nAppName As String
  Dim nSection As String
  
  nAppName = Trim$(AppName)
  If Len(AppName) = 0 Then
    nAppName = App.Title
  End If
  nSection = Trim$(Section)
  If Len(nSection) = 0 Then
    nSection = "WorkArea"
  End If
  SaveSetting nAppName, nSection, "AreaSaved", 0
End Sub

Mit der Prozedur SetArea setzen Sie nun den gewünschten (Arbeits-)Bereich, in dessen Mitte etwa die MessageBox erscheinen soll. Sie können die absolute Position des Bereichs in Twips in den Parametern Left, Top, Width und Height direkt angeben. Lassen Sie Left und/oder Top weg, wird statt dessen die aktuelle Cursor-Position verwendet. Lassen Sie Width und/oder Height weg, wird die Breite bzw. Höhe des Bereichs auf 2 Pixels reduziert (kleinere Werte verursachen einen Absturz!). Setzen Sie den letzten optionalen Parameter FromCursorPos auf True, werden die Werte von Left und Top relativ zur Cursor-Position gesetzt - Breite und Höhe bleiben weiterhin relativ zu Left und Top.

Public Sub SetArea(Optional ByVal Left As Variant, _
 Optional ByVal Top As Variant, _
 Optional ByVal Width As Variant, _
 Optional ByVal Height As Variant, _
 Optional ByVal FromCursorPos As Boolean)

  Dim nRect As Rect
  Dim nPoint As POINTAPI
  
  GetCursorPos nPoint
  With nRect
    If IsMissing(Left) Then
      .Left = nPoint.X
    Else
      If FromCursorPos Then
        .Left = nPoint.X + (Left \ Screen.TwipsPerPixelX)
      Else
        .Left = Left \ Screen.TwipsPerPixelX
      End If
    End If
    If IsMissing(Top) Then
      .Top = nPoint.Y
    Else
      If FromCursorPos Then
        .Top = nPoint.Y + (Top \ Screen.TwipsPerPixelY)
      Else
        .Top = Top \ Screen.TwipsPerPixelY
      End If
    End If
    If IsMissing(Width) Then
      .Right = .Left + 2
    Else
      .Right = .Left + (Width \ Screen.TwipsPerPixelX)
    End If
    If IsMissing(Height) Then
      .Bottom = .Top + 2
    Else
      .Bottom = .Top + (Height \ Screen.TwipsPerPixelY)
    End If
  End With
  SystemParametersInfoArea SPI_SETWORKAREA, 0, nRect, 0
End Sub

Damit eine MessageBox tatsächlich zentriert in einem Bereich angezeigt wird, muss dieser allerdings groß genug sein - die MessageBox muss vollständig in den Bereich hineinpassen können. Anderenfalls, etwa beim Weglassen der Angaben für Width und Height und der daraus resultierenden Größe des Bereichs von 2 x 2 Pixels, wird die linke obere Ecke der MessageBox in diesem winzigen Bereich positioniert. Sie können auch einfach die Left/Top/Width/Height-Werte eines Forms übergeben - die MessageBox wird dann über diesem Form zentriert. In dem Beispiel-Projekt sehen Sie, dass ich den Wert für Height mit dem Faktor 0,85 ein klein wenig reduziert habe - die MessageBox wird so noch genauer vertikal zentriert (Je nach Bildschirmeinstellungen kann allerdings ein anderer Wert als 0,85 kann notwendig sein!).

Das Prinzip funktioniert übrigens auch, wenn Sie Standard-Dialoge positionieren möchten.

Wenn Sie die Werte des Arbeitsbereichs nicht in der Registrierung sichern und auf die dadurch mögliche Sicherung durch das Flag verzichten möchten, können Sie die Prozeduren GetArea und ResetArea verwenden, um den Bereich direkt zu sichern und wiederherzustellen.

Public Sub GetArea(Left As Long, Top As Long, Right As Long, _
 Bottom As Long)

  SystemParametersInfoArea SPI_GETWORKAREA, 0, mSavedArea, 0
  With mSavedArea
    Left = .Left
    Top = .Top
    Right = .Right
    Bottom = .Bottom
  End With
End Sub

Public Sub ResetArea()
  SystemParametersInfoArea SPI_SETWORKAREA, 0, mSavedArea, 0
End Sub

Falls alles schief gehen sollte, können Sie mit der Prozedur FullScreenArea den Arbeitsbereich auf die volle Bildschirmgröße setzen - allerdings werden die Taskleiste usw. hierbei nicht berücksichtigt, die normalerweise den Arbeitsbereich reduzieren. nach einem Windows-Neustart ist allerdings der Arbeitsbereich wieder auf seinen Standardwerte zurückgesetzt.

Public Sub FullScreenArea()
  Dim nRect As Rect
  
  With nRect
    .Right = (Screen.Width \ Screen.TwipsPerPixelX)
    .Bottom = (Screen.Height \ Screen.TwipsPerPixelY)
  End With
  SystemParametersInfoArea SPI_SETWORKAREA, 0, nRect, 0
End Sub

Beispiel-Projekt SetArea (setarea.zip - ca. 3,2 KB)


Artikel
Zum Download-Bereich dieses Artikel
Mail an den Autor dieses Artikels

KnowHow
Zur KnowHow-Übersicht

KnowHow-Themen
Themen - Allgemeines
Themen - Entwicklungsumgebung (VB-IDE)
Themen - Forms
Themen - Steuerelemente (Controls)
Themen - Grafik
Themen - Dateien
Themen - UserControls
Themen - Einsteiger-Tipps
Themen - Wussten Sie...?

Übersicht nach Titeln in alphabetischer Reihenfolge
Übersicht nach Erscheinungsdatum

Schnellsuche



Zum Seitenanfang

Copyright © 1999 - 2017 Harald M. Genauck, ip-pro gmbh  /  Impressum

Zum Seitenanfang

Zurück...

Zurück...

Download Internet Explorer