Hi Freunde,
Ich habe eine Form "Monitor Display-Manager" geknotet, welche alle an den PC angeschlossene und eingeschaltete Screens, deren Positionen und sonstige Eigenschaften anzeigt.
Falls mal jemand so einen Dialog braucht - hier der Code:
Erforderlich sind nur folgende zwei My.Settings-Einträge, um Form.Location und Form.Size zu speichern:
My.Settings.Form_MonitorDisplayManager_Location
My.Settings.Form_MonitorDisplayManager_Size
Spoiler anzeigen
Den Code könnt Ihr einfach in ein neues Formular einfügen - alle benötigten Controls werden dynamisch erzeugt.
Die Form wird als Dialog mit :
aufgerufen und angezeigt.
Das Public-Array "Form_MonitorDisplayManager.Displays" beinhaltet nach dem Aufbau durch Aufruf der Public Sub: "Form_MonitorDisplayManager.MonitorArrayAufbauen" oder durch erstmaliges Öffnen des Dialogfensters die Eigenschaften aller Monitore in einer Form_MonitorDisplayManager.DisplayListe Struktur:
Mittels dieses "Displays"-Arrays könnt Ihr in Eurer Anwendung gezielt auf die Eigenschaften aller Monitore zugreifen.
Dier verwendeten Propertys sind im Script in der Region "Information zur Bedienung" beschrieben.
Die Property-Default-Werte können im Script in der Region "Variablen-Zuweisung" geändert werden.
----------------------------------------------------------------------------------------------------
Überarbeitung und Erweiterung des Codes (12.03.25 19:45Uhr):
Hi Freunde,
Ich habe den Form "Monitor Display-Manager" erweitert.
Falls mal jemand so einen Dialog braucht - hier der Code:
Erforderlich sind nur folgende zwei My.Settings-Einträge, um Form.Location und Form.Size zu speichern:
My.Settings.Form_MonitorDisplayManager_Location
My.Settings.Form_MonitorDisplayManager_Size
Zusätzlich erforderlich ist für die Nutzung dieses erweiterten "Monitor Diaplay-Manager", das "System Management" in das eigene Projekt einzubinden:
Menu "Projekt" - "Verweis hinzufügen ..." - unter "Assemblys" den Eintrag "System.Management" anhakerln - "OK"-Button aklicken.
Hinzugekommen:
Mgl. exakte Bildschirmgrössen-Anzeige in Millimeter durch Auslesen der EDID-Werte.
Information:
Die EDID-Abfrage (Extended Display Identification Data) dient dazu, Informationen über den angeschlossenen Monitor direkt aus dessen Firmware (EEPROM des Monitors) auszulesen. Die Grafikkarte fragt diese Daten beim Systemstart über das I²C-Protokoll von der DDC-Schnittstelle (Display Data Channel) des Monitors ab.
Windows speichert diese Daten und stellt sie über WMI (Windows Management Instrumentation) oder direkt über die Registry bereit.
Nur, wenn diese EDID-Werte nicht gelesen werden können (billige Graphikkarte, billiger Monitor und viele Laptops), werden im "Monitor Display-Manager" die ungenauen DPI-Berechnungen zur Ermittlung der Bildschirmabmessungen verwendet.
Zusätzliche Anzeige aus EDID-Werten (wenn möglich):
Hardware: Monitor-Hersteller-Kürzel, Produkt-Code, S/N
Sehr genaue Bildschirmabmessungen (in mm)
Pixelgrösse physikalisch, DPI physikalisch
Pixelgrösse skaliert, DPI skaliert
Neue Variable:
Bei_Öffnen_Aktuelles_Fenster_Auswählen (Boolean)
True = Selektiert beim Öffnen des Fensters den Monitor, auf welchem das Fenster geöffnet wird
False = Selektiert beim Öffnen des Fensters den primären Monitor
Neue Funktion:
Public Form_MonitorDisplayManager.GetMonitorDeviceNumberFromCursor()
Liefert die Monitornummer des Monitors, auf welchem sich der Mauszeiger befindet
Aufruf: Dim MonitorDetails as Form_MonitorDisplayManager.Displayliste
MonitorDetails = Form_MonitorDisplayManager.GetMonitorDetails(Form_MonitorDisplayManager.GetMonitorDeviceNumberFromCursor())
Den Code könnt Ihr einfach in ein neues Formular einfügen - alle benötigten Controls werden dynamisch erzeugt.
Die Form wird als Dialog mit :
aufgerufen und angezeigt.
Das Public-Array "Form_MonitorDisplayManager.Displays" beinhaltet nach dem Aufbau durch Aufruf der Public Sub: "Form_MonitorDisplayManager.MonitorArrayAufbauen" oder durch erstmaliges Öffnen des Dialogfensters die Eigenschaften aller Monitore in einer Form_MonitorDisplayManager.DisplayListe Struktur:
Mittels dieses "Displays"-Arrays könnt Ihr in Eurer Anwendung gezielt auf die Eigenschaften aller Monitore zugreifen.
Propertys:
Dier verwendeten Propertys sind im Script in der Region "Information zur Bedienung" beschrieben.
Die Property-Default-Werte können im Script in der Region "Variablen-Zuweisung" geändert werden.
Da das Script zu gross für dieses Forum ist, hier als ZIP-Anlage
Ich habe eine Form "Monitor Display-Manager" geknotet, welche alle an den PC angeschlossene und eingeschaltete Screens, deren Positionen und sonstige Eigenschaften anzeigt.
Falls mal jemand so einen Dialog braucht - hier der Code:
Erforderlich sind nur folgende zwei My.Settings-Einträge, um Form.Location und Form.Size zu speichern:
My.Settings.Form_MonitorDisplayManager_Location
My.Settings.Form_MonitorDisplayManager_Size
Quellcode
- Imports System.Windows.Forms
- Imports System.Drawing
- Imports System.Threading.Tasks
- Imports System.Linq
- Imports System.Runtime.InteropServices
- Imports System.Threading
- Imports System.Reflection.Emit
- #Region "Information zur Bedienung"
- ' Propertys
- '
- ' MonitorDisplayManager_Fenster_Als_MonitorAuswahl (Boolean) :
- ' True = Zeigt einen "Monitor-Auswahl"-Dialog mit Action-Button "OK" (Schliesst die Form)
- ' False = Zeigt einen "Monitor-Viewer"-Dialog mit Action-Button "Information" (Bei Klick: Anzeige der Overlays mit den jeweiligen Monitornummern auf allen Monitoren)
- ' OK_Button_Pressed (Boolean):
- ' True, wenn der "OK"-Button (bei MonitorDisplayManager_Fenster_Als_MonitorAuswahl = true) angeklickt wird
- ' False, wenn das Fenster ausge-x-t wird
- '
- ' Monitor_Auswahl_MonitorNummer (Integer):
- ' Beinhaltet nach der Auswahl eines Monitors dessen MonitorNummer bzw. nach dem Schliessen der Form die MonitorNummer des selektierten Monitors.
- ' Form_Hintergrundfarbe (Color):
- ' Stellt die Hintergrundfarbe des freien Form-Bereichs links und rechts des Panels ein, wenn die Form.Width > Panel.width aufgezogen wird
- ' Monitor_Panel_Hintergrundfarbe (Color):
- ' Setzt die Hintergrundfarbe des Panels auf welchem sich die Monitor-Buttons befinden
- ' Monitor_Buttons_Font (Font):
- ' Setzt die Schriftart der Monitor-Buttons
- '
- ' Monitor_Buttons_Schriftfarbe (Color):
- ' Setzt die Schriftfarbe der Monitor-Buttons
- '
- ' Monitor_Buttons_Hintergrundfarbe (Color):
- ' Setzt die Hintergrundfarbe der Monitor-Buttons
- '
- ' Monitor_SelektierterButton_Hintergrundfarbe (Color):
- ' Setzt die Hintergrundfarbe des ausgewählten Monitor-Buttons
- '
- ' ActionButton_Font (Font):
- ' Setzt die Schriftart des Action-Buttons ("OK" bzw. "Identifizieren")
- '
- ' ActionButton_Schriftfarbe (Color):
- ' Setzt die Schriftfarbe des Action-Buttons ("OK" bzw. "Identifizieren")
- '
- ' ActionButton_Hintergrundfarbe (Color):
- ' Setzt die Hintergrundfarbe des Action-Buttons ("OK" bzw. "Identifizieren")
- '
- ' Monitor_Information_TextBox_Font (Font):
- ' Setzt die Schriftart der Monitor-Information Textbox
- '
- ' Monitor_Information_TextBox_Schriftfarbe (Color):
- ' Setzt die Schriftfarbe der Monitor-Information Textbox
- '
- ' Monitor_Information_TextBox_Hintergrundfarbe (Color):
- ' Setzt die Hintergrundfarbe der Monitor-Information Textbox
- '
- ' Overlay_Position (Integer):
- ' Struktur "Overlay_Corner" TopLeft = 0, TopRight = 1, BottomLeft = 2, BottomRight = 3
- ' Stellt die AnzeigeEcke der Monitor Overlays ein
- '
- ' Overlay_AnzeigenBeiMonitorClick (Boolean):
- ' Schaltet Anzeige des Monitor-Overlays beim Anklicken eines Monitor-Buttons Ein/Aus
- ' True = Beim Anklicken eines Monitor-Buttons wird das Overlay mit der Monitornummer im angeklickten Monitor angezeigt
- ' False = Beim Anklicken eines Monitor-Buttons wird kein Overlay angezeigt
- '
- ' Overlay_Opacity (Integer):
- ' Stellt die Transparenz der Monitor Overlays ein (0 = voll Transparent - 1 = keine Transparenz)
- '' Overlay_AnzeigeDauer (Integer):
- ' Setzt die Anzeigedauer (In ms) der Overlays mit Ausgabe der Monitor-Nummer
- '
- ' Overlay_Breite (Integer):
- ' Setzt die Breite der Overlays mit Ausgabe der Monitor-Nummer durch vor und nach der Monitornummer eingefügte Leerzeichen (zulässige Werte 0 - 5)
- '
- ' Overlay_Font (Font):
- ' Setzt die Schriftart der Overlays mit Ausgabe der Monitor-Nummer
- '
- ' Overlay_Schriftfarbe (Color):
- ' Setzt die Schriftfarbe der Overlays mit Ausgabe der Monitor-Nummer
- '
- ' Overlay_Hintergrundfarbe (Color):
- ' Setzt die Hintergrundfarbe der Overlays mit Ausgabe der Monitor-Nummer
- '
- '
- ' Public Funktionen
- '
- ' Aufruf aus anderen Formen wie z.B. dem Mainform
- '
- ' Form_MonitorDisplayManager.Initialize
- ' Öffnet das Fenster MonitorDisplayManager als Dialog-Fenster
- '
- ' Public Form_MonitorDisplayManager.MonitorArrayAufbauen()
- ' Erstellt das Array Form_MonitorDisplayManager.Displays as Form_MonitorDisplayManager.Displayliste mit der Auflistung der Details aller Monitore
- '
- ' Public Form_MonitorDisplayManager.GetMonitorDetails(monitorNummer) as Form_MonitorDisplayManager.DisplayListe
- ' Liefert die Details des Monitors mit der MonitorNummer als DisplayListe
- ' Aufruf: Dim MonitorDetails as Form_MonitorDisplayManager.Displayliste
- ' MonitorDetails = Form_MonitorDisplayManager.GetMonitorDetails(monitorNummer)
- #End Region
- #Region "Strukturen"
- <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto)>
- Public Structure DEVMODE
- Private Const CCHDEVICENAME As Integer = 32
- Private Const CCHFORMNAME As Integer = 32
- <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=CCHDEVICENAME)>
- Public dmDeviceName As String
- Public dmSpecVersion As Short
- Public dmDriverVersion As Short
- Public dmSize As Short
- Public dmDriverExtra As Short
- Public dmFields As Integer
- Public dmPositionX As Integer
- Public dmPositionY As Integer
- Public dmDisplayOrientation As Integer
- Public dmDisplayFixedOutput As Integer
- Public dmColor As Short
- Public dmDuplex As Short
- Public dmYResolution As Short
- Public dmTTOption As Short
- Public dmCollate As Short
- <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=CCHFORMNAME)>
- Public dmFormName As String
- Public dmLogPixels As Short
- Public dmBitsPerPel As Integer
- Public dmPelsWidth As Integer
- Public dmPelsHeight As Integer
- Public dmDisplayFlags As Integer
- Public dmDisplayFrequency As Integer
- Public dmICMMethod As Integer
- Public dmICMIntent As Integer
- Public dmMediaType As Integer
- Public dmDitherType As Integer
- Public dmReserved1 As Integer
- Public dmReserved2 As Integer
- Public dmPanningWidth As Integer
- Public dmPanningHeight As Integer
- End Structure
- <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto)>
- Public Structure DisplayListe
- Public MonitorNummer As Integer
- Public MonitorNummerLogisch As Integer
- Public MonitorName As String
- Public MonitorArt As Integer
- Public SkalierungDetected As Integer
- Public SkalierungCalculated As Integer
- Public SkalierungMaximal As Integer
- Public LogischeAuflösung As Size
- Public PhysikalischeAuflösung As Size
- Public Position As Point
- End Structure
- Public Enum DpiType
- Effective = 0
- Angular = 1
- Raw = 2
- End Enum
- Public Enum Overlay_Corner
- LeftTop = 0
- RightTop = 1
- LeftBottom = 2
- RightBottom = 3
- End Enum
- #End Region
- Public Class Form_MonitorDisplayManager
- #Region "Variablen-Zuweisungen"
- Public displays(15) As DisplayListe
- Private isLoaded As Boolean
- ' Default-Propertys
- Private _MonitorDisplayManager_Fenster_Als_MonitorAuswahl As Boolean = True
- Private _Monitor_Auswahl_MonitorNummer As Integer = 0
- Private _OK_Button_Pressed As Boolean = False
- Private _Form_Hintergrundfarbe As Color = SystemColors.Window
- Private _Monitor_Panel_Hintergrundfarbe As Color = SystemColors.Window
- Private _Monitor_Buttons_Font As New Font("Microsoft Sans Serif", 11, FontStyle.Regular)
- Private _Monitor_Buttons_Schriftfarbe As Color = SystemColors.ControlText
- Private _Monitor_Buttons_Hintergrundfarbe As Color = SystemColors.ButtonFace
- Private _Monitor_SelektierterButton_Hintergrundfarbe As Color = Color.LightBlue
- Private _Action_Button_Font As New Font("Microsoft Sans Serif", 11, FontStyle.Regular)
- Private _Action_Button_Schriftfarbe As Color = SystemColors.ControlText
- Private _Action_Button_Hintergrundfarbe As Color = SystemColors.ButtonFace
- Private _Monitor_Information_Textbox_Font As New Font("Microsoft Sans Serif", 11, FontStyle.Regular)
- Private _Monitor_Information_TextBox_Schriftfarbe As Color = SystemColors.WindowText
- Private _Monitor_Information_TextBox_Hintergrundfarbe As Color = SystemColors.Window
- Private _Overlay_AnzeigenBeiMonitorClick As Boolean = True
- Private _Overlay_Position As Integer = Overlay_Corner.RightTop
- Private _Overlay_Opacity As Double = 0.5
- Private _Overlay_AnzeigeDauer As Integer = 5000
- Private _Overlay_Breite As Integer = 2
- Private _Overlay_Font As New Font("Microsoft Sans Serif", 60, FontStyle.Regular)
- Private _Overlay_Schriftfarbe As Color = Color.Yellow
- Private _Overlay_Hintergrundfarbe As Color = Color.Red
- #End Region
- #Region "Controls erstellen"
- Dim overlayTimer As System.Windows.Forms.Timer
- Dim OverlayPanels As New List(Of Form)
- Private panelMonitore As New Panel With {
- .Top = 0,
- .Left = 0,
- .Height = 350,
- .Width = 800,
- .BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle,
- .AutoScroll = True,
- .BackColor = Monitor_Panel_Hintergrundfarbe,
- .Anchor = AnchorStyles.Left Or AnchorStyles.Right Or AnchorStyles.Top
- }
- Private btnAction As New Button With {
- .Left = 0,
- .Height = 30,
- .Width = 800,
- .Text = "",
- .Font = Action_Button_Font,
- .ForeColor = Action_Button_Schriftfarbe,
- .BackColor = Action_Button_Hintergrundfarbe,
- .AutoSize = True,
- .Anchor = AnchorStyles.Left Or AnchorStyles.Right Or AnchorStyles.Bottom
- }
- Private txtInfo As New TextBox With {
- .Left = 0,
- .Width = 800,
- .Multiline = True,
- .Font = Monitor_Information_TextBox_Font,
- .ForeColor = Monitor_Information_TextBox_Schriftfarbe,
- .BackColor = Monitor_Information_TextBox_Hintergrundfarbe,
- .ScrollBars = ScrollBars.None,
- .Anchor = AnchorStyles.Left Or AnchorStyles.Right Or AnchorStyles.Top Or AnchorStyles.Bottom
- }
- #End Region
- #Region "DLLS"
- ' Monitor Auflistung
- <DllImport("user32.dll", SetLastError:=True)>
- Public Shared Function MonitorFromPoint(pt As Point, flags As UInteger) As IntPtr
- End Function
- <DllImport("shcore.dll", SetLastError:=True)>
- Public Shared Function GetDpiForMonitor(hmonitor As IntPtr, dpiType As Integer, ByRef dpiX As UInteger, ByRef dpiY As UInteger) As Integer
- End Function
- ' API-Definitionen für EnumDisplaySettings und EnumDisplayDevices
- <DllImport("user32.dll", CharSet:=CharSet.Auto, SetLastError:=True)>
- Public Shared Function EnumDisplaySettings(ByVal deviceName As String, ByVal modeNum As Integer, ByRef devMode As DEVMODE) As Boolean
- End Function
- <DllImport("user32.dll", CharSet:=CharSet.Auto, SetLastError:=True)>
- Public Shared Function EnumDisplayDevices(ByVal deviceName As String, ByVal deviceIndex As Integer, ByRef devMode As DEVMODE, ByVal dwFlags As Integer) As Boolean
- End Function
- #End Region
- #Region "Form-Funktionen"
- Public Sub Initialize()
- Me.ShowDialog()
- End Sub
- Public Sub New()
- Me.Visible = False
- Me.Opacity = 0
- Me.Size = New Size(816, 630)
- Me.MinimumSize = New Size(816, 630)
- Me.MinimizeBox = False
- Me.MaximizeBox = False
- Me.BackColor = Form_Hintergrundfarbe
- End Sub
- Private Sub Form_MonitorDisplayManager_Load(sender As Object, e As EventArgs) Handles MyBase.Load
- End Sub
- Private Sub Form_MonitorDisplayManager_Shown(sender As Object, e As EventArgs) Handles MyBase.Shown
- Me.Visible = True
- Dim mousePos As Point = Cursor.Position
- Dim screen As Screen = Screen.FromPoint(mousePos)
- If My.Settings.Form_MonitorDisplayManager_Location = New Point(-1, -1) Then
- Me.Location = New Point(CInt((screen.WorkingArea.Left + (screen.WorkingArea.Size.Width - Me.MinimumSize.Width) / 2)), CInt((screen.WorkingArea.Top + (screen.WorkingArea.Size.Height - Me.MinimumSize.Height) / 2)))
- Else
- Me.Location = My.Settings.Form_MonitorDisplayManager_Location
- End If
- If My.Settings.Form_MonitorDisplayManager_Size = New Size(-1, -1) Then
- Me.Size = New Size(Me.MinimumSize.Width, Me.MinimumSize.Height)
- Else
- Me.Size = My.Settings.Form_MonitorDisplayManager_Size
- End If
- 'Controls hinzufügen
- Me.Controls.Add(panelMonitore)
- Me.Controls.Add(btnAction)
- btnAction.Top = Me.ClientSize.Height - btnAction.Height
- Me.Controls.Add(txtInfo)
- txtInfo.Top = panelMonitore.Height
- txtInfo.Height = Me.ClientSize.Height - panelMonitore.Height - btnAction.Height
- 'Event-Handler
- AddHandler btnAction.Click, AddressOf ButtonAction_Click
- 'Monitor-Funktionen aufrufen
- MonitorArrayAufbauen()
- MonitorButtonsAufbauen()
- If MonitorDisplayManager_Fenster_Als_MonitorAuswahl = True Then
- btnAction.Text = "OK"
- Me.Text = "Monitor-Auswahl"
- Else
- btnAction.Text = "Identifizieren"
- Me.Text = "Monitor-Viewer"
- End If
- SelektierePrimärenMonitor()
- Me.ActiveControl = panelMonitore
- Me.Opacity = 1
- isLoaded = True
- End Sub
- Private Sub Form_MonitorDisplayManager_Resize(sender As Object, e As EventArgs) Handles MyBase.Resize
- If isLoaded = True Then
- If Me.WindowState = FormWindowState.Normal Then
- My.Settings.Form_MonitorDisplayManager_Size = Me.Size
- End If
- End If
- End Sub
- Private Sub Form_MonitorDisplayManager_LocationChanged(sender As Object, e As EventArgs) Handles MyBase.LocationChanged
- If isLoaded = True Then
- If Me.WindowState = FormWindowState.Normal Then
- My.Settings.Form_MonitorDisplayManager_Location = Me.Location
- End If
- End If
- End Sub
- Private Sub Form_MonitorDisplayManager_FormClosing(sender As Object, e As FormClosingEventArgs) Handles MyBase.FormClosing
- isLoaded = False
- End Sub
- #End Region
- #Region "Buttons"
- Private Sub ButtonMonitor_MouseDown(button As Button, monitornummer As Integer)
- Me.ActiveControl = panelMonitore
- AlleButtonsFarbeSetzen(Monitor_Buttons_Hintergrundfarbe)
- button.BackColor = Monitor_SelektierterButton_Hintergrundfarbe
- IdentifiziereMonitor(monitornummer)
- End Sub
- Private Sub ButtonAction_Click(sender As Object, e As EventArgs)
- Me.ActiveControl = panelMonitore
- If MonitorDisplayManager_Fenster_Als_MonitorAuswahl = True Then
- OK_Button_Pressed = True
- Me.Close()
- Else
- IdentifiziereMonitore()
- End If
- End Sub
- #End Region
- #Region "Methoden"
- Public Sub MonitorArrayAufbauen()
- Dim dpiX As UInteger
- Dim dpiY As UInteger
- For monitorNummer As Integer = 0 To Screen.AllScreens.Length - 1
- Dim scr As Screen = Screen.AllScreens(monitorNummer)
- Dim hMonitor As IntPtr = MonitorFromPoint(New Point(scr.Bounds.Left + 1, scr.Bounds.Top + 1), 2)
- If GetDpiForMonitor(hMonitor, DpiType.Effective, dpiX, dpiY) = 0 Then
- Dim devMode As New DEVMODE()
- devMode.dmSize = CShort(Marshal.SizeOf(devMode)) ' Wichtig!
- If EnumDisplaySettings(scr.DeviceName, -1, devMode) Then
- Dim detectedScaling As Single = dpiX / 96.0F
- Dim calculatedScaling As Single = CSng(devMode.dmPelsHeight) / CSng(scr.Bounds.Height)
- Dim maxScaling As Single = detectedScaling
- If calculatedScaling > detectedScaling Then
- maxScaling = calculatedScaling
- End If
- Dim logicalWidth As Integer = devMode.dmPelsWidth
- Dim logicalHeight As Integer = devMode.dmPelsHeight
- Dim Primär As Integer = If(scr.Primary, 1, 0)
- If monitorNummer < 16 AndAlso scr.DeviceName <> "" Then
- displays(monitorNummer) = New DisplayListe With {
- .MonitorNummer = monitorNummer + 1,
- .MonitorName = scr.DeviceName,
- .MonitorArt = Primär,
- .SkalierungDetected = CInt(detectedScaling * 100),
- .SkalierungCalculated = CInt(calculatedScaling * 100),
- .SkalierungMaximal = CInt(maxScaling * 100),
- .LogischeAuflösung = New Drawing.Size(logicalWidth, logicalHeight),
- .PhysikalischeAuflösung = New Drawing.Size(GetNativeResolution(scr.DeviceName).Width, GetNativeResolution(scr.DeviceName).Height),
- .Position = New Point(scr.Bounds.Left, scr.Bounds.Top)
- }
- End If
- End If
- End If
- Next monitorNummer
- Dim sortedDisplays = displays.
- Where(Function(d) d.MonitorName <> ""). ' Filtert nur Monitore mit Namen
- OrderBy(Function(d) d.Position.Y). ' Zuerst nach Y (oben -> unten) sortieren
- ThenBy(Function(d) d.Position.X). ' Falls Y gleich ist, nach X (links -> rechts) sortieren
- Concat(displays.Where(Function(d) d.MonitorName = "")). ' Unsortierte leere Einträge hinten anhängen
- ToArray()
- ' **Füge die logische Nummer hinzu**
- For i As Integer = 0 To sortedDisplays.Length - 1
- sortedDisplays(i).MonitorNummerLogisch = i + 1
- Next
- displays = sortedDisplays
- End Sub
- Private Sub SelektierePrimärenMonitor()
- For Each btn As Button In panelMonitore.Controls.OfType(Of Button)()
- Dim monitorIndex As Integer
- If Integer.TryParse(btn.Name.Replace("btn", ""), monitorIndex) Then
- If displays(monitorIndex).MonitorArt = 1 Then
- btn.BackColor = Color.LightBlue ' Beispiel: Farbe ändern zur Hervorhebung
- btn.Focus() ' Falls du den Button auch aktiv setzen möchtest
- Dim primaererMonitor = displays.FirstOrDefault(Function(d) d.MonitorArt = 1)
- ButtonMonitor_DetailsAnzeigen(primaererMonitor.MonitorNummer, primaererMonitor.MonitorNummerLogisch)
- Monitor_Auswahl_MonitorNummer = primaererMonitor.MonitorNummer
- Exit For
- End If
- End If
- Next
- End Sub
- Private Sub MonitorButtonsAufbauen()
- panelMonitore.Controls.Clear()
- ' Bestimme die Begrenzungen der Monitore
- Dim minX As Integer = displays.Min(Function(d) d.Position.X)
- Dim minY As Integer = displays.Min(Function(d) d.Position.Y)
- Dim maxX As Integer = displays.Max(Function(d) d.Position.X + d.LogischeAuflösung.Width)
- Dim maxY As Integer = displays.Max(Function(d) d.Position.Y + d.LogischeAuflösung.Height)
- ' Relative Breite und Höhe der Gesamtanzeige
- Dim totalWidth As Integer = maxX - minX
- Dim totalHeight As Integer = maxY - minY
- ' Skalierungsfaktor für die Darstellung (damit alles in das Panel passt)
- Dim scaleFactor As Single = Math.Min(CSng((panelMonitore.Width - 4) / totalWidth), CSng((panelMonitore.Height - 4) / totalHeight) * 0.9F)
- For vara As Integer = 0 To displays.Count - 1
- If displays(vara).MonitorName <> "" Then
- Dim monitorNummer As Integer = vara + 1
- Dim buttonBounds = New Rectangle(New Point(displays(vara).Position.X, displays(vara).Position.Y),
- New Size(displays(vara).LogischeAuflösung.Width, displays(vara).LogischeAuflösung.Height))
- ' Suche Monitore, die sich teilweise oder ganz oberhalb befinden
- Dim varb As Integer = vara
- Dim darüberliegendeMonitore = displays.Where(Function(d) d.Position.Y < displays(varb).Position.Y AndAlso
- d.Position.X + d.LogischeAuflösung.Width > displays(varb).Position.X AndAlso
- d.Position.X < displays(varb).Position.X + displays(varb).LogischeAuflösung.Width).
- OrderByDescending(Function(d) d.Position.Y).
- ToList()
- Dim newX As Integer = buttonBounds.Left
- If darüberliegendeMonitore.Count > 0 Then
- ' Berechne den gemeinsamen Überlappungsbereich mit den oberen Monitoren
- Dim minXOverlap As Integer = Math.Max(displays(vara).Position.X, darüberliegendeMonitore.Min(Function(d) d.Position.X))
- Dim maxXOverlap As Integer = Math.Min(displays(vara).Position.X + displays(vara).LogischeAuflösung.Width,
- darüberliegendeMonitore.Max(Function(d) d.Position.X + d.LogischeAuflösung.Width))
- ' Setze X in die Mitte des Überlappungsbereichs
- newX = minXOverlap + ((maxXOverlap - minXOverlap) \ 2) - (buttonBounds.Width \ 2)
- End If
- ' Skaliere die berechneten Werte
- Dim scaledX As Integer = CInt((newX - minX) * scaleFactor) + 5
- Dim scaledY As Integer = CInt((buttonBounds.Top - minY) * scaleFactor) + 5
- Dim btn As New Button With {
- .Name = "btn" & CStr(vara),
- .Text = CStr(displays(vara).MonitorNummer) & " (" & CStr(vara + 1) & ")",
- .Font = Monitor_Buttons_Font,
- .Size = New Size(CInt(buttonBounds.Width * scaleFactor), CInt(buttonBounds.Height * scaleFactor)),
- .Location = New Point(scaledX, scaledY),
- .BackColor = Color.LightGray
- }
- Dim monNummer As Integer = vara
- AddHandler btn.MouseDown, Sub(sender, e) ButtonMonitor_MouseDown(CType(sender, Button), displays(monNummer).MonitorNummer)
- AddHandler btn.MouseUp, Sub() ButtonMonitor_DetailsAnzeigen(displays(monNummer).MonitorNummer, CInt(monNummer + 1))
- panelMonitore.Controls.Add(btn)
- End If
- Next
- AlleButtonsFarbeSetzen(Monitor_Buttons_Hintergrundfarbe)
- End Sub
- Private Sub ButtonMonitor_DetailsAnzeigen(monitornummer As Integer, logischeNummer As Integer)
- Dim monitor As DisplayListe = displays.FirstOrDefault(Function(m) m.MonitorNummer = monitornummer)
- Dim native As String = ""
- If monitor.MonitorNummer <> 0 Then ' Falls gefunden
- If monitor.LogischeAuflösung.Width = monitor.PhysikalischeAuflösung.Width AndAlso monitor.LogischeAuflösung.Height = monitor.PhysikalischeAuflösung.Height Then
- native = " (Native Auflösung)"
- End If
- Dim art As String = "Primärer Monitor"
- If monitor.MonitorArt = 0 Then art = "Sekundärer Monitor"
- txtInfo.Text = " Monitor Details" & vbCrLf & vbCrLf &
- $" Monitornummer: {monitor.MonitorNummer}{Environment.NewLine}" &
- $" Logische Nummer: ({logischeNummer}){Environment.NewLine}" &
- $" Display-Name: {monitor.MonitorName}{Environment.NewLine}" &
- $" Art: {art}{Environment.NewLine}" &
- $" Skalierung: {monitor.SkalierungMaximal}%{Environment.NewLine}" &
- $" Position: ({monitor.Position.X} , {monitor.Position.Y}){Environment.NewLine}" &
- $" Logische Auflösung: {monitor.LogischeAuflösung.Width} x {monitor.LogischeAuflösung.Height}{native}{Environment.NewLine}" &
- $" Physikalische Auflösung: {monitor.PhysikalischeAuflösung.Width} x {monitor.PhysikalischeAuflösung.Height}"
- Monitor_Auswahl_MonitorNummer = monitor.MonitorNummer
- End If
- OverlayPanelsEntfernen()
- End Sub
- Private Sub AlleButtonsFarbeSetzen(Farbe As Color)
- For Each btn As Button In panelMonitore.Controls
- btn.BackColor = Farbe
- Next
- End Sub
- #End Region
- #Region "Funktionen"
- Public Function GetMonitorDetails(Monitornummer As Integer) As DisplayListe
- Dim monitorGefunden As DisplayListe = displays.FirstOrDefault(Function(m) m.MonitorNummer = Monitornummer)
- If monitorGefunden.MonitorNummer <> 0 Then ' Falls gefunden
- Return monitorGefunden
- End If
- Return New DisplayListe
- End Function
- Public Function GetNativeResolution(ByVal monitorDeviceName As String) As Size
- Dim devMode As New DEVMODE()
- devMode.dmSize = CShort(Marshal.SizeOf(devMode))
- Dim maxWidth As Integer = 0
- Dim maxHeight As Integer = 0
- Dim modeIndex As Integer = 0
- While EnumDisplaySettings(monitorDeviceName, modeIndex, devMode)
- If devMode.dmPelsWidth > maxWidth OrElse devMode.dmPelsHeight > maxHeight Then
- maxWidth = devMode.dmPelsWidth
- maxHeight = devMode.dmPelsHeight
- End If
- modeIndex += 1
- End While
- If maxWidth > 0 AndAlso maxHeight > 0 Then
- Return New Size(maxWidth, maxHeight)
- Else
- Return Size.Empty ' Fehlerfall
- End If
- End Function
- #End Region
- #Region "Overlay-Panels"
- Private Sub IdentifiziereMonitore()
- ' Button deaktivieren, um Mehrfachklicks zu verhindern
- btnAction.Enabled = False
- For i As Integer = 0 To Screen.AllScreens.Length - 1
- Dim scr As Screen = Screen.AllScreens(i)
- Dim monitorNummer As Integer = displays.Where(Function(d) d.MonitorName = scr.DeviceName).Select(Function(d) d.MonitorNummer).FirstOrDefault()
- ZeigeOverlayAufMonitor(monitorNummer)
- Next
- ' Timer initialisieren und starten
- overlayTimer = New System.Windows.Forms.Timer()
- AddHandler overlayTimer.Tick, AddressOf Timer_Tick
- overlayTimer.Interval = Overlay_AnzeigeDauer ' Dauer der Anzeige in Millisekunden
- overlayTimer.Start()
- End Sub
- Private Sub IdentifiziereMonitor(monitorNummer As Integer)
- ' Button wieder aktivieren
- btnAction.Enabled = True
- overlayTimer?.Stop()
- ' Alle OverlayPanels entfernen
- OverlayPanelsEntfernen()
- If Overlay_AnzeigenBeiMonitorClick = True Then
- ZeigeOverlayAufMonitor(monitorNummer)
- End If
- End Sub
- Private Sub ZeigeOverlayAufMonitor(monitorNummer As Integer)
- ' Alle Monitore abrufen
- Dim alleMonitore As Screen() = Screen.AllScreens
- ' Prüfen, ob die gewünschte Monitornummer existiert
- If monitorNummer > 0 AndAlso monitorNummer <= alleMonitore.Length Then
- Dim scr As Screen = alleMonitore(monitorNummer - 1) ' Array-Index ist 0-basiert
- Dim workingArea As Rectangle = scr.WorkingArea
- Dim xPos As Integer = 0
- Dim yPos As Integer = 0
- Dim echteXPos As Integer = 0
- Dim echteYPos As Integer = 0
- Dim echteWidth As Integer
- Dim echteHeight As Integer
- Dim overlay As New Form With {
- .Visible = False,
- .FormBorderStyle = FormBorderStyle.None,
- .StartPosition = FormStartPosition.Manual,
- .BackColor = Overlay_Hintergrundfarbe,
- .Opacity = Overlay_Opacity,
- .Size = New Drawing.Size(0, 0),
- .Location = New Point(xPos, yPos),
- .TopMost = True
- }
- Dim lbl As New System.Windows.Forms.Label With {
- .Text = Space(Overlay_Breite) & monitorNummer.ToString() & Space(Overlay_Breite),
- .Font = Overlay_Font,
- .ForeColor = Overlay_SchriftFarbe,
- .Dock = DockStyle.Fill,
- .TextAlign = ContentAlignment.MiddleCenter,
- .AutoSize = True
- }
- overlay.Controls.Add(lbl)
- overlay.Show()
- echteWidth = lbl.Width
- echteHeight = lbl.Height
- overlay.Size = New Size(echteWidth, echteHeight)
- Select Case Overlay_Position
- Case Overlay_Corner.LeftTop
- echteXPos = workingArea.Left + 10
- echteYPos = scr.Bounds.Top + 10
- Case Overlay_Corner.RightTop
- echteXPos = workingArea.Left + workingArea.Width - overlay.Width - 10
- echteYPos = scr.Bounds.Top + 10
- Case Overlay_Corner.LeftBottom
- echteXPos = workingArea.Left + 10
- echteYPos = scr.Bounds.Top + workingArea.Height - overlay.Height - 10
- Case Overlay_Corner.RightBottom
- echteXPos = workingArea.Left + workingArea.Width - overlay.Width - 10
- echteYPos = scr.Bounds.Top + workingArea.Height - overlay.Height - 10
- End Select
- overlay.Location = New Point(echteXPos, echteYPos)
- overlay.Visible = True
- OverlayPanels.Add(overlay)
- Else
- MessageBox.Show($"Monitor {monitorNummer} nicht gefunden.", "Fehler", MessageBoxButtons.OK, MessageBoxIcon.Error)
- End If
- End Sub
- Private Sub OverlayPanelsEntfernen()
- ' Alle OverlayPanels entfernen
- For Each p In OverlayPanels
- p.Close()
- Next
- End Sub
- Private Sub Timer_Tick(sender As Object, e As EventArgs)
- ' Alle OverlayPanels entfernen
- OverlayPanelsEntfernen()
- ' Button wieder aktivieren
- btnAction.Enabled = True
- ' Timer stoppen und aufräumen
- overlayTimer.Stop()
- overlayTimer.Dispose()
- End Sub
- #End Region
- #Region "Propertys"
- Public Property Form_Hintergrundfarbe As Color
- Get
- Return _Form_Hintergrundfarbe
- End Get
- Set(value As Color)
- _Form_Hintergrundfarbe = value
- End Set
- End Property
- Public Property MonitorDisplayManager_Fenster_Als_MonitorAuswahl As Boolean
- Get
- Return _MonitorDisplayManager_Fenster_Als_MonitorAuswahl
- End Get
- Set(value As Boolean)
- _MonitorDisplayManager_Fenster_Als_MonitorAuswahl = value
- End Set
- End Property
- Public Property Monitor_Auswahl_MonitorNummer As Integer
- Get
- Return _Monitor_Auswahl_MonitorNummer
- End Get
- Set(value As Integer)
- _Monitor_Auswahl_MonitorNummer = value
- End Set
- End Property
- Public Property OK_Button_Pressed As Boolean
- Get
- Return _OK_Button_Pressed
- End Get
- Set(value As Boolean)
- _OK_Button_Pressed = value
- End Set
- End Property
- Public Property Monitor_Panel_Hintergrundfarbe As Color
- Get
- Return _Monitor_Panel_Hintergrundfarbe
- End Get
- Set(value As Color)
- _Monitor_Panel_Hintergrundfarbe = value
- End Set
- End Property
- Public Property Monitor_Buttons_Font As Font
- Get
- Return _Monitor_Buttons_Font
- End Get
- Set(value As Font)
- _Monitor_Buttons_Font = value
- End Set
- End Property
- Public Property Monitor_Buttons_Schriftfarbe As Color
- Get
- Return _Monitor_Buttons_Schriftfarbe
- End Get
- Set(value As Color)
- _Monitor_Buttons_Schriftfarbe = value
- End Set
- End Property
- Public Property Monitor_Buttons_Hintergrundfarbe As Color
- Get
- Return _Monitor_Buttons_Hintergrundfarbe
- End Get
- Set(value As Color)
- _Monitor_Buttons_Hintergrundfarbe = value
- End Set
- End Property
- Public Property Monitor_SelektierterButton_Hintergrundfarbe As Color
- Get
- Return _Monitor_SelektierterButton_Hintergrundfarbe
- End Get
- Set(value As Color)
- _Monitor_SelektierterButton_Hintergrundfarbe = value
- End Set
- End Property
- Public Property Action_Button_Font As Font
- Get
- Return _Action_Button_Font
- End Get
- Set(value As Font)
- _Action_Button_Font = value
- End Set
- End Property
- Public Property Action_Button_Schriftfarbe As Color
- Get
- Return _Action_Button_Schriftfarbe
- End Get
- Set(value As Color)
- _Action_Button_Schriftfarbe = value
- End Set
- End Property
- Public Property Action_Button_Hintergrundfarbe As Color
- Get
- Return _Action_Button_Hintergrundfarbe
- End Get
- Set(value As Color)
- _Action_Button_Hintergrundfarbe = value
- End Set
- End Property
- Public Property Monitor_Information_TextBox_Font As Font
- Get
- Return _Monitor_Information_Textbox_Font
- End Get
- Set(value As Font)
- _Monitor_Information_Textbox_Font = value
- End Set
- End Property
- Public Property Monitor_Information_TextBox_Schriftfarbe As Color
- Get
- Return _Monitor_Information_TextBox_Schriftfarbe
- End Get
- Set(value As Color)
- _Monitor_Information_TextBox_Schriftfarbe = value
- End Set
- End Property
- Public Property Monitor_Information_TextBox_Hintergrundfarbe As Color
- Get
- Return _Monitor_Information_TextBox_Hintergrundfarbe
- End Get
- Set(value As Color)
- _Monitor_Information_TextBox_Hintergrundfarbe = value
- End Set
- End Property
- Public Property Overlay_AnzeigenBeiMonitorClick As Boolean
- Get
- Return _Overlay_AnzeigenBeiMonitorClick
- End Get
- Set(value As Boolean)
- _Overlay_AnzeigenBeiMonitorClick = value
- End Set
- End Property
- Public Property Overlay_Font As Font
- Get
- Return _Overlay_Font
- End Get
- Set(value As Font)
- _Overlay_Font = value
- End Set
- End Property
- Public Property Overlay_Opacity As Double
- Get
- Return _Overlay_Opacity
- End Get
- Set(value As Double)
- If value > 0.1 AndAlso value <= 1 Then
- _Overlay_Opacity = value
- Else
- _Overlay_Opacity = 0.5
- End If
- End Set
- End Property
- Public Property Overlay_Position As Integer
- Get
- Return _Overlay_Position
- End Get
- Set(value As Integer)
- If value >= 0 AndAlso value < 4 Then
- _Overlay_Position = value
- Else
- _Overlay_Position = 1
- End If
- End Set
- End Property
- Public Property Overlay_AnzeigeDauer As Integer
- Get
- Return _Overlay_AnzeigeDauer
- End Get
- Set(value As Integer)
- _Overlay_AnzeigeDauer = value
- End Set
- End Property
- Public Property Overlay_Breite As Integer
- Get
- Return _Overlay_Breite
- End Get
- Set(value As Integer)
- If value >= 0 AndAlso value < 6 Then
- _Overlay_Breite = value
- Else
- _Overlay_Breite = 1
- End If
- End Set
- End Property
- Public Property Overlay_SchriftFarbe As Color
- Get
- Return _Overlay_Schriftfarbe
- End Get
- Set(value As Color)
- _Overlay_Schriftfarbe = value
- End Set
- End Property
- Public Property Overlay_Hintergrundfarbe As Color
- Get
- Return _Overlay_Hintergrundfarbe
- End Get
- Set(value As Color)
- _Overlay_Hintergrundfarbe = value
- End Set
- End Property
- #End Region
- End Class
Den Code könnt Ihr einfach in ein neues Formular einfügen - alle benötigten Controls werden dynamisch erzeugt.
Die Form wird als Dialog mit :
aufgerufen und angezeigt.
Das Public-Array "Form_MonitorDisplayManager.Displays" beinhaltet nach dem Aufbau durch Aufruf der Public Sub: "Form_MonitorDisplayManager.MonitorArrayAufbauen" oder durch erstmaliges Öffnen des Dialogfensters die Eigenschaften aller Monitore in einer Form_MonitorDisplayManager.DisplayListe Struktur:
VB.NET-Quellcode
- Public Structure DisplayListe
- Public MonitorNummer As Integer
- Public MonitorNummerLogisch As Integer
- Public MonitorName As String
- Public MonitorArt As Integer
- Public SkalierungDetected As Integer
- Public SkalierungCalculated As Integer
- Public SkalierungMaximal As Integer
- Public LogischeAuflösung As Size
- Public PhysikalischeAuflösung As Size
- Public Position As Point
- End Structure
Mittels dieses "Displays"-Arrays könnt Ihr in Eurer Anwendung gezielt auf die Eigenschaften aller Monitore zugreifen.
Dier verwendeten Propertys sind im Script in der Region "Information zur Bedienung" beschrieben.
Die Property-Default-Werte können im Script in der Region "Variablen-Zuweisung" geändert werden.
----------------------------------------------------------------------------------------------------
Überarbeitung und Erweiterung des Codes (12.03.25 19:45Uhr):
Hi Freunde,
Ich habe den Form "Monitor Display-Manager" erweitert.
Falls mal jemand so einen Dialog braucht - hier der Code:
Erforderlich sind nur folgende zwei My.Settings-Einträge, um Form.Location und Form.Size zu speichern:
My.Settings.Form_MonitorDisplayManager_Location
My.Settings.Form_MonitorDisplayManager_Size
Zusätzlich erforderlich ist für die Nutzung dieses erweiterten "Monitor Diaplay-Manager", das "System Management" in das eigene Projekt einzubinden:
Menu "Projekt" - "Verweis hinzufügen ..." - unter "Assemblys" den Eintrag "System.Management" anhakerln - "OK"-Button aklicken.
Hinzugekommen:
Mgl. exakte Bildschirmgrössen-Anzeige in Millimeter durch Auslesen der EDID-Werte.
Information:
Die EDID-Abfrage (Extended Display Identification Data) dient dazu, Informationen über den angeschlossenen Monitor direkt aus dessen Firmware (EEPROM des Monitors) auszulesen. Die Grafikkarte fragt diese Daten beim Systemstart über das I²C-Protokoll von der DDC-Schnittstelle (Display Data Channel) des Monitors ab.
Windows speichert diese Daten und stellt sie über WMI (Windows Management Instrumentation) oder direkt über die Registry bereit.
Nur, wenn diese EDID-Werte nicht gelesen werden können (billige Graphikkarte, billiger Monitor und viele Laptops), werden im "Monitor Display-Manager" die ungenauen DPI-Berechnungen zur Ermittlung der Bildschirmabmessungen verwendet.
Zusätzliche Anzeige aus EDID-Werten (wenn möglich):
Hardware: Monitor-Hersteller-Kürzel, Produkt-Code, S/N
Sehr genaue Bildschirmabmessungen (in mm)
Pixelgrösse physikalisch, DPI physikalisch
Pixelgrösse skaliert, DPI skaliert
Neue Variable:
Bei_Öffnen_Aktuelles_Fenster_Auswählen (Boolean)
True = Selektiert beim Öffnen des Fensters den Monitor, auf welchem das Fenster geöffnet wird
False = Selektiert beim Öffnen des Fensters den primären Monitor
Neue Funktion:
Public Form_MonitorDisplayManager.GetMonitorDeviceNumberFromCursor()
Liefert die Monitornummer des Monitors, auf welchem sich der Mauszeiger befindet
Aufruf: Dim MonitorDetails as Form_MonitorDisplayManager.Displayliste
MonitorDetails = Form_MonitorDisplayManager.GetMonitorDetails(Form_MonitorDisplayManager.GetMonitorDeviceNumberFromCursor())
Den Code könnt Ihr einfach in ein neues Formular einfügen - alle benötigten Controls werden dynamisch erzeugt.
Die Form wird als Dialog mit :
aufgerufen und angezeigt.
Das Public-Array "Form_MonitorDisplayManager.Displays" beinhaltet nach dem Aufbau durch Aufruf der Public Sub: "Form_MonitorDisplayManager.MonitorArrayAufbauen" oder durch erstmaliges Öffnen des Dialogfensters die Eigenschaften aller Monitore in einer Form_MonitorDisplayManager.DisplayListe Struktur:
VB.NET-Quellcode
- Public Structure DisplayListe
- Public MonitorNummer As Integer
- Public MonitorNummerLogisch As Integer
- Public MonitorName As String
- Public MonitorArt As Integer
- Public DpiX As UInteger
- Public DpiY As UInteger
- Public SkalierungDetected As Integer
- Public SkalierungCalculated As Integer
- Public SkalierungMaximal As Integer
- Public LogischeAuflösung As Size
- Public PhysikalischeAuflösung As Size
- Public Position As System.Drawing.Point
- Public BildschirmgrössePhysikalisch As Size
- Public DPIXPhysikalisch As Double
- Public DPIYPhysikalisch As Double
- Public PixelgrössePhysikalischXMM As Double
- Public PixelgrössePhysikalischYMM As Double
- Public DPIXSkaliert As Double
- Public DPIYSkaliert As Double
- Public PixelgrösseSkaliertXMM As Double
- Public PixelgrösseSkaliertYMM As Double
- Public Berechnung As String
- Public Hardware As String
- End Structure
Mittels dieses "Displays"-Arrays könnt Ihr in Eurer Anwendung gezielt auf die Eigenschaften aller Monitore zugreifen.
Propertys:
Dier verwendeten Propertys sind im Script in der Region "Information zur Bedienung" beschrieben.
Die Property-Default-Werte können im Script in der Region "Variablen-Zuweisung" geändert werden.
Da das Script zu gross für dieses Forum ist, hier als ZIP-Anlage

Dieser Beitrag wurde bereits 16 mal editiert, zuletzt von „Dideldum“ ()