editor.hsp
/***********************************************************
名なしパイプと独自メッセージによるプロセス間通信
のサンプル。エディタ側スクリプト
動作確認環境: HSP3.1 beta3 / WinXP Pro SP2
更新日: 2006/6/20
***********************************************************/
/******************************/
/* 実行ファイル作成オプション */
/******************************/
#packopt name "editor"
#packopt runtime "hsp3c.hrt"
/****************************/
/* Win32API用ヘッダファイル */
/****************************/
#include "kernel32.as"
/********************************/
/* Editコントロール用メッセージ */
/********************************/
#const WM_COPY 0x0301
#const EM_GETSEL 0x00b0 // 選択範囲取得 wprm=pStart, lprm=pEnd
// 戻り値=範囲
#const EM_REPLACESEL 0x00c2 // 選択テキストを置換
// 置換後、UNDO機能を有効にするとき wprm=1
// 置換後、UNDO機能を無効にするとき wprm=0
// lprm=文字列変数のポインタ
// 戻り値=0(エラーのとき)
/******************************************/
/* 外部プログラムとの通信用独自メッセージ */
/******************************************/
#const WM_APP 0x8000
#const EDT_WM_GETSELTEXT WM_APP+0 // 外部プログラムからの選択テキスト送信要求
#const EDT_WM_SETSELTEXT WM_APP+1 // 外部プログラムからの置換用テキスト受信要求
/**************/
/* その他定数 */
/**************/
#const TRUE 1
#const FALSE 0
#const NULL 0
#const ERR_WRITEFILE 0 // WriteFile APIが失敗した
#const SIZE_BUF 1024 // ReadFile/WriteFile用バッファサイズ
/**********************/
/* 自作汎用モジュール */
/**********************/
#include "gm_clipboard_text.hsp"
title "editor"
/********************/
/* 割り込み実行指定 */
/********************/
oncmd gosub *OnToolMsg, EDT_WM_GETSELTEXT
oncmd gosub *OnToolMsg, EDT_WM_SETSELTEXT
/**************/
/* mesbox作成 */
/**************/
sdim _mboxbuf, 256*256
notesel _mboxbuf
noteload "editor.hsp"
mesbox _mboxbuf, ginfo(12), ginfo(13)-20, 5
id = stat
_hmbox = objinfo(id,2) // mesboxのウィンドウハンドル
/**********************************/
/* 外部プログラム起動用ボタン作成 */
/**********************************/
objsize 200, 20
button gosub "外部プログラム起動", *StartTool
; pos 200,ginfo(13)-20 : mes hwnd
/****************/
/* メインループ */
/****************/
_toolmsg = NULL // メインループの中で0以外の値になったら
// 外部プログラムから通信要求が来た合図
_hpipe = NULL // 外部プログラムから受け取るパイプハンドル
// (書き込み・読み出し兼用)
_htoolwnd = NULL // 外部プログラムから受け取る外部プログラムのウィンドウハンドル
// (このスクリプトの中では特に使用していません)
*EventLoop
await 1
switch _toolmsg
case EDT_WM_GETSELTEXT
gosub *SendSelText
swbreak
case EDT_WM_SETSELTEXT
gosub *ReplaceSelText
swbreak
swend
goto *EventLoop
/****************************/
/* 割り込み実行サブルーチン */
/****************************/
*OnToolMsg
/* メッセージ、WPARAM、LPARAMを記録 */
_toolmsg = iparam
_hpipe = wparam
_htoolwnd = lparam
return
*StartTool
/* 外部プログラム起動 */
exec "tool"
return
/********************************/
/* 選択テキスト送信サブルーチン */
/********************************/
*SendSelText
/* mesboxから選択テキストを取得 */
startidx = 0
endidx = 0
sendmsg _hmbox, EM_GETSEL, varptr(startidx), varptr(endidx)
if (endidx - startidx)=0 {
goto *@f // 選択テキストがなければなにも送らない
}
sendmsg _hmbox, WM_COPY, 0, 0
seltext = ""
getcbtext seltext
/* WriteFileするべき回数を取得 */
seltextlen = strlen(seltext)
loopcnt = seltextlen / SIZE_BUF
if (seltextlen \ SIZE_BUF)!0 {
loopcnt ++
}
/* パイプを通じてデータを送信 */
curidx = 0
size = 0 // WriteFile書き込みサイズ
repeat loopcnt
sdim buf, SIZE_BUF + 1 // WriteFile用バッファ
/* WriteFileするデータを取得 */
if cnt=(loopcnt-1) { // 最後のループ
memcpy buf, seltext, seltextlen-curidx, 0, curidx
}
else {
memcpy buf, seltext, SIZE_BUF, 0, curidx
curidx += SIZE_BUF
}
WriteFile _hpipe, buf, strlen(buf), varptr(size), NULL
if stat=ERR_WRITEFILE {
break
}
loop
*@
CloseHandle _hpipe
_hpipe = NULL
_toolmsg = NULL
return
/**********************************************/
/* テキスト受信・選択テキスト置換サブルーチン */
/**********************************************/
*ReplaceSelText
/* パイプを通じてデータを受け取る */
seltext = "" // データ受け取り用バッファ
size = 0 // ReadFile読み取りサイズ
repeat
sdim buf, SIZE_BUF + 1 // ReadFile用バッファ
ReadFile _hpipe, varptr(buf), SIZE_BUF, varptr(size), NULL
if stat { // ReadFile成功
if size=0 { // 読み取り完了
break
}
seltext += buf
}
else { // ReadFile失敗
break
}
loop
CloseHandle _hpipe
_hpipe = NULL
_toolmsg = NULL
/* 受け取ったテキストと選択テキストを置換 */
sendmsg _hmbox, EM_REPLACESEL, TRUE, varptr(seltext)
return
|
tool.hsp
/***********************************************************
名なしパイプと独自メッセージによるプロセス間通信
のサンプル。外部プログラム側スクリプト
動作確認環境: HSP3.1 beta3 / WinXP Pro SP2
更新日: 2006/6/20
***********************************************************/
/******************************/
/* 実行ファイル作成オプション */
/******************************/
#packopt name "tool"
#packopt runtime "hsp3c.hrt"
#packopt hide 1
/****************************/
/* Win32API用ヘッダファイル */
/****************************/
#include "user32.as"
#include "kernel32.as"
/************************************/
/* エディタとの通信用独自メッセージ */
/************************************/
#const WM_APP 0x8000
#const EDT_WM_GETSELTEXT WM_APP+0 // エディタへの選択テキスト送信要求
#const EDT_WM_SETSELTEXT WM_APP+1 // エディタへの置換用テキスト受信要求
/**************/
/* その他定数 */
/**************/
#const TRUE 1
#const FALSE 0
#const NULL 0
#const OK 0
#const ERROR -1
#define ERR_MES_0 "エラー"
#define ERR_MES_1 "エディタのプロセスハンドルの取得に失敗しました。tool.exeを終了します。"
#define ERR_MES_2 "パイプの作成に失敗しました。tool.exeを終了します。"
#const SIZE_SEC_ATTR 12 // SECURITY_ATTRIBUTES構造体サイズ
#const SIZE_BUF 1024 // ReadFile/WriteFile用バッファサイズ
#const PROCESS_DUP_HANDLE 0x40 // OpenProcess API引数用
// (プロセスハンドルをDuplicateHandle APIで使えるように)
#const DUPLICATE_CLOSE_SOURCE 0x01 // DuplicateHandle API動作オプション指定用
// (コピー元のハンドルをクローズする)
#const DUPLICATE_SAME_ACCESS 0x02 // DuplicateHandle API動作オプション指定用
// (第5引数を無視する)
/******************/
/* 重要な変数一覧 */
/******************/
_heditwnd = NULL // エディタのウィンドウハンドル
_heditproc = NULL // エディタのプロセスハンドル
_hmyproc = NULL // 自分の(擬似)プロセスハンドル
_hpread = NULL // 名なしパイプの読み出し側ハンドル
_hpwrite = NULL // 名なしパイプの書き込み側ハンドル
_hpedit = NULL // エディタに渡すパイプハンドル(書き込み・読み出し兼用)
/**********************************************************/
/* フォアグラウンドウィンドウ(エディタ)のハンドルを取得 */
/* -> プロセスIDを取得 -> プロセスハンドルを取得 */
/**********************************************************/
GetForegroundWindow
_heditwnd = stat
procid = NULL
GetWindowThreadProcessId _heditwnd, varptr(procid)
desiredaccess = PROCESS_DUP_HANDLE
OpenProcess desiredaccess, FALSE, procid
_heditproc = stat
if _heditproc=NULL {
dialog ERR_MES_1, 1, ERR_MES_0
end
}
/****************************************/
/* 自分の(擬似)プロセスハンドルを取得 */
/****************************************/
GetCurrentProcess
_hmyproc = stat
/****************************************/
/* エディタのmesboxの選択テキストを取得 */
/****************************************/
/* 名なしパイプを作成 */
gosub *CreatePipe_
if result=ERROR {
dialog ERR_MES_2, 1, ERR_MES_0
goto *Quit
}
/* エディタに渡すパイプハンドル(書き込み側)を複製 */
_hpedit = NULL
opt = DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS
DuplicateHandle _hmyproc, _hpwrite, _heditproc, varptr(_hpedit), NULL, FALSE, opt
/* 通信の準備を促すメッセージをパイプハンドルと共にエディタに送信 */
sendmsg _heditwnd, EDT_WM_GETSELTEXT, _hpedit, hwnd
await 1 // これを入れないとなぜかうまくいかない
/* 不要なハンドルを閉じる */
CloseHandle _hpedit
/* パイプを通じてデータを受け取る */
seltext = "" // データ受け取り用バッファ
size = 0 // ReadFile読み取りサイズ
repeat
sdim buf, SIZE_BUF + 1 // ReadFile用バッファ
ReadFile _hpread, varptr(buf), SIZE_BUF, varptr(size), NULL
if stat { // ReadFile成功
if size=0 { // 読み取り完了
break
}
seltext += buf
}
else { // ReadFile失敗
break
}
loop
/* 残りのハンドルを閉じる */
CloseHandle _hpread
/**************************************/
/* エディタから取得したテキストを加工 */
/**************************************/
textlen = strlen(seltext)
if textlen=0 { // エディタでテキストが選択されていなければなにもしない
goto *Quit
}
// 全行頭に"// "を追加
notesel seltext
repeat notemax
noteget linestr, cnt
linestr = "// " + linestr
noteadd linestr, cnt, 1
loop
/**************************************************************************/
/* エディタのmesboxの選択テキストと置換するためのテキストをエディタに送信 */
/**************************************************************************/
/* 名なしパイプを作成 */
gosub *CreatePipe_
if result=ERROR {
dialog ERR_MES_2, 1, ERR_MES_0
goto *Quit
}
/* エディタに渡すパイプハンドル(読み出し側)を複製 */
_hpedit = NULL
opt = DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS
DuplicateHandle _hmyproc, _hpread, _heditproc, varptr(_hpedit), NULL, FALSE, opt
/* 通信の準備を促すメッセージをパイプハンドルと共にエディタに送信 */
sendmsg _heditwnd, EDT_WM_SETSELTEXT, _hpedit, hwnd
/* 不要なハンドルを閉じる */
CloseHandle _hpedit
/* WriteFileするべき回数を取得 */
seltextlen = strlen(seltext)
loopcnt = seltextlen / SIZE_BUF
if (seltextlen \ SIZE_BUF)!0 {
loopcnt ++
}
/* パイプを通じてデータを送信 */
curidx = 0
size = 0 // WriteFile書き込みサイズ
repeat loopcnt
/* WriteFile用バッファ */
sdim buf, SIZE_BUF + 1
/* WriteFileするデータを取得 */
if cnt=(loopcnt-1) { // 最後のループ
memcpy buf, seltext, seltextlen-curidx, 0, curidx
}
else {
memcpy buf, seltext, SIZE_BUF, 0, curidx
curidx += SIZE_BUF
}
WriteFile _hpwrite, buf, strlen(buf), varptr(size), NULL
if stat=ERR_WRITEFILE {
break
}
loop
/* 残りのハンドルを閉じる */
CloseHandle _hpwrite
/**********/
/* 後始末 */
/**********/
*Quit
CloseHandle _heditproc
end
/********************************/
/* 名なしパイプ作成サブルーチン */
/********************************/
*CreatePipe_
_hpread = NULL // 読み出し側ハンドル
_hpwrite = NULL // 書き込み側ハンドル
secattr = SIZE_SEC_ATTR, NULL, FALSE // SECURITY_ATTRIBUTES構造体
CreatePipe varptr(_hpread), varptr(_hpwrite), varptr(secattr), 0
if stat=FALSE {
result = ERROR
}
else {
result = OK
}
return
|
|