トップページ > 過去ログ > 記事閲覧
テキスト入力について
名前:f2 日時: 2008/07/04 00:28

ゲーム内で、1行のエディットボックスを実現したいと思っています。 そこで、DxLibにあるKeyInput系の関数を試してみましたが 望むような効果が得られませんでしたので、質問させて頂きます。 ◎「ai愛」という文字列を、アプリが受け取るまで。 現状では、 1.「a」キーを押下、「i」キーを押下 2.「漢字」キーを押下 3.「あ」を押下、「い」を押下 4.「スペース」で候補リスト出現 5.「エンター」で候補を決定 6.「エンター」で入力を決定 7.GetKeyInputString()で文字列を取得 となっていますが、 ここで、6を省略し、以下のようにすることは可能でしょうか? 1.「a」キーを押下 → GetKeyInputString()のような関数で「a」取得 2.「i」キーを押下 → GetKeyInputString()のような関数で「i」取得 2.「漢字」キーを押下 3.「あ」を押下、「い」を押下 4.「スペース」で候補リスト出現 5.「エンター」で候補を決定 → GetKeyInputString()のような関数で「愛」取得 つまり、入力が決定した文字については、 どんどんアプリ側で情報を得たいのです。 もし可能でしたら、ご教授頂けないでしょうか よろしくお願いします。

Page: 1 |

Re: テキスト入力について ( No.1 )
名前:かたぱると 日時:2008/07/04 13:50

文字列の入力が確定していなくても入力中の文字列は GetKeyInputStringで取得することができます。 入力中の文字列をリアルタイムでGetKeyInputStringにて取得し、 文字列の変化を監視すればよいのではないでしょうか。 ちなみに日本語変換途中にGetKeyInputStringで文字列を取得すると その文字列には変換中の文字列は含まれません。 変換が確定したときに初めてGetKeyInputStringで取得できる文字列に含まれる模様です。
Re: テキスト入力について ( No.2 )
名前:かたぱると 日時:2008/07/04 16:55

冗長ですが以下が試したソースです。 かなり適当で突っ込みどころ満載。 Releaseビルドじゃないと怒られる始末。 半角カタカナに対応してないのを見直して気が付いたッ! ▽以下をコピー #pragma once #include "DxLib.h" #include <list> #include <ctype.h> struct MOJI_DATA { char moji[3]; }; std::list<MOJI_DATA> g_fonts; // 文字データ int g_InputHandle ; // インプットハンドル void dataUpdate(void); // データを更新 void drawData(void); // データ表示 int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { SetGraphMode( 640 , 480 , 16 ) ; ChangeWindowMode( true ) ; SetMainWindowText( "文字列分割てすと" ); if( DxLib_Init() == -1 ) // DXライブラリ初期化処理 { return -1; // エラーが起きたら直ちに終了 } // キー入力ハンドルを作る(キャンセルなし全角文字有り数値入力じゃなし) g_InputHandle = MakeKeyInput( 30 , FALSE , FALSE , FALSE ) ; // 作成したキー入力ハンドルをアクティブにする SetActiveKeyInput( g_InputHandle ) ; // 描画先を裏画面にセット SetDrawScreen( DX_SCREEN_BACK ) ; // ループ while( !ProcessMessage() ) { bool isUpdateData = false; // 入力が終了している場合は終了 if( CheckKeyInput( g_InputHandle ) != 0 ) break ; // 画面のクリア ClearDrawScreen(); // 入力モードを描画 DrawKeyInputModeString( 640 , 480 ) ; // 入力途中の文字列を描画 DrawKeyInputString( 0 , 0 , g_InputHandle ) ; dataUpdate(); drawData(); // 裏画面の内容を表画面に反映させる ScreenFlip() ; } // 用済みのインプットハンドルを削除する DeleteKeyInput( g_InputHandle ) ; DxLib_End() ; // DXライブラリ使用の終了処理 return 0 ; // ソフトの終了 } void dataUpdate() { char String[ 256 ]; // 入力された文字列を取得 GetKeyInputString( String , g_InputHandle ) ; g_fonts.clear(); // 細かく作りこむのが面倒だった為に邪道処理。 for( int j = 0 ; j < strlen(String);j++) { MOJI_DATA add_data; if( isalnum( (int)String[j]) != 0 ) { // 半角 sprintf( add_data.moji , "%c",String[j] ); } else { // 全角。邪道処理。よい子は真似しちゃ駄目。 sprintf( add_data.moji , "%c%c",String[j],String[j+1] ); j++; } g_fonts.push_back(add_data); } } void drawData() { int ypos =14; int count = 0; ::std::list<MOJI_DATA>::iterator ite; for(ite=g_fonts.begin();ite!=g_fonts.end();ite++) { DrawFormatString( 0,ypos,GetColor(255,255,255),"%02d:%s",count,ite->moji); ypos+=14; count++; } }
Re: テキスト入力について ( No.3 )
名前:f2 日時:2008/07/04 18:32

ありがとうございます。 CheckKeyInput()なしでも取得できたのですね。 やりたいことが出来るようになりそうです! 組み込んでみたところ、もう一つ疑問が生まれたため、質問させてください。 日本語入力中の文字は表示させたいので、DrawKeyInputString()を使用しますが、 カーソルの線は表示させたくないのです。 (自分で描画するため) もし方法がありましたら、ご教授頂けないでしょうか よろしくお願い致します。
Re: テキスト入力について ( No.4 )
名前:かたぱると 日時:2008/07/04 19:05

DrawKeyInputStringを使わずに GetKeyInputStringで得た文字列と DrawIMEInputString(X座標,Y座標,g_InputHandle); でIME入力中の文字列とを別々に描画してやれば カーソルは描画されないはずなので あとは自身のカーソルをかさねてやれば描画できるのではないでしょうか。 文字列の幅はGetDrawStringWidthで取得できるので IMEの表示位置を合わせてやれば出来ないこともなさそうです。 IME関連の色変更は SetKeyInputStringColor あたりで頑張るしかなさそうですが…。 管理人様、DrawIMEInputStringの使い方はこれで合ってますでしょうか・・・。
Re: テキスト入力について ( No.5 )
名前:f2 日時:2008/07/04 19:20

そんな関数があったとは… やばいです… ほぼやりたいことが出来てしまいました。 変換候補の描画も自分でやりたいなぁとか 思ってしまいますが、それは抜きにしても 十分実用レベルとなりました。 本当にありがとうございました!
Re: テキスト入力について ( No.6 )
名前:管理人 日時:2008/07/11 21:10

変換候補の描画を自前で、となると画面から外れないように座標を 補正したり結構面倒ですが、それでも宜しければ機能を用意しますが・・・ (・・; > かたぱるとさん  合っています。 というか、もともと単体で使用することはあんまり想定していませんが。(^^;
Re: テキスト入力について ( No.7 )
名前:f2 日時:2008/07/13 07:28

管理人様レスありがとうございます。 教えて頂いた情報で、テキストボックスをはじめ、 フォームやリスト、メニュー等も実装してみましたが、 もし変換候補の描画さえも自前で出来るようになれば さらにかっこいいコントロール制御が出来そうに思います。 面倒な部分もあるかと思いますが、ぜひ用意して頂きたいです…
Re: テキスト入力について ( No.8 )
名前:管理人 日時:2008/07/15 00:36

了解しました 少々お待ちください
Re: テキスト入力について ( No.9 )
名前:管理人 日時:2008/07/24 13:46

遅くなり申し訳ありません。 こちらに機能追加をしたバージョンをアップしましたので 宜しければダウンロードしてください。m(_ _)m http://homepage2.nifty.com/natupaji/DxLib/DxLibVCTest.exe //VC用 http://homepage2.nifty.com/natupaji/DxLib/DxLibBCCTest.exe //BCC用 (中身を既存のライブラリのファイルに上書きして、BCCをお使いの 場合は『再構築』、VCをお使いの場合は『リビルド』をして下さい) 以下の関数を追加しました // IMEで入力中の文字列の情報を取得する IMEINPUTDATA *GetIMEInputData( void ) ; // キー入力の現在のカーソル位置を取得する int GetKeyInputCursorPosition( int InputHandle ) ; 今回追加した機能は MakeKeyInput での入力中の表示を自前で行う為のもので、 GetIMEInputData は全角文字入力中の情報を、GetKeyInputCursorPosition は 半角文字入力中のカーソルの位置を取得できます。 IMEINPUTDATA は構造体で、中身は以下のようになっています。 // IME入力文字列の描画に必要な情報の内の文節情報 typedef struct tagIMEINPUTCLAUSEDATA { int Position ; // 何バイト目から int Length ; // 何バイトか } IMEINPUTCLAUSEDATA, *LPIMEINPUTCLAUSEDATA ; // IME入力文字列の描画に必要な情報 typedef struct tagIMEINPUTDATA { const char * InputString ; // 入力中の文字列 int CursorPosition ; // カーソルの入力文字列中の位置(バイト単位) const IMEINPUTCLAUSEDATA * ClauseData ; // 文節情報 int ClauseNum ; // 文節情報の数 int SelectClause ; // 選択中の分節( -1 の場合はどの文節にも属していない( 末尾にカーソルがある ) ) int CandidateNum ; // 変換候補の数( 0の場合は変換中ではない ) const char ** CandidateList ; // 変換候補文字列リスト( 例:n番目の候補を描画する場合 DrawString( 0, 0, data.CandidateList[ n ], GetColor(255,255,255) ); ) int SelectCandidate ; // 選択中の変換候補 } IMEINPUTDATA, *LPIMEINPUTDATA ; 自前での描画処理の実装を大雑把にご説明すると以下のようになります。 1.GetKeyInputString で現時点での確定入力文字列を取得、描画 2.GetIMEInputData で全角入力中の情報を取得 3.GetIMEInputData の戻り値がNULLだったら全角入力中ではないので GetKeyInputCursorPosition で   カーソルの位置を取得してカーソルを描画、終了 4.GetIMEInputData の戻り値がNULLではない場合は戻り値 IMEINPUTDATA の内容に従って   全角文字列入力中の文字列等を描画 5.最初に入力中の全角文字列を描画( IMEINPUTDATA構造体のメンバ変数 InputString の描画 ) 6.文節情報に従って下線の描画( メンバ変数 ClauseData, ClauseNum, SelectClause を使用 ) 7.カーソルの描画( メンバ変数 CursorPosition を使用 ) 8.候補リストが表示されている場合は候補リストの描画( メンバ変数 CandidateNum, CandidateList, SelectCandidate を使用 )  MakeKeyInput 関数のサンプルを DrawKeyInputString を使用しないで入力中の文字列を 描画するように改造してみましたので、よろしければ参考にしてみて下さい。 DrawOriginalInputString という関数が DrawKeyInputString の代わりを務めています。 ( 「ひらがな」「カタカナ」等の入力モードのみ DrawKeyInputModeString を使用して描画  していますが、こちらも GetIMEInputModeStr を使用すれば自前で描画することが可能です ) #include "DxLib.h" #define CANDIDATE_SPACE (20) // 変換候補毎の間隔 #define BOTTOMLINE_Y (20) // 下線を描画する高さ // 入力文字列を描画する関数 void DrawOriginalInputString( int x, int y, int InputHandle, int OnePageListNum ) { char String[ 1024 ] ; IMEINPUTDATA *ImeData ; int i, CursorPos, CursorDotPos, SelectClauseX, LineStartX, LineLength, StartNumber ; // 現時点での確定入力文字列を取得する GetKeyInputString( String , InputHandle ) ; // 確定入力文字列を描画する DrawString( x, y, String, GetColor( 255,255,255 ) ) ; // カーソルの位置を取得する CursorPos = GetKeyInputCursorPosition( InputHandle ) ; // カーソルのドット単位の位置を取得する CursorDotPos = GetDrawStringWidth( String, CursorPos ) ; // IME入力情報を取得する ImeData = GetIMEInputData() ; // IME入力情報があるかどうか(IME入力をしているかどうか)で処理を分岐 if( ImeData ) { // IME入力をしている場合 // IMEで入力中の文字列を描画する DrawString( CursorDotPos + x, y, ImeData->InputString, GetColor( 255,0,0 ) ); // 文節の数だけ下線を描画する for( i = 0; i < ImeData->ClauseNum ; i++ ) { // 下線の開始座標を計算 LineStartX = GetDrawStringWidth( ImeData->InputString, ImeData->ClauseData[ i ].Position ) ; // 下線の長さを計算 LineLength = GetDrawStringWidth( ImeData->InputString + ImeData->ClauseData[ i ].Position, ImeData->ClauseData[ i ].Length ) ; // 下線の描画 DrawLine( CursorDotPos + LineStartX + 1 + x, y + BOTTOMLINE_Y, CursorDotPos + LineStartX + LineLength - 1 + x, y + BOTTOMLINE_Y, GetColor( 255,255,0 ) ) ; // もし選択している文節だった場合は文節の開始座標を保存しておく if( i == ImeData->SelectClause ) { SelectClauseX = CursorDotPos + LineStartX + x ; } } // カーソルの描画 LineStartX = GetDrawStringWidth( ImeData->InputString, ImeData->CursorPosition ) ; DrawBox( CursorDotPos + x + LineStartX, y, CursorDotPos + x + LineStartX + 2, y + 16, GetColor( 255,255,255 ), TRUE ) ; // 変換候補リストが存在する場合は描画処理を行う if( ImeData->CandidateNum ) { // 変換候補リストの開始ナンバーを計算 StartNumber = ImeData->SelectCandidate / OnePageListNum * OnePageListNum ; // 変換候補リストの同時表示数に達するか、変換候補リストの終端に来るまでループ for( i = 0; StartNumber + i < ImeData->CandidateNum && i < OnePageListNum; i ++ ) { // 変換候補の描画 DrawString( SelectClauseX, i * CANDIDATE_SPACE + y + 24, ImeData->CandidateList[ StartNumber + i ], GetColor( 0,255,0 ) ) ; } // 選択している変換候補を囲う枠の描画 DrawBox( SelectClauseX - 2, ( ImeData->SelectCandidate - StartNumber ) * CANDIDATE_SPACE + y + 22, SelectClauseX + 2 + GetDrawStringWidth( ImeData->CandidateList[ ImeData->SelectCandidate - StartNumber ], strlen( ImeData->CandidateList[ ImeData->SelectCandidate - StartNumber ] ) ), ( ImeData->SelectCandidate - StartNumber ) * CANDIDATE_SPACE + y + 42, GetColor( 0,255,128 ), FALSE ) ; } } else { // IME入力をしていない場合 // カーソルを描画 DrawBox( x + CursorDotPos, y, x + CursorDotPos + 2, y + 16, GetColor( 255,255,255 ), TRUE ); } } // WinMain 関数 int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { int InputHandle ; char String[ 512 ] ; // ウインドウモードで起動 ChangeWindowMode( TRUE ) ; // DXライブラリの初期化 if( DxLib_Init() == -1 ) return -1 ; // 描画先を裏にする SetDrawScreen( DX_SCREEN_BACK ) ; // キー入力ハンドルを作る(キャンセルなし全角文字有り数値入力じゃなし) InputHandle = MakeKeyInput( 50 , FALSE , FALSE , FALSE ) ; // 作成したキー入力ハンドルをアクティブにする SetActiveKeyInput( InputHandle ) ; // メインループ while( ProcessMessage() == 0 ) { // 入力が終了している場合は終了 if( CheckKeyInput( InputHandle ) != 0 ) break ; // 画面の初期化 ClearDrawScreen() ; // 入力モードを描画 DrawKeyInputModeString( 640 , 480 ) ; // 入力中文字列の描画 DrawOriginalInputString( 100, 100, InputHandle, 5 ) ; // 裏画面の内容を表画面に反映させる ScreenFlip() ; } // 入力された文字列を取得 GetKeyInputString( String , InputHandle ) ; // 用済みのインプットハンドルを削除する DeleteKeyInput( InputHandle ) ; // 画面の初期化 ClearDrawScreen() ; // 入力された文字列を画面に表示する DrawString( 0 , 0 , "あなたが入力した文字列は" , GetColor( 255 , 255 , 255 ) ) ; DrawString( 0 , 16 , String , GetColor( 255 , 255 , 255 ) ) ; // 裏画面の内容を表画面に反映させる ScreenFlip() ; // キー入力待ち WaitKey() ; // DXライブラリの使用終了 DxLib_End() ; // 終了 return 0 ; }  因みにはみ出し対応処理を省いたり変換候補リストがしょぼかったりと、基本的に DrawKeyInputString より適当な作りです。(汗)  不明な点がありましたらご指摘ください。
Re: テキスト入力について ( No.10 )
名前:koga2020 日時:2008/09/04 13:04

はじめまして。 koga2020と申します MS-DOS時代の少し特殊な印刷向きのエディタをwindows上に作ろうと思い、DXライブラリと拡張されたIMEINPUTDATA等で動かそうとしています。 現在はカーソルを表示・移動することができ、DrawOriginalInputStringからStringに文字が存在したときにエディタの内部バッファに書き込む > 画面に描画 > 入力待ち という動作を作っています。 1.文字・フォントサイズについて   DrawStringで固定ピッチにするにはどのようにしたらよいでしょうか。   具体的には、フォントサイズを16に指定したときに半角文字は横幅8ドットなのに対し、全角文字は横幅17ドットで描画されているようです。(カーソルと文字の位置が右に行く程ズレていきました)   フォント周りで、RPGのキャラクタ移動のように文字同士の隙間や全角は半角の倍として扱えるようにするには、どのようにしたらよいでしょうか。   尚、1文字ずつDrawStringすると、かなり動作が遅くなるようです。   2.マルチバイトとは     半角や全角が表示されるのでよくわからないのですが、String[512]の中には、半角は1バイト、全角は2バイトで入っているのでしょうか?     SJISとは違いますよね。     特定の位置が全角の右半分かどうかを調べたりしたいのですが、マルチバイトの文字コードというのがわかりません。できればSJISであってほしいのですが・・・   他には、後々以下のような機能を入れることを目標にしております。   A.罫線をカーソルの移動にしたがって入れる。     半角罫線にも対応する為、半角外字表示にもBMP表示を織り交ぜる方法か何かで対応したい。   B.命令段落(複数行の場合もある)の概念を入れる。     行挿入 ファイル●●●●●  拡張子●●●       挿入行●●●          のように、印刷時に挟み込む命令を入れることができる。   あと、最下行にDOSのFEP風に、横に候補一覧が表示されるように改造したりしております。     こういう細かい動作は標準のwindowsでは無理っぽいと思ったときに、カーソルの移動とその下に罫線が現れるというのはRPGっぽくないか?という発想のもと、DXライブラリで勉強させて頂いています。 ゲーム本来の機能とは違う方向の話になってしまっていますが、ご教授頂けると助かります。
Re: テキスト入力について ( No.11 )
名前:Will 日時:2008/09/04 16:15

スレッドのもともとの内容とまったく違う質問をされる場合は新規スレッドにしてください。 ・スレッドが長くて読みにくくなる ・f2さんと同じ問題で悩んでこのスレを見た人にとってあなたの質問&回答は無意味である ・あなたと同じ問題で悩む人が過去ログを見ようとしてもこのスレにはたどり着かない というような弊害が出ます。 答えられる範囲だけ回答します。 > 2.マルチバイトとは 勘違いされているようなのでこちらを読んでください。 http://ja.wikipedia.org/wiki/%E3%83%9E%E3%83%AB%E3%83%81%E3%83%90%E3%82%A4%E3%83%88%E6%96%87%E5%AD%97 SJISはマルチバイト文字の一種です。
Re: テキスト入力について ( No.12 )
名前:koga2020 日時:2008/09/05 00:34

わかりました。 新規スレッドで質問させて頂きます。 ありがとうございます。

Page: 1 |