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だけですが見させて頂きました。
あまりの量の多さに感服しております。
あまり機能を追加・・・とは言いづらいですね。
アドバイスありがとうございました。
|