Re: 日本語入力時に特定の文字を受け付けないようにしたい ( No.1 ) |
- 名前:管理人 日時:2022/05/14 23:14
すみません、DXライブラリでは入力決定前の日本語入力時の文字については制御対象としていないので、
日本語入力時の入力文字の制限をすることはできません
ただ、リファレンスには載っていませんが GetIMEInputData という関数を使用することで
日本語入力中の文字列を取得することはできますので、\ や " が入力されていたら画面に
『 \ は入力できません』などの表示を画面に出すことは可能です
// 日本語入力の文字列に \ が含まれていたら『\ は入力できません』と表示するプログラム
#include "DxLib.h"
#include <string.h>
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
const IMEINPUTDATA *IMEData ;
int KeyInputHandle ;
// ウインドウモードで起動
ChangeWindowMode( TRUE ) ;
// DXライブラリの初期化
if( DxLib_Init() < 0 ) return -1 ;
// 描画先を裏画面にする
SetDrawScreen( DX_SCREEN_BACK ) ;
// キー入力関連初期化
KeyInputHandle = MakeKeyInput( 64, FALSE, FALSE, FALSE ) ;
SetActiveKeyInput( KeyInputHandle ) ;
// メインループ
while( ProcessMessage() == 0 )
{
// 画面のクリア
ClearDrawScreen() ;
// IMEの情報を取得
IMEData = GetIMEInputData() ;
// GetIMEInputData が NULL 以外の場合のみ処理
if( IMEData != NULL )
{
// 入力中の文字列に \ があったら入力できないと表示する
if( strchr( IMEData->InputString, '\\' ) != NULL )
{
DrawString( 10, 26, "\\ は入力できません", GetColor( 255,0,0 ) ) ;
}
}
// 入力中の文字列を描画
DrawKeyInputString( 10, 10, KeyInputHandle ) ;
// 入力モードの描画
DrawKeyInputModeString( 300, 300 ) ;
// 裏画面の内容を表画面に反映
ScreenFlip() ;
}
// DXライブラリの後始末
DxLib_End() ;
// ソフトの終了
return 0 ;
}
因みに GetIMEInputData で取得できる構造体 IMEINPUTDATA の中身は以下のようになっていて、
主にDXライブラリの『日本語入力中文字列の描画機能』を使用せずに、自前で入力中の文字列や
変換候補などを描画したい時に使用するものとなっています( 尚、情報参照用の機能なので
IMEINPUTDATA 構造体の中の InputString の中身を書き換えても入力中文字列には反映されません )
// IME入力文字列の描画に必要な情報の内の文節情報
struct IMEINPUTCLAUSEDATA
{
int Position ; // 何文字目から
int Length ; // 何文字か
} ;
// IME入力文字列の描画に必要な情報
struct IMEINPUTDATA
{
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 ; // 選択中の変換候補
int ConvertFlag ; // 文字変換中かどうか( TRUE:変換中 FALSE:変換中ではない( 文字単位でカーソルが移動できる状態 ) )
} ;
|
Re: 日本語入力時に特定の文字を受け付けないようにしたい ( No.2 ) |
- 名前:管理人 日時:2022/05/15 01:53
すみません、No.1 では日本語入力中の文字列を変更することができないと申し上げましたが、
その後少し調べて関数を追加した所変更することができました
よろしければその関数を追加したこちらの暫定最新バージョンをダウンロードしてください m(_ _)m
https://dxlib.xsrv.jp/temp/DxLibVCTest.zip // Windows版 VisualC++ 用
https://dxlib.xsrv.jp/temp/DxLibBCCTest.zip // Windows版 BorlandC++ 用
https://dxlib.xsrv.jp/temp/DxLibBCC2Test.zip // Windows版 C++ Builder 10.3 用
https://dxlib.xsrv.jp/temp/DxLibGCC_MinGWTest.zip // Windows版 MinGW 用
https://dxlib.xsrv.jp/temp/DxLibDotNet.zip // Windows版 .NET用
https://dxlib.xsrv.jp/temp/DxLibMakeTest.zip // ソース
(中身を既存のライブラリのファイルに上書きして『リビルド』をして下さい)
以下の関数を追加しました
// IMEで入力中の文字列を変更する( IMEで文字列を入力中ではなかった場合は何も起こりません )
int SetIMEInputString( const char *String ) ;
注釈の通り、日本語入力中の文字列を引数で渡した文字列に置き換えます
この関数を使用して、
GetIMEInputData() で取得できる入力中文字列の中に \ や " があったらそれを取り除いた文字列を作成して、
それを SetIMEInputString に渡すと入力文字列から \ や " を取り除くことができる
というわけです
試しに \ が入力文字列に出現したら削除して、且つ『\ は入力できません』という文言も表示する
プログラムを組んでみましたので、よろしければご覧ください m(_ _)m
#include "DxLib.h"
#include <string.h>
// 文字列から指定の文字を抜く関数
void DeleteChar( char *String, char Char )
{
char *p ;
size_t length ;
for(;;)
{
p = strchr( String, Char ) ;
if( p == NULL )
{
break ;
}
length = strlen( p ) ;
if( length == 1 )
{
*p = '\0' ;
}
else
{
memmove( p, p + 1, length - 1 ) ;
p[ length - 1 ] = '\0' ;
}
}
}
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
const IMEINPUTDATA *IMEData ;
int KeyInputHandle ;
int ErrorInputTimer = 0 ;
char StringBuffer[ 256 ] ;
// ウインドウモードで起動
ChangeWindowMode( TRUE ) ;
// DXライブラリの初期化
if( DxLib_Init() < 0 ) return -1 ;
// 描画先を裏画面にする
SetDrawScreen( DX_SCREEN_BACK ) ;
// キー入力関連初期化
KeyInputHandle = MakeKeyInput( 64, FALSE, FALSE, FALSE ) ;
SetActiveKeyInput( KeyInputHandle ) ;
// メインループ
while( ProcessMessage() == 0 )
{
// 画面のクリア
ClearDrawScreen() ;
// IMEの情報を取得
IMEData = GetIMEInputData() ;
// GetIMEInputData が NULL 以外の場合のみ処理
if( IMEData != NULL )
{
// 入力中の文字列に \ があったら入力できないと表示する
if( strchr( IMEData->InputString, '\\' ) != NULL )
{
// エラー表示フレーム数をセット
ErrorInputTimer = 60 ;
// 入力文字列から \ を無くした文字列を作成する
strcpy( StringBuffer, IMEData->InputString ) ;
DeleteChar( StringBuffer, '\\' ) ;
// 入力文字列から \ を無くした文字列を入力中文字列としてセットする
SetIMEInputString( StringBuffer ) ;
}
}
// 通常入力の文字列に \ があったら削除して入力できない表示も行う
GetKeyInputString( StringBuffer, KeyInputHandle ) ;
if( strchr( StringBuffer, '\\' ) != NULL )
{
// エラー表示フレーム数をセット
ErrorInputTimer = 60 ;
// 入力文字列から \ を無くした文字列を作成する
DeleteChar( StringBuffer, '\\' ) ;
// 入力文字列から \ を無くした文字列を入力中文字列としてセットする
SetKeyInputString( StringBuffer, KeyInputHandle ) ;
}
// 入力中の文字列を描画
DrawKeyInputString( 10, 10, KeyInputHandle ) ;
// エラー表示
if( ErrorInputTimer > 0 )
{
ErrorInputTimer -- ;
DrawString( 10, 26, "\\ は入力できません", GetColor( 255,0,0 ) ) ;
}
// 入力モードの描画
DrawKeyInputModeString( 300, 300 ) ;
// 裏画面の内容を表画面に反映
ScreenFlip() ;
}
// DXライブラリの後始末
DxLib_End() ;
// ソフトの終了
return 0 ;
}
|
Re: 日本語入力時に特定の文字を受け付けないようにしたい ( No.3 ) |
- 名前:あっぷる 日時:2022/05/17 12:02
いつも速やかなご対応ありがとうございます。
言葉足らずで正しくお伝えできていませんでした
状況についてもう少し補足致します
通常通り、日本語入力をおこないます
まずは「あいう」とタイプします
↓
次にあいうを変換しないまま、漢字モードを解除して半角の\をタイプして確定します
頂いたサンプルでも\を許してしまいます。
かな入力の場合は、現象が異なってきます
通常通り、日本語入力をおこないます
まずは「あいう」とタイプします
↓
次にあいうを変換しないまま、漢字モードを解除して半角の\をタイプした後、別の文字もタイプします
この時点で少し動作が怪しいです(かな入力の場合はエスケープシーケンスを処理しようとしている??)
どちらのケースでもIMEData->InputStringによって入力した\は取得できないみたいです
今の所、変換中の\や"の入力と表示は許可して、確定した時に削除するような処理してみましたが、
理想は、変換中のタイプから半角の\や"の入力は無視するようにしたいです
|
Re: 日本語入力時に特定の文字を受け付けないようにしたい ( No.4 ) |
- 名前:あっぷる 日時:2022/05/17 13:08
別件になりますが、以下の現象を確認しました
かな入力にて
「あ」を入力して確定
バックスペースにて「あ」を削除
aをタイプすると
チa
になります
ローマ字入力だと問題ないようです
|
Re: 日本語入力時に特定の文字を受け付けないようにしたい ( No.5 ) |
- 名前:管理人 日時:2022/05/19 21:34
> 次にあいうを変換しないまま、漢字モードを解除して半角の\をタイプして確定します
> 頂いたサンプルでも\を許してしまいます。
手元でもこちらの現象を確認しました
私も今回初めて知ったのですが、普通に \ を入力した時の文字と、
載せていただいた手順で入力された \ は別の文字( 文字コードが違う )でした
( ただの \ = 0x5C 件の手順で入力された \ = 0xA5 )
どちらの \ も入力できないようにするには \(0x5C) の他に \(0xA5) も同様の処理をする必要があります
ただ、日本語入力中の文字列から \(0xA5) を削除する処理を追加すると日本語入力の挙動が明らかに
おかしくなってしまったので、結果的には以下のように確定された入力からのみ削除することしかできませんでした
#include "DxLib.h"
#include <string.h>
// 文字列から指定の文字を抜く関数
void DeleteChar( wchar_t *String, wchar_t Char )
{
wchar_t *p ;
size_t length ;
for(;;)
{
p = wcsrchr( String, Char ) ;
if( p == NULL )
{
break ;
}
length = wcslen( p ) ;
if( length == 1 )
{
*p = L'\0' ;
}
else
{
memmove( p, p + 1, ( length - 1 ) * sizeof( wchar_t ) ) ;
p[ length - 1 ] = L'\0' ;
}
}
}
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
const IMEINPUTDATA *IMEData ;
int KeyInputHandle ;
int ErrorInputTimer = 0 ;
wchar_t StringBuffer[ 256 ] ;
// ウインドウモードで起動
ChangeWindowMode( TRUE ) ;
// DXライブラリの初期化
if( DxLib_Init() < 0 ) return -1 ;
// 描画先を裏画面にする
SetDrawScreen( DX_SCREEN_BACK ) ;
// キー入力関連初期化
KeyInputHandle = MakeKeyInput( 64, FALSE, FALSE, FALSE ) ;
SetActiveKeyInput( KeyInputHandle ) ;
// メインループ
while( ProcessMessage() == 0 )
{
// 画面のクリア
ClearDrawScreen() ;
// IMEの情報を取得
IMEData = GetIMEInputData() ;
// GetIMEInputData が NULL 以外の場合のみ処理
if( IMEData != NULL )
{
// 入力中の文字列に \ があったら入力できないと表示する
if( wcschr( IMEData->InputString, L'\\' ) != NULL )
{
// エラー表示フレーム数をセット
ErrorInputTimer = 60 ;
// 入力文字列から \ を無くした文字列を作成する
wcscpy( StringBuffer, IMEData->InputString ) ;
DeleteChar( StringBuffer, L'\\' ) ;
// 入力文字列から \ を無くした文字列を入力中文字列としてセットする
SetIMEInputString( StringBuffer ) ;
}
}
// 通常入力の文字列に \ があったら削除して入力できない表示も行う
GetKeyInputString( StringBuffer, KeyInputHandle ) ;
if( wcschr( StringBuffer, L'\\' ) != NULL )
{
// エラー表示フレーム数をセット
ErrorInputTimer = 60 ;
// 入力文字列から \ を無くした文字列を作成する
DeleteChar( StringBuffer, L'\\' ) ;
// 入力文字列から \ を無くした文字列を入力中文字列としてセットする
SetKeyInputString( StringBuffer, KeyInputHandle ) ;
}
// 通常入力の文字列に特殊な \ があったら削除して入力できない表示も行う
GetKeyInputString( StringBuffer, KeyInputHandle ) ;
if( wcschr( StringBuffer, L'\xA5' ) != NULL )
{
// エラー表示フレーム数をセット
ErrorInputTimer = 60 ;
// 入力文字列から特殊な \ を無くした文字列を作成する
DeleteChar( StringBuffer, L'\xA5' ) ;
// 入力文字列から特殊な \ を無くした文字列を入力中文字列としてセットする
SetKeyInputString( StringBuffer, KeyInputHandle ) ;
}
// 入力中の文字列を描画
DrawKeyInputString( 10, 10, KeyInputHandle ) ;
// エラー表示
if( ErrorInputTimer > 0 )
{
ErrorInputTimer -- ;
DrawString( 10, 26, L"\\ は入力できません", GetColor( 255,0,0 ) ) ;
}
// 入力モードの描画
DrawKeyInputModeString( 300, 300 ) ;
// 裏画面の内容を表画面に反映
ScreenFlip() ;
}
// DXライブラリの後始末
DxLib_End() ;
// ソフトの終了
return 0 ;
}
因みに件の \(0xA5) はシフトJISコードには無い文字なので、上記のプログラムは Unicode を使用する
( char ではなく wchar_t を使用する )プログラムとなっています
> 次にあいうを変換しないまま、漢字モードを解除して半角の\をタイプした後、別の文字もタイプします
> この時点で少し動作が怪しいです(かな入力の場合はエスケープシーケンスを処理しようとしている??)
DXライブラリ側はエスケープシーケンスの処理などは行っておらず、メモ帳など別のアプリでも同様の
現象が発生したので、Microsoft IME の仕様( バグ? )のようです
> 「あ」を入力して確定
> バックスペースにて「あ」を削除
> aをタイプすると
>
> チa
> になります
『チ』は Aキー に割り当てられている『かな入力』の文字『ち』の半角カタカナですね…
すみません、こちらの現象は原因不明です
メモ帳などでは発生しない現象ですが、DXライブラリとしては IMEから渡された文字を表示しているだけなので、
こちらも Microsoft IEM の仕様というか、バグなのかもしれません (- -;
> 今の所、変換中の\や"の入力と表示は許可して、確定した時に削除するような処理してみましたが、
> 理想は、変換中のタイプから半角の\や"の入力は無視するようにしたいです
『日本語入力中に入力された \(0xA5) を削除すると Microsoft IME の挙動がおかしくなる』という現象がある以上
下手に \(0xA5) を削除することができないので、残念ながら入力が完了された文字列から \(0xA5) を削除するという
処理にするしかないかと思います… ( 通常の \(0x5C) は日本語入力中に削除しても大丈夫なようです )
|
Re: 日本語入力時に特定の文字を受け付けないようにしたい ( No.6 ) |
- 名前:あっぷる 日時:2022/05/20 20:28
詳しく調査頂きましてありがとうございます!
IMEの挙動であれば、今の所はなんともならなさそうですね
今の所、変換確定後に禁止文字を削除する方向で問題なさそうなので
本件はクローズしたいと思います
半角カナも同様に禁止文字処理して自動削除するようにしました
今回も助けて頂きありがとうございました
|
|