Anti-FAQ: Jak wywoływać poszczególne aplikacje/komponenty znajdujące się w Panelu sterowania (WinNT, Win98, Win95)?

W windowsowym Panelu sterowania znajduje sie szereg ustawień, które mają bezpośredni wpływ pracę naszej aplikacji napisanej w Accessie. Wspomnę chociażby o formacie daty, separatorach dziesiętnych lub rozdzielczości monitora. Czasem musimy narzucić użytkownikowi pewne określone ustawienia. Wtedy dobrze by było po wykryciu błędnych ustawień dać odpowiedni komunikat i automatycznie wyświetlić właściwą aplikację z Panelu sterowania. Tylko jak to zrobić? Opisują to poniższe przykłady:

1. Kilka słów wyjaśnienia co to jest ten Panel sterowania?

Panel sterowania stanowi zbiór apletów zapisanych w postaci plików CPL. Aby uruchomić taką aplikację potrzebny jest program rundll32.exe (Rundll32.exe to plik systemowy i jest w każdym Windows), albo control.exe (Control.exe to tez plik systemowy). Sposób wywołania konkretnego apletu np. intl.cpl jest taki:

'za pomocą rundll32.exe
(aby zobaczyć efekt wpisz poniższy tekst do okienka Start/Uruchom w swoim Windows)
Rundll32.exe shell32.dll,Control_RunDLL intl.cpl,@0,4

'lub za pomocą Control.exe (dla zgodności ze starszymi wersjami Windows)
control.exe intl.cpl,@0,4

A teraz wyjaśnię, co oznaczają poszczególne parametry:
1) shell32.dll - oznacza bibliotekę, użytą do wywołania apletu,
2) Control_RunDLL - oznacza funkcję, która jest wywoływana z biblioteki,
3) intl.cpl to przykładowa nazwa wywoływanego apletu,
4) @0 - informuje system do którego "poziomu zagnieżdżenia" aplikacji się odwołujemy (Niektóre aplety posiadają przyciski, które wywołują kolejne 'poziomy zagnieżdżenia' aplikacji. Ten parametr pozwala nam na bezpośrednie odwolanie się do dowolnego 'poziomu zagnieżdżenia'.)
5) cyfra - oznacza zakładkę, którą chcemy wyświetlić. (0 - pierwsza zakładka, 1 - druga itd.)

U W A G I:
1. Ważne jest, aby oddzielając poszczególne parametry przecinkami, nie wpisywać spacji. Dlaczego? Bo taka jest składnia i ze spacjami nie działa!
2. Jeśli chodzi nam o pierwszy poziom zagnieżdzenia - a tak będzie w większości przypadków - to parametr @0 możemy pominąć.

2. Przechodzimy do konkretów. Jak sprawdzić z poziomu naszej aplikacji w Accessie, czy w Panelu sterowania ustawiony jest oczekiwany przez nas format daty i jak można programowo wyświetlić odpowiednią zakładkę z prośbą o zmianę ustawień?

Na początek należy w jakiś module globalnym zdefiniować jedną lub dwie (wyjaśnienie dalej) funkcje API:

Declare Function GetSystemDirectory& Lib "kernel32" _
         Alias "GetSystemDirectoryA" (ByVal P$, ByVal S%)

Declare Function GetWindowsDirectory& Lib "kernel32" _
         Alias "GetWindowsDirectoryA" (ByVal P$, ByVal S%)

Teraz (najlepiej na początku programu) trzeba sprawdzić, czy w Panelu sterowania ustawiony jest odpowiedni format. Można znowu skorzystać z funkcji API (jak odczytać systemowe ustawiania za pomocą API znajdzie się na tej witrynie w pó?niejszym terminie), ale w tym przypadku API nie są konieczne. Wystarczy nam trochę pomysłowości. Poniżej przedstawiam fragment kodu, który potrafi wykryć, czy data została ustawiona w prawidłowym formacie dd-MM-rrrr:

If CStr(#10/11/12#) Like "11?10*12" Then
	'OK, data ustawiona w formacie dd-MM-rrrr
Else
	'Zły format daty, trzeba zmienić ustawienia w Panelu sterowania
End If

A teraz cały kod, który w razie potrzeby wyświetla zakładkę z formatem daty (wybrałem metodę z control.exe, ale łatwo dostosować kod do rundll32.exe):

Dim strSysDirPath As String, vRetval As Double
If CStr(#10/11/12#) Like "11?10*12" Then
	'OK, data ustawiona w formacie dd-MM-rrrr
Else
 	'Przygotowuje string do wpisania katalogu systemowego
	strSysDirPath = String$(145, Chr$(0))
	strSysDirPath = Left$(strSysDirPath, _
	GetWindowsDirectory(strSysDirPath, _
	Len(strSysDirPath)))
                    
	If Dir(strSysDirPath & "\control.exe") = "control.exe" Then
		'OK, znaleziono "control.exe" 
		'
		'Ten fragment kodu potrzebny tylko dlatego, ze Microsoft nie może sie zdecydować,
		'gdzie umieścić control.exe i raz go wtyka do głównego katalogu Windows (Win98), 
		'a raz do WinNT\System32 (WinNT). Nasz chwyt powoduje, że jednen kod obsługuje oba systemy.
        Else
            	strSysDirPath = String$(145, Chr$(0))
            	strSysDirPath = Left$(strSysDirPath, _
                         GetSystemDirectory(strSysDirPath, _
                         Len(strSysDirPath)))
        End If
        vRetval = Shell(strSysDirPath & "\control.exe intl.cpl,,4", 1)
	'albo w drugim rozwiązaniu:
	'Shell(strSysDirPath & "\Rundll32.exe shell32.dll,Control_RunDLL intl.cpl,@0,4", 1)
	
	'Uwaga: Jeśli control.exe jest w scieżce dostępu zdefiniowanej w Autoexec.bat jako PATH,
	'to nie potrzeba już podawać w Shellu pełnej ścieżki i wystarczy wtedy 
	'prostsza składnia:
	'vRetval = Shell("control.exe intl.cpl,,4", 1)
End If

3. Przedstawię teraz kilka innych wywołań wybranych apletów z grupy Panel sterowania. Dla uproszczenia przyjmujemy, że ścieżka dostępu do control.exe jest w zmiennej systemowej PATH.

'Wywołuje zakładkę do ustawiania formatu waluty
call Shell("control.exe intl.cpl,,2", 1)

'Wywołuje zakładkę do ustawiania czasu systemowego
call Shell("control.exe timedate.cpl,,0", 1)

'Wywołuje ekran do ustawiania ilości kolorów i rozdzielczości monitora.
'Można na początku wykrywać aktualny tryb pracy monitora (jak to zrobić
'opisano w dziale Anti-FAQ) i w przypadku stwierdzenia nieodpowiednich
'ustawień wywoływać właściwą zakładkę z Panelu sterowania.
call Shell("control.exe desk.cpl,,3", 1)

'Wywołuje ekran z drukarkami
call Shell("control.exe main.cpl,@2,0", 1)

'Wywołuje Administratora źródłami danych ODBC
call Shell("control.exe odbccp32.cpl,,0", 1)

'itd...

4. Zamiast mnożyć w porzednim punkcie możliwości użycia control.exe (Rundll32.exe) przedstawię wybrane pliki CPL i ich tytuły. Zapraszam do samodzielnych testów.

+======================================+
| Tytuł                 | Nazwa pliku  | 
+======================================+
| Dodaj/Usuń programy   | Appwiz.cpl   | 
+--------------------------------------+
| Konsola MSDOS         | Console.cpl  | 
+--------------------------------------+
| Data/Czas             | Timedate.cpl | 
+--------------------------------------+
| Ekran                 | Desk.cpl     | 
+--------------------------------------+
| Find Fast             | Findfast.cpl | 
+--------------------------------------+
| Czcionki              | Main.cpl     | 
+--------------------------------------+
| Internet              | Inetcpl.cpl  | 
+--------------------------------------+
| Klawiatura            | Main.cpl     | 
+--------------------------------------+
| Poczta i Fax          | Mlcfg32.Cpl  | 
+--------------------------------------+
| Modemy                | Modem.cpl    | 
+--------------------------------------+
| Mysz                  | Main.cpl     | 
+--------------------------------------+
| Multimedia            | Mmsys.cpl    | 
+--------------------------------------+
| Sieć                  | Ncpa.cpl     | 
+--------------------------------------+
| ODBC32                | Odbccp32.cpl | 
+--------------------------------------+
| Porty                 | Ports.cpl    | 
+--------------------------------------+
| Drukarki              | Main.cpl     | 
+--------------------------------------+
| Ustawienia regionalne | Intl.cpl     | 
+--------------------------------------+
| Urządzenia SCSI       | Devapps.cpl  | 
+--------------------------------------+
| Serwer                | Srvmgr.cpl   | 
+--------------------------------------+
| D?więki               | Mmsys.cpl    | 
+--------------------------------------+
| System                | Sysdm.cpl    | 
+--------------------------------------+
| Urządzenia taśmowe    | Devapps.cpl  | 
+--------------------------------------+
| Telefon               | Telephon.cpl | 
+--------------------------------------+
| UPS                   | Ups.cpl      | 
+--------------------------------------+
Wspomaganie: MSDN.

K. P.