2009-06-05 13 views
0

Ich versuche ChangeDisplaySettingsEx in Delphi 7 verwenden, um einen bestimmten Monitor als primäre festlegen. In Windows.pas, alsVerwenden von ChangeDisplaySettingsEx in Delphi zum primären Monitor festlegen

function ChangeDisplaySettingsEx(lpszDeviceName: PChar; var lpDevMode: TDeviceMode; 
     wnd: HWND; dwFlags: DWORD; lParam: Pointer): Longint; stdcall; 

In MSDN definiert ist, die Dokumentation für ChangeDisplaySettingsEx hat den folgenden Kommentar für LPDEVMODE meldet: „Wenn LPDEVMODE NULL ist, werden alle Werte derzeit in der Registrierung für die Anzeige verwendet werden Rahmen."

Mein Ziel ist es, den primären Monitor auf einem System mit zwei aktiven Monitoren zu ändern, ohne etwas anderes zu ändern - Auflösung, Bittiefe usw. sollten alle gleich bleiben. Es scheint, als ob lpDevMode als null (nil) übergeben wird, ist die Methode, die bereitgestellt wird, um dies zu erreichen.

Allerdings ist LpDevMode als ein gepackter Datensatztyp (TDeviceMode) definiert, kein Zeigertyp in Delphi Windows.pas. Anscheinend führt die Delphi-Schnittstelle zur Windows-API die Übersetzung in die Zeiger aus, die von der Windows-API "hinter den Kulissen" verwendet werden.

Ich habe versucht, es so nennen:

var 
    alldevs : array[0..maxdev] of TDisplayDevice; 
    lpDevMode : pointer; 

begin 
    lpDevMode := nil; 
    lparam := nil; 
    my_hwnd := nil; 

    {... snip....} 

    with alldevs[NewPri] do 
     ChangeDisplaySettingsEx(devicename,TDeviceMode(lpDevMode),my_hwnd,CDS_SET_PRIMARY,lparam); 

Das bin ich eine ungültige Typumwandlung Fehler auf "TDeviceMode (LPDEVMODE)" gibt. Wie kann ich einen Nullzeiger an ChangeDisplaySettingsEx übergeben? Oder gibt es einen besseren Weg, dies zu tun? obwohl

Antwort

1

könnten Sie

versuchen
ChangeDisplaySettingsEx(devicename, PDeviceMode(0)^, my_hwnd, CDS_SET_PRIMARY, 
    lparam); 

es zumindest auf Delphi nicht kompiliert 2009. Ich kann es nicht testen können.

Edit:

Nach den knappen Informationen im Netz (this is the most detailed I could find) die primäre Anzeige zu ändern ist kein einfacher Prozess, so dass Sie auf dem Weg einen Schritt fehlen. Ich habe zwei Monitore, aber kann das primäre Gerät überhaupt nicht ändern, nicht einmal mit dem Bedienfeld - sieht aus wie der Dual-Head-Grafikkartentreiber es nicht zulässt. Das Folgende wird daher nicht getestet, aber vielleicht hilft es Ihnen:

Um eine neue primäre Anzeige einzustellen, müssen Sie zuerst die aktuelle primäre Anzeige von der Position (0, 0) wegbewegen. Das ist komplizierter, als es sein muss, da die Delphi-Datei Windows.pas einen unvollständigen TDeviceMode-Typ aufweist. Es wird angegeben, wie

_devicemodeA = record 
    dmDeviceName: array[0..CCHDEVICENAME - 1] of AnsiChar; 
    ... 
    dmOrientation: SHORT; 
    dmPaperSize: SHORT; 
    dmPaperLength: SHORT; 
    dmPaperWidth: SHORT; 
    dmScale: SHORT; 
    dmCopies: SHORT; 
    dmDefaultSource: SHORT; 
    dmPrintQuality: SHORT; 
    dmColor: SHORT; 
    ... 
end; 

, wenn es statt

_devicemodeA = record 
    dmDeviceName: array[0..CCHDEVICENAME - 1] of AnsiChar; 
    ... 
    case boolean of 
    FALSE: (
     dmOrientation: SHORT; 
     dmPaperSize: SHORT; 
     dmPaperLength: SHORT; 
     dmPaperWidth: SHORT; 
     dmScale: SHORT; 
     dmCopies: SHORT; 
     dmDefaultSource: SHORT; 
     dmPrintQuality: SHORT; 
    ); 
    TRUE: (
     dmPosition: TPoint; 
     dmDisplayOrientation: DWORD; 
     dmDisplayFixedOutput: DWORD; 
    ); 
    dmColor: SHORT; 
    ... 
end; 

sollten Sie sollten den festen Satztyp zu Ihren Quellen hinzuzufügen, wie Sie dmPosition müssen den Ursprung der Displays anzupassen. Es soll in etwa so gehen:

// get current display settings 
EnumDisplaySettings(PChar(AOldPrimaryDevice), ENUM_REGISTRY_SETTINGS, DevMode1); 
EnumDisplaySettings(PChar(ANewPrimaryDevice), ENUM_REGISTRY_SETTINGS, DevMode2); 

// move old primary display to new position 
DevMode1.dmFields := DM_POSITION; 
DevMode1.dmPosition.x := DevMode2.dmPelsWidth; 
DevMode1.dmPosition.y := 0; 
Win32Check(ChangeDisplaySettingsEx(PChar(AOldPrimaryDevice), DevMode1, 0, 
    CDS_UPDATEREGISTRY or CDS_NORESET, nil)): 

// move old secondary display to (0, 0) and make the primary display 
DevMode2.dmFields := DM_POSITION; 
DevMode2.dmPosition.x := 0; 
DevMode2.dmPosition.y := 0; 
Win32Check(ChangeDisplaySettingsEx(PChar(ANewPrimaryDevice), DevMode2, 0, 
    CDS_SET_PRIMARY or CDS_UPDATEREGISTRY or CDS_NORESET or DM_DISPLAYFLAGS, nil)): 

// magic ??? 
Win32Check(ChangeDisplaySettingsEx(nil, PDeviceMode(0)^, 0, 0, nil)); 
+0

Danke für den Vorschlag. Das kompiliert, aber es funktioniert nicht wirklich. ChangeDisplaySettingsEx gibt 0 (Erfolg) zurück, aber der primäre Monitor bleibt unverändert. – tim11g

+0

mghie - danke für die detaillierten Informationen. Ich wusste nicht, dass ich die Anzeigeursprünge anpassen musste, bevor ich das Primärgerät einstellte. Ich kann das Problem jetzt nicht lösen, aber wenn ich das tue, lasse ich Sie wissen und poste hier einen funktionierenden Code. – tim11g

0

ich es nicht überprüft haben, aber es gibt einen Eintrag in den MSDN forums, die diese abdeckt und C++ Code. Der "primäre" Monitor ist der an der Position 0,0, Sie müssen also die Positionen der Monitore neu anordnen, um dies zu ermöglichen.

0

Das sind meine Ergebnisse nach dem Durchsuchen zahlreicher C++ - und Delphi-Beiträge im Internet.

  • wollte keinen neuen TMyDevMode Typ mit Union Optionen für fehlende Felder
  • Verwendung bestehender TDevMode Typ, aber gesetzt fehlenden Felder mit Move() memcopy Befehl und 32bit unterzeichnet temporäre Variable
  • Abrücken aktuellen primären erklären Desktop von 0,0 pos, gelten nicht Änderungen noch
  • setzen neue aktuelle primäre Desktop auf 0,0 mit CDS_SET_PRIMARY Flagge, gelten nicht Änderungen noch
  • xy-Position und Breite, Höhe nicht überlappen sollten, aber es scheint, Win7 kann einige Probleme selbst beheben
  • Aufruf ChangeDisplaySettingsEx mit null Parameter alle ausstehenden Änderungen

Set dmPosition.x und dmPosition.y Werte anzuwenden, verwenden Speicher-Offset:

var dm: TDevMode; 
var tempx, tempy: Integer; 
Move(tempx, dm.dmOrientation, sizeOf(tempx)); 
Move(tempy, dm.dmPaperLength, sizeOf(tempy)); 

Get dmPosition.x und dmPosition.y Werte, Verwenden Sie Speicher-Offset:

var dm: TDevMode; 
var tempx, tempy: Integer; 
Move(dm.dmOrientation, tempx, sizeOf(tempx)); 
Move(dm.dmPaperLength, tempy, sizeOf(tempy)); 

Legen Sie primären Desktop von Display1 zu Display2-Instanz. Nehmen Sie Änderungen vor und wenden Sie alle anstehenden Änderungen an:

flags := CDS_UPDATEREGISTRY or CDS_NORESET; 
ChangeDisplaySettingsEx('\\.\DISPLAY1', devMode1, 0, flags, nil); 
flags := CDS_UPDATEREGISTRY or CDS_SET_PRIMARY or CDS_NORESET; 
ChangeDisplaySettingsEx('\\.\DISPLAY2', devMode2, 0, flags, nil); 
ChangeDisplaySettingsEx(nil, PDeviceMode(0)^, 0, 0, nil); 
Verwandte Themen