|
|
|
2015/12/20(Sun) 01:17:27|NO.73699
自作エディタに、入力補完機能を入れようと思ったのですが思うように動作しません。
改善してください。お願いします。
改善してほしい点
・一覧をダブルクリックをしくはスペースキーを押すと候補確定されるようにしたい
・入力中にスペースを押すと、入力補完ウィンドウを消したい(また文字を入力すると表示される)
(要はVisualBasicのような感じで)
#include "user32.as"
#define ctype HIWORD(%1) (%1 >> 16 & 0xFFFF)
KeyWordList=/*HSP定義ワード*/{"
comevarg\ncomevent\ndelcom\nnewcom\nquerycom\nsarrayconv\ncomevdisp
assert\nlogmes\nbutton\nchkbox\nclrobj\ncombox\ninput\nlistbox\nmesbox\nobjenable
objimage\nobjmode\nobjprm\nobjsel\nobjsize\nobjskip\ncnt\nerr\nhdc\nhinstance
hspstat\nhspver\nhwnd\niparam\nlooplev\nlparam\nmousew\nmousex\nmousey\nrefdval
refstr\nstat\nstrsize\nsublev\nthismod\nwparam\nbcopy\nbload\nbsave\nchdir\nchdpm
delete\ndirlist\nexist\nmemfile\nmkdir\nawait\nbreak\ncontinue\nelse\nend\nexec
exgoto\nforeach\ngosub\ngoto\nif\nloop\non\nonclick\noncmd\nonerror\nonexit\nonkey
repeat\nreturn\nrun\nstop\nwait\nmci\nmmload\nmmplay\nmmstop\ncomres\ndelmod\ndim
dimtype\nlpoke\nmemcpy\nmemexpand\nmemset\nnewlab\nnewmod\npoke\nsdim\nwpoke
lpeek\npeek\nwpeek\ngetkey\nmcall\nmouse\nrandomize\nsetease\nstick\nabs\nabsf
atan\ncallfunc\ncos\ndirinfo\ndouble\nexpf\ngetease\ngeteasef\ngettime\nginfo\nint
length\nlength2\nlength3\nlength4\nlibptr\nlimit\nlimitf\nlogf\nobjinfo\npowf\nrnd
sin\nsqrt\nstr\nstrlen\nsysinfo\ntan\nvarptr\nvartype\nvaruse\ncnvstow\ngetstr
noteadd\nnotedel\nnoteget\nnoteload\nnotesave\nnotesel\nnoteunsel\nsplit\nstrrep
cnvwtos\ngetpath\ninstr\nnoteinfo\nstrf\nstrmid\nstrtrim\ndup\ndupptr\nmref\naxobj
bgscr\nbmpsave\nboxf\nbuffer\nceldiv\ncelload\ncelput\nchgdisp\ncircle\ncls\ncolor
dialog\nfont\ngcopy\ngmode\ngradf\ngrect\ngroll\ngrotate\ngsel\ngsquare\ngzoom
hsvcolor\nline\nmes\npalcolor\npalette\npget\npicload\npos\nprint\npset\nredraw
screen\nsendmsg\nsyscolor\nsysfont\ntitle\nwidth\nwinobj\ndir_cmdline\ndir_cur
dir_desktop\ndir_exe\ndir_mydoc\ndir_sys\ndir_tv\ndir_win\nginfo_accx\nginfo_accy
ginfo_accz\nginfo_act\nginfo_b\nginfo_cx\nginfo_cy\nginfo_dispx\nginfo_dispy
ginfo_g\nginfo_intid\nginfo_mesx\nginfo_mesy\nginfo_mx\nginfo_my\nginfo_newid
ginfo_paluse\nginfo_r\nginfo_sel\nginfo_sizex\nginfo_sizey\nginfo_sx\nginfo_sy
ginfo_vx\nginfo_vy\nginfo_winx\nginfo_winy\nginfo_wx1\nginfo_wx2\nginfo_wy1
ginfo_wy2\nmsgothic\nmsmincho\nnotemax\nnotesize\n_break\n_continue\ncase\ndefault
do\nfor\nnext\nswbreak\nswend\nswitch\nuntil\nwend\nwhile\nalloc\nddim\nldim\nM_PI
__date__\n__file__\n__hsp30__\n__hspver__\n__line__\n__time__\n_debug\nand\ndeg2rad
font_antialias\nfont_bold\nfont_italic\nfont_normal\nfont_strikeout\nfont_underline
gmode_add\ngmode_alpha\ngmode_gdi\ngmode_mem\ngmode_pixela\ngmode_rgb0
gmode_rgb0alpha\ngmode_sub\nnot\nobjinfo_bmscr\nobjinfo_hwnd\nobjinfo_mode
objmode_guifont\nobjmode_normal\nobjmode_usefont\nor\nrad2deg\nscreen_fixedsize
screen_frame\nscreen_hide\nscreen_normal\nscreen_palette\nscreen_tool\nxor
#addition\n#cfunc\n#cmd\n#cmpopt\n#comfunc\n#const\n#defcfunc\n#deffunc\n#define
#else\n#endif\n#enum\n#epack\n#func\n#global\n#if\n#ifdef\n#ifndef\n#include
#modcfunc\n#modfunc\n#modinit\n#modterm\n#module\n#pack\n#packopt\n#regcmd
#runtime\n#undef\n#usecom\n#uselib"}
dim Rect,4
dim GUIThreadInfo,12
GUIThreadInfo(0) = 48 // 構造体のサイズを入れておかないとエラーになる
screen 0
hMainWindow=hwnd
title "入力補完"
font "Lucida Console",14,1:objmode 2
KeyWord=""
//input KeyWord,ginfo(12),25
mesbox KeyWord,ginfo(12),ginfo(13)
hInput=objinfo(stat,2)
oncmd gosub *OnCommand,0x0111
screen 8,300,121
hCompletionWindow=hwnd
SetWindowLong hCompletionWindow,-16,0x10400000
SetWindowLong hCompletionWindow,-20,0x00000001
SetWindowLong hCompletionWindow,-8,hInput
//SetParent hCompletionWindow,hMainWindow
font "Lucida Console",14,1:objmode 2
objsize ginfo(12),ginfo(13):pos 0,0
winobj "LISTBOX","",0x200,0x50210103
hListBox=objinfo(stat,2)
mref BMSCR,67
sendmsg hListBox,0x30,BMSCR.38
stop
*OnCommand
oncmd 0
if lparam == hInput {
//if HIWORD (wparam) = 0x100 : ShowWindow hCompletionWindow,5
//if HIWORD (wparam) = 0x200 : ShowWindow hCompletionWindow,0
if HIWORD (wparam) = 0x300 {
GetWindowThreadProcessId hInput,0:threadID = stat
GetGUIThreadInfo threadID,varptr(GUIThreadInfo(0))
GetWindowRect hInput,varptr(Rect)
MoveWindow hCompletionWindow,GUIThreadInfo(8)+Rect(0),GUIThreadInfo(11)+Rect(1),310,155,1
sendmsg hListbox,0x0184
notesel KeyWordList
repeat noteinfo(0)
noteget _KeyWordList,cnt
if getpath(strmid(_KeyWordList,0,strlen(KeyWord)),16)=getpath(KeyWord,16):sendmsg hListbox,0x180,0,_KeyWordList
loop
}
}
oncmd 1
return
| |
|
2015/12/20(Sun) 07:23:10|NO.73701
とりあえず、候補を外部ファイルに分離しましょう。
|
|
2015/12/20(Sun) 18:33:28|NO.73706
|
|
2015/12/22(Tue) 19:15:23|NO.73724
>ダブルクリック
WM_Command(LBN_DblClk)で捕捉、LB_GetCurSelで選択候補取得
>スペースキー
onkeyで捕捉、フラグやフォーカスで処理分け
…などで出来そうな気がします。
何か上手く行かない部分があるのでしょうか。
|
|
2015/12/22(Tue) 23:35:25|NO.73726
>(要はVisualBasicのような感じで)
どんな感じか知らないけど
スペースかダブルクックで決定
マウスクリックかコントロール+上下キーで選択移動(エディタ内も動いてしまうのでCtrl+)
コントロール+左右キーでキーワード選択
#include "user32.as"
#define ctype HIWORD(%1) (%1 >> 16 & 0xFFFF)
#uselib "Shlwapi"
#cfunc StrStrW "StrStrW" int,sptr
#uselib "msvcrt"
#cfunc Wcslen "wcslen" var
notesel KeyWordList/*HSP定義ワード*/
noteload "KeyWordList.txt"
dim Rect,4
dim GUIThreadInfo,12
GUIThreadInfo(0) = 48 // 構造体のサイズを入れておかないとエラーになる
screen 0
hMainWindow=hwnd
title "入力補完"
font "Lucida Console",14,1:objmode 2
KeyWord=""
//input KeyWord,ginfo(12),25
mesbox KeyWord,ginfo(12),ginfo(13),,0
idInput=stat
hInput=objinfo(stat,2)
oncmd gosub *OnCommand_main,0x0111 //メインウィンドウ用
screen 8,300,121,2
hCompletionWindow=hwnd
SetWindowLong hCompletionWindow,-16,0x00400000 //非表示
SetWindowLong hCompletionWindow,-20,0x00000001
SetWindowLong hCompletionWindow,-8,hInput
//SetParent hCompletionWindow,hMainWindow
font "Lucida Console",14,1:objmode 2
objsize ginfo(12),ginfo(13):pos 0,0
winobj "LISTBOX","",0x200,0x50210103
hListBox=objinfo(stat,2)
mref BMSCR,67
sendmsg hListBox,0x30,BMSCR.38
oncmd gosub *OnCommand_comp,0x0111 //候補ウィンドウ用
gsel 0,1
objsel idInput
onkey gosub *On_Key
stop
*OnCommand_comp
if lparam == hListBox { //ダブルクリック
if HIWORD (wparam) = 2 {
SPACE=0
oncmd 0
gosub *Completion
oncmd 1
}else{
if Showf {
if (ginfo_act=-1) and (HIWORD (wparam) = 5) {
ShowWindow hCompletionWindow,0
}
}
}
}
return
*OnCommand_main
oncmd 0
if lparam == hInput {
if HIWORD (wparam) = 0x300 {
getkey sp_key,32
if sp_key=0 {//スペース以外なら
gosub *CompletionWin
}
}else{
if Showf {
if (ginfo_act=-1) and (HIWORD (wparam) = 0x200) {
ShowWindow hCompletionWindow,0
}else{
if HIWORD (wparam) = 0x100 {gosub *CompletionWin}
}
}
}
}
oncmd 1
return
//候補ウィンドウ処理
*CompletionWin
if vartype(GetLime)=4 {//各種変数初期設定
sdim GetLine,1024 //一行を取得する変数
spw=""
cnvstow spw," "//スペース
tbw=""
cnvstow tbw," " //タブ
}
GetWindowThreadProcessId hInput,0:threadID = stat
GetGUIThreadInfo threadID,varptr(GUIThreadInfo(0))
GetWindowRect hInput,varptr(Rect)
MoveWindow hCompletionWindow,GUIThreadInfo(8)+Rect(0),GUIThreadInfo(11)+Rect(1),310,155,1
sendmsg hListbox,0x0184
sendmsg hInput,0xB0,varptr(selStart),varptr(selEnd) //EM_GETSEL
sendmsg hInput,0xC9 ,selEnd,0 //EM_LINEFROMCHAR 文字インデックスから行番号を取得する
LineFromChar=stat
wpoke GetLine,0,1024-1 //適当な長さを設定
sendmsg hInput,0xC4,LineFromChar,varptr(GetLine) //EM_GETLINE 指定行の文字列を取得
asise=stat
if asise=0 {ShowWindow hCompletionWindow,0 :Showf=0:return}
sendmsg hInput,0xBB ,LineFromChar,0 //EM_LINEINDEX 行の文字インデックスを取得する
LineInde=stat
sdim unicode,(asise+1)*2
cnvstow unicode,GetLine
kwlinest_ptr=varptr(unicode)
kwline_ptr=kwlinest_ptr
kwlineend_ptr=kwlinest_ptr+Wcslen(unicode)*2
kwend_ptr=kwlinest_ptr+(selEnd-LineInde)*2
if kwend_ptr>(kwlineend_ptr+1) {ShowWindow hCompletionWindow,0 :Showf=0:return}
repeat //選択されてる単語を抽出(スペースかタブで区切られててキャレット位置が含まれてる単語)
sp_ptr=StrStrW(kwline_ptr,spw)
tb_ptr=StrStrW(kwline_ptr,tbw)
if sp_ptr=0 {sp_ptr=kwlineend_ptr} //sp_ptrが0だったら終端までスペースが無いので終端アドレスをセット
if tb_ptr=0 {tb_ptr=kwlineend_ptr} //tb_ptrが0だったら終端までタブが無いので終端アドレスをセット
if (sp_ptr>=kwend_ptr) and (tb_ptr>=kwend_ptr) {//タブ、スペース両方ともキャレット位置を超えてるので検索終了
if sp_ptr<=tb_ptr {unsize=sp_ptr-kwline_ptr}else{unsize=tb_ptr-kwline_ptr}//タブ、スペースで小さいアドレスの方をキーワードの終わりとして文字数算出
if unsize>0 {
dupptr kw_dup,kwline_ptr,unsize,2
sdim kw_un,unsize+2 //ゴミが残らないように毎回初期化
memcpy kw_un,kw_dup,unsize
_KeyWord = cnvwtos(kw_un)
}else{
unsize=0
_KeyWord = ""
}
selStart=LineInde+(kwline_ptr-kwlinest_ptr)/2 //ユニコードアドレスを2で割って文字数にして行開始文字インデックスに加算
selEnd=selStart+unsize/2 //ユニコード文字列サイズを2で割って文字インデックスに加算
break
}
if sp_ptr<tb_ptr {kwline_ptr=sp_ptr+2}else{kwline_ptr=tb_ptr+2}//次を検索するのに1文字(2バイト)移動
loop
Showf=0 //候補ウィンドウ表示フラグクリア(0以外なら表示)
if _KeyWord!"" {
sendmsg hListbox,0x000B,0,0 //WM_SETREDRAW
notesel KeyWordList
repeat noteinfo(0)
noteget _KeyWordList,cnt
if getpath(strmid(_KeyWordList,0,strlen(_KeyWord)),16)=getpath(_KeyWord,16):sendmsg hListbox,0x180,0,_KeyWordList
loop
sendmsg hListbox,0x018B,0,0 //LB_GETCOUNT
Showf=stat
if Showf=1 {//候補が一つなら
sendmsg hListbox,0x189,0,varptr(_KeyWordList) //LB_GETTEXT
Showf=_KeyWordList!_KeyWord //キーワードと候補が一致してなければ候補表示フラグ1
}
sendmsg hListbox,0x0186,0,0 //LB_SETCURSEL
sendmsg hListbox,0x000B,1,0 //WM_SETREDRAW
}
if Showf {
ShowWindow hCompletionWindow,4
}else{
ShowWindow hCompletionWindow,0
}
return
//候補決定して文字列置き換え
*Completion
SetFocus hInput
sendmsg hListbox,0x188,0,0 //LB_GETCURSEL
lbindex=stat
if lbindex<0 {
_KeyWordList=""
selStart=selEnd
}else{
sendmsg hListbox,0x189,lbindex,varptr(_KeyWordList) //LB_GETTEXT
}
sendmsg hListbox,0x189,lbindex,varptr(_KeyWordList) //LB_GETTEXT
sendmsg hInput,0x00B1,selStart,selEnd+SPACE //EM_SETSEL
sendmsg hInput,0xC2,0,varptr(_KeyWordList) //EM_REPLACESEL
ShowWindow hCompletionWindow,0
Showf=0
return
*On_Key
IsWindowVisible hCompletionWindow
if stat=1 {
if wparam=' ' {//スペース
oncmd 0
onkey 0 : await 0 : onkey 1 //スペースを先に挿入
GetFocus
SPACE=(hInput=stat) //hInputがアクティブならスペース分として1
gosub *Completion
oncmd 1
}else{
GetFocus
if stat=hInput {
if wparam>=37 and wparam<=40 {//方向キーが押された
getkey Ctrt,17
if Ctrt {//コントロールが押されてる
sendmsg hListbox,0x188,0,0 //LB_GETCURSEL
if wparam=38 {sendmsg hListbox,0x0186,stat-1,0} //LB_SETCURSEL//コントロール押しながら上下キーを押されたら候補リスト選択移動
if wparam=40 {sendmsg hListbox,0x0186,stat+1,0} //LB_SETCURSEL
if wparam=37 or wparam=39 {gosub *CompletionWin}//コントロール押しながら左右キーを押されたら候補ウィンドウ処理
}else{//候補ウィンドウを消す
ShowWindow hCompletionWindow,0
Showf=0
}
}
}
}
}else{
getkey Ctrt,17
if Ctrt {//コントロールが押されてる
if wparam=37 or wparam=39 {gosub *CompletionWin}//コントロール押しながら左右キーを押されたら候補ウィンドウ処理
}
}
return
これ以上はプロシージャ差し替えとか割り込みフックとか必要になりそう・・・
| |
|
2015/12/23(Wed) 00:24:35|NO.73728
>・入力中にスペースを押すと、入力補完ウィンドウを消したい(また文字を入力すると表示される)
これは自分で選択するまでは未選択状態だからスペースで消えるって事なら
169行目辺りの
> sendmsg hListbox,0x0186,0,0 //LB_SETCURSEL
を削除して
|
|
2015/12/23(Wed) 12:57:46|NO.73735
皆さんありがとうございます。
よくできていました。
|
|