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


HSPTV!掲示板


未解決 解決 停止 削除要請

2013
1213
くまねこコマンプロンプト風の入力5未解決


くまねこ

リンク

2013/12/13(Fri) 15:42:04|NO.58706

現在コマンドプロンプト風のものを作っているのですがなかなかうまくいきません。
onkyeサンプルプログラムにある

onkey *jump stop *jump pos xvalue, 0 mes strf("%c", iparam) xvalue += ginfo(14) stop
このプログラムを応用しようとして、いろいろ試行錯誤しましたがBackspaceを用いての文字の消去や打ち込んだ文字列の取得がうまく思いつきません。
テキストボックスなどを使えばそのあたりは簡単なんでしょうが、自分で入力した文字列以外(初期表示されている文字)を消されないようにしたいのでonkey以外の方法で
コマンドプロンプト風のものが作れないでしょうか?

まとめると
・自分で文字列の打ち込みができる
・打ち込まれた文字列を取得できる
・初期表示されている文字列は消すことができない

このようなプログラムにするためにはなにかいい案ありませんでしょうか?



この記事に返信する


(’’

リンク

2013/12/13(Fri) 16:56:12|NO.58708

消したくない文字は別機構で表示し、文字列取得時に連結するのが手っ取り早いです
入力は普通にinputを使ってはどうでしょう?
入力機構を自分で用意するのはとても面倒です(IMEを取得したり、キャレットを移動したり...etc)



FunnyMaker

リンク

2013/12/13(Fri) 17:49:36|NO.58709

くまねこさんのやりたいことを実現するには、何はともあれ、

「今、何が表示されているのか」という情報を保持する

こと。これが根っこになりますね。mesで表示しっぱなしでは、「以前何を打ったか?。今カーソルはどこか?」
等々、いろんな情報が失われてしまいます。全部保持して、初めて適切な動きができます。


下は、穴ぼこだらけのカスいサンプルですが、エッセンスは詰まっていると思います。
参考になれば幸いです。


*start1 ;初期設定 color_text(0) = 255,255,255 color_back(0) = 0,0,0 BufSize_TEXT_CONSOLE_ORG = 10000 ;コンソール文字列の保持サイズ。デフォで10KB sdim TEXT_CONSOLE_ORG,BufSize_TEXT_CONSOLE_ORG ;コンソール文字列のオリジナルを保持する変数 STR_CMDPRMPT = dir_cur + ">" ;コマンドプロンプト(文字列) TEXT_CONSOLE_ORG = STR_CMDPRMPT ;コマンドプロンプト表示 TEXT_CONSOLE = TEXT_CONSOLE_ORG ;「TEXT_CONSOLE_ORG = dir_cur」の影武者。都合に応じて改変が入る。 index_line_cursor = 0 ;カーソルの存在する行インデックス index_char_TheLine_cursor = strlen(TEXT_CONSOLE) ;カーソルの存在する行(以下、「カーソルカレント行」「CC行」と呼びます。)におけるカーソルの文字インデックス。 interval_blink_cursor = 150 ;カーソルの点滅周期〔ms〕 stat_cursor_blink = 0 ;カーソルの状態(0,1)=(滅,点) FontName_console = msgothic : FontSize_console = 14 : Param_font = 0 ;フォント設定 pos_start_TEXT_CONSOLE(0) = 0,0 ;文字列の描画開始位置 *start2 ;GUI作成 size_scr(0) = 600,400 screen 0,size_scr(0),size_scr(1),0,2 title dir_cur onkey gosub *EVENT_KEY font FontName_console,FontSize_console,Param_font *start3 ;環境適応 *main timer_300ms = 0 ;300msカウンタ repeat ;< カーソルの点滅処理 > if timer_300ms >= interval_blink_cursor { gosub *Control_CursorBlink timer_300ms = 0 ;カウンタリセット } timer_300ms += 50 ;時間経過 await 50 ;周期50ヘルツ loop stop *EVENT_KEY ;キー入力対応ルーチン getkey KEY_ENTER,13 if KEY_ENTER = 1 { ;ENTER処理 gosub *DealCommand return } flg_OnKey_alphabet = 0 repeat 26,'A' ;アルファベット26文字取得 getkey key,cnt if key = 1 : flg_OnKey_alphabet = 1 : Code_char_Alphabet = cnt : break ;A〜Zどれか押されていたら... loop getkey key_SHIFT,16 getkey key_BS,8 getkey key_SPACE,32 flg_Onkey_numeric = 0 repeat 10,48 ;0〜9(メインキーボード) getkey key,cnt if key = 1 : flg_Onkey_numeric = 1 : num_char_numeric = cnt-48 : break loop repeat 10,96 ;0〜9(テンキー) getkey key,cnt if key = 1 : flg_Onkey_numeric = 1 : num_char_numeric = cnt-96 : break loop if flg_OnKey_alphabet = 1 { ;アルファベットキー if key_SHIFT = 1 { ;大文字 poke TEXT_CONSOLE_ORG,strlen(TEXT_CONSOLE_ORG),Code_char_Alphabet } else { ;小文字 poke TEXT_CONSOLE_ORG,strlen(TEXT_CONSOLE_ORG),Code_char_Alphabet + 32 ;※因みに、小文字のSJISコードは大文字のそれ +32 である。 } index_char_TheLine_cursor ++ ;カーソルインデックス更新 } if (key_BS = 1)&(index_char_TheLine_cursor > strlen(STR_CMDPRMPT)) { ;BSキーが押されていて、かつ、文字を消す余裕がある場合 poke TEXT_CONSOLE_ORG,strlen(TEXT_CONSOLE_ORG)-1,0 : index_char_TheLine_cursor -- ;一文字消去 } if key_SPACE = 1 { ;スペースキー TEXT_CONSOLE_ORG += " " index_char_TheLine_cursor ++ } if flg_Onkey_numeric = 1 { ;0〜9 TEXT_CONSOLE_ORG += str(num_char_numeric) index_char_TheLine_cursor ++ } TEXT_CONSOLE = TEXT_CONSOLE_ORG redraw 0 : gosub *DrawRoutine : redraw 1 ;画面更新 wait 20 ;ちょっと待つ(∵暴走防止) return *Control_CursorBlink ;カーソル点滅管理ルーチン if stat_cursor_blink = 0 { ;「滅」の場合 TEXT_CONSOLE = TEXT_CONSOLE_ORG + "_" stat_cursor_blink = 1 } else { ;「点」の場合 TEXT_CONSOLE = TEXT_CONSOLE_ORG stat_cursor_blink = 0 } redraw 0 : gosub *DrawRoutine : redraw 1 ;画面更新 return *DrawRoutine ;描画ルーチン color color_back(0),color_back(1),color_back(2) : boxf color color_text(0),color_text(1),color_text(2) pos pos_start_TEXT_CONSOLE(0),pos_start_TEXT_CONSOLE(1) : mes TEXT_CONSOLE return *DealCommand ;コマンド処理ルーチン ;< 解釈 > notesel TEXT_CONSOLE_ORG : noteget TheLine,index_line_cursor ;CC行読み出し STR_INPUT_USER = strmid(TheLine,-1,strlen(TheLine)-strlen(STR_CMDPRMPT)) ;ユーザー入力取得 repeat 1 if STR_INPUT_USER = "exit" : end if STR_INPUT_USER = "notepad" : exec STR_INPUT_USER : num_line_responce = 0 : break TEXT_CONSOLE_ORG += "\n不明なコマンドです。" : num_line_responce = 1 loop STR_CMDPRMPT = dir_cur + ">" TEXT_CONSOLE_ORG += "\n\n" + STR_CMDPRMPT TEXT_CONSOLE = TEXT_CONSOLE_ORG index_line_cursor += num_line_responce+2 : index_char_TheLine_cursor = strlen(STR_CMDPRMPT) ;カーソルインデックス更新 redraw 0 : gosub *DrawRoutine : redraw 1 ;画面更新 ;< 文字のスクロール > if ginfo_cy > size_scr(1) : pos_start_TEXT_CONSOLE(1) -= ginfo_cy - size_scr(1) return



くまねこ

リンク

2013/12/14(Sat) 17:13:58|NO.58733

みなさま回答ありがとうございます。

FunnyMakerさんのプログラム拝見させていただきました。
質問のばかりで申し訳ないのですが、例えばコマンドプロンプトは初期表示の"Microsoft Windows〜"のような
初期表示がありますよね?
そのような初期表示を入れたくFunnyMakerさんのプログラムとにらめっこしていたのですがうまくいきません。

描画ルーチンのところで、coloerやboxfで一旦画面が塗りつぶされてしまっているためその前に記述することはできませんし、
その下に記述すると毎回でできてしまいます。

そこでカウントを入れるように改良もしたのですが、コマンドを入力しEnterを押すと消えてしまいました。

何かいいアイデアないでしょうか?



FunnyMaker

リンク

2013/12/14(Sat) 21:26:26|NO.58734

起動時のセットアップで組み込めばいいとおもいます。

↓ちょっとだけ改良したやつです。


*start1 ;初期設定 color_text(0) = 255,255,255 color_back(0) = 0,0,0 BufSize_TEXT_CONSOLE_ORG = 10000 ;コンソール文字列の保持サイズ。デフォで10KB sdim TEXT_CONSOLE_ORG,BufSize_TEXT_CONSOLE_ORG ;コンソール文字列のオリジナルを保持する変数 STR_BootMessage = "Funny Terminal Emulator [Ver 1.1]\nby FunnyMaker" ;起動メッセージ STR_CMDPRMPT = dir_cur + ">" ;コマンドプロンプト(文字列) TEXT_CONSOLE_ORG += STR_BootMessage + "\n" + STR_CMDPRMPT ;コンソールの表示内容の初期化 TEXT_CONSOLE = TEXT_CONSOLE_ORG ;「TEXT_CONSOLE_ORG = dir_cur」の影武者。都合に応じて改変が入る。 notesel TEXT_CONSOLE_ORG : index_line_cursor = notemax - 1 ;カーソルの存在する行インデックス index_char_TheLine_cursor = strlen(TEXT_CONSOLE) ;カーソルの存在する行(以下、「カーソルカレント行」「CC行」と呼びます。)におけるカーソルの文字インデックス。 interval_blink_cursor = 150 ;カーソルの点滅周期〔ms〕 stat_cursor_blink = 0 ;カーソルの状態(0,1)=(滅,点) FontName_console = msgothic : FontSize_console = 14 : Param_font = 0 ;フォント設定 pos_start_TEXT_CONSOLE(0) = 0,0 ;文字列の描画開始位置 *start2 ;GUI作成 size_scr(0) = 600,400 screen 0,size_scr(0),size_scr(1),0,2 title dir_cur onkey gosub *EVENT_KEY font FontName_console,FontSize_console,Param_font *start3 ;環境適応 *main timer_300ms = 0 ;300msカウンタ repeat ;< カーソルの点滅処理 > if timer_300ms >= interval_blink_cursor { gosub *Control_CursorBlink timer_300ms = 0 ;カウンタリセット } timer_300ms += 50 ;時間経過 await 50 ;周期50ヘルツ loop stop *EVENT_KEY ;キー入力対応ルーチン getkey KEY_ENTER,13 if KEY_ENTER = 1 { ;ENTER処理 gosub *DealCommand return } flg_OnKey_alphabet = 0 repeat 26,'A' ;アルファベット26文字取得 getkey key,cnt if key = 1 : flg_OnKey_alphabet = 1 : Code_char_Alphabet = cnt : break ;A〜Zどれか押されていたら... loop getkey key_SHIFT,16 getkey key_BS,8 getkey key_SPACE,32 flg_Onkey_numeric = 0 repeat 10,48 ;0〜9(メインキーボード) getkey key,cnt if key = 1 : flg_Onkey_numeric = 1 : num_char_numeric = cnt-48 : break loop repeat 10,96 ;0〜9(テンキー) getkey key,cnt if key = 1 : flg_Onkey_numeric = 1 : num_char_numeric = cnt-96 : break loop if iparam = 46 : flg_Onkey_46 = 1 : else : flg_Onkey_46 = 0 ;「.」キー if flg_OnKey_alphabet = 1 { ;アルファベットキー if key_SHIFT = 1 { ;大文字 poke TEXT_CONSOLE_ORG,strlen(TEXT_CONSOLE_ORG),Code_char_Alphabet } else { ;小文字 poke TEXT_CONSOLE_ORG,strlen(TEXT_CONSOLE_ORG),Code_char_Alphabet + 32 ;※因みに、小文字のSJISコードは大文字のそれ +32 である。 } index_char_TheLine_cursor ++ ;カーソルインデックス更新 } if (key_BS = 1)&(index_char_TheLine_cursor > strlen(STR_CMDPRMPT)) { ;BSキーが押されていて、かつ、文字を消す余裕がある場合 poke TEXT_CONSOLE_ORG,strlen(TEXT_CONSOLE_ORG)-1,0 : index_char_TheLine_cursor -- ;一文字消去 } if key_SPACE = 1 { ;スペースキー TEXT_CONSOLE_ORG += " " index_char_TheLine_cursor ++ } if flg_Onkey_numeric = 1 { ;0〜9 TEXT_CONSOLE_ORG += str(num_char_numeric) index_char_TheLine_cursor ++ } if flg_Onkey_46 = 1 { ;「.」キー if key_SHIFT = 1 {;「>」 TEXT_CONSOLE_ORG += ">" } else {;「.」 TEXT_CONSOLE_ORG += "." } index_char_TheLine_cursor ++ } TEXT_CONSOLE = TEXT_CONSOLE_ORG redraw 0 : gosub *DrawRoutine : redraw 1 ;画面更新 wait 20 ;ちょっと待つ(∵暴走防止) return *Control_CursorBlink ;カーソル点滅管理ルーチン if stat_cursor_blink = 0 { ;「滅」の場合 TEXT_CONSOLE = TEXT_CONSOLE_ORG + "_" stat_cursor_blink = 1 } else { ;「点」の場合 TEXT_CONSOLE = TEXT_CONSOLE_ORG stat_cursor_blink = 0 } redraw 0 : gosub *DrawRoutine : redraw 1 ;画面更新 return *DrawRoutine ;描画ルーチン color color_back(0),color_back(1),color_back(2) : boxf color color_text(0),color_text(1),color_text(2) pos pos_start_TEXT_CONSOLE(0),pos_start_TEXT_CONSOLE(1) : mes TEXT_CONSOLE return *DealCommand ;コマンド処理ルーチン ;< 解釈 > notesel TEXT_CONSOLE_ORG : noteget TheLine,index_line_cursor ;CC行読み出し STR_INPUT_USER = strmid(TheLine,-1,strlen(TheLine)-strlen(STR_CMDPRMPT)) ;ユーザー入力取得 ;「num_line_responce」変数にはレスポンスに費やした行数を保存。 repeat 1 if STR_INPUT_USER = "exit" : end if STR_INPUT_USER = "cls" { ;CLSコマンド sdim TEXT_CONSOLE_ORG,BufSize_TEXT_CONSOLE_ORG index_line_cursor = 0 ;カーソルインデックス更新 pos_start_TEXT_CONSOLE(1) = 0 num_line_responce = 0 break } if STR_INPUT_USER = "ver" { TEXT_CONSOLE_ORG += "\nFunny Terminal Emulator [Ver 1.1]" num_line_responce = 1 break } ;< カレントディレクトリ内のアプリケーション起動またはファイルオープンのトライ > exist STR_INPUT_USER if strsize ! -1 { exec STR_INPUT_USER,16 num_line_responce = 0 break } ;< Windowsシステムディレクトリ内のアプリケーション起動のトライ > str1 = dir_sys+"/"+getpath(STR_INPUT_USER,1)+".exe" exist str1 if strsize ! -1 { exec str1 num_line_responce = 0 break } ;< ここまで来てしまった場合 > TEXT_CONSOLE_ORG += "\n不明なコマンドです。" : num_line_responce = 1 loop STR_CMDPRMPT = dir_cur + ">" TEXT_CONSOLE_ORG += "\n\n" + STR_CMDPRMPT ;基本的に2回改行。 TEXT_CONSOLE = TEXT_CONSOLE_ORG index_line_cursor += num_line_responce+2 : index_char_TheLine_cursor = strlen(STR_CMDPRMPT) ;カーソルインデックス更新 redraw 0 : gosub *DrawRoutine : redraw 1 ;画面更新 ;< CC行が最下辺まできてしまった際の文字のスクロール > if ginfo_cy > size_scr(1) : pos_start_TEXT_CONSOLE(1) -= ginfo_cy - size_scr(1) redraw 0 : gosub *DrawRoutine : redraw 1 ;画面更新 return

いっちょまえのターミナルエミュレータとしては、上のものはまだまだ不十分な箇所が大量にあります。
(’’さんが上で仰るように、IMEを取得して日本語入力にも対応するべきですし、
自動改行、スクロール、マウスカーソルによる文字列の選択&コピー、貼り付け等の各種操作、
各種基本コマンドの実装、コマンドラインアプリケーションとのやりとり、
等々.......
気が遠くなるほど多くの機能のサポートが必要です。

しかしそこがプログラミングの醍醐味とも言えるでしょうから、(※趣味でやるなら)やってみると面白いかもしれませんね。



掘木

リンク

2013/12/14(Sat) 23:05:19|NO.58736

野暮用でテキストエディタを組んでいるので何かしら助力ができるやも・・・。

文字を打つのであればWM_CHAR(0x0102)を捕まえる方が楽に行けるかもしれません。
この場合特に制御することなくIMEによる全角入力が可能です・・・が、
IMEの表示位置の指定をしないと見栄えが非常に悪い。(下記のソースでは悪いまま)
また、全角を入力可能にすると全角2バイトの間にカーソルが行かないような配慮が増えてきます。

WM_CHARとWM_KEYDOWN(onkey)のどちらで動作を指示するべきなのかは適当にテストしてみるといいかと。

以下テストソース(約150行)になります。横長な行があります(どうにかならんのか)。

#define global WM_CHAR 0x0102 #const global FONTSIZE 16 #const global WINDOWSIZEX 640 #const global WINDOWSIZEY 480 #const global LINETEXTPOSY WINDOWSIZEY-FONTSIZE #define global CONST #module dim seekpos // #cmpopt varinit 1 対策と使用変数の宣言。なくて問題ない。 #defcfunc InvalidCursorPos int cpos,CONST var string // 第一パラメータ(cpos):シークポイント(バイト単位) // 第二パラメータ(string):シーク検査する文字列 // // 関数はstringの、cposバイト目にカーソルが挿入不能であればTRUEが返る。 // 具体的に挿入不能であるとは、マルチバイト文字の間である状態を指す。 // // cposが負の値の場合や、 // cposがstrlen(string)を超えている場合、正しい挙動をしない上に後者はエラーになりうる。 seekpos = 0 repeat if cpos <= seekpos : break strcode = peek(string,seekpos) if ( strcode >= 0x81 && strcode <= 0x9F ) : seekpos ++ if ( strcode >= 0xE0 && strcode <= 0xFC ) : seekpos ++ seekpos ++ loop return cpos < seekpos #global cls 4 oncmd gosub *typechar,WM_CHAR onkey gosub *hitkey // font msgothic,FONTSIZE font "MS Pゴシック",FONTSIZE gosub *init nowstring = "*** LineText Test ***" gosub *putstring gosub *resettext repeat redraw 0 gosub *draw redraw 1 wait 1 loop *init // デフォルト文字列の指定 defaultstring = "test>" defaultstringlen = strlen(defaultstring) // 表示を行送りで流用しているための苦肉のフラグ。 cursordrawflag = 1 return *resettext // デフォルトの文字を入れてカーソル位置をデフォルト文字の末端に設定する nowstring = defaultstring cursorpos = defaultstringlen return *seekleft // カーソル位置(cursorpos)を左に一文字ずらす if ( cursorpos <= defaultstringlen ) : return cursorpos -- if ( InvalidCursorPos(cursorpos,nowstring) ){ cursorpos -- } return *seekright // カーソル位置(cursorpos)を右に一文字ずらす if ( cursorpos >= strlen(nowstring) ) : return cursorpos ++ if InvalidCursorPos(cursorpos,nowstring){ cursorpos ++ } return *typechar // 文字入力処理。 // logmes strf("CHAR: %X",wparam) if wparam == 0x7F || wparam == 0x08 { // バックスペースの処理 cursorpostemp = cursorpos gosub *seekleft nowstring = strmid(nowstring,0,cursorpos)+strmid(nowstring,cursorpostemp,strlen(nowstring)) }else : if wparam == 0x0D { // RETURNの処理 gosub *putstring gosub *operate gosub *resettext }else : if wparam >= 0x20 { // それ以外の非コントロール文字は挿入する nowstring = strmid(nowstring,0,cursorpos)+strf("%c",wparam)+strmid(nowstring,cursorpos,strlen(nowstring)) cursorpos ++ } return *hitkey // 文字以外の入力キー処理 // logmes strf("KEY : %X",wparam) // DEL , LEFT , RIGHT の処理 if wparam == 0x25 { // [←] gosub *seekleft }else : if wparam == 0x27 { // [→] gosub *seekright }else : if wparam == 0x2E { // DELETEキー cursorpostemp = cursorpos gosub *seekright nowstring = strmid(nowstring,0,cursorpostemp)+strmid(nowstring,cursorpos,strlen(nowstring)) cursorpos = cursorpostemp } return *draw color boxf ,LINETEXTPOSY color 255,255,255 if ( gettime(7)<500 )&&( cursordrawflag ){ pos 0,LINETEXTPOSY mes strmid(nowstring,0,cursorpos) line ginfo_mesx,LINETEXTPOSY+1,ginfo_mesx,WINDOWSIZEY-2 } pos 0,LINETEXTPOSY mes nowstring return *putstring // nowstringに入っているものを描画し行を送る cursordrawflag = 0 gosub *draw cursordrawflag = 1 pos 0,0 gcopy 0,0,FONTSIZE,WINDOWSIZEX,WINDOWSIZEY return *operate //実際の処理? // 文字列はnowstringに入っているが、デフォルト文字列を伴って入っている。 // operateの動作前に、打った文字はputstringによって描画確定している。 // 必要によってnowstringの値を書き換えputstringを呼べば何かしらの文字を出力できる。 stringtemp = strmid(nowstring,defaultstringlen,strlen(nowstring)) nowstring = strf({"You typed "%s"."},stringtemp) gosub *putstring nowstring = "" gosub *putstring defaultstring = stringtemp+">" defaultstringlen = strlen(defaultstring) return
自己流の適当コーディングなので読みづらい部分が多いかと思いますが参考になれば幸いです。
見栄えがFunnyMakerさんと全然違う・・・。

FunnyMakerさんのコメントはこちらにも言えて不十分な部分は多いですねえ。



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