[Nim] Multi-Monitor-Auswahl

    • Offizieller Beitrag

    Probiers mal mit EnumMonitors

    Diese Funktion existiert und ist zu finden in der Datei:

    C:\Users\USER\.nimble\pkgs\winim-3.3.0\winim\inc\winspool.nim

    Habs jetzt nicht probiert, ob sie mit import winim verfügbar ist. Ansonsten sollte es auch gehen mit import winim\inc\winspool.nim

    • Offizieller Beitrag

    Was ich brauche, ist EnumDisplayMonitors. Gefunden habe ich das auch schon in winuser.nim.

    Laut MSDN brauche ich:

    Code
    BOOL EnumDisplayMonitors(
      HDC             hdc,
      LPCRECT         lprcClip,
      MONITORENUMPROC lpfnEnum,
      LPARAM          dwData
    );

    Als Aufruf für alle Monitore:

    Code
    EnumDisplayMonitors(NULL, NULL, MyInfoEnumProc, 0);  

    Wobei "MyInfoEnumProc" ein Pointer auf eine Callback-Function (MONITORENUMPROC) ist.

    Dort bekomme ich einen Pointer auf eine RECT-Struktur, zu jedem angeschlossenen Monitor.

    Leider finde ich keinen Nim-Beispielcode dafür.

    In AutoIt habe ich sowas schonmal geschrieben:

    Kann mir jemand mit Nim behilflich sein?

    • Offizieller Beitrag

    Technisch sollte es so funktionieren. Den Callback musst du ja nicht initialisieren. Die Funktion erwartet nur eine Callbackfunktion vom Typ "MONITORENUMPROC" (winuser.nim, #4083)

    • Offizieller Beitrag

    Klasse! Mit dieser Vorlage habe ich die Daten auslesen können.

    Ich hab's noch etwas abgeändert, so dass ich die benötigten Werte in einem Array habe:

    BugFix : Vielen Dank für Deine Hilfe! :):thumbup:

    • Offizieller Beitrag

    Klasse! Mit dieser Vorlage habe ich die Daten auslesen können.

    Freut mich, wenn ich helfen konnte.

    Das coole daran, wenn man sich gemeinsam eine neue Sprache aneignet: Der Lerneffekt ist für beide da. :theke:

    Ich hatte erst mal verschiedene Varianten ausprobiert um die Datei sauber einzubinden, bis ich endlich die optimale Syntax gefunden habe. - Wieder was gelernt. ;)

    Inzwischen habe ich mir angewöhnt mit "Suche in Dateien" (Startpunkt: .nimble) Begriffs- oder Funktionserklärungen zu suchen. Das ist recht effektiv.

  • Ihr seid ja ein wirklich gutes Team... ;)

    Ich habe es etwas geändert, damit auch hMonitor übergeben und die Ausgabe formatiert wird.

    • Offizieller Beitrag

    Den Desktop-DC braucht man schon, damit die Werte relativ zum primären Monitor sind.

    Ansonsten kannst Du evtl. benötigte Fenster nicht auf die anderen Monitore verschieben.

    Mit "hDC = 0" sind die Werte relativ zum virtuellen Desktop (immer positiv).

    Ich habe mein Programm noch etwas kommentiert und das Monitor-Handle mit abgespeichert:

  • Den Desktop-DC braucht man schon, damit die Werte relativ zum primären Monitor sind.

    Ansonsten kannst Du evtl. benötigte Fenster nicht auf die anderen Monitore verschieben.

    Mit "hDC = 0" sind die Werte relativ zum virtuellen Desktop (immer positiv).

    Hm, die Werte sind bei mir identisch, egal ob mit oder ohne DC.

    Code
    EnumDisplayMonitors(0, nil, lpfnenum, data)
    ----------------------------------------------------------------
    Display 0: 0x0000000000010001,      0,      0,   1920,   1080
    Display 1: 0x0000000000010003,  -1920,      0,      0,   1080
    ----------------------------------------------------------------
    dcScreen = GetDC(0)
    EnumDisplayMonitors(dcScreen, nil, lpfnenum, data)
    Display 0: 0x0000000000010001,      0,      0,   1920,   1080
    Display 1: 0x0000000000010003,  -1920,      0,      0,   1080
    ----------------------------------------------------------------

    Hier finde ich zumindest nichts zu 'relativ': https://docs.microsoft.com/en-us/windows/…displaymonitors

    Wo kann ich das nachlesen?

    • Offizieller Beitrag

    Hm, die Werte sind bei mir identisch, egal ob mit oder ohne DC.

    Hmm...Du hast recht.

    Irgendwie hatte ich bei meinen Tests da mal andere Werte. Ich weiß aber nicht mehr, was ich da gerade ausprobiert hatte.

    Jetzt bekomme ich hier auch die gleichen Werte (egal, ob mit oder ohne DC).

    Na gut, dann geht es also noch kürzer. Ich ändere mein obiges Beispiel.

    Danke! :):thumbup:

  • Jetzt noch GetMonitorInfo hinzufügen, um rcWork und dwFlags zu bekommen, dann wäre es perfekt... 8o

    rcMonitorwird benötigt , wenn ein Fenster maximiert ist, wenn nicht, dann rcWork.

    • Offizieller Beitrag

    Ich hab's noch etwas abgeändert, so dass ich die benötigten Werte in einem Array habe

    Array ist hier zu unflexibel (Datentypen kann man nicht mixen), wozu gibt es Objekte? 8o

    Und die steckst du dann in eine Sequenz von Objekten:

    • Offizieller Beitrag

    Mal noch eine Frage zur Funktion selbst.

    Ich hatte die Funktion "EnumDisplayMonitors" so verstanden, dass alle angeschlossenen physikalischen Monitore erkannt werden. Das stimmt aber nicht mit meinen Ergebnissen überein:

    • Monitor 2 ist gespiegelt angeschlossen: wird nicht erkannt

    • Monitor 2 ist erweitert angeschlossen: wird erkannt

    Insofern denke ich, dass der DC wohl doch übergeben werden muss. Ich werde das nochmal testen.

    EDIT: Ändert nichts, ob mit oder ohne DC. Es werden ausschliesslich erweiterte Monitore erkannt. Wenn das der Sinn der Funktion ist, ist es OK - hatte ich nur anders erwartet.

    • Offizieller Beitrag

    Array ist hier zu unflexibel (Datentypen kann man nicht mixen), wozu gibt es Objekte?

    Wow! Ja, so ist es natürlich noch besser! :thumbup:


    Monitor 2 ist gespiegelt angeschlossen: wird nicht erkannt

    Wenn Du mit "gespiegelt" dupliziert meinst, dann muss der Monitor ja auch nicht erkannt werden.

    Ich denke, das ist so gewollt.

    • Offizieller Beitrag

    Array ist hier zu unflexibel (Datentypen kann man nicht mixen), wozu gibt es Objekte?

    So habe ich wenigstens gleich auch verstanden, wie man ein Array von Objekten erstellt.

    Und weil ich für mein Projekt sowieso eher die Position und die Größe der Monitore brauche, habe ich das mal dahin umgestellt:

  • Ich verstehe jetzt nicht so ganz, was Du mir damit sagen willst!?

    Nun, ich dachte erst, weil du ja hier pos und size als int deklariert hast...

    Code
    type oMonitor = object
      hMon: HMONITOR
      pos: (int, int)
      size: (int, int)

    dass es unnötig ist, hier auch noch mal nach int zu konvertieren...

    Code
      aDispInfo.add(
        oMonitor(hMon: hMonitor,
                pos: (int(rect.left), int(rect.top)),
                size: (int(rect.right - rect.left), 
                       int(rect.bottom - rect.top))
                ))

    bis ich es dann getestet habe...

    Code
    ...
    import typetraits
    ...
    echo "rect.left = " & $rect.left.type.name
    ==>> rect.left = LONG

    und da kam dann das "aha" bei mir... deshalb!