Plugin API. Пишем панельный плагин. Шаг1: Первое приближение

Обсуждение энциклопедии.
Post Reply
User avatar
Skirda
Posts: 3474
Joined: Wed 16 Mar, 2005 11:01
Been thanked: 1 time

Plugin API. Пишем панельный плагин. Шаг1: Первое приближение

Post by Skirda » Wed 12 Dec, 2012 13:56

Полная реализация идеи. Информацию о местоположении Доски пользователя берем из реестра - HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders\Desktop (в последующих уроках будет использоваться более цивилизованный метод).

Имеется так же возможность задания конкретного каталога для перехода (не только Desktop текущего пользователя) - достигается путем введения блока конфигурирования плагина. Этим самым "конкретным каталогом" может быть каталог, в котором лежит куча LNK-файлов, связи на папки и файлы, etc.

На данном шаге плагин не создает собственной панели. Работа плагина аналогична команде Far Manager "Ссылки на папки" для одного каталога.

Попробуем решить задачу в лоб, как есть, т.е. в меню дисков и меню выбора плагинов должен появится пункт меню, выбрав который пользователь попадет на свою Доску. Для создания полноценного плагина на данном этапе нам понадобятся 6 экспортируемых функций:
  1. GetGlobalInfoW - передать в FAR глобальную информацию о плагине (версия, автор, etc.)
  2. SetStartupInfoW - получить от FAR начальные значения, необходимые плагину
  3. GetPluginInfoW - передать в FAR информацию о плагине
  4. ConfigureW - настройки плагина: показывать ли плагин в меню выбора дисков и задание каталога по умолчанию.
  5. OpenW - пользователь вызвал плагин
  6. GetFindDataW - передача в FAR нашего каталога для позиционирования на панели
Функции GetGlobalInfoW, SetStartupInfoW, GetPluginInfoW и ConfigureW важны, но рассматривать их мы не будем дабы не потерять основную мысль. Сосредоточимся на последних двух - OpenW и GetFindDataW (для реальной панели вместе с функцией GetFindDataW должна идти FreeFindDataW, но т.к. мы панель не создаем, то FreeFindDataW сейчас использовать не будем).

Так же нам нужны будут 3 команды функции управления панелями PanelControl:
  1. FCTL_SETPANELDIRECTORY - установить нужный нам каталог в панели
  2. FCTL_REDRAWPANEL - перерисовать панель, чтобы не было артефактов прорисовки
  3. FCTL_CLOSEPANEL - заставит закрыть текущую панель с указанием каталога назначения
Вариантов вызова этого плагина два, поэтому по очереди их и рассмотрим. Начнем с простого - вызов из меню плагинов.

Вариант 1. OPEN_PLUGINSMENU

Пока мы "не знаем" как создавать свою файловую панель (да она нам сейчас и ни к чему), поэтому воспользуемся тем фактом, что в функцию PanelControl первым параметром можно передать значение PANEL_ACTIVE:
hPanel - Текущий описатель панели. При запросе информации относительно активной панели установите этот параметр равным PANEL_ACTIVE, для пассивной - PANEL_PASSIVE. Это позволяет использовать эту функцию в командах плагина без создания новой панели. Так же PANEL_ACTIVE(PANEL_PASSIVE) можно использовать для неплагиновой панели.
Далее все просто. В OpenW для активной панели (PANEL_ACTIVE) установить каталог (FCTL_SETPANELDIRECTORY), обновить панель (FCTL_REDRAWPANEL) и вернуть в FAR значение nullptr (при этом FAR сразу "закроет" плагин):

Code: Select all

HANDLE WINAPI OpenW(const struct OpenInfo *OInfo)
{
  if(Opt.DefaultFolder[0] != 0)
  {
    if(OInfo->OpenFrom == OPEN_PLUGINSMENU)
    {
      FarPanelDirectory dirInfo = {sizeof(dirInfo), Opt.DefaultFolder, nullptr, {}, nullptr};
      ::Info.PanelControl(PANEL_ACTIVE, FCTL_SETPANELDIRECTORY, 0, &dirInfo);
      ::Info.PanelControl(PANEL_ACTIVE,FCTL_REDRAWPANEL,0,nullptr);
    }
    ...
  }
  return nullptr;
}
Вариант 2. OPEN_LEFTDISKMENU/OPEN_RIGHTDISKMENU

На данном этапе известно, что FAR вызовет функцию плагина OpenW со значением OpenInfo::OpenFrom, равным OPEN_LEFTDISKMENU или OPEN_RIGHTDISKMENU. В этом случае в FAR необходимо вернуть все, что угодно, кроме nullptr. Для простоты вернем адрес переменной Opt.

Code: Select all

HANDLE WINAPI OpenW(const struct OpenInfo *OInfo)
{
  if(Opt.DefaultFolder[0] != 0)
  {
    ...
    else if(OInfo->OpenFrom == OPEN_LEFTDISKMENU || OInfo->OpenFrom == OPEN_RIGHTDISKMENU)
    {
      return (HANDLE)&Opt;
    }
  }
  return nullptr;
}
Это сделано по следующим причинам:
  • нам нужно что-то "сказать", чтобы Far Manager перешел на панели в нужный каталог; это можно сделать с помощью PanelControl(FCTL_CLOSEPANEL,"Каталог")
  • нам известно из какого меню (слева или справа) вызван плагин, но неизвестно какая из панелей активна, поэтому простым вызовом PanelControl(PANEL_ACTIVE,FCTL_CLOSEPANEL,"Каталог") не обойтись (в этом случае наш каталог всегда будет позиционироваться на активной панели, т.е. действие аналогичное варианту OPEN_PLUGINSMENU)
  • ближайшая функция, которая позволит нам позиционировать каталог с помощью PanelControl(FCTL_CLOSEPANEL,"Каталог") - это GetFindDataW: функция GetFindDataW во-первых будет вызвана тогда, когда FAR будет обновлять панели (т.е. сразу после закрытия меню), во-вторых у нее есть описатель нужной нам панели (здесь знания "активная/не активная" уже не нужны).
Вызовом функции GetFindDataW Far Manager хочет взглянуть на список наших файлов, но т.к. панели как таковой нет, то с учетом выше сказанного... просто закроем плагин, с указанием каталога:

Code: Select all

intptr_t WINAPI GetFindDataW(GetFindDataInfo *Info)
{
  ::Info.PanelControl(Info->hPanel,FCTL_CLOSEPANEL,0,(void*)Opt.DefaultFolder);
  return TRUE;
}
На этом первый этап заканчиваем. Исходники для этого "урока" можно взять здесь.
Attachments
les1.zip
Исходники и бинарники...
(12.91 KiB) Downloaded 195 times
We are the Borg. You will be assimilated.
So Say We All!

Post Reply

Return to “Энциклопедия”