Entwickler-Ecke

Windows API - DWM neustarten


Martok - Fr 09.05.14 22:20
Titel: DWM neustarten
Moin!

Wenn man über die (immer spärlicher werdenden) Darstellungsoptionen von Windows etwas ändert und das übernimmt, initialisiert Windows den DWM neu. Das ist das, was man mit diesem Fullscreen-"Einen Moment Geduld bitte" vermittelt bekommt.

Wie kann ich das selber auslösen?

Viele Grüße,
Martok


jaenicke - Sa 10.05.14 09:05

Ich glaube wenn das ginge, würden nicht so viele Tools mit Tricks arbeiten und die dwm.exe abschießen oder ähnliches...

Da es in der offiziellen API des DWM soweit ich das sehe keinen Weg dafür gibt, wird es Tricks dafür vermutlich ohnehin nur für einzelne Windowsversionen geben. Insofern ist der unsaubere Weg wohl eine Überlegung wert: Einfach den dwm abschießen... taskkill /f /im dwm.exe...


Delete - Sa 10.05.14 12:44

Zitat:
In Windows 8, Desktop Window Manager (DWM) is always ON and cannot be disabled by end users and apps. As in Windows 7, DWM is used to compose the desktop. In addition to experiences enabled in Windows 7, now DWM desktop composition enables desktop composition for all themes, support for Stereoscopic 3D, and management, separation, and protection of the experience with Windows Store apps.

http://msdn.microsoft.com/en-us/library/windows/desktop/hh848042%28v=vs.85%29.aspx

RedrawWindow function
http://msdn.microsoft.com/en-us/library/windows/desktop/dd162911%28v=vs.85%29.aspx

IShellView::Refresh method
http://msdn.microsoft.com/en-us/library/windows/desktop/bb774836%28v=vs.85%29.aspx

How to Refresh Desktop and Windows Explorer?
http://social.msdn.microsoft.com/Forums/en-US/357bcf9a-58ab-42f9-9a1d-70d1f146238a/how-to-refresh-desktop-and-windows-explorer?forum=vblanguage

Ist hier was Brauchbares dabei?
http://www.swissdelphicenter.ch/de/showcode.php?id=1054

Zum Testen:


Delphi-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:
function GetDesktopHandle: HWND;
var
 S : String;
begin
 Result := FindWindow('ProgMan'nil);
 Result := GetWindow(Result, GW_CHILD);
 Result := GetWindow(Result, GW_CHILD);
 SetLength(S, 40);
 GetClassName(Result, PChar(S), 39);
  if PChar(S) <> 'SysListView32' then Result := 0;
end;

procedure RefreshDesktop;
begin
 PostMessage(GetDesktopHandle, WM_KEYDOWN, VK_F5, 0);
 PostMessage(GetDesktopHandle, WM_KEYUP, VK_F5, 1 shl 31);
 SendMessage(GetDesktopHandle, WM_COMMAND, $A0650);
 InvalidateRect(GetDesktopHandle, nil, True);
end;

procedure TForm2.Button5Click(Sender: TObject);
begin
   RefreshDesktop;
end;


Martok - Sa 10.05.14 19:08

user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Insofern ist der unsaubere Weg wohl eine Überlegung wert: Einfach den dwm abschießen... taskkill /f /im dwm.exe...
Hm. Ich hab das mal probiert, reicht aber nicht für alles. Teilweise gehts nur mit Neuanmeldung - das was Windows da selber macht braucht aber keine. Ich mein, ich könnte da ja mal den ProcessMonitor draufwerfen, aber das artet ja in Arbeit aus :lol:

@Hathor: weißt du zufällig, ob das auch den Explorer zu einem "realign mal deine Icons" veranlassen kann?


jaenicke - Sa 10.05.14 20:44

user profile iconMartok hat folgendes geschrieben Zum zitierten Posting springen:
Ich mein, ich könnte da ja mal den ProcessMonitor draufwerfen, aber das artet ja in Arbeit aus :lol:
Du meinst wohl eher den API Monitor. ;-)


Delete - Sa 10.05.14 20:54

Man kann das hier
http://www.swissdelphicenter.ch/de/showcode.php?id=1054
beliebig erweitern - siehe Anhang...


Martok - Sa 10.05.14 22:23

user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconMartok hat folgendes geschrieben Zum zitierten Posting springen:
Ich mein, ich könnte da ja mal den ProcessMonitor draufwerfen, aber das artet ja in Arbeit aus :lol:
Du meinst wohl eher den API Monitor. ;-)
Joa, den auch ;) Ich hätt jetzt ProcMon gemeint wegen IO + "Irgendwas passiert mit dem Prozess".

user profile iconhathor hat folgendes geschrieben Zum zitierten Posting springen:
Man kann das hier
http://www.swissdelphicenter.ch/de/showcode.php?id=1054
beliebig erweitern - siehe Anhang...
Hihi, ja, um diesen Key geht es unter anderem. SPI_SETNONCLIENTMETRICS ist ein gutes Stichwort, danke!

Oh. SystemParametersInfo kann mittlerweile schreiben - "Upps" :D


jaenicke - So 11.05.14 09:43

Vielleicht fehlt auch nur ein WM_THEMECHANGED oder WM_DWMCOLORIZATIONCOLORCHANGED danach, wenn es nicht gleich greift?


Martok - Fr 16.05.14 15:10

So, Thread mal wieder aufwärmen: SystemParamtersInfo() ist leider so verbuggt, dass man die nicht gefahrlos nutzen kann - einige Werte werden nicht richtig gelesen, wenn man die Structs dann wieder zurückschreibt kommen komische Dinge raus. Muss man also über die Registry direkt machen.

Nur die Messages broadcasten reicht leider nicht, obwohl ich im API Monitor auch nicht mehr gesehen hab. Noch jemand Ideen?


Martok - So 18.05.14 02:07

Es scheint leider kein Weg an SystemParametersInfo vorbei zu führen - auch wenn das gefährlich sein kann [https://github.com/martok/win-tweaker/blob/master/uFrmSysParameters.pas#L12]. Muss man halt jede Einstellung testen und gucken ob etwas explodiert.


jaenicke - So 18.05.14 07:58

Das Verhalten dieser Funktion hängt von der in die Exe in den PE Header kompilierten MajorSubsystemVersion ab. Steht dort ein Wert von 5.0 drin (wie ihn z.B. Delphi XE6 standardmäßig schreibt), wird diese Exe wie eine XP Anwendung behandelt, also wird in iBorderWidth der kombinierte Wert zurückgegeben wie dies bei XP gemacht wurde:
http://objectmix.com/clipper/749482-getsystemmetrics-sm_cxpaddedborder.html

In Delphi kann man in den Projektoptionen unter Projekt --> Optionen --> Delphi-Compiler --> Linken einstellen welche Version dort geschrieben werden soll. Die Einstellung heißt:
Untersystem-Versionsfelder in PE-Header als <Haupt>.<Neben> setzen
Diese gibt es seit Delphi 2009. Vorher bleibt nur den PE Header nach dem Kompilieren manuell zu manipulieren.


Martok - So 18.05.14 15:57

user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
wird diese Exe wie eine XP Anwendung behandelt, also wird in iBorderWidth der kombinierte Wert zurückgegeben wie dies bei XP gemacht wurde:
Sind die bekloppt oder so? Dafür gebe ich doch die andere cbSize (344 statt 340) an... Es ist sogar lang und breit dokumentiert wie man diese Unterscheidung machen soll wenn man auch auf WINVER < 0600 funktionieren will (Plattform abfragen und kleinere struct angeben) - und dann wird das ignoriert?

Ich schlage dann mal SystemParametersInfo für die Am Schlechtesten Dokumentierte Funktion vor.

€: das ändert natürlich nichts daran dass es kreuzgefährlich ist dann den falschen Wert zu schreiben. Hätten sie das dann wieder auseinandergepflückt, z.B. unter der Annahme dass die PaddedBorderWidth konstant bleibt... oder einen Fehler geworfen.