戻る

DelphiでCharu3プラグインを作る

DelphiでCharu3プラグインを作る際にハマった事や参照した場所等をメモしていきます。



ソフト公開

DelphiでCharu3プラグインを作るサンプルソース&DLL

DelphiでCharu3のプラグインを作る方法が書かれているソースが入っています。

ダウンロード

80x15.png この作品はクリエイティブ・コモンズ・ライセンスの下でライセンスされています。

DelphiTControlToName

 DelphiのIDE(統合開発環境)で、TControlから派生したクラス(見えているコンポーネント全てです)をコピーして、このプラグインを通すと、コピーしたクラスのNameプロパティのリストが改行区切りで返されます。

ダウンロード

80x15.png この作品はクリエイティブ・コモンズ・ライセンスの下でライセンスされています。

LoadHtmlHelp_Charu3

 設定されたHtmlHelpファイルを開いて、選択されていた文字列で検索します。
 プログラミング言語のリファーレンスマニュアルがHtmlHelpファイルであれば、エディタ上で関数等を選択してヘルプを引けるようになるので、便利だと思います。

ダウンロード
2/25バグ発見!ただいま修正中です

#ref(): File not found: "LoadHtmlHelp_Charu3_100.LZH" at page "DelphiでCharu3プラグインを作る"

80x15.png この作品はクリエイティブ・コモンズ・ライセンスの下でライセンスされています。

はまり雑記

参考にしたページ

  • KeiziWeb ver 4.3 Charu3
    クリップボード拡張+入力支援ソフト「Charu3」のダウンロードページです。
    ここに一緒にある「プラグイン開発キット」の内容を元しています。
  • Delphiメーリングリスト
    Delphiのメーリングリストです。
    今回プラグインを作るに当たって、はまっていた内容をこのメーリングリストで教えていただきました。
  • About Delphi
    Delphiのメーリングリストの過去ログが置いてあります。

DelphiでCharu3プラグインを作るサンプルソース

  • S-JIS版
    library CharuPlugInTest;
    
    uses
      SysUtils,
      Classes,
      Windows,
      System,
      Messages;
    
    {$R *.res}
    
    (*
    // Charu3DLL_SRC\Plugins\addBR\replace.cppのソース引用
    // Cの場合の構造体
    //---------------------------------------------------
    // データ構造体
    //---------------------------------------------------
    struct STRING_DATA
    {
    	char	m_cKind;		//データ種別
    	char	m_cIcon;		//アイコン種別
    	int		m_nMyID;		//データのID
    	int		m_nParentID;	//親データのID
    	time_t	m_timeCreate;	//作成日時
    	time_t	m_timeEdit;		//変更日時
    	CString  m_strTitle;	//設定データタイトル
    	CString  m_strData;		//設定データ文字列
    	CString  m_strMacro;	//拡張用文字列データ
    };
    *)
    
    // Delphiの場合の構造体
    // ---------------------------------------------------
    type
      TSTRING_DATA = record
        m_cKind: Char;         // データ種別         (Charu3:種類)
                               //   1:一時データ 2:ロック
        m_cIcon: Char;         // アイコン種別       (Charu3:アイコン)
                               //   0:普通ロック項目 1:日時 時間系 2:ファイル実行
                               //   3:関連付け実行 4:文字列選択 5:クリップボード
                               //   6:プラグイン 7:キー入力 255:自動選択
        m_nMyID: Integer;      // データのID         (何を示したIDなのか不明)
        m_nParentID: Integer;  // 親データのID       (何を示したIDなのか不明)
        m_timeCreate: LongInt; // 作成日時
                               //   (暦時間(カレンダー時間)形式の作成日時)
        m_timeEdit: LongInt;   // 変更日時
                               //   (暦時間(カレンダー時間)形式の変更日時)
        m_strTitle: Pointer;   // 設定データタイトル (Charu3:名前)
        m_strData: Pointer;    // 設定データ文字列   (Charu3:テキスト編集のテキスト)
        m_strMacro: Pointer;   // 拡張用文字列データ (Charu3:拡張マクロ)
      end;
      PSTRING_DATA = ^TSTRING_DATA;
    // ---------------------------------------------------
    
    
    // [Delphi-ML:20584] Re: time_t -> TDateTime ?
    // を参考にしたtime_t -> TDateTimeの関数。
    // ---------------------------------------------------
    const
      cStart    = 25569.0;  // = EncodeDate( 1970, 1, 1 )
      cSecPerDay = 86400.0;  // 1日あたりの秒数
      cAdjust    = 9 / 24;  // 時間帯の調整
    
    function time_tToDateTime(t: LongInt): TDateTime;
    begin
      Result := (cStart * cSecPerDay + t) / cSecPerDay + cAdjust;
    end;
    
    function DateTimeTotime_t(d: TDateTime): LongInt;
    begin
      Result := Round((d - cStart - cAdjust) * cSecPerDay);
    end;
    // ---------------------------------------------------
    
    (*
    // Cの場合の関数宣言
    // Charu3DLL_SRC\Plugins\addBR\replace.cppのソース引用
    extern "C" __declspec (dllexport) bool CharuPlugIn
    	(TCHAR *strSource,TCHAR *strResult,int nSize,STRING_DATA *data,void *pVoid)
    *)
    
    (*
    // Charu3DLL_SRC\readme.htmlのマニュアル引用
    ■テキスト処理プラグイン
     簡単な関数を一つ実装すればテキスト処理プラグインを作ることが出来ます。
     TCHARはMBCSの時はcharになり、Unicodeの場合はwchar_tになります。
    
    bool CharuPlugIn(TCHAR *strSource,TCHAR *strResult,int nSize,STRING_DATA *data,void *pVoid);
    □TCHAR *strSource 
     処理の元になるテキストデータが入ってきます。$SELなどのマクロは置換されたあとです。
    
    □TCHAR *strResult
     結果のテキストを格納します。 
    
    □int nSize
     結果のテキストを格納するバッファのサイズです。最低で10kbあります。
     大きなテキストを扱う場合は、このバッファのサイズも大きく確保されます。
    
    □STRING_DATA *data
     選択していたデータの元です。
     拡張マクロやID、作成時間や変更時間などのデータも取れます。$SELなどのマクロも置換前の状態です。拡張マクロにオリジ ナルの機能を持たせたりすることも出来ます。
    
    □void *pVoid
     拡張用ポインタでしたが、現在は貼り付けのターゲットになるウィンドウのハンドルが
    入ってきます。使う場合はキャストして使ってください。
     将来変更される可能性もなきにしもあらずですけど。
    *)
    
    
    // [Delphi:89848] Re: VC++で作られたソフトのプラグインDLLの作成
    // を参考にして、関数の呼び出し規約をcdeclにしています
    
    // Delphiの場合、TCHARはMBCSの時はPCharになり、Unicodeの場合はPWideCharになる?
    
    // Charu3 S-JIS版
    function CharuPlugIn(
      strSource: PChar; strResult: PChar; nSize: integer;
      data: PSTRING_DATA; pVoid: Pointer): BOOL; cdecl;
    var
      WkStrSource: string;
      WkStrResult: string;
    
      Wkm_strTitle: string;
      Wkm_strData: string;
      WKm_strMacro: string;
    
      Wkm_cKind: Char;
      Wkm_cIcon: Char;
    
      Wkm_nMyID: Integer;
      Wkm_nParentID: Integer;
    
      Wkm_timeCreate2: TDateTime;
      Wkm_timeEdit2: TDateTime;
    
      WkpVoid: HWND;
    begin
      try
        // String型にコピーする
        WkStrSource := strSource;
    
        // data.m_cKindの保持
        Wkm_cKind := data.m_cKind;
        // data.m_cIconの保持
        Wkm_cIcon := data.m_cIcon;
    
        // data.m_nMyIDの保持
        Wkm_nMyID := data.m_nMyID;
        // data.m_nParentIDの保持
        Wkm_nParentID := data.m_nParentID;
    
        // data.m_timeCreateはCのtime_t型なのでTDateTime型に変換&コピー
        Wkm_timeCreate2 := time_tToDateTime(data.m_timeCreate);
        // data.m_timeEditはCのtime_t型なのでTDateTime型に変換&コピー
        Wkm_timeEdit2 := time_tToDateTime(data.m_timeEdit);
    
        // String型にコピーする
        Wkm_strTitle := PChar(data.m_strTitle);
        // String型にコピーする
        Wkm_strData := PChar(data.m_strData);
        // String型にコピーする
        Wkm_strMacro := PChar(data.m_strMacro);
    
        // pVoidをHWND型に変換する
        WkpVoid := HWND(pVoid^);
    
        //---------------ここからコードを書くといいです---------------------
    
        // strSourceがきちんと受け取れているかのテストコード
        MessageBox(0, PChar('strSource [' + WkStrSource + ']'), '情報',
          MB_OK or MB_ICONINFORMATION or MB_TASKMODAL);
    
        // data.m_cKindがきちんと受け取れているかのテストコード
        MessageBox(0, PChar('data.m_cKind [' + IntToStr(Integer(Wkm_cKind)) + ']'), '情報',
          MB_OK or MB_ICONINFORMATION or MB_TASKMODAL);
        // data.m_cIconがきちんと受け取れているかのテストコード
        MessageBox(0, PChar('data.m_cIcon [' + IntToStr(Integer(Wkm_cIcon)) + ']'), '情報',
          MB_OK or MB_ICONINFORMATION or MB_TASKMODAL);
    
        // data.m_nMyIDがきちんと受け取れているかのテストコード
        MessageBox(0, PChar('data.m_nMyID [' + IntToStr(Wkm_nMyID) + ']'), '情報',
          MB_OK or MB_ICONINFORMATION or MB_TASKMODAL);
        // data.m_nParentIDがきちんと受け取れているかのテストコード
        MessageBox(0, PChar('data.m_nParentID [' + IntToStr(Wkm_nParentID) + ']'), '情報',
          MB_OK or MB_ICONINFORMATION or MB_TASKMODAL);
    
        // TDateTime型に変換されたdata.m_timeCreateがきちんと受け取れているかのテストコード
        MessageBox(0, PChar(
          'data.m_timeCreate(TDateTime) [' + DateTimeToStr(Wkm_timeCreate2) + ']'),
          '情報',
          MB_OK or MB_ICONINFORMATION or MB_TASKMODAL);
        // TDateTime型に変換されたdata.m_timeEditがきちんと受け取れているかのテストコード
        MessageBox(0, PChar(
          'data.m_timeEdit(TDateTime) [' + DateTimeToStr(Wkm_timeEdit2) + ']'),
          '情報',
          MB_OK or MB_ICONINFORMATION or MB_TASKMODAL);
    
        // data.m_strTitleがきちんと受け取れているかのテストコード
        MessageBox(0, PChar('data.m_strTitle [' + Wkm_strTitle + ']'), '情報',
          MB_OK or MB_ICONINFORMATION or MB_TASKMODAL);
        // data.m_strDataがきちんと受け取れているかのテストコード
        MessageBox(0, PChar('data.m_strData [' + Wkm_strData + ']'), '情報',
          MB_OK or MB_ICONINFORMATION or MB_TASKMODAL);
        // data.m_strMacroがきちんと受け取れているかのテストコード
        MessageBox(0, PChar('data.m_strMacro [' + Wkm_strMacro + ']'), '情報',
          MB_OK or MB_ICONINFORMATION or MB_TASKMODAL);
    
        // pVoidがきちんと受け取れているかのテストコード
        MessageBox(0, PChar('pVoid [' + IntToStr(WkpVoid) + ']'), '情報',
          MB_OK or MB_ICONINFORMATION or MB_TASKMODAL);
    
        // 受け取ったstrSourceの文字列を'<'で囲う加工をするテストコード
        WkStrResult := '<' +  WkStrSource + '>';
    
        //---------------ここまでコードを書くといいです---------------------
    
        // 値は直接strResultに入れる
        StrLCopy(strResult, PChar(WkStrResult), nSize);
    
        result := True;
      except
        result := False;
        Exit;
      end;
    end;
    
    exports
      CharuPlugIn;
    
    end.
  • Unicode版
    library CharuPlugInTestu;
    
    uses
      SysUtils,
      Classes,
      Windows,
      System,
      Messages;
    
    {$R *.res}
    
    (*
    // Charu3DLL_SRC\Plugins\addBR\replace.cppのソース引用
    // Cの場合の構造体
    //---------------------------------------------------
    // データ構造体
    //---------------------------------------------------
    struct STRING_DATA
    {
    	char	m_cKind;		//データ種別
    	char	m_cIcon;		//アイコン種別
    	int		m_nMyID;		//データのID
    	int		m_nParentID;	//親データのID
    	time_t	m_timeCreate;	//作成日時
    	time_t	m_timeEdit;		//変更日時
    	CString  m_strTitle;	//設定データタイトル
    	CString  m_strData;		//設定データ文字列
    	CString  m_strMacro;	//拡張用文字列データ
    };
    *)
    
    // Delphiの場合の構造体
    // ---------------------------------------------------
    type
      TSTRING_DATA = record
        m_cKind: Char;         // データ種別         (Charu3:種類)
                               //   1:一時データ 2:ロック
        m_cIcon: Char;         // アイコン種別       (Charu3:アイコン)
                               //   0:普通ロック項目 1:日時 時間系 2:ファイル実行
                               //   3:関連付け実行 4:文字列選択 5:クリップボード
                               //   6:プラグイン 7:キー入力 255:自動選択
        m_nMyID: Integer;      // データのID         (何を示したIDなのか不明)
        m_nParentID: Integer;  // 親データのID       (何を示したIDなのか不明)
        m_timeCreate: LongInt; // 作成日時
                               //   (暦時間(カレンダー時間)形式の作成日時)
        m_timeEdit: LongInt;   // 変更日時
                               //   (暦時間(カレンダー時間)形式の変更日時)
        m_strTitle: Pointer;   // 設定データタイトル (Charu3:名前)
        m_strData: Pointer;    // 設定データ文字列   (Charu3:テキスト編集のテキスト)
        m_strMacro: Pointer;   // 拡張用文字列データ (Charu3:拡張マクロ)
      end;
      PSTRING_DATA = ^TSTRING_DATA;
    // ---------------------------------------------------
    
    
    // [Delphi-ML:20584] Re: time_t -> TDateTime ?
    // を参考にしたtime_t -> TDateTimeの関数。
    // ---------------------------------------------------
    const
      cStart    = 25569.0;  // = EncodeDate( 1970, 1, 1 )
      cSecPerDay = 86400.0;  // 1日あたりの秒数
      cAdjust    = 9 / 24;  // 時間帯の調整
    
    function time_tToDateTime(t: LongInt): TDateTime;
    begin
      Result := (cStart * cSecPerDay + t) / cSecPerDay + cAdjust;
    end;
    
    function DateTimeTotime_t(d: TDateTime): LongInt;
    begin
      Result := Round((d - cStart - cAdjust) * cSecPerDay);
    end;
    // ---------------------------------------------------
    
    (*
    // Cの場合の関数宣言
    // Charu3DLL_SRC\Plugins\addBR\replace.cppのソース引用
    extern "C" __declspec (dllexport) bool CharuPlugIn
    	(TCHAR *strSource,TCHAR *strResult,int nSize,STRING_DATA *data,void *pVoid)
    *)
    
    (*
    // Charu3DLL_SRC\readme.htmlのマニュアル引用
    ■テキスト処理プラグイン
     簡単な関数を一つ実装すればテキスト処理プラグインを作ることが出来ます。
     TCHARはMBCSの時はcharになり、Unicodeの場合はwchar_tになります。
    
    bool CharuPlugIn(TCHAR *strSource,TCHAR *strResult,int nSize,STRING_DATA *data,void *pVoid);
    □TCHAR *strSource 
     処理の元になるテキストデータが入ってきます。$SELなどのマクロは置換されたあとです。
    
    □TCHAR *strResult
     結果のテキストを格納します。 
    
    □int nSize
     結果のテキストを格納するバッファのサイズです。最低で10kbあります。
     大きなテキストを扱う場合は、このバッファのサイズも大きく確保されます。
    
    □STRING_DATA *data
     選択していたデータの元です。
     拡張マクロやID、作成時間や変更時間などのデータも取れます。$SELなどのマクロも置換前の状態です。拡張マクロにオリジ ナルの機能を持たせたりすることも出来ます。
    
    □void *pVoid
     拡張用ポインタでしたが、現在は貼り付けのターゲットになるウィンドウのハンドルが
    入ってきます。使う場合はキャストして使ってください。
     将来変更される可能性もなきにしもあらずですけど。
    *)
    
    
    // [Delphi:89848] Re: VC++で作られたソフトのプラグインDLLの作成
    // を参考にして、関数の呼び出し規約をcdeclにしています
    
    // Delphiの場合、TCHARはMBCSの時はPCharになり、Unicodeの場合はPWideCharになる?
    
    // Charu3 Unicode版
    function CharuPlugIn(
      strSource: PWideChar; strResult: PWideChar; nSize: integer;
      data: PSTRING_DATA; pVoid: Pointer): BOOL; cdecl;
    var
      WkStrSource: string;
      WkStrResult: string;
    
      Wkm_strTitle: string;
      Wkm_strData: string;
      WKm_strMacro: string;
    
      Wkm_cKind: Char;
      Wkm_cIcon: Char;
    
      Wkm_nMyID: Integer;
      Wkm_nParentID: Integer;
    
      Wkm_timeCreate2: TDateTime;
      Wkm_timeEdit2: TDateTime;
    
      WkpVoid: HWND;
    begin
      try
        // strSourceはUNICODEなので、String型(S-JIS)に変換&コピーする
        WkStrSource := WideCharToString(strSource);
    
        // data.m_cKindの保持
        Wkm_cKind := data.m_cKind;
        // data.m_cIconの保持
        Wkm_cIcon := data.m_cIcon;
    
        // data.m_nMyIDの保持
        Wkm_nMyID := data.m_nMyID;
        // data.m_nParentIDの保持
        Wkm_nParentID := data.m_nParentID;
    
        // data.m_timeCreateはCのtime_t型なのでTDateTime型に変換&コピー
        Wkm_timeCreate2 := time_tToDateTime(data.m_timeCreate);
        // data.m_timeEditはCのtime_t型なのでTDateTime型に変換&コピー
        Wkm_timeEdit2 := time_tToDateTime(data.m_timeEdit);
    
        // data.m_strTitleはUNICODEなので、String型(S-JIS)に変換&コピーする
        Wkm_strTitle := WideCharToString(data.m_strTitle);
        // data.m_strDataはUNICODEなので、String型(S-JIS)に変換&コピーする
        Wkm_strData := WideCharToString(data.m_strData);
        // data.m_strMacroはUNICODEなので、String型(S-JIS)に変換&コピーする
        Wkm_strMacro := WideCharToString(data.m_strMacro);
    
        // pVoidをHWND型に変換する
        WkpVoid := HWND(pVoid^);
    
        //---------------ここからコードを書くといいです---------------------
    
        // strSourceがきちんと受け取れているかのテストコード
        MessageBox(0, PChar('strSource [' + WkStrSource + ']'), '情報',
          MB_OK or MB_ICONINFORMATION or MB_TASKMODAL);
    
        // data.m_cKindがきちんと受け取れているかのテストコード
        MessageBox(0, PChar('data.m_cKind [' + IntToStr(Integer(Wkm_cKind)) + ']'), '情報',
          MB_OK or MB_ICONINFORMATION or MB_TASKMODAL);
        // data.m_cIconがきちんと受け取れているかのテストコード
        MessageBox(0, PChar('data.m_cIcon [' + IntToStr(Integer(Wkm_cIcon)) + ']'), '情報',
          MB_OK or MB_ICONINFORMATION or MB_TASKMODAL);
    
        // data.m_nMyIDがきちんと受け取れているかのテストコード
        MessageBox(0, PChar('data.m_nMyID [' + IntToStr(Wkm_nMyID) + ']'), '情報',
          MB_OK or MB_ICONINFORMATION or MB_TASKMODAL);
        // data.m_nParentIDがきちんと受け取れているかのテストコード
        MessageBox(0, PChar('data.m_nParentID [' + IntToStr(Wkm_nParentID) + ']'), '情報',
          MB_OK or MB_ICONINFORMATION or MB_TASKMODAL);
    
        // TDateTime型に変換されたdata.m_timeCreateがきちんと受け取れているかのテストコード
        MessageBox(0, PChar(
          'data.m_timeCreate(TDateTime) [' + DateTimeToStr(Wkm_timeCreate2) + ']'),
          '情報',
          MB_OK or MB_ICONINFORMATION or MB_TASKMODAL);
        // TDateTime型に変換されたdata.m_timeEditがきちんと受け取れているかのテストコード
        MessageBox(0, PChar(
          'data.m_timeEdit(TDateTime) [' + DateTimeToStr(Wkm_timeEdit2) + ']'),
          '情報',
          MB_OK or MB_ICONINFORMATION or MB_TASKMODAL);
    
        // data.m_strTitleがきちんと受け取れているかのテストコード
        MessageBox(0, PChar('data.m_strTitle [' + Wkm_strTitle + ']'), '情報',
          MB_OK or MB_ICONINFORMATION or MB_TASKMODAL);
        // data.m_strDataがきちんと受け取れているかのテストコード
        MessageBox(0, PChar('data.m_strData [' + Wkm_strData + ']'), '情報',
          MB_OK or MB_ICONINFORMATION or MB_TASKMODAL);
        // data.m_strMacroがきちんと受け取れているかのテストコード
        MessageBox(0, PChar('data.m_strMacro [' + Wkm_strMacro + ']'), '情報',
          MB_OK or MB_ICONINFORMATION or MB_TASKMODAL);
    
        // pVoidがきちんと受け取れているかのテストコード
        MessageBox(0, PChar('pVoid [' + IntToStr(WkpVoid) + ']'), '情報',
          MB_OK or MB_ICONINFORMATION or MB_TASKMODAL);
    
        // 受け取ったstrSourceの文字列を'<'で囲う加工をするテストコード
        WkStrResult := '<' +  WkStrSource + '>';
    
        //---------------ここまでコードを書くといいです---------------------
    
        // 加工後のWkStrResultはString型(S-JIS)なので、UNICODEに変換&コピーする
        // 値は直接strResultに入れる
        StringToWideChar(WkStrResult, strResult, nSize);
    
        result := True;
      except
        result := False;
        Exit;
      end;
    end;
    
    exports
      CharuPlugIn;
    
    end.

コメント