Delphi programming blog
Источник: http://teran.karelia.pro/articles/item_4412.html
 

thumbnail toolbars

Опубликовано 10.04.2010 г. 22:40

В продолжении темы изучения возможностей панели задачи windows 7 решил изучить как добавлять кнопки в превью окон панели задач и обрабатывать их нажатия. Заодно узнал как реализовывать окошко проводника в своих приложениях. Для добавления подобных кнопок в превью, нам понадобится интерфейс ITaskBarList3. Вобще после создания экземпляра такого интерфейса пользоваться им можно только после того как от системы получено сообщение о создании кнопки на панели задач. Согласно MSDN для этого требуется зарегистрировать у себя сообщение RegisterWindowMessage('TaskbarButtonCreated') и после его прихода уже проводить свои действия с интерфейсом. Поэтому добавим переменную в которой сохраним код нашего сообщения, и в событии создания главной формы зарегистрируем сообщение.

var tbCreate : Cardinal;

procedure TmainForm.FormCreate(Sender: TObject);
begin
    tbCreated := RegisterWindowMessage('TaskbarButtonCreated');
end;

Далее в обработчике сообщений нам надо отследить приход данного сообщения и вызвать нашу процедуру создания кнопок InitTaskBar(). Для этого перепишем стандартный обработчик сообщений формы DefaulHandler.

TMainForm = class(TForm)
  private
    procedure defaultHandler(var msg); override;
  end;
..
procedure TMainForm.defaultHandler(var msg);
begin
    inherited;
    with TMessage(msg) do begin
        if msg = tbCreated then InitTaskBar(self);
    end;
end;

В процедуре InitTaskBar сначала создадим экземпляр ITaskBar3 который сохраним в private нашей формы с именем tb. Максимальное количество создаваемых кнопок равно семи. Для описания кнопок используется структура TThumbButton, и поскольку кнопки создаются все сразу, то нам требуется массив данных структур. Иконки кнопок можно устанавливать как с помощью imageList так и отдельно. код кнопки, который будет передаваться при обработке ее нажатия содержится в поле iID, индекс иконки в imageList содержится в поле iBitmap. Набор полей который используется задается в dwMask.

procedure TmainForm.InitTaskBar(Sender: TObject);
var    i:integer;
    pButtons : array[0..1] of TThumbButton;
begin
    tb := CreateComObject(CLSID_TaskBarList) as ITaskBarList3;

    for i in [0,1] do begin
        pButtons[i].iId := i;
        pButtons[i].iBitmap :=i+1;
        pButtons[i].dwMask := THB_BITMAP + THB_TOOLTIP;
    end;

    pButtons[0].szTip := 'Назад';
    pButtons[1].szTip := 'Вперед';
    tb.ThumbBarSetImageList(handle, imageList.Handle);
    tb.ThumbBarAddButtons(handle, 2, @pButtons);
end;

Теперь при запуске приложения мы получаем две кнопки в превью, с картинками(1,2) из imageList. Обработка нажатия на кнопки проводится в обработчике сообщения WM_COMMAND. если старшее слово параметра wparam равно THBN_CLICKED следовательно была нажата одна из кнопок, и код нажатой кнопки содержится во младшем слове.

    procedure wmCommand(var msg:TMessage);message WM_COMMAND;
...
procedure TMainForm.wmCommand(var msg: TMessage);
begin
    inherited;
    if msg.WParamHi= THBN_CLICKED then begin
        case msg.WParamLo of
            0: BackButtonClick(nil);
            1: ForwardButtonClick(nil);
        end;
    end;
end;

ах да. наши кнопки будут выполнять действия Вперед и Назад. На данном этапе мы поучили следующее:
 
Теперь предадим некоторый смысл нашему приложению. Допустим наша программа будет являться некоторым файловым менеджером и будет отрывать в себе окна проводника. добавим в приложение TToolBar c тремя кнопками: создание окна(NewWindowButton), навигация вперед(ForwardButton), навигация назад(BackButton). Окна проводника будут открываться как дочерние во вкладках, и с использованием интерфейса IExplorerBrowser представлять проводник windows. Стиль главной формы приложения сделаем fsMDIForm, добавим на форму browserTab : TTabControl, добавим в проект новую форму, которая будет дочерней fsMDIChild - TBrowserForm. При нажатии на кнопку создания нового окна, создадим собственно новое окно, вкладку для него, причем в stringList вкладок добавим так же ссылку на саму форму этого окна:

procedure TmainForm.NewWindowButtonClick(Sender: TObject);
var index : Integer;
    child : TBrowserForm;
begin
    child := TBrowserForm.create(self);
    index := self.MDIChildCount - 1;

    BrowserTabs.Tabs.AddObject(intToStr(index),child);
    browserTabs.tabIndex := index;
end;

при переключении вкладок требуется отображать нужные окна, делать это будем сравнивая как раз таки сохраненные объекты.

procedure TmainForm.BrowserTabsChange(Sender: TObject);
var child : TBrowserForm;
    i:integer;
begin
    child := browserTabs.tabs.Objects[browserTabs.TabIndex] as TBrowserForm;
    for i:=0 to MDIChildCount - 1 do begin
        if MDIChildren[i] = child then
            MDIChildren[i].Show;
    end;
end;

Теперь перейдем к дочерней форме. Для отображения окна проводника нам понадобится экземпляр интерфейса IExplorerBrowser, который мы опишем в private секции формы. в процедуре создания окна выполним следующие действия: создадим экземпляр eb:IExplorerBrowser, заполним структуру fs:TFolderSettings для установки параметров отображения папки, установим размер области отображения, установим начальную папку для отображения (для этого сначала получим IShellItem, из которого уже получим структуру PItemIDList, которая используется для установки отображаемой директории.)

procedure TBrowserForm.FormCreate(Sender: TObject);
var fs : TFolderSettings;
    rect : TRect;
    pidl : PItemIDList;
    item : IShellItem;
begin
    eb := CreateComObject(CLSID_ExplorerBrowser) as IExplorerBrowser;

    fs.ViewMode  :=   FVM_DETAILS;
    fs.fFlags :=    0;

    rect := self.GetClientRect;
    eb.SetOptions(EBO_SHOWFRAMES);
    if S_OK  eb.Initialize(handle, rect, fs) then begin
        showMessage('init err');
        exit;
    end;

    SHCreateItemFromParsingName('C:\', nil, IID_ISHellItem, item);
    SHGetIDListFromObject(item, pidl);
    eb.BrowseToIDList(pidl,0);
    ilFree(pidl);
end;

при закрытии окна необходимо вызвать метод destroy нашего IExplorerBrowser, а при изменении размеров окна, соответственно изменить и его размеры. поэтому добавим:

procedure TBrowserForm.FormDestroy(Sender: TObject);
begin
    eb.Destroy;
end;

procedure TBrowserForm.FormResize(Sender: TObject);
var pdwp: Cardinal;
begin
    pdwp :=0;
    eb.SetRect(pdwp, self.GetClientRect);
end;

При закрытии основного окна, вручную вызовем методы destroy дочерних форм, при этом учтем, что список дочерних форм сразу перестраивается, поэтому перебор дочерних окон следует осуществлять с конца.

procedure TMainForm.FormClose(Sender: TObject; var Action: TCloseAction);
var i:integer;
begin
    for i:=MDIChildCount - 1 downto 0 do
        MDIChildren[i].Destroy;
end;

При вызове функции BrowseTOIdList не обязательно передавать структуру PItemIDList, можно также с помощью второго аргумента, определить переход например к предыдущей папке. Для этого добавим две процедуры в раздел public дочерней формы.

procedure TBrowserForm.NavigateBack;
begin
    eb.BrowseToIDList(nil,SBSP_NAVIGATEBACK);
end;

procedure TBrowserForm.NavigateForward;
begin
    eb.BrowseToIDList(nil,SBSP_NAVIGATEFORWARD);
end;

ну и чтобы завершить процесс использования кнопок в превью, поскольку при нажатии на них происходит вызов обработчиков нажатий кнопок BackButton & ForwardButton из главного тулбара, то добавим эти обработчики в код главной формы.

procedure TmainForm.ForwardButtonClick(Sender: TObject);
begin
    if MDIChildCount = 0 then exit;
    with mdiChildren[0] as TBrowserForm do
        navigateForward();
end;

procedure TmainForm.BackButtonClick(Sender: TObject);
begin
    if MDIChildCount = 0 then exit;
    with mdiChildren[0] as TBrowserForm do
        navigateBack();
end;


Логично было бы отображать в заголовках вкладок названия текущей папки (: но для этого надо изучить как обращаться с IExplorerBrowserEvents, чего я еще немного не понял.

Метки:  IExplorerBrowser  |  thumb toolabr  |  проводник 

Комментарии

Нет комментариев
- Имя
- e-mail*
- Сайт
вы можете использовать теги [i],[b],[code],[quote]
Дополнительно