トップページ > 過去ログ > 記事閲覧
キーリピートを十字キーにも適用するには
名前:koga2020 日時: 2008/09/07 11:33

環境について Windows XP SP2 VisualC++ 2008 Express Edition VisualC++用DXライブラリ(Ver2.24e --IME拡張版--) エディタで文字を入力するとき、キーを押しっぱなしにしても1文字出て、その後2文字目が出るまで少しタイムラグがあります。3文字目以降は比較的連続して出ます。 これをキーリピートと言います。 DXライブラリの入力も、文字(アルファベットのキー)はキーリピートが有効となっている動作を示すのですが、十字キー、INSやDELキーは最初から連続しています。(キャラクラーの移動に適したようになっています。) 逆に、十字キーなどにも、キー全体にキーリピートが適用されたようにしたいのです。 どのような方法があるかご教授頂けますでしょうか。 よろしくお願いします。

Page: 1 |

Re: キーリピートを十字キーにも適用するには ( No.1 )
名前:管理人 日時:2008/09/07 23:39

KeyInputString 等の関数での文字入力処理では十字キーもキーリピートが適応されている と思うのですが、koga2020 さんがお使いになっているキー入力関数は何でしょうか? とりあえず GetInputChar 関数を使用すればキーリピートされます。
Re: キーリピートを十字キーにも適用するには ( No.2 )
名前:koga2020 日時:2008/09/08 03:18

ご提示ありがとうございます。 さっそく GetInputChar を試したところ、最下段の再現方法に示したように、GetKeyInputString とは排他的な動作をしてしまうようです。 以下になぜこの2つの関数を同時に使用する必要があるのかを詳述します。 現在、MakeKeyInput でキー入力ハンドルを有効にしてループしている中、上カーソルキー押下で【1つ上の行に移動する】といった機能を入れています。 GetKeyInputString( String , InputHandle );でStringに1文字以上データがあれば直ちに行バッファに反映させて、キー入力ハンドルを再作成しています。 そうすることで GetHitKeyStateAll を使用してカーソルキーの押下状態を得て、上下のカーソル移動を実現していました。 その状況で、カーソルキーのキーリピートの質問をしておりました。 このプログラムで GetHitKeyStateAll の代わりに GetInputChar をTRUEモードでプログラム使用すると、排他的に扱われるようです。 具体的には   1.GetInputChar と GetKeyInputString が同じループで入力処理をさせているとき   2.最初はGetKeyInputString のみ有効(文字を受け取れる)   3.1度、エンターを押下すると GetInputChar のみが有効(文字を受け取れる) また、やりたいことは  GetKeyInputString でIME入力や半角文字入力を受け取らせ、入力文字のバッファへの反映や、BackSpaceキーや上カーソルなどの処理はエディタ用のバッファ(外字・罫線対応の構造のもの)に反映させる為に、自作プログラム上で処理させたいのです。  GetKeyInputStringを1文字半角入力・IME連続文字入力専用関数 のように使用して、カーソルキー入力などをキーリピートを効かせて取得する、という処理を書こうとしています。 ここで、現在 GetInputChar を使用すると排他的動作をしてしまい、不具合が出ているようです。 再現方法: 【Re: テキスト入力について ( No.9 )】のサンプルプログラムで、【// 入力中文字列の描画】の前後にGetInputCharの処理を入れると再現いたしました。
Re: キーリピートを十字キーにも適用するには ( No.3 )
名前:koga2020 日時:2008/09/08 04:50

現在の解決策について   ループ中にGetKeyInputString関数とGetHitKeyStateAll 関数を書き、   GetHitKeyStateAll の取得値の評価(カーソルの移動など)に、入力後にウェイトを置くことで解決しております。   INSERTキーにも、キーリピートが必要なので GetHitKeyStateAll を使うようにしました。
Re: キーリピートを十字キーにも適用するには ( No.4 )
名前:koga2020 日時:2008/09/08 09:24

先の解決策では、機種により入力文字を取得する動作が微妙なときがあるようです。(私のプログラムミスかも。現在奮闘中です) できれば、GetKeyInputString関数で、GetInputCharのキー判定(カーソル、DELETEやできればINSERTも)ができるようになるといいのですが、キーリピートを実現する為にこのような仕様にすることは可能でしょうか?
Re: キーリピートを十字キーにも適用するには ( No.5 )
名前:koga2020 日時:2008/09/09 11:10

GetKeyInputString( NameString , InputHandle ); ここで、NameStringの文字列長が 0 より大きければ、キー入力ハンドルを削除>作成>アクティブして再作成しています。 これは、エディタのバッファが特殊な為、IMEからの文字取得以外のカーソル移動やBSなどは、自作ソフトの方で制御する必要があるからです。 DxWin.cppの以下の関数中にループ処理があります。 【関数名】   // キー入力処理関数   extern int ST_ProcessActKeyInput( void ) 【ループ処理】   while( Input->EndFlag == FALSE )   {     if( ( CharLen = ST_GetOneChar( C , TRUE ) ) == 0 ) break ;     // カーソル点滅処理のカウンタをリセット     ResetKeyInputCursorBrinkCount() ;     switch( C[0] )     {       // 上下タブキーは無視       case CTRL_CODE_UP :       case CTRL_CODE_DOWN :       case CTRL_CODE_TAB :         break ; このループ処理で MakeKeyInput 関係のキー入力を受けているのではと思います。 既存のGetKeyInputString 又は 新規にGetKeyInputCodeのような関数を用いて、 半角英数やIME漢字変換確定後の文字列がある場合以外は、 キーコードを取得できるようにすることができれば、 恐らくキーリピートを保ったまま取得できるのかな、 と思います。 VisualC++用DXライブラリ(Ver2.24e --IME拡張版--)から修正できればと思いますが、2.24cをいじれるか試してみようと思います。 やりたいことは、GetKeyInputString をIME入力、半角英数カナ入力専用として考え、 IME変換中はライブラリの制御下ですが、それ以外は自作プログラムの方で コントロール関係のキーを取得して、 カーソル移動などの処理を行おうとしています。
Re: キーリピートを十字キーにも適用するには ( No.6 )
名前:koga2020 日時:2008/09/10 10:37

ある程度、自己解決できましたので以下の報告させて頂きます。 キーリピートを管理するプログラムを作成していたときに、IMEの入力中にESCAPEキーでキャンセルしたときに次の問題がありました。 GetHitKeyStateAll等ではIMEのキャンセルか、ただ単に押されたのか判別がつかないのです。 これを、ImeData->InputStringの長さをチェックすることで判別できるようになりました。 IMEのキャンセルは、前回の長さチェック時に長さが1以上なのに、今回は長さが0 のときにキャンセル又は確定又はBSキーで削除された、と判定できます。 このときに、ESCAPEとENTERキーが押下状態なら、離されるまで待つ関数を入れれば解決しました。 また、押下状態が1秒以上続いたら、そのまま関数を終了するようにしました。 以下に関数を提示します。 ////////////////////////////////////////////////////////////////////////////////////// //IMEの入力終了(キャンセル含む)時点で、EscapeやEnterキーが押下状態にあれば、離されるまで待つ。 void Ime_Cancel_YOBUN_key( IMEINPUTDATA *ImeData, int *ImeData_InputString_length_b, wait_time=1000 ) { int StartTime; if(*ImeData_InputString_length_b > 0) { if(!ImeData) //ImeOffの状態で、一回前の入力文字が存在するときは、ESCキーが話されるまで待機 { //押され続けたとしても、1秒経過したら戻る。 // 現在経過時間を得る StartTime = GetNowCount() ; // 計測開始からwait_time秒が過ぎるか、キーが離されるまでループ while( GetNowCount() - StartTime < wait_time ) { // メッセージ処理 if( ProcessMessage() == -1 ) { break ; // エラーが起きたらループから抜ける } if( CheckHitKey(KEY_INPUT_ESCAPE) || CheckHitKey(KEY_INPUT_RETURN) ) {//ESCまたはENTERが押下されている間は、何もしない。 }else { break; } } *ImeData_InputString_length_b = 0; //0にセット (IME OFFの状態では、ImeData->InputStringの値は未定の為、strlenが使えない) } } if(ImeData) { *ImeData_InputString_length_b = strlen(ImeData->InputString); } } 使用するときは以下の宣言と IMEINPUTDATA *ImeData ; int ImeData_InputString_length_b=0;//IMEのESCキー入力取得用 (一回前時点での長さ) 関数の呼び出し Ime_Cancel_YOBUN_key( ImeData, &ImeData_InputString_length_b, 1000 ); で私の目下の問題であるESCAPEとENTERキーの判別ができるようになりました。 私が欲しい機能というのは、例えればキャラクターを操作しながら、いつでも文字入力することによりチャットを常時できる、といったことを支援する機能になります。 DXライブラリのソースをDxWin.cppだけですが見させて頂きました。 あまりの量の多さに感服しております。 あまり機能を追加・・・とは言いづらいですね。 アドバイスありがとうございました。

Page: 1 |