|
Geraten auf Ihrem Windows-Desktop, auf Ihren
Taskbar-Symbolleisten oder im Explorer die Icons hin und wieder
durcheinander und zeigen nicht mehr die korrekten Icons zu den
entsprechenden Dateien und Verknüpfungen? Egal aus welchem Grund
auch immer - falls Sie bei der Suche nach einer API-Funktion, die
die Darstellung der Icons aktualisiert, auf die Funktion SystemParametersInfo
mit dem Aktionsparameter SPI_SETICONS gestoßen sein sollten, werden
Sie sich vielleicht darüber gewundert haben, dass der Aufruf dieser
Funktion offensichtlich ohne Wirkung zu bleiben scheint. Selbst wenn
Sie in deren letztem Parameter entsprechend der Dokumentation das
Flag SPIF_SENDCHANGE übergeben, scheint sich immer noch nichts zu
tun, zumindest nicht auf allen Systemen. Den genauen Grund weiß ich
allerdings auch nicht. Bekannt ist nur, dass sich die Funktion nicht
immer so verhält, wie sie soll.
Eine tatsächliche Aktualisierung der Shell-Icons, genauer
gesagt, der System-Icon-Liste, erreichen Sie nur, wenn Sie
kurzfristig die Größe der Icons ändern, die Message WM_SETTINGCHANGE
an alle Fenster senden, die Größe wieder restaurieren und die
Message noch einmal senden.
Doch wie ändern Sie nun die Größe der Shell-Icons? Mit
SystemParametersInfo können Sie zwar allerhand Veränderungen in
den Systemeinstellungen vornehmen, auch die nahe verwandt
erscheinenden Standard-Abstände der Icons auf dem Desktop bzw. in
ListViews mit Icon-Darstellung. Doch ausgerechnet zur Manipulation
der Icon-Größe werden Sie keinen Aktionsparameter finden können.
Sie können die Icon-Größe zwar mit der API-Funktion GetSystemMetrics
und den Indices SM_CXICON und SM_CYICON auslesen - das Gegenstück
zu dieser Funktion, die etwa SetSystemMetrics heißen müsste,
werden Sie genau so wenig finden. Die einzige Möglichkeit ist, den
Wert direkt in der Windows-Registrierung unter dem Schlüssel
HKEY_CURRENT_USER\Control Panel\Desktop\WindowMetrics\Shell Icon Size
zu ändern.
Nun sind Zugriffe auf die Registrierung nicht gerade trivial,
wenn Sie an jeden beliebigen Schlüssel heran kommen möchten, und
sich nicht auf die Visual Basic-eigenen GetSetting/SaveSetting-Möglichkeiten
beschränken wollen (und hier eben auch nicht können).
Wenn Sie ein wenig in der Microsoft Knowledge-Base, im Internet,
in Foren und in Newsgroups herumstöbern, werden Sie viele
Code-Beispiele, sogar auf gebrauchsfertige Module, Klassen und
Controls für Registrierungszugriffe stoßen. Die meisten bilden
jedoch die dahinterstehenden API-Funktionen auf aus Visual
Basic-Sicht eher ungewohnte Weise ab, so dass die Verwendung oft
nicht gerade als komfortabel zu bezeichnen wäre. Doch
interessanterweise bietet Microsoft selbst schon seit ewigen Zeiten
(seit Visual Basic 4) eine kleine, aber feine und
praktische ActiveX-DLL (REGOBJ.DLL) genau zu diesem Zweck an. Das
darin enthaltende Registry-Objekt ist zum einen nicht nur
ausgesprochen stabil und fehlerfrei, sondern bietet zudem auch die
Möglichkeit, die gesamte Registrierung in der Form eines Baumes mit
allen Verzweigungen zu durchlaufen (ähnlich dem, wie das
FileSystemObject aus der Scripting-DLL das Dateisystem abbildet).
Sie können die DLL kostenlos bei Microsoft
herunterladen und brauchen sie anschließend nur noch mit RegSvr32
zu registrieren:
RegSvr32.EXE [Pfad]REGOBJ.DLL)
Für unsere Absicht, die Shell-Icon-Größe vorübergehend zu
ändern, genügt der Zugriff auf den oben genannten Schlüssel. Den
Schlüssel erhalten Sie direkt mit einem Aufruf der globalen Methode
RegKeyFromString des Registry-Objekts (da dieses ein globales Objekt
ist, brauchen Sie es noch nicht einmal ausdrücklich zu instanzieren).
Und den gesuchten Wert finden Sie in der Values-Collection des
betreffenden Schlüssel-Objekts (Regkey-Objekt).
Da die Standard-Einstellung für die Shell-Icon-Größe meistens 32
Pixels beträgt, genügt es, den Wert vorübergehend auf 31
Pixels zu setzen. Falls er jedoch schon 31 Pixels
betragen sollte, setzen wir ihn eben umgekehrt auf 32 Pixels.
In jedem Fall merken wir uns den vorgefundenen Wert in der Variablen
nOldSize.
Dann senden wir die Nachricht WM_SETTINGCHANGE systemweit an alle
Top-Fenster - anstelle eines spezifischen Fenster-Handles geben wir
die Konstante HWND_BROADCAST an. Allerdings verwenden wir hier nicht
wie sonst meistens die Funktion SendMessage,
sondern deren Variante SendMessageTimeout.
Diese hat den Vorteil, dass ihr Aufruf auch dann nach einer in
Sekunden einstellbaren Zeitspanne zurückkehrt, wenn eines der die
Nachricht empfangenden Fenster die Nachricht nicht (oder nicht
sofort) verarbeiten kann (weil sie vielleicht anderweitig
beschäftigt ist, oder gar unbemerkt abstürzt oder bereits
abgestürzt ist). Für den letzten Parameter (eigentlich eine
Erfolgsmeldung) müssen wir zwar eine Variable dimensionieren,
können hier aber auf eine Auswertung und Berücksichtigung
verzichten.
Damit der Desktop genügend Zeit bekommt, die Größenänderung
nachzuvollziehen, legen wir unseren Code für kurze Zeit mit der
API-Funktion Sleep schlafen - etwa 4 Sekunden (4000
Millisekunden). Nun setzen wir die Größe der Shell-Icons
wieder auf den Ursprungswert zurück und senden zum Abschluß erneut
die Nachricht WM_SETTINGCHANGE an alle Fenster.
Private Declare Function SendMessageTimeout Lib "user32" _
Alias "SendMessageTimeoutA" (ByVal hwnd As Long, _
ByVal msg As Long, ByVal wParam As Long, ByVal lParam As Long, _
ByVal fuFlags As Long, ByVal uTimeout As Long, lpdwResult As Long) _
As Long
Private Declare Sub Sleep Lib "kernel32" _
(ByVal dwMilliseconds As Long)
Private Const WM_SETTINGCHANGE = &H1A
Private Const SMTO_ABORTIFHUNG = &H2
Private Const HWND_BROADCAST = &HFFFF&
Public Sub ReloadShellIcons()
Dim nResult As Long
Dim nOldSize As Long
With RegKeyFromString _
("\HKEY_CURRENT_USER\Control Panel\Desktop\WindowMetrics")
nOldSize = .Values("Shell Icon Size")
If nOldSize = 31 Then
.Values("Shell Icon Size") = 32
Else
.Values("Shell Icon Size") = 31
End If
SendMessageTimeout HWND_BROADCAST, WM_SETTINGCHANGE, 0, 0, _
SMTO_ABORTIFHUNG, 3, nResult
Sleep 4000
.Values("Shell Icon Size") = nOldSize
SendMessageTimeout HWND_BROADCAST, WM_SETTINGCHANGE, 0, 0, _
SMTO_ABORTIFHUNG, 3, nResult
End With
End Sub
Natürlich können Sie die Technik auch für sich alleine dazu
verwenden, die Shell-Icon-Größe zu ändern:
Public Property Let ShellIconSize(ByVal New_ShellIconSize As Long)
Dim nResult As Long
Select Case New_ShellIconSize
Case 0
New_ShellIconSize = 32
Case Is < 16
New_ShellIconSize = 16
Case Is > 72
New_ShellIconSize = 72
End Select
RegKeyFromString _
("\HKEY_CURRENT_USER\Control Panel\Desktop\WindowMetrics") _
.Values("Shell Icon Size") = New_ShellIconSize
SendMessageTimeout HWND_BROADCAST, WM_SETTINGCHANGE, 0, 0, _
SMTO_ABORTIFHUNG, 3, nResult
End Property
Und falls Sie nur neugierig sein sollten, können Sie die Größe
auch über das Registry-Objekt auslesen:
Public Property Get ShellIconSize() As Long
ShellIconSize = RegKeyFromString _
("\HKEY_CURRENT_USER\Control Panel\Desktop\WindowMetrics") _
.Values("Shell Icon Size")
End Property
|