HSPポータル
サイトマップ お問い合わせ


HSPTV!掲示板


未解決 解決 停止 削除要請

2015
1220
Rich入力補完の作り方を教えてください6解決


Rich

リンク

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



この記事に返信する


kanamaru

リンク

2015/12/20(Sun) 07:23:10|NO.73701

とりあえず、候補を外部ファイルに分離しましょう。



Rich

リンク

2015/12/20(Sun) 18:33:28|NO.73706




774

リンク

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
を削除して



Rich

リンク

2015/12/23(Wed) 12:57:46|NO.73735

皆さんありがとうございます。
よくできていました。



ONION software Copyright 1997-2023(c) All rights reserved.