Как самому сделать plug-in к FAR на Visual C++
шаг за шагом

Phoenix aka Руслан Ильгасов [phoenixbird@hotmail.ru]phoenixbird@hotmail.ru

Трудно найти человека, которые не знает или не использует Far - IMHO лучший клон NC для Windows. Кроме того, что это просто очень хороший файл менеджер, к нему есть огромное количество plug-in модулей. Plug-in модуль это DLL-файл, который вместо стандартных Windows функций по работе с монитором, клавиатурой и т.д. обращается к функциям Far-а. Far поддерживает весь набор функций для работы в текстовом режиме. Установка plug-in модуля происходит предельно просто - DLL файл и файлы данных копируются в каталог в каталоге Far\Plugins и Far перезапускается.

FAR распространяется с полным набором файлов для написания самим plug-in на любом С компиляторе для Windows. Темой этой статьи является написание этих модулей самим на Visual C++ (я использовал Visual C++ 5.0). При установке в каталог Far копируется PlugDoc.rar, в нем есть примеры plug-in-ов и header файл (ред: начиная с FAR 1.70 beta 5 примеры устанавливаются в отдельный каталог PlugDoc). Все примеры используются Еще там есть VCReadme.txt, в котором описываются тонкости работы с Visual C++. Потом поразбираетесь с примерами.

Мы с вами напишем plug-in, который получает список открытых окон Windows, он может пригодиться как заготовка для своих. И вообще - стоит начать - все это не так сложно, как можно подумать. Вот, а теперь - поехали:

  1. Запускает VC, делаем новый проект типа "Win32 Dynamic-Link Library" по имени SimpleFP. Создает файл simplefp.cpp - здесь, собственно, мы и будем писать. В каталог SimpleFP копируем header файл plugin.hpp из архива PlugDoc.rar (ред: начиная с FAR 1.70 beta 5 примеры устанавливаются в отдельный каталог PlugDoc).
  2. Теперь нам надо сделать .def файл - это файл, в котором описываются функции, которые вызываются из внешних модулей. Мы должны описать функции Far-а, которые мы будем использовать в нашем модуле. Делаем текстовый файл simplefp.def, в котором пишем:
    LIBRARY
    EXPORTS
    GetPluginInfo=_GetPluginInfo@4
    OpenPlugin=_OpenPlugin@8
    SetStartupInfo=_SetStartupInfo@4
    Здесь мы описываем 3 функции, которые нам пригодятся. А теперь добавим simpledef.def к файлам проекта (Project - Add to project - Files - simplefp.def).
  3. Теперь пишем сам plug-in - работаем с файлом simplefp.cpp. Я решил дать текст самой программы с комментариями - можно скопировать в С++ и начать с ним возиться. Но сначала о основах.

Far работает по тем же принципам, что и Windows - вы ссылаетесь в программе на те функции, уже имеющиеся в системе, которые хотите использовать. Far предоставляет функции для работы с экранными формами в режиме console application. При запуске plug-in-а Far запускает функцию OpenPlugin, мы будем ее рассматривать как аналог main() или WinMain(). Но кроме этого надо еще сообщить Far-у данные о нашем plug-in-е. Это делает функция GetPluginInfo.

/*
* SimpleFP - простой plug-in к Far-у. (С) 2000 Phoenix, Moscow
*/

#include <stdio.h>    // для вызова sprintf
#include <windows.h>  // для функций Windows
#include "plugin.hpp" // для функций Far

#define PLUGIN_NAME "Open windows"      // Название plug-in-а
#define WINDOW_HEAD "Open windows list" // Заголовок меню, которое мы сделаем

//
// Описываем функции Far, которые с которыми мы работаем.
//

extern "C"
{
void WINAPI _export SetStartupInfo(struct PluginStartupInfo *Info);
HANDLE WINAPI _export OpenPlugin(int OpenFrom,int Item);
void WINAPI _export GetPluginInfo(struct PluginInfo *Info);
};

static struct PluginStartupInfo Info; // Информация о нашем plug-in-е

//
// Информация о модуле определена нами в структуре Info
//

void WINAPI _export SetStartupInfo(struct PluginStartupInfo *Info)
{
  ::Info=*Info;
}

// Эта функция вызывается для получения информации о plug-in.
// Мы должны заполнить поля структуры Info.
//

void WINAPI _export GetPluginInfo(struct PluginInfo *Info)
{
  Info->StructSize=sizeof(*Info); // Размер структуры Info
  Info->Flags=0; // Это нам не нужно
  Info->DiskMenuStringsNumber=0; // Это нам тоже не нужно

  // Определяем строку с названием модуля
  static char *PluginMenuStrings[1];
  PluginMenuStrings[0]= PLUGIN_NAME;

  // Определяем название plug-in модуля
  Info->PluginMenuStrings=PluginMenuStrings;
  Info->PluginMenuStringsNumber=
    sizeof(PluginMenuStrings)/sizeof(PluginMenuStrings[0]);
  Info->PluginConfigStringsNumber=0; // Это нам не нужно
}

// Эта функция вызывается при запуске plug-in модуля.
//

HANDLE WINAPI _export OpenPlugin(int OpenFrom,int Item)
{
  HWND hwnd; // Используем для получения handle
  char p[128], o[128]; // Для создания строк меню
  int i=0; // Счетчик

  struct FarMenuItem MenuItems[64]; // Описание меню, которое создаст для нас Far
  memset(MenuItems,0,sizeof(MenuItems)); // Инициализируем наше меню
  MenuItems[0].Selected=TRUE;

  hwnd = GetDesktopWindow(); // Получаем handle для desktop
  hwnd = GetWindow(hwnd, GW_CHILD); // Получаем его handle
  while (hwnd !=0) // Пока оно не последнее
  {
    hwnd = GetWindow(hwnd, GW_HWNDNEXT); // получим handle окна
    GetWindowText(hwnd,p,128); // и его заголовок
    if (strlen(p)>0) // если заголовок есть
    {
      sprintf(o,"%0.8xld %s", hwnd, p); // сделаем строчку
      strcpy(MenuItems[i++].Text, o); // скопируем эту строчку в массив MenuItems
    }
  }

  // вызываем созданное нами меню, получаем номер выбранного пункта - MenuCode
  //
  int MenuCode=Info.Menu(Info.ModuleNumber,
                  -1,-1,0,
                  FMENU_AUTOHIGHLIGHT|FMENU_WRAPMODE,
                  WINDOW_HEAD,
                  NULL,
                  "Menu content",
                  NULL,
                  NULL,
                  MenuItems,
                  i);

  return(INVALID_HANDLE_VALUE);
}

Компилируйте, копируйте в Far\Plugin и перезапускайте Far. В Far-е нажмите F11 - это список plug-in модулей. Теперь в нем должна появиться строка Open windows. Посмотрите на результат. Теперь можно развивать, например - обрабатывая результат MenuCode посылать выбранному окну сообщение WM_CLOSE, или сделать еще что-нибудь нетривиальное :) Создание plug-in модулей к Far-у документировано замечательно, разбирайтесь.

В поставку Энциклопедии входит архив simplefp.zip - пример DLL файла (~20Кб)

Phoenix aka Руслан Ильгасов, Москва
E-Mail:phoenixbird@hotmail.ru
FIDO: 2:5020/2637.2
 
13.05.2000
наверх