Entwickler-Ecke

Windows API - ChangeDisplaySettings dreht Bildschirm


mg4all - So 19.12.10 10:25
Titel: ChangeDisplaySettings dreht Bildschirm
Hallo Leute

Ich suche hier schon eine ganze Weile herum, finde aber nichts passendes. Ich ändere mit folgendem Code die Bildschirmauflösung :


Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
function ChangeResolution(sizex, sizey, bpp: DWORD): Boolean;
var
  DeviceMode: TDeviceMode;
  i: Integer;
begin
  i := 0;
  Result := False;
  ZeroMemory(@DeviceMode, sizeof(DeviceMode));
  while EnumDisplaySettings(nil, i, DeviceMode) do begin
    with DeviceMode do
      if (dmPelsWidth = sizex) and
        (dmPelsHeight = SizeY) and
        (dmBitsPerPel = bpp) then begin
        // erst testen, bevor wir umschalten!
        case ChangeDisplaySettings(DeviceMode, CDS_TEST) of
          // es wird klappen!
          DISP_CHANGE_SUCCESSFUL:
            Result := True;

          DISP_CHANGE_RESTART:
            Showmessage('Neustart erforderlich');

          DISP_CHANGE_BADFLAGS:
            Showmessage('Ungültige Bildschirmeinstellungen');

          DISP_CHANGE_FAILED:
            Showmessage('Auflösung konnte nicht geändert werden');

          DISP_CHANGE_BADMODE:
            Showmessage('Bildschirm unterstützt diese Auflösung nicht');

          // Nur Windows NT
          DISP_CHANGE_NOTUPDATED:
            Showmessage('Registry konnte nicht aktualisiert werden');

        else
          Result := True;
        end;

        if Result then
          //jetzt wird umgeschaltet
          ChangeDisplaySettings(DeviceMode, CDS_FULLSCREEN)
      end;
    Inc(i);
  end;
end;


Unter WIN 7 auch kein Problem. Wenn ich es aber unter WIN XP ausprobiere wird der Bildschirm gedreht. Kann mir jemand helfen ?

Danke


jaenicke - So 19.12.10 12:20

Du prüfst ja auch die Orientierung nicht. Ich vermute einmal es gibt bei dir dann mehrere Einträge mit den selben Daten, aber verschiedenen Orientierungen. Und da du einfach irgendeinen nimmst, weißt du auch nicht welche genommen wird.

Ich rate einmal, dass du dmOrientation auch prüfen musst.


mg4all - So 19.12.10 12:33

Kannst du mir einen Tip geben wie ich das machen kann ?


jaenicke - So 19.12.10 12:36

Wie meinst du das? Genauso wie du die anderen Werte wie Bildschirmbreite auch prüfst. :nixweiss:

Lass dir doch erst einmal die Werte ausgeben. Dann weißt du, ob es so ist, wenn du nämlich dort nicht nur Null bekommst:

Delphi-Quelltext
1:
2:
3:
4:
5:
      if (DeviceMode.dmPelsWidth = sizex) and
        (DeviceMode.dmPelsHeight = SizeY) and
        (DeviceMode.dmBitsPerPel = bpp) then
      begin
        ShowMessage(IntToStr(Integer(DeviceMode.dmOrientation)));
Was mir auch aufgefallen ist:
Die Bildschirmfrequenz prüfst du auch nicht. Zumindest dabei gibt es meistens mehrere Möglichkeiten.


mg4all - So 19.12.10 12:42

Ja ich bekomme bei allen Auflösungen eine 0 zurück wobei die letzten beiden wieder gedreht sind.


jaenicke - So 19.12.10 13:16

Naja, dann bleibt nur zu debuggen und die restlichen Werte einmal zu vergleichen.

Da das bei Delphi 7 noch nicht per MouseOver ging, musst du glaube ich beim Haltepunkt dann DeviceMode markieren, Strg + F7 drücken und dann untersuchen oder so drücken.


mg4all - So 19.12.10 13:23

Danke erst mal für die Antworten, werde es dann später weiterprobieren. Jetzt muß ich erst einmal los.


Martok - So 19.12.10 14:58

user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Da das bei Delphi 7 noch nicht per MouseOver ging, musst du glaube ich beim Haltepunkt dann DeviceMode markieren, Strg + F7 drücken und dann untersuchen oder so drücken.
Was natürlich Quatsch ist, in Delphi 7 hat sich das MouseOver-Ding (das es seit D3 oder so gibt) lediglich leichter von with-Strukturen verwirren lassen. Das geht logischerweise erst richtig, seit es ErrorInsight gibt und ein kompletter Parse-Tree in der IDE vorgehalten wird.
Just sayin' ;)


jaenicke - So 19.12.10 15:30

user profile iconMartok hat folgendes geschrieben Zum zitierten Posting springen:
Was natürlich Quatsch ist, in Delphi 7 hat sich das MouseOver-Ding (das es seit D3 oder so gibt) lediglich leichter von with-Strukturen verwirren lassen.
Was hast du denn da für ein Addon drin? Bei mir geht das nicht. :nixweiss:

Wenn da überhaupt mal ein Hint kommt, dann kann ich da nie was ausklappen und damit auch nicht die Werte innerhalb von z.B. DisplayMode anschauen. So sieht das nach Delphi 7 aus:
Delphi_LiveHints

Und das mit with klappt auch mit XE noch nicht. Deshalb hasse ich das, wenn wieder irgendwer ein with gestreut hat und ich es debuggen muss. :roll:

// EDIT:
Bei mir kommt noch nichtmal überhaupt ein Hint, keine Ahnung ob man das noch aktivieren musste. Ausklappen ließ sich jedenfalls auf jeden Fall nix. Und bei Delphi 3 rührt sich erst recht nix.


Martok - So 19.12.10 16:05

Gut, aufklappen wirklich nicht, da braucht man noch den Debug-Inspektor für. Wobei ich sagen muss, dass mir dieses freifliegende auch nicht so gefällt, jedenfalls nicht auf meinen Bildschirmauflösungen. Und in TD2006 ist das Ding ja auch noch immer mal einfach so wieder verschwunden wenn man grade 5 Ebenen tief drin war, das hat den Spaß etwas getrübt.

Wenn die Datenstrukturen einfach genug sind, reicht aber auch das:
delphihint

user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Bei mir kommt noch nichtmal überhaupt ein Hint, keine Ahnung ob man das noch aktivieren musste. Ausklappen ließ sich jedenfalls auf jeden Fall nix. Und bei Delphi 3 rührt sich erst recht nix.
Es gibt eine Einstellung "Auswertung durch Kurzhinweis" in den Editoroptionen (Tab Programmierhilfe), aber die ist standardmäßig aktiv. :nixweiss:
Dann eben D4, das weiß ich definitiv. Ich war aber eigentlich der Meinung, sie hätten da nicht groß was am Debugger gemacht...


jaenicke - So 19.12.10 16:10

user profile iconMartok hat folgendes geschrieben Zum zitierten Posting springen:
Dann eben D4, das weiß ich definitiv.
Die Option gibts, auch in D3, passieren tut trotzdem nix. :nixweiss:

Ist ja auch egal, was ich eingangs meinte war ja gerade das Ausklappen zum Vergleich der Werte. ;-)

// EDIT:
Was mir bei dem Hint fehlt ist ein Link "Open in inspector". :mrgreen:


Tilman - So 19.12.10 16:14

@jaenicke bevor du lange rumsuchst... diese Funktion ist in D7 enthalten, aber extrem buggy. Ich glaube unter XP hat sie bei mir immer nach der Installation von Delphi so 1-2 Wochen funktioniert, dann war sie weg und ließ sich auch über die Einstellungen nicht wieder bekommen, unter Vista ging sie bei mir noch nie.


jaenicke - So 19.12.10 16:15

user profile iconTilman hat folgendes geschrieben Zum zitierten Posting springen:
Ich glaube unter XP hat sie bei mir immer nach der Installation von Delphi so 1-2 Wochen funktioniert, dann war sie weg und ließ sich auch über die Einstellungen nicht wieder bekommen, unter Vista ging sie bei mir noch nie.
Das kommt mir sehr bekannt vor. ;-)
Ich hab dann immer ein Backupimage zurückgespielt seinerzeit. :mrgreen:


mg4all - So 19.12.10 21:33

Ok Leute habe eine Lösung gefunden.

Erst mal Danke an alle für die rege Beteiligung. Ich nehme jetzt einfach die 2. funktionierende Auflösung, diese geht unter XP und WIN 7. Hier mal der geänderte Code:


Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
function ChangeResolution(sizex, sizey, bpp: DWORD): Boolean;
var
  DeviceMode: TDeviceMode;
  i: Integer;
begin
  i := 0;
  Result := False;
  ZeroMemory(@DeviceMode, sizeof(DeviceMode));
  while EnumDisplaySettings(nil, i, DeviceMode) do begin
    with DeviceMode do
      if (dmPelsWidth = sizex) and
        (dmPelsHeight = SizeY) and
        (dmBitsPerPel = bpp) then begin
        // erst testen, bevor wir umschalten!
        case ChangeDisplaySettings(DeviceMode, CDS_TEST) of
          // es wird klappen!
          DISP_CHANGE_SUCCESSFUL:
            Result := True;

          DISP_CHANGE_RESTART:
            Showmessage('Neustart erforderlich');

          DISP_CHANGE_BADFLAGS:
            Showmessage('Ungültige Bildschirmeinstellungen');

          DISP_CHANGE_FAILED:
            Showmessage('Auflösung konnte nicht geändert werden');

          DISP_CHANGE_BADMODE:
            Showmessage('Bildschirm unterstützt diese Auflösung nicht');

          // Nur Windows NT
          DISP_CHANGE_NOTUPDATED:
            Showmessage('Registry konnte nicht aktualisiert werden');

        else
          Result := True;
        end;

        if Result then
          //jetzt wird umgeschaltet
          ChangeDisplaySettings(DeviceMode, CDS_FULLSCREEN);
          if i = 1 then
          break;
      end;
    Inc(i);
  end;
end;


Thanks


jaenicke - So 19.12.10 21:42

Naja, das funktioniert dann rein zufällig auf deinem System. Bei einem System gibt es bei mir nur eine Einstellung pro Auflösung, bei einem anderen deren 4. Also was hat das für einen Sinn, es sei denn das ist ausschließlich für deine Systeme? :nixweiss:

Und die Bildschirmfrequenzen beachtest du ja gar nicht erst.


mg4all - So 19.12.10 21:45

Hast du einen anderen Tip wie ich das Problem lösen kann ?


jaenicke - So 19.12.10 22:12

Hast du denn mal geschaut was der Unterschied zwischen den beiden Einträgen ist? Du kannst auch jeweils einen Screenshot vom Inspektor machen, wenn du möchtest, dann können wir auch schauen.


mg4all - So 19.12.10 22:19

Gibt es keine andere Möglichkeit auf Vollbild zu schalten ohne den Desktop zu verändern ?


jaenicke - So 19.12.10 22:33

Was hat das eine mit dem anderen denn zu tun? :gruebel:

was hast du eigentlich vor?


mg4all - So 19.12.10 22:39

Ich schreibe ein Spiel in 1024 x 768 Auflösung und möchte dieses im Vollbild anzeigen lassen.


jaenicke - So 19.12.10 22:43

DirectX? OpenGL? Die bieten eigentlich auch entsprechende Funktionen.

Oder selbst gezeichnet? Dann skaliere es einfach auf die richtige Auflösung...


mg4all - So 19.12.10 22:45

Nee ohne alles, einfach nur 2D. Soll ein Artillery-Clone werden und wie gesagt bei mir auf dem Rechner funktioniert es jetzt unter WIN 7 und XP.


jaenicke - So 19.12.10 22:55

Aber wozu brauchst du denn dann eine bestimmte Auflösung? Ist das Spiel sonst zu langsam, wenn du es auf der realen Auflösung zeichnest?

Ohne dass du DirectX oder so verwendest wirst du kaum die Auflösung einstellen können.

Jedenfalls würde ich das Spiel sofort in die virtuelle Tonne treten, wenn es mir meine Auflösung ändern würde und damit sämtliche Einstellungen durcheinanderschmeißen würde... (Iconanordnung, Programmlayouts, ...)


mg4all - So 19.12.10 23:01

Ich möchte das das Spiel auch bei höheren Auflösungen als 1024 x 768 im Vollbildmodus angezeigt wird.


jaenicke - So 19.12.10 23:04

Ja, Formular auf WindowState wsMaximized und dann ist es Vollbild. :gruebel:

Solange das Spiel dann nicht zu langsam wird, reicht es dann die Elemente entsprechend zu skalieren. :nixweiss:


mg4all - So 19.12.10 23:12

Ja ich weiss aber genau das wollte ich vermeiden, da dann die Images alle verzerrt aussehen je höher die Auflösung ist bzw. sie werden ziemlich klein dargestellt ohne strech.


jaenicke - So 19.12.10 23:14

Wenn du das richtig zeichnest (mit StretchBlt nehme ich an?), sollte das schon ordentlich aussehen. Oder nimmst du etwa einfach mehrere TImages und bewegst die? :shock:

Und wegen der gewählten Auflösung: Was machst du dann bei den heute ja nun üblichen Widescreen-Monitoren? Die lassen sich gar nicht auf 1024x768 schalten. Egal wie du es versuchst.

Jedenfalls müsstest du wie gesagt einmal die beiden Einstellungen vergleichen, die du hast. Schließlich muss da ja ein Unterschied sein.


mg4all - So 19.12.10 23:18

Ja du hast recht ich nehme einfach mehrere TImages. Und ich habe auch einen Widescreenmonitor mit einer Auflösung von 1680 x 945 da ist das überhaupt kein Problem.


bummi - Mo 20.12.10 01:01

Machst doch gleich richtig und Dein Spiel richtest sich nach der jeweiligen Bildschirmauflösung....