Zmiana standardowych dialogów Windows

necrokris

Delphi oferuje kilka standartowych dialogów Windows, jednak nie możemy mieć na nich dużego wpływu. Czy jednak na pewno tak jest? Pomocą może być tutaj WinAPI. Postaram się wyjaśnić kwestię modyfikacji dialogów na przykładzie TFindDialog i dostosowania go do naszych potrzeb. Potrzebny nam będzie do tego jakiś edytor zasobów, ja osobiście polecam darmowy PE Resource Explorer (http://www.wilsonc.demon.co.uk/d7resourceexplorer.htm).

Na początek dodajemy do projektu komponent TFindDialog z palety Dialogs i nazywamy go Find. Załóżmy, że chcemy zmienić Kierunek (Dół/Góra) na Wyszukiwanie specjalne (Tak/Nie) oraz chcemy ukryć guzik Anuluj.

Uruchamiamy zatem nasz edytor zasobów i dekompilujemy plik comdlg32.dll, który znajduje się w katalogu {windows}\system lub {windows}\system32. Otwieramy zakładkę Dialogs i wyszukujemy tam interesujący nas dialog. W naszym przypadku będziemy potrzebowali otworzyć dialog numer 1540, w którym znajduje się dialog wyszukiwania. Musimy pobrać ID 4 kontrolek, które potrzebujemy. W PE Resource Explorer wystarczy kliknąć na dany komponent, a w tabelce obok pojawi się ID. Są to:
Anuluj - ID 2
Kierunek - ID 1072
W górę - ID 1056
W dół - ID 1057

Teraz musimy stworzyć obsługę zdarzenia OnShow dla komponentu Find. Po kolei dodajemy tam linie:

SetWindowText(GetDlgItem(Find.Handle, 1072), 'Wyszukiwanie specjalne');
SetWindowText(GetDlgItem(Find.Handle, 1056), 'Tak');
SetWindowText(GetDlgItem(Find.Handle, 1057), 'Nie');

Gwoli wyjaśnienia : funkcja SetWindowText pozwala nam na zmianę tekstu kontrolki, a GetDlgItem zwraca uchwyt.

Następnie aby schować przycisk Anuluj musimy dodać linię

MoveWindow(GetDlgItem(Find.Handle, 2),0,0,0,0,true);

W tym przypadku przycisk Anuluj posiada zerową wysokość i długość, a więc jest niewidoczny.

Następnym krokiem będzie sprawdzanie, czy użytkownik wybrał tak lub nie. Jak wiadomo wcześniej kontrolka pozwalała nam zmienić kierunek wyszukiwania, a więc odpowiada za to opcja Find.Options[frDown]. Tworzymy zdarzenie OnFind oraz dodajemy nastepujące linie:

    if frDown in Find.Options then begin;
        //procedury jeśli wybrano "Nie" (czyli stare W dół)
        end else begin;
        //procedury jeśli wybrano "Tak" (czyli stare W górę)
        end;

Wszystko jest już gotowe, wystarczy jeszcze dodać przycisk. Nazwijmy go Btn. Tworzymy obsługę zdarzenia OnClick:

Font.Execute;

Cały kod wyglądać powinien następująco:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Find: TFindDialog;
    Btn: TButton;
    procedure BtnClick(Sender: TObject);
    procedure FindShow(Sender: TObject);
    procedure FindFind(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FindShow(Sender: TObject);
begin
    SetWindowText(GetDlgItem(Find.Handle, 1072), 'Wyszukiwanie specjalne');
    SetWindowText(GetDlgItem(Find.Handle, 1056), 'Tak');
    SetWindowText(GetDlgItem(Find.Handle, 1057), 'Nie');
    MoveWindow(GetDlgItem(Find.Handle, 2),0,0,0,0,true);
end;

procedure TForm1.FindFind(Sender: TObject);
begin
    if frDown in Find.Options then begin;
        //procedury jeśli wybrano "Nie" (czyli stare W dół)
        end else begin;
        //procedury jeśli wybrano "Tak" (czyli stare W górę)
        end;
end;

procedure TForm1.BtnClick(Sender: TObject);
begin
    Find.Execute;
end;

end.

Pamiętajmy, że w ten sposób możemy edytować wszystkie dialogi z karty Dialogs. Ja osobiście używam tego prostego sposobu czasami, gdy chce nieznacznie zmodyfikować dialog, a nie chce sam pisać całego od nowa. Mam nadzieję, że Wam też przyda się ten sposób na standardowe okienka Windows.

10 komentarzy

A może by ktoś opisał biblioteki windowsa (oczywiście nie wszystkie) - myślę, że przydałby się taki artykuł po polsku, a narazie 6 dla necrokris :)

Fajna porada. Zamieniłbym tylko funkcje MoveWindow na ShowWindow, DestroyWindow czy coś w tym stylu. Poza tym, w ten sposób można zrobić dużo więcej niż tylko modyfikować wygląd dialogów. Ja na przykład kiedyś napisałem nakładke na program która ukrywała większość przycisków z niepotrzebnymi funkcjami, zmieniła rozmiar okna głównego, a reszte przycisków ułożyła w ładnym żądku:). Jedyna różnica polegała na tym że uchwyty uzyskałem za pomocą FindWindow i FindWindowEx.

Dzieki, teraz juz kompletnie nie ma zadnych bledow jezykowych :p Z drugiej strony zastanawia mnie czemu Office ma w slowniku slowo 'standart', a w SJP nie ma nic takiego.

Się będę czepiał ;P

nadzieję, że Wam też przyda się ten sposób na standartowe okienka Windows

Dalej twierdzę, że standarDowe okienka ;P Jak poprawiasz to postaraj się poprawiać kompletnie :) To chyba tyle, masz 5 :)

Fajne, fajne... :D Sie przyda :)

No bywa :) Coraz częściej niestety :/ Chociaż kiedyś chyba pisano "standartowy"... Ale mniejsza z tym, ważne, że jest OK :) I nie ma za co :P

thx brodny, po nocce z WinAPI ortografia idzie w las :p

standarDowych

Elegancko.. później przetestuję, ale porada OK.