Forum: PC-Programmierung Auflösungswechsel


von Joel (Gast)


Lesenswert?

Hi,

ich möchte Auflösungswechsel automatisch (nach einer Zeit x) 
durchführen.
Wie kann ich unter C# (wpf) eine Auflösung einstellen? Gibt es hierfür 
eine spezielle Klasse?

Vielen Dank für Eure Vorschläge.

VG, Joel

von Timmo H. (masterfx)


Lesenswert?

[DllImport("user32.dll")]
public static extern int ChangeDisplaySettings(ref DEVMODE devMode, int 
flags);

: Bearbeitet durch User
von Joel (Gast)


Lesenswert?

Hier mein erster Versuch, funktioniert leider noch nicht.
 Mir ist nicht ganz klar, was bspw. CDS_UPDATEREGISTRY beinhalten muss.

1
using System;
2
using System.Collections.Generic;
3
using System.ComponentModel;
4
using System.Data;
5
using System.Drawing;
6
using System.Linq;
7
using System.Text;
8
using System.Windows.Forms;
9
using System.Runtime.InteropServices;
10
11
namespace ChangeResolution
12
{
13
    public partial class Form1 : Form
14
    {
15
        public Form1()
16
        {
17
            InitializeComponent();
18
        }
19
20
        private void button1_Click(object sender, EventArgs e)
21
        {
22
            aendereAufloesung(1280, 1024);
23
        }
24
25
26
        [DllImport("user32.dll")]
27
        public static extern int ChangeDisplaySettings
28
          (ref DEVMODE devMode, int flags);
29
30
31
        int DM_PELSWIDTH = 1;
32
        int DM_PELSHEIGHT = 1;
33
34
        int CDS_UPDATEREGISTRY = 1;
35
36
        private void aendereAufloesung(int breite, int hoehe)
37
        {
38
            DEVMODE dm = new DEVMODE();
39
            dm.dmSize = (short)Marshal.SizeOf(dm);
40
            dm.dmPelsWidth = breite;
41
            dm.dmPelsHeight = hoehe;
42
            dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
43
            int erg = ChangeDisplaySettings(ref dm, CDS_UPDATEREGISTRY);
44
            
45
        }
46
47
48
        public struct DEVMODE
49
        {
50
            // . . .
51
            public short dmSize;   // weitere Felder
52
            public int dmFields;   // weitere Felder
53
            public int dmPelsWidth;
54
            public int dmPelsHeight;   // weitere Felder
55
        };
56
57
    }
58
}

von Karl H. (kbuchegg)


Lesenswert?


von Joel (Gast)


Lesenswert?

Wenn ich
1
int CDS_UPDATEREGISTRY = 1;

auskommentiere, dann wird UPDATEREGISTRY als unbekannt gemeldet. In der 
Tabelle 
http://msdn.microsoft.com/en-us/library/windows/desktop/dd183411%28v=vs.85%29.aspx 
hat die Variable keinen Wert, den man festlegen muss. Also wie mache ich 
CDS_UPDATEREGISTRY bekannt?

von Joel (Gast)


Lesenswert?

Noch eine Beobachtung:


Wenn ich den ursprügnlich gezeigten Code so belasse, dann passiert gar 
nichts, wenn ich unter Visual Studio 2010 F5 drücke. Wenn ich STRG+F5 
drücke stürzt meine Applikation ab, nachdem ich den Button gedrückt 
habe.

Kann ich im Debug-Modus die ganze Klamotte gar nicht testen?

von Karl H. (kbuchegg)


Lesenswert?

Joel schrieb:
> Wenn ich
>
>
1
> int CDS_UPDATEREGISTRY = 1;
2
>
>
> auskommentiere, dann wird UPDATEREGISTRY als unbekannt gemeldet. In der
> Tabelle
> 
http://msdn.microsoft.com/en-us/library/windows/desktop/dd183411%28v=vs.85%29.aspx
> hat die Variable keinen Wert, den man festlegen muss.

Natürlich hat die einen Wert.
Die sind üblicherweise durch die Includes festgelegt. In C# ist das dann 
wohl ein entsprechendes using

> Also wie mache ich
> CDS_UPDATEREGISTRY bekannt?

Am besten machst du das selber gar nicht, sondern überlässt das einem 
using, dir die entsprechenden Konstanten zur Verfügung zu stellen.

von Karl H. (kbuchegg)


Lesenswert?

Ps.
In Google einfach mal das eingeben was man weiß

"ChangeDisplaySettings C#"

hilft einem oft weiter.

http://www.news2news.com/vfp/?example=374&ver=vcs

Gewöhn dich daran, dir Information zu ergoogeln.

von Joel (Gast)


Angehängte Dateien:

Lesenswert?

OK, habe das Beispiel mal übernommen. Ein Button "btnSet" und zwei 
Listboxen eingefügt: listSettings, listDevices.

1
using System;
2
using System.Collections.Generic;
3
using System.ComponentModel;
4
using System.Data;
5
using System.Drawing;
6
using System.Linq;
7
using System.Text;
8
using System.Windows.Forms;
9
using System.Runtime.InteropServices;
10
11
12
namespace ChangeResolution
13
{
14
    public partial class Form1 : Form
15
    {
16
17
        [StructLayout(LayoutKind.Sequential)]
18
        public struct DISPLAY_DEVICE
19
        {
20
            public int cb;
21
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
22
            public string DeviceName;
23
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
24
            public string DeviceString;
25
            public int StateFlags;
26
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
27
            public string DeviceID;
28
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
29
            public string DeviceKey;
30
31
            public DISPLAY_DEVICE(int flags)
32
            {
33
                cb = 0;
34
                StateFlags = flags;
35
                DeviceName = new string((char)32, 32);
36
                DeviceString = new string((char)32, 128);
37
                DeviceID = new string((char)32, 128);
38
                DeviceKey = new string((char)32, 128);
39
                cb = Marshal.SizeOf(this);
40
            }
41
        }
42
43
        [StructLayout(LayoutKind.Sequential)]
44
        public struct DEVMODE
45
        {
46
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
47
            public string dmDeviceName;
48
            public short dmSpecVersion;
49
            public short dmDriverVersion;
50
            public short dmSize;
51
            public short dmDriverExtra;
52
            public int dmFields;
53
            public short dmOrientation;
54
            public short dmPaperSize;
55
            public short dmPaperLength;
56
            public short dmPaperWidth;
57
            public short dmScale;
58
            public short dmCopies;
59
            public short dmDefaultSource;
60
            public short dmPrintQuality;
61
            public short dmColor;
62
            public short dmDuplex;
63
            public short dmYResolution;
64
            public short dmTTOption;
65
            public short dmCollate;
66
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
67
            public string dmFormName;
68
            public short dmUnusedPadding;
69
            public short dmBitsPerPel;
70
            public int dmPelsWidth;
71
            public int dmPelsHeight;
72
            public int dmDisplayFlags;
73
            public int dmDisplayFrequency;
74
        }
75
76
        public Form1()
77
        {
78
            InitializeComponent();
79
            EnumDevices();
80
        }
81
82
        private void listDevices_SelectedIndexChanged(
83
            object sender, EventArgs e)
84
        {
85
            int devNum = listDevices.SelectedIndex;
86
            bool isMain = MainDevice(devNum);
87
            btnSet.Enabled = isMain; // enable only for the main device
88
            EnumModes(devNum);
89
        }
90
91
        private void btnSet_Click(object sender, EventArgs e)
92
        { //set selected display mode
93
            int devNum = listDevices.SelectedIndex;
94
            int modeNum = listSettings.SelectedIndex;
95
            DEVMODE d = GetDevmode(devNum, modeNum);
96
            if (d.dmBitsPerPel != 0 & d.dmPelsWidth != 0
97
                & d.dmPelsHeight != 0)
98
            {
99
                ChangeDisplaySettings(ref d, 0);
100
            }
101
        }
102
103
        private void EnumModes(int devNum)
104
        {
105
            listSettings.Items.Clear();
106
107
            string devName = GetDeviceName(devNum);
108
            DEVMODE devMode = new DEVMODE();
109
            int modeNum = 0;
110
            bool result = true;
111
            do
112
            {
113
                result = EnumDisplaySettings(devName,
114
                    modeNum, ref devMode);
115
116
                if (result)
117
                {
118
                    string item = DevmodeToString(devMode);
119
                    MessageBox.Show("hallo");
120
                    listSettings.Items.Add(item);
121
                }
122
                modeNum++;
123
            } while (result);
124
125
            if (listSettings.Items.Count > 0)
126
            {
127
                DEVMODE current = GetDevmode(devNum, -1);
128
                int selected = listSettings.FindString(
129
                    DevmodeToString(current));
130
                if (selected >= 0)
131
                    listSettings.SetSelected(selected, true);
132
            }
133
        }
134
135
        private DEVMODE GetDevmode(int devNum, int modeNum)
136
        { //populates DEVMODE for the specified device and mode
137
            DEVMODE devMode = new DEVMODE();
138
            string devName = GetDeviceName(devNum);
139
            EnumDisplaySettings(devName, modeNum, ref devMode);
140
            return devMode;
141
        }
142
143
        private string DevmodeToString(DEVMODE devMode)
144
        {
145
            return devMode.dmPelsWidth.ToString() +
146
                " x " + devMode.dmPelsHeight.ToString() +
147
                ", " + devMode.dmBitsPerPel.ToString() +
148
                " bits, " +
149
                devMode.dmDisplayFrequency.ToString() + " Hz";
150
        }
151
152
        private void EnumDevices()
153
        { //populates Display Devices list
154
            this.listDevices.Items.Clear();
155
            DISPLAY_DEVICE d = new DISPLAY_DEVICE(0);
156
157
            int devNum = 0;
158
            bool result;
159
            do
160
            {
161
                result = EnumDisplayDevices(IntPtr.Zero,
162
                    devNum, ref d, 0);
163
164
                if (result)
165
                {
166
                    string item = devNum.ToString() +
167
                        ". " + d.DeviceString.Trim();
168
                    if ((d.StateFlags & 4) != 0) item += " - main";
169
                    this.listDevices.Items.Add(item);
170
                }
171
                devNum++;
172
            } while (result);
173
        }
174
175
        private string GetDeviceName(int devNum)
176
        {
177
            DISPLAY_DEVICE d = new DISPLAY_DEVICE(0);
178
            bool result = EnumDisplayDevices(IntPtr.Zero,
179
                devNum, ref d, 0);
180
            return (result ? d.DeviceName.Trim() : "#error#");
181
        }
182
183
        private bool MainDevice(int devNum)
184
        { //whether the specified device is the main device
185
            DISPLAY_DEVICE d = new DISPLAY_DEVICE(0);
186
            if (EnumDisplayDevices(IntPtr.Zero, devNum, ref d, 0))
187
            {
188
                return ((d.StateFlags & 4) != 0);
189
            } return false;
190
        }
191
192
        [DllImport("User32.dll")]
193
        private static extern bool EnumDisplayDevices(
194
            IntPtr lpDevice, int iDevNum,
195
            ref DISPLAY_DEVICE lpDisplayDevice, int dwFlags);
196
197
        [DllImport("User32.dll")]
198
        private static extern bool EnumDisplaySettings(
199
            string devName, int modeNum, ref DEVMODE devMode);
200
201
        [DllImport("user32.dll")]
202
        public static extern int ChangeDisplaySettings(
203
            ref DEVMODE devMode, int flags);  
204
205
206
    }
207
}



Wenn ich die Forms-Anwendung starte, ist die listDevices gefüllt, die
listSettings bleibt jedoch leer, siehe Anhang.

von bluppdidupp (Gast)


Lesenswert?

MS hat für C# auch hier ein Beispiel (mit leicht anderem Einsatzzweck):
http://msdn.microsoft.com/en-us/library/ms812499.aspx
siehe auch:
http://pinvoke.net/default.aspx/user32/ChangeDisplaySettings.html
http://pinvoke.net/default.aspx/user32/ChangeDisplaySettingsFlags.html

CDS_UPDATEREGISTRY(=1) wird nur benötigt, wenn die geänderte Auflösung 
auch z.B. nach Neustart beibehalten werden soll. Für temporäre Änderung 
der Auflösung reicht es einfach 0(CDS_NONE) zu übergeben.
Die Definition von CDS_UPDATEREGISTRY wie im 3. Post ist schon korrekt.

Die Werte für DM_PELSWIDTH(=0x80000) und DM_PELSHEIGHT(=0x100000) im 
Code ganz oben sind allerdings falsch ;D

von bluppdidupp (Gast)


Lesenswert?

In EnumModes() hast du dmSize nicht gesetzt (dmDriverExtra=0 würde ich 
auch setzen)

von Joel (Gast)


Lesenswert?

Vielen Dank für Eure Hinweise.

von Joel (Gast)


Lesenswert?

Eine Frage noch:

Wie kriege ich es hin, auch noch die Auflösung eines zweiten Bildschirms 
zu ändern?


Joel

von bluppdidupp (Gast)


Lesenswert?

Bei ChangeDisplaySettingsEx() kann das Display mit angegeben werden.

von Joel (Gast)


Lesenswert?

Vielen Dank

von Joel (Gast)


Lesenswert?

Wenn mir schon mal dabei sind: Versuche über


DEVMODE dm = new DEVMODE();
dm.dmDisplayFrequency = 30;


die Bildwiederholrrate zu ändern, jedoch ohne Erfolg. Muss ich hier noch 
zusätzlich etwas beachten?

von Joel (Gast)


Lesenswert?

Habe bislang folgendes eingestellt:

int DM_PELSWIDTH = 0x80000;
int DM_PELSHEIGHT = 0x100000;

dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;



1. Wie kommt man überhaupt auf die Werte? Wo finde ich die?

2. Wie finde ich heraus, wie DM_DISPLAYFREQUENCY eingestellt werden 
muss?

von Andreas D. (rackandboneman)


Lesenswert?

"ich möchte Auflösungswechsel automatisch (nach einer Zeit x) 
durchführen"

Frage hiermit neugierig was damit bezweckt werden soll... wenn das 
PC-Software (ausser vielleicht ein Spiel, ein Monitor-Utility oder etwas 
für einen Embedded-PC) werden soll machst Du Dich damit bei Nutzern und 
Administratoren sehr schnell sehr unbeliebt. In seltenen Fällen 
(CRT-Monitore) kannst Du damit sogar bleibenden Schaden anrichten. Und 
wenn Du jemand irrtümlich eine Auflösung einstellst mit der sein Monitor 
nicht klarkommt wird er Dich verwünschen.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Joel schrieb:
> 1. Wie kommt man überhaupt auf die Werte? Wo finde ich die?

Die stehen in einer zum Windows-SDK gehörenden Headerdatei. Die wird 
wiederum eingebunden, wenn man "#include <windows.h>" in sein Programm 
schreibt und der Include-Pfad das Windows-SDK enthält.

von Joel (Gast)


Lesenswert?

OK, habe es gefunden in "WinGDI.h".


Ich schreibe also folgendes:


int DM_PELSWIDTH = 0x80000;
int DM_PELSHEIGHT = 0x100000;
int DM_DISPLAYFREQUENCY = 0x00400000;


....


dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
dm.dmFields |= DM_DISPLAYFREQUENCY;
dm.dmDisplayFrequency = 30;


Rufe ChnageDisplaySettings auf. Es werden jedoch keine 30Hz eingestellt.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Tja, vielleicht können nur Frequenzen eingestellt werden, die auch von 
der Hardware und dem verwendeten Devicetreiber überhaupt unterstützt 
werden?

von Andreas D. (rackandboneman)


Lesenswert?

Es gibt doch durchaus Utilities ala Powerstrip im Netz, und sicher auf 
einíge die quelloffen sind... da kann man sich sicher einiges abschauen.

von bluppdidupp (Gast)


Lesenswert?

Ich meine die DEVMODE-Struktur wird mehr oder weniger zum Treiber 
durchgereicht und der kann dann in der Tat entscheiden ob er damit klar 
kommt oder nicht.

Das einfachste wäre natürlich mit EnumDisplaySettingsEx() vorher zu 
schauen, welche Modi unterstützt werden und davon den Passendsten zu 
wählen ;D

von Joel (Gast)


Lesenswert?

Ok, Ihr habt natürlich Recht. Ich kann durchaus unterschiedliche 
Bildwiederholraten einstellen, natürlich nur solche, die auch 
unterstützt werden!

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.