![]() |
Windows 7 Theme wechseln
Ich würde gerne aus meinem Delphi-Programm das aktuell verwendete Windows Design Theme ändern können.
Also beispielsweise auf C:\Windows\Resources\Themes\architecture.theme umschalten. Unter XP gab's ja noch spezielle ThemeManager-Schnittstellen dafür, unter Win7/Vista finde ich jedoch leider nichts dazu. Die einfachste Methode ist wohl, die Theme-Datei direkt auszuführen:
Delphi-Quellcode:
.
ShellExecute(0, 'open', PChar('C:\Windows\Resources\Themes\architecture.theme'), nil, nil, SW_SHOWNORMAL);
Dann wird das Design auch tatsächlich sofort übernommen. Allerdings öffnet sich dabei leider auch die Theme-Verwaltung von Windows, die noch manuell geschlossen werden muss. Gibt es eine bessere Möglichkeit, um Themes unter Windows 7 direkt aktivieren zu können? Oder lässt sich das Öffnen der Themes-Verwaltung unterbinden? Oder notfalls irgendwie gezielt, schnell automatisch schließen? |
AW: Windows 7 Theme wechseln
Ich denke, dass Dir die System-Funkton "SetSystemVisualStyle" weiterhelfen wird. Auf den ersten Blick scheint die aber ... "unterdurchschnittlich" ... dokumentiert zu sein.
Google liefert Dir aber eine Handvoll Treffer, u.a. auch ![]() |
AW: Windows 7 Theme wechseln
Hm, ich habe mich jetzt eine Weile über die empfohlene Funktion SetSystemVisualStyle eingelesen. In allen Beispielen wurde diese aber verwendet, um eine .msstyles Datei zu aktivieren, nicht eine .theme Datei. Diese .msstyles-Dateien wurden aber soweit ich weiß nur XP verwendet. Zumindest finde ich in meinem Win7 keine .msstyles-Dateien (doch genauer gesagt exakt eine "aero.msstyles", aber da sehe ich erstmal keinen Bezug zu den vielen vorhandenen .theme Dateien.)
Habe jetzt trotzdem mal versucht, was die Funktion unter Win7 mit einer .theme Datei bewirkt:
Delphi-Quellcode:
Als Rückgabewert erhalte ich -1878589247, was mir leider nichts sagt. Bewirken tut die Funktion augenscheinlich auch nichts.
function SetSystemVisualStyle(pszFilename, pszColor, pszSize: PChar;
dwReserved: Integer): Integer; stdcall; external 'uxtheme.dll' index 65; res := SetSystemVisualStyle('C:\Windows\Resources\Themes\nature.theme', 'NormalColor', 'NormalSize', 1); |
AW: Windows 7 Theme wechseln
Zitat:
Wenn es tatsächlich keine direkte Lösung geben sollte, würde mich mich mittlerweile auch mit einem manuellen Schließen des Theme-Fensters begnügen. Leider bekomme ich das auch nicht so recht hin... Das Problem ist, dass beim Aufrufen eines cpl-Fensters in nachfolgender Form kein passendes Handle zurückgeliefert wird. Hier mal aufs Nötigste heruntergebrochen:
Delphi-Quellcode:
Wird zwar geöffnet aber nicht wieder geschlossen. Vermutlich gehört das zurückgegebene Handle zu rundll32.exe oder einem anderen aufrufenden Prozess.
h := ShellExecute(0, 'open', PChar('C:\Windows\system32\desk.cpl'), nil, nil, SW_SHOWNORMAL);
sleep(5000); PostMessage(h, WM_CLOSE, 0, 0); Ich könnte das Handle nachträglich per FindWindow holen, aber dafür muss ich den Fenstertitel festlegen, der aber sprachabhängig ist und ich kann keine bestimmte Sprache vorab voraussetzen. |
AW: Windows 7 Theme wechseln
Der Artikel bringt vielleicht etwas Licht ins Dunkel bei den .THEME-Dateien:
![]() Das sind wohl eigentlich INI-Dateien, wo zwar auf die Aero.msstyles verwiesen wird, aber auch noch andere Infos, wie Bildschirmhintergrund und Mauszeiger festgelegt werden. Vielleicht ist Dir das ja noch ein Ansatzpunkt, Deine Suche noch mal in eine andere Richtung zu gestalten? Irgendwie müsste das ja bestimmt gehen... :) |
AW: Windows 7 Theme wechseln
Argh, lies doch bitte mal die Dokumentation, was ShellExecute für einen Wert zurück gibt.
Suche mit FindWindow das Fenster und Sende an das gefundene Handle die WM_CLOSE Nachricht. |
AW: Windows 7 Theme wechseln
Zitat:
Zitat:
Zitat:
|
AW: Windows 7 Theme wechseln
Dann starte den Prozess mit CreateProcess oder ShellExecuteEx, dann hast du ein Prozesshandle, welches du TerminateProcess übergeben kannst. Ist zwar nicht sehr schön, den Prozess so hart zu beenden. Man könnte auch alle Fenster enummerieren und gucken zu welchen Prozess sie gehören und wenn man das richtige gefunden hat WM_CLOSE an das Fenster senden. Das wäre die sauberere aber aufwendigerer Lösung.
Und nebenbei bemerkt, gibt es zu dem Problem (Programm starten und beenden) schon genug Beitrage hier im Forum. |
AW: Windows 7 Theme wechseln
Zitat:
Mein Versuch:
Delphi-Quellcode:
Das öffnet zwar den Dialog, schließt ihn aber nicht wieder.
ShExecInfo.cbSize := sizeof(SHELLEXECUTEINFO);
ShExecInfo.fMask := SEE_MASK_NOCLOSEPROCESS; ShExecInfo.lpVerb := 'runas'; ShExecInfo.lpFile := 'control'; ShExecInfo.lpDirectory := nil; ShExecInfo.lpParameters := 'C:\Windows\system32\desk.cpl desk,@Themes'; ShExecInfo.nShow := SW_SHOWNORMAL; ShellExecuteEx(@ShExecInfo); sleep(5000); //PostMessage(ShExecInfo.Wnd, WM_CLOSE, 0,0); TerminateProcess(ShExecInfo.hProcess, 0); Ich weiß leider wirklich nicht, wie ich das Handle des Fensters bekommen soll. :( |
AW: Windows 7 Theme wechseln
Wie wäre es mit einem Versuch über die Registry und dann einer Broadcast-Message mit WM_STYLECHANGED?
|
AW: Windows 7 Theme wechseln
Zitat:
Ohne das du auf den OK Button drücken mußt. Alternativ kannst du ja uses ShellObj einbinden und objShell.Sendkeys(VK_ENTER) verwenden. nicht getestet! ;) Zitat:
eng. FindWindow('CabinetWClass', 'Personalization') de. FindWindow('CabinetWClass', 'Anpassung') PS: Wenn du den Dialog nicht sehen willst solltest du SW_HIDE anstelle SW_SHOWNORMAL verwenden oder? gruss |
AW: Windows 7 Theme wechseln
Hier mal ein minimales Beispiel.
Was nicht geht! Alle "SW_" Flags haben keinen Einfluss beim Start des Dialogs. Es wird nicht auf die Anwendung gewartet unter verwendung von MsgWaitForMultipleObjects warum auch immer.. mit der abgeänderten Function von Luckie ExecAndWait gruss |
AW: Windows 7 Theme wechseln
Zitat:
Zitat:
Soweit ich weiß, wäre das hier der vollständige Aufruf:
Code:
Also entweder man kann irgendwie das (Child?-)Handle vom durch die exe aufgerufenen Fenster erhalten oder dann doch so wie Lucky als Alternative schrieb:
C:\Windows\system32\rundll32.exe C:\Windows\system32\shell32.dll,Control_RunDLL C:\Windows\system32\desk.cpl desk,@Themes /Action:OpenTheme /file:"C:\Windows\Resources\Themes\nature.theme"
Zitat:
|
AW: Windows 7 Theme wechseln
Ein Fenster kann nur zu einem Prozess gehören.
|
AW: Windows 7 Theme wechseln
Zitat:
|
AW: Windows 7 Theme wechseln
Zitat:
Ist doch uninteressant ob exe oder cpl Auch ein Dialog-Fenster hat ein Handle sollte also auch auf die messagen SW_SHOW oder SW_HIDE reagieren. Das Handle kommt nicht von der rundll32.exe sondern vom Dialog-Fenster. Und zwar wie schon geschrieben mit
Delphi-Quellcode:
FindWindow('CabinetWClass', 'Anpassung')
gruss |
AW: Windows 7 Theme wechseln
Zitat:
Zitat:
![]() Zitat:
|
AW: Windows 7 Theme wechseln
Zitat:
Vorraus gesetzt du verwendest das richtige Handle was du "zum dritten mal" über FindWindow in Erfahrung bringen mußt und das geht nun mal nur über den Window Titel Und warum soll das nicht gehen über die Sprachen? Es wird doch eine Api geben mit der man die Lokale Sprache identifizieren kann. Meim Sample funktioniert und der Dialog wird auch ordnungsgemäß geschlossen. PS: Mit "Was nicht geht!" Meinte ich die funktionen die ich nachher aufgelistet habe SW_ Flags und das warten auf den Dialog (Deshalb auskommentiert und Sleep(2000) eingefügt) Zitat:
Alternativ könntest du den Namen auch über TCPLInfo in erfahrung bringen. gruss |
AW: Windows 7 Theme wechseln
Zitat:
Ich habe mal einen neuen Ansatz gestartet:
Delphi-Quellcode:
Das ist schön, denn damit erhalte ich eine Test-Ausgabe wie:
function EnumWindowsProc(wHandle: HWND; m: TMemo): Bool; stdcall; export;
var Title, ClassName: array[0..255] of char; tid, pid: DWORD; begin Result := True; GetWindowText(wHandle, Title, 255); GetClassName(wHandle, ClassName, 255); tid := GetWindowThreadProcessId(wHandle, @pid); if IsWindowVisible(wHandle) then m.Lines.Add(string(Title) + ' | ' + string(ClassName) + ' | '+ IntToStr(tid)+'/'+IntToStr(pid)); end; procedure TSystemForm.Button5Click(Sender: TObject); var pi: TProcessInformation; si: TStartupInfo; aFile : String; begin aFile := 'notepad.exe'; //aFile := 'C:\Windows\system32\rundll32.exe C:\Windows\system32\shell32.dll,Control_RunDLL C:\Windows\system32\desk.cpl'; FillMemory( @si, sizeof( si ), 0 ); si.cb := sizeof( si ); si.dwFlags := STARTF_USESHOWWINDOW; si.wShowWindow := SW_SHOWNORMAL; CreateProcess( Nil, PChar( aFile + '' ), Nil, Nil, False, NORMAL_PRIORITY_CLASS, Nil, Nil, si, pi ); Memo1.Lines.Add('processinfo.dwProcessId: '+IntToStr(pi.dwProcessId)); sleep(5000); EnumWindows(@EnumWindowsProc, Integer(Memo1)); end; processinfo.dwProcessId: 7896 Unbenannt - Editor | Notepad | 10084/7896 Womit ich das Fenster dem aufrufenden Prozess zuordnen kann. Das funktioniert dann zwar mit einem ausführbaren Programm wie notepad.exe, aber nicht beim Ausführen einer .cpl per rundll.32.exe. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 00:26 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz