DelphiでCharu3プラグインを作る際にハマった事や参照した場所等をメモしていきます。
ケイジさんが作成した、クリップボード拡張+入力支援ソフトです。
■KeiziWeb ver 4.3
※2010/2/4あたりに移転した様です
■Keijiweb ver β - どうしてkeijiweb.comになったのか?
DelphiでCharu3のプラグインを作る方法が書かれているソースが入っています。
2008/3/2修正 Unicodeに完全対応(今まではShift-JISで処理していたのをUnicodeに完全対応)
ダウンロード
DelphiのIDE(統合開発環境)で、TControlから派生したクラス(見えているコンポーネント全てです)をコピーして、このプラグインを通すと、コピーしたクラスのNameプロパティのリストが改行区切りで返されます。
ダウンロード
この作品はクリエイティブ・コモンズ・ライセンスの下でライセンスされています。
設定されたHtmlHelpファイルを開いて指定したキーワードで検索します。
コマンドライン版もありますので、他の環境でも使えると思います。
プログラミング言語のリファーレンスマニュアルがHtmlHelpファイルだった場合、エディタ上で文字列を選択してヘルプを引くような使い方を想定しています。
ダウンロード
この作品はクリエイティブ・コモンズ・ライセンスの下でライセンスされています。
library CharuPlugInTest; { DLL でのメモリ管理について: もしこの DLL が引数や返り値として String 型を使う関数/手続きをエクスポー トする場合、以下の USES 節とこの DLL を使うプロジェクトソースの USES 節 の両方に、最初に現れるユニットとして ShareMem を指定しなければなりません。 (プロジェクトソースはメニューから[プロジェクト|ソース表示] を選ぶこと で表示されます) これは構造体やクラスに埋め込まれている場合も含め String 型を DLL とやり 取りする場合に必ず必要となります。 ShareMem は共用メモリマネージャである BORLNDMM.DLL とのインターフェース です。あなたの DLL と一緒に配布する必要があります。BORLNDMM.DLL を使うの を避けるには、PChar または ShortString 型を使って文字列のやり取りをおこ なってください。} 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 + '>'; // 加工後のWkStrResultを表示するテストコード MessageBox(0, PChar('strSource [' + WkStrResult + ']'), '情報', MB_OK or MB_ICONINFORMATION or MB_TASKMODAL); //---------------ここまでコードを書くといいです--------------------- // 値は直接strResultに入れる StrLCopy(strResult, PChar(WkStrResult), nSize); result := True; except result := False; Exit; end; end; exports CharuPlugIn; end.
library CharuPlugInTestu; { DLL でのメモリ管理について: もしこの DLL が引数や返り値として String 型を使う関数/手続きをエクスポー トする場合、以下の USES 節とこの DLL を使うプロジェクトソースの USES 節 の両方に、最初に現れるユニットとして ShareMem を指定しなければなりません。 (プロジェクトソースはメニューから[プロジェクト|ソース表示] を選ぶこと で表示されます) これは構造体やクラスに埋め込まれている場合も含め String 型を DLL とやり 取りする場合に必ず必要となります。 ShareMem は共用メモリマネージャである BORLNDMM.DLL とのインターフェース です。あなたの DLL と一緒に配布する必要があります。BORLNDMM.DLL を使うの を避けるには、PChar または ShortString 型を使って文字列のやり取りをおこ なってください。} uses SysUtils, Classes, Windows, System, Messages, {以下 TntWare Delphi Unicode Controls フリー版ライブラリを使用} TntSystem, TntSysUtils, TntDialogs, TntWideStrUtils; {$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: WideString; WkStrResult: WideString; Wkm_strTitle: WideString; Wkm_strData: WideString; WKm_strMacro: WideString; Wkm_cKind: Char; Wkm_cIcon: Char; Wkm_nMyID: Integer; Wkm_nParentID: Integer; Wkm_timeCreate2: TDateTime; Wkm_timeEdit2: TDateTime; WkpVoid: HWND; begin try // strSourceはUNICODEなのでWideString型にコピーする 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); // data.m_strTitleはUNICODEなのでWideString型にコピーする Wkm_strTitle := PWideChar(data.m_strTitle); // data.m_strDataはUNICODEなのでWideString型にコピーする Wkm_strData := PWideChar(data.m_strData); // data.m_strMacroはUNICODEなのでWideString型にコピーする Wkm_strMacro := PWideChar(data.m_strMacro); // pVoidをHWND型に変換する WkpVoid := HWND(pVoid^); //---------------ここからコードを書くといいです--------------------- // strSourceがきちんと受け取れているかのテストコード // UNICODEなのでMessageBoxW使用 MessageBoxW(0, PWideChar('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がきちんと受け取れているかのテストコード // UNICODEなのでMessageBoxW使用 MessageBoxW(0, PWideChar('data.m_strTitle [' + Wkm_strTitle + ']'), '情報', MB_OK or MB_ICONINFORMATION or MB_TASKMODAL); // data.m_strDataがきちんと受け取れているかのテストコード // UNICODEなのでMessageBoxW使用 MessageBoxW(0, PWideChar('data.m_strData [' + Wkm_strData + ']'), '情報', MB_OK or MB_ICONINFORMATION or MB_TASKMODAL); // data.m_strMacroがきちんと受け取れているかのテストコード // UNICODEなのでMessageBoxW使用 MessageBoxW(0, PWideChar('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を表示するテストコード // UNICODEなのでMessageBoxW使用 MessageBoxW(0, PWideChar('strSource [' + WkStrResult + ']'), '情報', MB_OK or MB_ICONINFORMATION or MB_TASKMODAL); //---------------ここまでコードを書くといいです--------------------- // 値は直接strResultに入れる WStrLCopy(strResult, PWideChar(WkStrResult), nSize); result := True; except result := False; Exit; end; end; exports CharuPlugIn; end.