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
[DllImport("user32.dll")] public static extern int ChangeDisplaySettings(ref DEVMODE devMode, int flags);
:
Bearbeitet durch User
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 | }
|
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?
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?
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.
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.
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.
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
In EnumModes() hast du dmSize nicht gesetzt (dmDriverExtra=0 würde ich auch setzen)
Eine Frage noch: Wie kriege ich es hin, auch noch die Auflösung eines zweiten Bildschirms zu ändern? Joel
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?
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?
"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.
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.
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.
Tja, vielleicht können nur Frequenzen eingestellt werden, die auch von der Hardware und dem verwendeten Devicetreiber überhaupt unterstützt werden?
Es gibt doch durchaus Utilities ala Powerstrip im Netz, und sicher auf einíge die quelloffen sind... da kann man sich sicher einiges abschauen.
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.