Windows環境で動作するテキストエディタの定番「秀丸エディタ」は、その豊富なマクロ資産に定評があります。
hm.NETは、秀丸エディタのマクロからC#で作ったプログラムを呼び出すライブラリです。つまり、C#で、秀丸エディタのマクロを作成できます。これを使うことにより、秀丸エディタのマクロの可能性が更に広がります。
hm.NET (秀丸マクロ用 .NET Framework ライブラリ via C#)
まず、ダウンロードしたhm.NET.dll を秀丸エディタのディレクトリ内(hidemaru.exeと同じ場所)へと コピーします。 hm.NET.dllには、使用している秀丸エディタが、32bit版か64bit版かに応じて、それぞれのhm.NET.dllが存在します。
C#と秀丸エディタでやり取りする変数型
秀丸エディタには、C#ほど変数型がありません。秀丸エディタのマクロと値のやり取りに使用できる変数型は限られています。
- System.IntPtr 数値
- System.String 文字列
IntPtrなのは、秀丸マクロが「32bit版だと数値が32bit」「64bit版だと数値が64bit」のためです。
C#でC#のdllあるいはexeファイルを作成する
それでは、C#でdllを作成します。Visual Studioで「新しいプロジェクト」を作成します。※ Visual Studio Community 2017を使用しています。
hm.NET.dll を使えば、C#側のメソッドを秀丸マクロ側から呼び出すことができます。特に、dill形式である必要もありません。この説明では、「WPFアプリ」のテンプレートを使いました。
「フォーム」で作成する場合については、「フォームを利用するパターン」を参照して下さい。
「hm.NET.dll」を参照に追加する
hm.Netには、秀丸を操作するためのクラスが用意されています。そのクラスを使用するためには、「hm.NET.dll」を参照に追加します。
「参照」ボタンを押して、秀丸エディタのインストールフォルダまで移動して、「hm.NET.dll」を選択して下さい。
hm.Netで用意されているクラスを使用する方法については、「入門編の基本となるクラス」を参照して下さい。
コンパイルする際は、「ディバッグ」ではなく、「ビルド」を使用して下さい。
ボタンを配置する
UserControl.xamlにボタンを配置します。
<Window x:Class="TextInsert01.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="150" Width="200">
<Grid>
<Button Name="btn0" HorizontalAlignment="Center" VerticalAlignment="Center"
Width="100" Height="50" Click="btn0_Click">
押してね。
</Button>
</Grid>
</Window>
デザイナーで、ツールを使って、ボタンを配置しても構いませんが、基本的なUIのxamlコードは、作成するたびにまとめておき、xamlコードをコピーして使用すると便利かと思います。
単純なUIを持つアプリケーションで使用するxamlコードについては、「単純なデザインのウィンドウ」が活用できます。
マクロから呼び出すメソッドと終了を知らせるメソッド
秀丸エディタのマクロから呼び出すメソッドを作成します。hm.NET.dll の参照を追加しておけば、秀丸エディタのマクロからメソッドを呼び出すことができます。この部分は、処理する内容が変化しても変わらないと思います。
マクロから呼び出すメソッドの名前は、秀丸エディタのマクロで呼び出す際に明示するので、名前は任意です。ここでは、「CreateForm」という名前にしています。このメソッドは、メインウィンドウを表示します。
秀丸エディタが終了した時を確認するクラスは、「プロセス終了時に実行するメソッドの指定」で紹介されているOnDetathMethod()です。
public class HmEntry
{
public static Window WpfForm;
public static IntPtr CreateForm()
{
// 秀丸マクロから呼び出されたときに実行されるメソッド
if (WpfForm != null)
{
WpfForm.Close();
WpfForm = null;
}
WpfForm = new MainWindow();
WpfForm.Show();
return (IntPtr)1;
}
public static IntPtr OnDetathMethod()
{
// 秀丸エディタが閉じられる前に実行されるコード
// このWPFアプリケーションを終了します。
if (WpfForm != null)
{
WpfForm.Close();
WpfForm = null;
}
return (IntPtr)1;
}
}
ボタンのクリックイベントを記述する
ボタンをクリックして、イベントコードを追加します。
カーソル位置にテキストを挿入するコードを記入します。詳細については、「入門編 ~秀丸でカーソルの行のテキスト~」を参考にして下さい。
ボタンが押されたことを確認するために、ボタンが押されたときに色を変更します。
「Hm.Edit.LineText」は、秀丸エディタのカーソル行のテキスト全体を表しています。そのため、カーソル行に文字列を挿入する場合は、工夫が必要です。
using Hidemaru;
using System;
using System.Windows;
using System.Windows.Media;
private void btn0_Click(object sender, RoutedEventArgs e)
{
// ボタンの色を変更する
var bc = new BrushConverter();
btn0.Background = (Brush)bc.ConvertFrom("#FFE21C1C");
// カーソル位置にテキストを挿入
Hm.Edit.LineText = "ボタンを押した";
}
MainWindow.xaml.csの内容
MainWindow.xaml.csの内容は、以下のように記述しました。(TextInsert01)
using Hidemaru;
using System;
using System.Windows;
using System.Windows.Media;
namespace TextInsert01
{
///
/// MainWindow.xaml の相互作用ロジック
///
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
// カーソル位置にテキストを挿入
Hm.Edit.LineText = "開始";
}
private void btn0_Click(object sender, RoutedEventArgs e)
{
// ボタンの色を変更する
var bc = new BrushConverter();
btn0.Background = (Brush)bc.ConvertFrom("#FFE21C1C");
// カーソル位置にテキストを挿入
Hm.Edit.LineText = "ボタンを押した";
}
}
public class HmEntry
{
public static Window WpfForm;
public static IntPtr CreateForm()
{
// 秀丸マクロから呼び出されたときに実行されるメソッド
if (WpfForm != null)
{
WpfForm.Close();
WpfForm = null;
}
WpfForm = new MainWindow();
WpfForm.Show();
return (IntPtr)1;
}
public static IntPtr OnDetathMethod()
{
// 秀丸エディタが閉じられる前に実行されるコード
// このWPFアプリケーションを終了します。
if (WpfForm != null)
{
WpfForm.Close();
WpfForm = null;
}
return (IntPtr)1;
}
}
}
c#アプリケーションを呼び出す秀丸エディタマクロを作成する
dllfuncw内で、ファイル名、名前空間名、クラス名、メソッド名を明示して呼び出します。「SetDetachMethod」が、秀丸エディタが終了した際に呼び出されるメソッドです。「CallMethod」が、マクロが実行された際に呼び出されるメソッドです。
#HMNET = loaddll( hidemarudir + @"\hm.NET.dll" );
#r = dllfuncw( #HMNET, "SetDetachMethod", currentmacrodirectory + @"\TextInsert01.exe", "TextInsert01.HmEntry", "OnDetathMethod");
#r = dllfuncw( #HMNET, "CallMethod", currentmacrodirectory + @"\TextInsert01.exe", "TextInsert01.HmEntry", "CreateForm");
実行する
マクロフォルダに、C#で作成したexeファイルとc#アプリケーションを呼び出す秀丸エディタマクロを格納して、マクロを呼び出します。
その結果、実行時に挿入される文字列「開始」は、挿入されるものの、ボタンを押した後に挿入されるはずの「ボタンを押した」は、挿入されません。(ボタンを押したのでボタンは、赤くなった。)
これは、フォームが表示された時点で、秀丸エディタの側のマクロが終了してるためです。hm.netでは、テキスト内容の読み取りは「常時」、一方テキスト内容の書き換えは「マクロ実行中」のみしか行えません。
詳細は、「入門編 ~秀丸で編集しているテキスト~」を参照して下さい。
ボタンを押してマクロを実行させる方法
C#を活用してマクロを作成する場合、UIメニューを用意して、ボタンをクリックするなどのイベントで、マクロを実行することが目的の1つだと思います。そこで、「ボタンを押してマクロを実行させる方法」を考えることで、イベントで、秀丸エディタを操作する方法について整理します。
紹介する内容のほとんどは、秀丸エディタマクロ作成者会議室で、vscode-life さん によって紹介された内容です。(08675から始まるスレッドです)
マクロ実行中を維持する
- 利点:記述が簡単
- 欠点:秀丸エディタでは、同時に1つのマクロのみが実行可能なため、他のマクロが実行できません。
Formを表示する際、showメソッドではなく、ShowDialog メソッドを使用すれば、モーダルで実行されるため、マクロ実行中が維持されます。そのため、ボタンで実行する内容が動作します。
コード抜粋(TextInsert02)
public class HmEntry
{
public static Window WpfForm;
public static IntPtr CreateForm()
{
// 秀丸マクロから呼び出されたときに実行されるメソッド
if (WpfForm != null)
{
WpfForm.Close();
WpfForm = null;
}
WpfForm = new MainWindow();
WpfForm.ShowDialog();
return (IntPtr)1;
}
新たなマクロを文字列で発行する
次の方法は、モーダルで実行し、マクロ実行中を維持するのではなく、ボタンが押された瞬間に「新たなマクロを文字列で発行する」です。
- 利点:マクロ実行中を維持する必要がない。
- 欠点:文字列で、実行するマクロを発行する必要がある(結構手間)
コード抜粋(TextInsert03)
private void btn0_Click(object sender, RoutedEventArgs e)
{
// ボタンの色を変更する
var bc = new BrushConverter();
btn0.Background = (Brush)bc.ConvertFrom("#FFE21C1C");
// カーソル位置にテキストを挿入
// マクロが実行されていないなれば…
if (!Hm.Macro.IsExecuting)
{
// マルチバイトの文字列の範囲を超えてしまうと文字化けを起こすという弱点あり
string message = "テスト\n\tテスト\n";
MyInsertFunc(message);
}
}
private void MyInsertFunc(string message)
{
// 秀丸マクロの「R」を上手く使うことで、エスケープ文字の使用を回避できる
string expression = String.Format(@"insert R""RAW({0})RAW""", message);
// 改めてマクロを実行する
Hm.Macro.Exec.Eval(expression);
}
ファイル名でマクロを実行する
hm.NETでは「秀丸マクロが実行されていない時、秀丸マクロを改めて実行する」ことが出来ます。
Hm.Macro.Exec.File("ファイルのフルパス")
参考「入門編 ~秀丸マクロを改めて実行(ファイル指定編)~」
C#で、作成したプログラムから、秀丸マクロを実行する場合、秀丸マクロフォルダのファイルパスを取得したいと考えると思います。
hm.NETでは秀丸マクロで定義されている変数(秀丸マクロからあらかじめ提供されているもの、ユーザーが独自に定義したもののどちらでも)を取得、 値を書き換えることが出来ます。
参考「入門編 ~秀丸マクロ上の変数の値を読み取る・書き換える~」
Hm.Macro.Var["変数名"]
マクロファイル用のフォルダ は、「macrodir 」です。 macrodirで取得するフォルダ名のテキストの末尾には、「\」がつかないことに注意して下さい。
コード抜粋(TextInsert04)
public partial class MainWindow : Window
{
public string macrodir; // 秀丸マクロディレクトリ
public MainWindow()
{
InitializeComponent();
// カーソル位置にテキストを挿入
Hm.Edit.LineText = "開始";
// マクロディレクトリを取得
macrodir = (string)(dynamic)Hm.Macro.Var["macrodir"];
// メッセージボックスで、マクロディレクトリの内容を確認する
// MessageBox.Show(macrodir);
}
private void btn0_Click(object sender, RoutedEventArgs e)
{
// ボタンの色を変更する
var bc = new BrushConverter();
btn0.Background = (Brush)bc.ConvertFrom("#FFE21C1C");
// 秀丸マクロを実行する
Hm.Macro.Exec.File(macrodir + @"\TextInsert00.mac");
}
}
TextInsert00.mac
// "ボタンを押した"を挿入する
insert "ボタンを押した" ;
hm.netを使って、C#のWPFアプリから、秀丸エディタを操作する方法と、秀丸マクロを実行する方法について紹介しました。クセはあるもののUIメニューを使ったマクロを作成したい時に活用できそうな気がします。
サンプルコード
注意:hm.NET.dll を秀丸エディタのディレクトリ内(hidemaru.exeと同じ場所)へと コピーしておく必要があります。
呼び出し側のマクロ(*.mac)と呼び出される側のマクロ(*.exe)は、秀丸マクロフォルダに入れておく必要があります。
「ディバッグビルド」でコンパイルするとエラーが発生します。「ソリューションのビルド」あるいは「ソリューションのリビルド」を使用してコンパイルすることをお勧めします。
- hmNetSample.zip
(*.mac)と(*exe)ファイルが含まれています。
- hmNetProjects.zip
C#のプロジェクトフォルダが含まれています。