遅くなり申し訳ありません。
こちらに機能追加をしたバージョンをアップしましたので
宜しければダウンロードしてください。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 より適当な作りです。(汗)
不明な点がありましたらご指摘ください。