Desktop-Icons führen bei Windows manchmal ein Eigenleben. Wenn sich die Auflösung ändert, etwa bei der Installation eines neuen Grafiktreibers oder nach dem Start älterer Spiele, ist die Anordnung der Icons auf dem Windows-Desktop nicht mehr dieselbe. Mit dem Tool pcwSIcons3 können Sie die Positionen der Icons sichern und wiederherstellen.
Downloads zu diesem Artikel:
pcwSIcons3_setup.exe: Setup-Programm für alle Programme. Das Installationsprogramm installiert automatisch die 32- oder 64-Bit-Version (für Windows Vista, Windows 7 oder Windows 8)
pcwSIcons3.zip: ZIP-Archiv mit allen Programmen. Achtung: Die ActiveX-DLL müssen Sie selbst registrieren. Batch-Dateien für diesen Zweck liegen bei (als Administrator ausführen)
pcwSIcons_CLI.zip: Nur das Kommandozeilenprogramm (32-Bit und 64-Bit), beispielsweise für die Verwendung in einer Batch-Datei.
pcwSIcons3-Source: Source-Code für alle Programm (Delphi XE3).
Das Problem begleitet Windows seit Jahren. Und jeder, der häufig die Icons auf dem Desktop nutzt und hier eine gewisse Ordnung bevorzugt, kennt es wahrscheinlich. Unter bestimmten Bedingungen werden die Icons neu angeordnet und die eigene Ordnung ist dahin. Das passiert bevorzugt bei Änderungen der Bildschirmauflösung, etwa bei der Installation einen neuen Grafiktreibers oder bei bestimmten Spielen. Ein weiteres Problem sind PCs, an denen in der Regel mehrere Monitore hängen, aber eben nicht immer. Icons die auf dem zweiten Bildschirm liegen, landen dann irgendwo auf dem ersten Bildschirm, wenn nur ein Monitor angeschlossen ist. Ähnliches gilt für Notebooks, wenn sie hin und wieder mit höherer Auflösung oder im Zwei-Bildschirm-Betrieb laufen.
Es wäre daher wünschenswert, die Anordnung der Icons zu speichern und bei Bedarf wiederherzustellen. Dafür gibt es bereits einige Tools, die jedoch nicht so flexibel sind, wie ich mir das wünsche. Da ich im Besitz eines Editors und eines Compilers bin, habe ich mich also selbst an Werk gemacht. Der verwendete Delphi-Code ist schon ziemlich alt. Er stammt ursprünglich aus den Zeiten von Windows 95, funktioniert mit einigen Anpassungen aber auch heute noch. Ich habe das Programm mit Embarcadero Delphi XE3 erstellt, es sollte aber mit einigen kleinen Änderungen auch mit anderen Delphi/Freepascal-Umgebungen zu erstellen sein. Das Programm ist ursprünglich für eine PC-WELT-Artikel entstanden und ich habe es jetzt etwas weiterentwickelt. Der Quellcode steht unter GPL.
Wie funktionieren die Programme?
Aber zuerst – für Nicht-Programmierer – zu den Programmen selbst. Um alle Wünsche abzudecken, gibt es davon mehrere Varianten. Das erste Progrämmchen ist eine ActiveX-DLL. Diese lässt sich per Script oder über ein mausbedienbares Programm nutzen. Das zweite Tool kann unabhängig davon auf der Kommandozeile oder in einer Batch-Datei verwendet werden.
Das erste Programm heißt pcwSIcon3 und lässt sich am einfachsten per Setup-Programm installieren. Dieses sorgt auch für die Registrierung der ActiveX-DLL. Das Setup-Programm installiert – je nach System-Architektur – die 32- oder die 64-Bit-Version der Dateien. Im Startmenü findet sich danach das Programm PC-WELT-pcwSIcons3. Es bietet eine einfache Oberfläche. Über die Schaltfläche „Positionen speichern“ lassen sich die Icon-Positionen in einer INI-Datei sichern. Diese liegt unter %APPDATA%\pcwSIcons3\pcwSIcon3.ini. Das Tool ermittelt die aktuelle Bildschirmauflösung und speichert diese als Layout-Namen. Auf diese Weise lassen sich die Icon-Positionen für unterschiedliche Auflösungen getrennt speichern. In das Eingabefeld hinter „Layout-Name“ kann man auch selbst einen Namen eintippen, beispielsweise MeinDesktop. Per Klick auf „Wiederherstellen“ setzt das Tool die Icons wieder an die zuvor gespeicherte Stelle.
Für die Automatisierung dieses Vorgangs dienen die beiden Scripte SaveIcons.vbs und RestoreIcons.vbs. Diese erreichen Sie über das Windows-Startmenü oder direkt über den Installationsordner, etwa „C:\Program Files\PC-WELT\pcwSIcons3“. Sie können die VBS-Scripte bei Bedarf anpassen. Dazu öffnen Sie die VBS-Dateien in einem Editor. Sie können hinter „.IniFileName“ den Pfad anpassen, in dem die INI-Datei gespeichert wird und hinter „ ‚.Resolution“ einen eigenen Namen für das Bildschirm-Layout festlegen. Standardmäßig wird die Bildschirmauflösung als Name verwendet. Für den täglichen Gebrauch sollten Sie noch die „MsgBox“-Zeile auskommentieren, damit keine Meldung auf dem Bildschirm erscheint.
Programm für die Kommandozeile: Wer statt VB-Script lieber eine Batch-Datei verwenden möchte nimmt das Programm pcwSIcons3_CLI_X64.exe beziehungsweise pcwSIcons3_CLI_x86.exe. Es arbeitet unabhängig von der ActiveX-DLL, bietet aber die gleichen Funktionen. Mit der Zeile
pcwSIcons3_CLI.exe /i:c:\MyIniFile.ini /s
lassen sich die Icon-Positionen in der Datei „MyIniFile.ini“ speichern und mit
pcwSIcons3_CLI.exe /i:c:\MyIniFile.ini /r
wieder zurücksichern. Über den Parameter „/l“ können Sie einen benutzerdefinierten Namen für das Bildschirmlayout angeben:
pcwSIcons3_CLI.exe /i:c:\MyIniFile.ini /s /l:"MyDesktopLyaout"
Der Quellcode
Beim Windows-Desktop handelt es sich um ein Fenster ohne Rahmen, das seit den ersten Windows „Progman“ heißt und den Titel „Program Manager“ trägt. Dieses Fenster wird komplett von einem SysListView32 ausgefüllt, das die Desktop-Icons anzeigt. In einem ersten Schritt muss man mit der API-Funktion FindWindow den Handle dieses Fensters ermitteln. Danach findet man mit EnumchildWindows heraus, wie die Unterfenster heißen. Eins davon trägt (hoffentlich) die Bezeichnung „FolderView“. Mit ListView_GetItemCount erhält man dann die Anzahl der Icons auf dem Desktop. Mit GetWindowThreadProcessId und OpenProcess kann man sich dann Zugang zumListView verschaffen und die einzelnen Elemente mit ListView_GetItemPosition auslesen. Hier der entscheidende Ausschnitt aus dem Quellcode:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 | Procedure IterateIcons(const S:string; TheAction: TIconAction); TYPE PSharedStuff = ^TSharedStuff; TSharedStuff = record Buffer : ARRAY[0..MAX_PATH] OF Char; LV : TLVItem; Pt : TPoint; end; var TI: TIniFile; hWnd1: HWND; dwProcessId: DWORD; hProcess: THandle; Pointer1: Pointer; PLVItem1: PLVITEM; PChar1: PChar; I: Integer; NumberOfBytesRead: SIZE_T; NumberOfItems: Integer; N: Integer; myIconPoint: TPoint; PSS:PSharedStuff; Procedure OneIconNT(N:Integer); begin //*************** ein Icon lesen ************** with PLVItem1^ do begin cchTextMax := 256; pszText := Pointer(Cardinal(Pointer1) + SizeOf(TLVItem)); mask := LVIF_TEXT; iItem := N; iSubItem := 0; end; WriteProcessMemory(hProcess, Pointer1, PLVItem1,SizeOf(TLVItem) ,NumberOfBytesRead); SendMessage(hWnd1, LVM_GETITEM, N, lparam(Pointer1)); ReadProcessMemory( hProcess, Pointer(Cardinal(Pointer1) + SizeOf(TLVItem)), PChar1,DWORD(256), NumberOfBytesRead); ListView_GetItemPosition(hWnd1, N, PPoint(Pointer1)^); ReadProcessMemory( hProcess, Pointer1, @myIconPoint, DWORD(sizeof(TPoint)), NumberOfBytesRead); Case TheAction Of SaveToIni: TI.WriteInteger (S, PChar1, Integer(PointToSmallPoint(myIconPoint))); RestFromIni: begin I:=TI.ReadInteger(S, PChar1, -1); If I <>-1 Then begin myIconPoint:=SmallPointToPoint(TSmallPoint(I)); end; ListView_SetItemPosition(hWnd1,N, myIconPoint.x, myIconPoint.y); end; end; end; //************** W95/98 **************** Procedure OneIcon95(N:Integer); Begin WITH PSS^.LV DO begin mask := LVIF_TEXT; iItem := N; iSubItem := 0; state := 0; statemask := 0; pszText := @PSS^.Buffer; cchTextMax := MAX_PATH; iImage := 0; end; SendMessage(hWnd1, LVM_GETITEM, 0, Integer(@PSS^.LV)); SendMessage(hWnd1, LVM_GETITEMPOSITION, N, Integer(@PSS^.pt)); Case TheAction Of SaveToIni: TI.WriteInteger(S, StrPas(Pss^.Buffer), Integer(PointToSmallPoint(PSS^.Pt))); RestFromIni: begin I:=TI.ReadInteger(S, StrPas(PSS^.Buffer), -1); If I <>-1 Then begin PSS^.Pt:=SmallPointToPoint(TSmallPoint(I)); end; ListView_SetItemPosition(hWnd1,N, PSS.Pt.x, PSS.Pt.y); end; end; end; //************* main ******************* Begin TI:=TIniFile.Create(sIniFileName); hWnd1 := DesktopListViewHandle; if hWnd1 = 0 then exit; //************** 95/98/ME *************** if TOSVersion.ToString='' then begin // end; If CheckForWin95= VER_PLATFORM_WIN32_WINDOWS Then begin NumberOfItems := ListView_GetItemCount(hWnd1); hProcess:=CreateFileMapping( $FFFFFFFF, NIL, PAGE_READWRITE, 0, SizeOf(TSharedStuff), LVMapName); PSS:=MapViewOfFile(hProcess, FILE_MAP_ALL_Access,0,0,0); IF TheAction=SaveToIni Then TI.EraseSection(S); try For N:=0 To NumberOfItems-1 Do OneIcon95(N); finally TI.Free; end; CloseHandle(hProcess); end //************** NT/2K/Vista/7/8*************** Else If CheckForWin95= VER_PLATFORM_WIN32_NT Then begin GetWindowThreadProcessId(hWnd1, @dwProcessId); hProcess := OpenProcess( PROCESS_VM_OPERATION or PROCESS_VM_READ or PROCESS_VM_WRITE, false, dwProcessId); if hProcess = 0 then exit; Pointer1 := VirtualAllocEx(hProcess, nil, 4096, MEM_RESERVE or MEM_COMMIT, PAGE_READWRITE); PLVItem1 := AllocMem(SizeOf(TLVItem)); PChar1 := StrAlloc(256); NumberOfItems := ListView_GetItemCount(hWnd1); IF TheAction=SaveToIni Then TI.EraseSection(S); try For N:=0 To NumberOfItems-1 Do OneIconNT(N); finally TI.Free; end; VirtualFreeEx(hProcess, PLVItem1, 0, MEM_RELEASE); CloseHandle(hProcess); end else WriteLn('Diese Plattform wird nicht unterstützt.'); end; |
Gibt es auf dem Notebook evtl. eine Sicherheitssoftware, die die Arbeit des Tools behindert? Ich kann mir gerade keinen Fehler vorstellen, der sonst dazu führt.
Sie können versuchen, die ActiveX-DLL neu zu registrieren. Dazu öffnen Sie als Administrator eine Kommandozeile und setzen den Befehl
regsvr32.exe „C:\Program Files\PC-WELT\pcwSIcons3\pcwSIcon3.dll“
ab. Passen Sie den Pfad zur Datei pcwSIcon3.dll ggf. an.
Es sollte die Meldung erscheinen
„DllRegisterServer in C:\Program Files\PC-WELT\pcwSIcons3\pcwSIcon3.dll erfolgreich durchgeführt.“
Probieren Sie bitte auch aus, ob pcwSIcons3_CLI.exe funktioniert. Das Kommandozeilenprogramm kommt ohne die ActiveX-DLL aus. Sollte auch dieses nicht funktionieren, muss das Problem woanders liegen.
Guten Abend Herr Eggeling!
Ich nutze Ihr pcwSIcons3 Software sehr gerne auf meinem Desktop Rechner und probiere gerade – verzweifelnd – die Software auch auf meinem Notebook zum Laufen zu bringen.
Wenn ich mit den vbs Scripts (SaveIcons und RestoreIcons) arbeite, dann erscheinen zwar die Meldungen wie „Layout speichern.“, aber die pcwSIcon3.ini bleibt leer.
Wenn ich die exe starte, einen Layout-Name eingebe und auf „Positionen speichern“ klicke, dann wird weder der Layout-Name eingetragen noch die ini bearbeitet.
Haben Sie mir einen Tipp, wie ich die Software zum Funktionieren überreden kann?
Vielen Dank!
Matthias
System: Windows 7, 64-bit, aktuelle Auflösung lt. SIcons3 3840x1080 (Notebook + externer Monitor).