[Nim] Multi-Monitor-Auswahl

  • 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?

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

  • 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:

  • 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.

  • 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-…nuser-enumdisplaymonitors

    Wo kann ich das nachlesen?

  • 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.

  • 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:


  • 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.

  • 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!