[[戻る>DoldoWorkz#delphi]]
*DelphiでCharu3プラグインを作る [#b6d19f99]
DelphiでCharu3プラグインを作る際にハマった事や参照した場所等をメモしていきます。
#hr
#contents
#hr
*Charu3とは? [#se519ac2]
ケイジさんが作成した、クリップボード拡張+入力支援ソフトです。~
[[■KeiziWeb ver 4.3>http://keijiweb.com/software.html]]~
※2010/2/4あたりに移転した様です~
[[■Keijiweb ver β - どうしてkeijiweb.comになったのか?>http://keijiweb.com/dView.pl?m=1&user=keizi&thid=20100207032344&tid=20100207050103]]~
*ソフト公開 [#x9c3e32b]
**DelphiでCharu3プラグインを作るサンプルソース&DLL [#d4e7533a]
DelphiでCharu3のプラグインを作る方法が書かれているソースが入っています。~
&color(red){''2008/3/2修正 Unicodeに完全対応''};(今まではShift-JISで処理していたのをUnicodeに完全対応)~
~
ダウンロード
#ref(CharuPlugInTest.LZH)
-サンプルソースの著作権~
[[&ref(http://i.creativecommons.org/l/by/2.1/jp/80x15.png);>http://creativecommons.org/licenses/by/2.1/jp/]]
この作品は[[クリエイティブ・コモンズ・ライセンス>http://creativecommons.org/licenses/by/2.1/jp/]]の下でライセンスされています。~
-TntWare Delphi Unicode Controls の著作権~
Copyright (c) 2002-2007, Troy Wolbrink (www.tntware.com)
**DelphiTControlToName [#ic824452]
DelphiのIDE(統合開発環境)で、TControlから派生したクラス(見えているコンポーネント全てです)をコピーして、このプラグインを通すと、コピーしたクラスのNameプロパティのリストが改行区切りで返されます。~
ダウンロード
#ref(DelphiTControlToName100.LZH)
[[&ref(http://i.creativecommons.org/l/by/2.1/jp/80x15.png);>http://creativecommons.org/licenses/by/2.1/jp/]]
この作品は[[クリエイティブ・コモンズ・ライセンス>http://creativecommons.org/licenses/by/2.1/jp/]]の下でライセンスされています。
**LoadHtmlHelp [#s8731a16]
設定されたHtmlHelpファイルを開いて指定したキーワードで検索します。~
コマンドライン版もありますので、他の環境でも使えると思います。~
プログラミング言語のリファーレンスマニュアルがHtmlHelpファイルだった場合、エディタ上で文字列を選択してヘルプを引くような使い方を想定しています。~
ダウンロード~
#ref(LoadHtmlHelp.ZIP)
[[&ref(http://i.creativecommons.org/l/by/2.1/jp/80x15.png);>http://creativecommons.org/licenses/by/2.1/jp/]]
この作品は[[クリエイティブ・コモンズ・ライセンス>http://creativecommons.org/licenses/by/2.1/jp/]]の下でライセンスされています。
*はまり雑記 [#pcd7570c]
**参考にしたページ [#ge61672d]
-[[KeiziWeb ver 4.3 Charu3>http://keiziweb.com/software.html]]~
クリップボード拡張+入力支援ソフト「Charu3」のダウンロードページです。~
ここに一緒にある「プラグイン開発キット」の内容を元しています。~
-[[Delphiメーリングリスト>http://www.users.gr.jp/content/delphiml.aspx]]~
Delphiのメーリングリストです。~
今回プラグインを作るに当たって、はまっていた内容をこのメーリングリストで教えていただきました。~
-[[About Delphi>http://www2.big.or.jp/~osamu/Delphi/]]~
Delphiのメーリングリストの過去ログが置いてあります。~
**DelphiでCharu3プラグインを作るサンプルソース [#c31fbdb3]
*S-JIS版 [#b32a2c2d]
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.
**Unicode版 [#ud3e427d]
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.