Far Manager插件编写2

在上一篇中,插件显示在插件菜单栏中,但是我们还没有实现该插件的功能。

开始之前,我们先来科普一下,在Far Manager中调用插件的几种方法,除了从插件菜单中调用插件,Far Manager还提供了Alt+F1(左侧硬盘菜单)、Alt+F2(右侧硬盘菜单)、宏、lua宏、文件查找结果列表、命令行、编辑器、文件面板、对话框等等。可以说在几乎在任意位置都能调用插件。

要插件实现功能,我们需要导出OpenW函数。当打开插件时会调用OpenW,OpenInfo记录了该插件被触发的信息。结构如下:

struct OpenInfo
{
  size_t StructSize;  //结构大小
  enum OPENFROM OpenFrom;  //触发方式
  const GUID *Guid;  //如果是通过插件菜单打开的,则该guid是插件菜单guid,如果是宏则是宏的guid。
  intptr_t Data; //取决于OpenFrom,不同触发方式,该字段表示的数据不同
};

Message

在OpenW中我们可以根据OpenFrom打开插件方式的不同来实现不同的功能。这里就实现一个小小功能弹一个消息框。

HANDLE WINAPI OpenW(const struct OpenInfo *Info)
{
    OPENFROM OpenFrom = Info->OpenFrom;
    //从插件菜单打开
    if (OpenFrom == OPEN_PLUGINSMENU)//从插件菜单触发插件
    {
        MessageBox(NULL, L"通过插件菜单调用插件", L"Test", NULL);
    }
    return NULL; 
}

按F11弹出插件菜单时点击插件名会弹出消息框。

其实Far Manager自己也有自己的Message显示方式。

这都是通过PluginStartupInfo结构的Message成员来实现的。

// {14FBA90A-2ED8-4780-970F-57C7DA73B4BC}
static const GUID messageID =
{ 0x14fba90a, 0x2ed8, 0x4780,{ 0x97, 0xf, 0x57, 0xc7, 0xda, 0x73, 0xb4, 0xbc } };

HANDLE WINAPI OpenW(const struct OpenInfo *Info)
{
    OPENFROM OpenFrom = Info->OpenFrom;

    //从插件菜单打开
    if (OpenFrom == OPEN_PLUGINSMENU)
    {
    //psi就是上一篇创建的PluginStartupInfo结构,后面不再解释
    const wchar_t *Msg[4];
        Msg[0] = L"Test";
        Msg[1] = L"通过插件菜单调用插件\n";
        Msg[2] = L"OK";
        Msg[3] = L"Cancel";

        psi.Message(
            &guid_PluginGuid,    //插件guid
            &messageID,   //Message guid,
            0, //flag
            L"Show Message",  //在帮助文件中的相关下信息
            Msg,//message 内容
            4,  //字符个数
            2   //按钮个数
            );
    }
    return NULL;
}

在上面这些例子中,我们都是直接使用字符串做参数,但是Far Manager并不提倡我们这样做,而是另外提供了一个函数GetMsg来从文件中取得字符串。这个文件后缀.lng,也就是语言文件,创建多个不同语言版本的.lng文件,每个文件的每一行对应一个字符串的不同语言,也就实现了一个多语言版本的插件。.lng语言内容格式如下:
这个函数也是在PluginStartupInfo结构中中的成员。

.Language=English,English

"Menu1"
"Menu2"
"Menu3"
"Menu4"

GetMsg接收参数:插件guid和字符串在文件中的行数,返回所在行对应的字符串。
也就是说GetMsg(&guid_PluginGuid,0)返回Menu1,GetMsg(&guid_PluginGuid,1)返回Menu2……
后面的例子就使用GetMsg函数来使用字符串,不再另行说明。

static const GUID MenuGuid =
{ 0xe02ce6f7, 0xc913, 0x479a,{ 0x9f, 0xfc, 0x74, 0xca, 0xd7, 0xe1, 0xbe, 0xbf } };

HANDLE WINAPI OpenW(const struct OpenInfo *Info)
{
    OPENFROM OpenFrom = Info->OpenFrom;

    //从插件菜单打开
    if (OpenFrom == OPEN_PLUGINSMENU)
    {
        FarMenuItem MenuItems[4];
        //使用的上个例子创建的lng文件。给每个菜单项的显示文本赋值。
        for (int i = 0; i < 4; i++)
        {
            MenuItems[i].Text = psi.GetMsg(&guid_PluginGuid,i);
        }

        psi.Menu(
            &guid_PluginGuid,  //插件guid
            &MenuGuid,   //菜单guid
            -1, -1, //x,y坐标。-1是自动设置合适的大小
            0,//设置显示的最大高度,如果菜单项多了,高度大于最大高度,则会出现滚动条,不使用设0;
            FMENU_AUTOHIGHLIGHT | FMENU_WRAPMODE,  //flag
            L"First Plugin Menu",
            NULL,  //帮助主题
            NULL,
            NULL,NULL,  //这两项是用来设置菜单的快捷键的。
            MenuItems, //菜单项
            4 //个数
            );
    }
    return NULL;
}

InputBox

接下来介绍输入框,它能够接收用户的输入,并赋值到一个变量。

// {14FBA90A-2ED8-4780-970F-57C7DA73B4BC}
static const GUID messageGuid =
{ 0x14fba90a, 0x2ed8, 0x4780,{ 0x97, 0xf, 0x57, 0xc7, 0xda, 0x73, 0xb4, 0xbc } };

HANDLE WINAPI OpenW(const struct OpenInfo *Info)
{
    OPENFROM OpenFrom = Info->OpenFrom;

    wchar_t destName[MAX_PATH * 2] = {L""};
    //从插件菜单打开
    if (OpenFrom == OPEN_PLUGINSMENU)
    {
        psi.InputBox(&guid_PluginGuid, 
                   &messageGuid, 
                   L"Test", L"Test2", NULL, NULL,
                  destName, sizeof(destName), //用户输入的数据保存在destName中
                   NULL, FIB_NONE);
    }
    return NULL;
}

上面介绍的Message、Menu和GetMsg、InputBox都是在PluginStartupInfo结构中定义的,如果我们前面没有导出SetStartupInfoW获取该结构的值,那我们也无法使用这些功能。

×

纯属好玩

扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

文章目录
  1. 1. Message
  2. 2. Menu显示
  3. 3. InputBox
,