Auflösungswechsel

Gast #3593863
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
}
Gast #3594049
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?
#3594088
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.
Gast #3594234
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.
Angehängte Dateien:
Gast #3594281
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
Gast #3602304
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?
Gast #3602316
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?
#3602349
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.
Gast #3603049
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.
Gast #3603298
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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren