トップページ > 記事閲覧
KeyInputを使用したIME入力時の時の挙動
名前:naru 日時: 2022/10/21 19:46

初めまして。 ゲームを作るためにDXライブラリの機能を試しながら楽しませていただいています。 KeyInputの挙動について疑問が生じたので2つ質問させてください。 1.キー入力ハンドルのIME入力時の挙動について。 キー入力ハンドルを使用し、IMEモードで文字列を入力後、変換状態にしてキーで文節を移動すると、 左から右にカーソルがワープしたり、複数回キーを押さないとカーソルが移動しなくなったりする。 これは正常な挙動でしょうか? GetIMEInputData関数で取得しているIME入力情報も正しい値が取得出来ていないように思えます。 2.GetIMEInputDataのメモリ管理について。 1フレームに1回、GetIMEInputDataを呼び出して返されたすべての情報を一度に参照するのが一般的かと思いますが、 仮にIMEINPUTDATA構造体の各メンバを参照する独立したメンバ関数をクラスに1対1で用意し、 必要なメンバを参照する都度内部でGetIMEInputDataをコールするように設計した場合(つまり無駄に何度もGetIMEInputDataをコールした場合)、 GetIMEInputData内部でどのようなメモリ管理を行っているかを知っておきたく、メモリ管理について大まかに教えていただたら有難いです。 DXライブラリの使い方や、テストコードに問題がある可能性があるので、こちらで試したコードを添付させていただきます。 何か御座いましたら、お手数ですがご指摘ください。 #include "DxLib.h" #include <string> #include <sstream> using DXHANDLE = int; // 項目の名前と値を表示する template <class T> void ShowParameter(int x, int y, const std::string& name, T value) { const unsigned white = DxLib::GetColor(255, 255, 255); std::stringstream ss; ss << name << ": " << value << " (" << typeid(T).name() << ")"; DxLib::DrawString(x, y, ss.str().c_str(), white); } // WinMain int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { DxLib::ChangeWindowMode(true); if (DxLib_Init() < 0) return -1; DxLib::SetDrawScreen(DX_SCREEN_BACK); // キー入力ハンドルの作成、アクティブ化 DXHANDLE ki = DxLib::MakeKeyInput(256, true, false, false); DxLib::SetActiveKeyInput(ki); while (ProcessMessage() == 0) { if (DxLib::CheckKeyInput(ki)) break; DxLib::ClearDrawScreen(); // 入力モード、入力中の文字の描画 DxLib::DrawKeyInputModeString(32, 32); DxLib::DrawKeyInputString(64, 64, ki); // IME 入力情報を取得する auto p = DxLib::GetIMEInputData(); constexpr int x = 64, y = 176; // IME 入力情報の表示 if (p) { ShowParameter(x, y + 16 * 0, "入力中の文字列", p->InputString); ShowParameter(x, y + 16 * 2, "カーソルの位置", p->CursorPosition); ShowParameter(x, y + 16 * 4, "文節の総数", p->ClauseNum); ShowParameter(x, y + 16 * 5, "選択中の文節番号", p->SelectClause); if (p->ClauseData) { ShowParameter(x, y + 16 * 6, "選択中の文節の位置", p->ClauseData->Position); ShowParameter(x, y + 16 * 7, "選択中の文節の長さ", p->ClauseData->Length); } ShowParameter(x, y + 16 * 9, "変換中", p->ConvertFlag); ShowParameter(x, y + 16 * 10, "変換候補の総数", p->CandidateNum); ShowParameter(x, y + 16 * 11, "選択中の変換候補番号", p->SelectCandidate); if (p->CandidateList) { ShowParameter(x, y + 16 * 12, "選択中の変換候補", p->CandidateList[p->SelectCandidate]); } } ShowParameter(x - 32, y + 16 * 14, "IME 入力情報のアドレス", p); DxLib::ScreenFlip(); } DxLib::DeleteKeyInput(ki); DxLib::DxLib_End(); return 0; } よろしくお願いいたします!
メンテ

Page: 1 |

Re: KeyInputを使用したIME入力時の時の挙動 ( No.1 )
名前:管理人 日時:2022/10/22 00:33

> 1.キー入力ハンドルのIME入力時の挙動について。 > キー入力ハンドルを使用し、IMEモードで文字列を入力後、変換状態にしてキーで文節を移動すると、 > 左から右にカーソルがワープしたり、複数回キーを押さないとカーソルが移動しなくなったりする。 > これは正常な挙動でしょうか? 『MicrosoftIME』の正常な挙動の様です( メモ帳でも同じ挙動になりました ) Google製のIMEである『Google日本語入力』ではそのような挙動はしないので、『MicrosoftIME』の仕様のようです > GetIMEInputData関数で取得しているIME入力情報も正しい値が取得出来ていないように思えます。 載せていただいたテストコードを実行させていただいた限りでは表示される情報は正しいようです 正しい値が取得出来ていないと思われたのはどのような値を見てそのように思われたのでしょうか? > 2.GetIMEInputDataのメモリ管理について。 GetIMEInputData を呼ぶと1回に付き1度メモリ確保が行われています( GetIMEInputData 呼び出しの際に 一つ前の呼び出しの際に確保したメモリを解放しています )ので、呼び出し回数の数にもよりますが処理負荷は 少し高いかもしれません ただ、最近のCPUは高速なので実用の面で問題が無ければ気にせず1フレームに何回も呼んで問題無いと思います
メンテ
Re: KeyInputを使用したIME入力時の時の挙動 ( No.2 )
名前:naru 日時:2022/10/22 06:43

管理人様、ご回答ありがとうございます。 >『MicrosoftIME』の正常な挙動の様です( メモ帳でも同じ挙動になりました ) >Google製のIMEである『Google日本語入力』ではそのような挙動はしないので、『MicrosoftIME』の仕様のようです こちらの環境をお伝えせず、お手数をおかけしました。 管理人様が仰る通り、当方MicrosoftIMEを使用しており、メモ帳で確認したところこちらでも同様の挙動になりました。 『Google日本語入力』をインストールして試したところ、そのような挙動は発生しないので、『MicrosoftIME』の仕様ということで理解致しました。 >載せていただいたテストコードを実行させていただいた限りでは表示される情報は正しいようです >正しい値が取得出来ていないと思われたのはどのような値を見てそのように思われたのでしょうか? ※こちらの件につきましては、問題らしきものと私の仕込んだバグの複合技によるもので、少々長くなるため投稿を分けさせていただきます。 >GetIMEInputData を呼ぶと1回に付き1度メモリ確保が行われています( GetIMEInputData 呼び出しの際に >一つ前の呼び出しの際に確保したメモリを解放しています )ので、呼び出し回数の数にもよりますが処理負荷は少し高いかもしれません >ただ、最近のCPUは高速なので実用の面で問題が無ければ気にせず1フレームに何回も呼んで問題無いと思います 詳しくご説明くださり、ありがとうございます。実装の際の参考にさせていただきます。 次に、※の部分について投稿させていただきます。
メンテ
Re: KeyInputを使用したIME入力時の時の挙動 ( No.3 )
名前:naru 日時:2022/10/22 06:51

調査結果 『Google日本語入力』を使用している場合、一切の問題は確認されなかった。 『MicrosoftIME』を使用し、文字コード体系をshift-jisとし、かつ、いずれかの文節の文字列の中にshift-jisで表現できない文字が含まれているとき、 その後方の文節のインデックスが見た目に反する値になる。 対策案 『Google日本語入力』をユーザーに強制することは出来ないので(私は気に入りましたが)、考えられる対策は、 A.UNICODE文字体系を使用する。 B.現在の文字体系で表現できない文字を、変換候補一覧から除外する。 過去のトピックを拝見して分かりましたが、問題となっている文字がDrawKeyInputStringで表示されているのは、DXライブラリ内部ではUNICODEで扱っているからなのですね。 今後の状況を鑑みまして、現在はA(具体的にはutf-8)で統一しようと考えています。 Bの処理についてですが、DXライブラリ内部、またはライブラリ使用者側で行うことは、実装コストも含めて可能でしょうか? 管理人様の考えをお聞かせいただけましたら幸いです。 蛇足ですが、以下は上記の結論に至るまでの過程です。 選択中の文節番号が何かおかしい。試しているうちに、変換中の文字列の中に変な文字が入っているときに、その後方のインデックスがおかしくなっている事におぼろげに気付く。 試しにその「変な文字」を手作業で見慣れた文字に変換し、カーソルを動かしてみると、表示されるインデックスが正常になった。 その後にメモ帳で試してみると、「環境依存」と表示される文字がそれに該当するようだ。 メモ帳で『Google日本語入力』に切り替えて再び試してみると、そもそも「環境依存」と表示される文字が変換候補一覧に出現しない。 『Google日本語入力』で問題が確認されないのは、これが原因だろうか。 文節の位置と文字数の情報がおかしい。よく見ると常に先頭の情報が表示されているように見える←重要 実用コードではこのような現象は発生していなかったので、最初から形容し難い違和感を感じてはいた テストコードをよくよく見直すと、選択中の文節の位置、選択中の文節の長さを取得する際のインデックス指定が抜けていた(バグ) 申し訳ございません。 以下、UTF-8を使用するように変更したコードで、問題は確認されませんでした(投稿を分けた方がいいでしょうか)。
メンテ
Re: KeyInputを使用したIME入力時の時の挙動 ( No.4 )
名前:naru 日時:2022/10/22 06:55

#include "DxLib.h" #include <string> #include <sstream> using DXHANDLE = int; // 項目の名前と値を表示する template <class T> void ShowParameter(int x, int y, const std::string& name, T value) { const unsigned white = DxLib::GetColor(255, 255, 255); std::stringstream ss; ss << name << ": " << value << " (" << typeid(T).name() << ")"; DxLib::DrawString(x, y, ss.str().c_str(), white); } // WinMain int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { DxLib::ChangeWindowMode(true); /* [その壱] UTF-8 対応、追加しました (UTF-8 を使用していることをDXライブラリに伝える) → */ DxLib::SetUseCharCodeFormat(DX_CHARCODEFORMAT_UTF8); /* ← [その壱] 追加しました (UTF-8 を使用していることをDXライブラリに伝える) */ if (DxLib_Init() < 0) return -1; DxLib::SetDrawScreen(DX_SCREEN_BACK); // キー入力ハンドルの作成、アクティブ化 DXHANDLE ki = DxLib::MakeKeyInput(256, true, false, false); DxLib::SetActiveKeyInput(ki); while (ProcessMessage() == 0) { if (DxLib::CheckKeyInput(ki)) break; DxLib::ClearDrawScreen(); // 入力モード、入力中の文字の描画 DxLib::DrawKeyInputModeString(32, 32); DxLib::DrawKeyInputString(64, 64, ki); // IME 入力情報を取得する auto p = DxLib::GetIMEInputData(); constexpr int x = 64, y = 176; /* [その弐] UTF-8 対応、変更しました (すべての文字列リテラルに u8 を付加) → */ // IME 入力情報の表示 if (p) { ShowParameter(x, y + 16 * 0, u8"入力中の文字列", p->InputString); ShowParameter(x, y + 16 * 2, u8"カーソルの位置", p->CursorPosition); ShowParameter(x, y + 16 * 4, u8"文節の総数", p->ClauseNum); ShowParameter(x, y + 16 * 5, u8"選択中の文節番号", p->SelectClause); if (p->ClauseData) { /* [その参] バグを修正しました (インデックスを指定して値を参照するように修正) → */ if (0 <= p->SelectClause && p->SelectClause < p->ClauseNum) { ShowParameter(x, y + 16 * 6, u8"選択中の文節の位置", p->ClauseData[p->SelectClause].Position); ShowParameter(x, y + 16 * 7, u8"選択中の文節の長さ", p->ClauseData[p->SelectClause].Length); } } ShowParameter(x, y + 16 * 9, u8"変換中", p->ConvertFlag); ShowParameter(x, y + 16 * 10, u8"変換候補の総数", p->CandidateNum); ShowParameter(x, y + 16 * 11, u8"選択中の変換候補番号", p->SelectCandidate); if (p->CandidateList) { ShowParameter(x, y + 16 * 12, u8"選択中の変換候補", p->CandidateList[p->SelectCandidate]); } } ShowParameter(x - 32, y + 16 * 14, u8"IME 入力情報のアドレス", p); /* ← [その弐] UTF-8 対応、変更しました (すべての文字列リテラルに u8 を付加) */ DxLib::ScreenFlip(); } DxLib::DeleteKeyInput(ki); DxLib::DxLib_End(); return 0; }
メンテ
Re: KeyInputを使用したIME入力時の時の挙動 ( No.5 )
名前:管理人 日時:2022/10/23 22:58

UTF-8 を使用することで問題は解決されたとのことで何よりです > Bの処理についてですが、DXライブラリ内部、またはライブラリ使用者側で行うことは、実装コストも含めて可能でしょうか? > 管理人様の考えをお聞かせいただけましたら幸いです。 IMEに関する挙動や表示物はあくまでIMEから取得できる情報を表示しているに過ぎず、 変換候補の一覧やリストの中のどの項目を現在選択しているかなどの処理もIME側で行っている ことなので、ちょっとこちらの機能を実装するのは難しいです ( やるとしたら『IME側の処理では変換候補から shift-jis で扱えないものも除外されていないけれども、 DXライブラリ側で表示する変換候補や GetIMEInputData から取得できる情報からは外れている』という 処理ですが、かなり無理矢理な実装になりそうです… ) UNICODE文字体系を使用すれば問題ないとの事ですので、今後 KeyInputString 系の機能を きちんとした形で使用されようとしている方には UTF-8 や UTF-16LE を使用していただくように ご案内するようにして、shift-jis に関しては現状のままの挙動で行こうと思います m(_ _)m
メンテ
Re: KeyInputを使用したIME入力時の時の挙動 ( No.6 )
名前:naru 日時:2022/10/24 00:31

ご回答ありがとうございます。 本番ではUTF-8を使用する、ということで気持ちは固まっているのですが、 一点気になっている点があるので、最後に質問させてください。 shift-jis使用時にいわゆる環境依存文字が含まれていても、DrawKeyInputStringでは問題なく描画できているように見えるので、 DrawKeyInputString内部では正しく情報を解析、処理出来ているのだと思われます。 そこで、GetIMEInputDataが返すIMEINPUTDATA.SelectClauseの値を、 DrawKeyInputString内部で使用している情報通り返すことはできないのでしょうか?
メンテ
Re: KeyInputを使用したIME入力時の時の挙動 ( No.7 )
名前:管理人 日時:2022/10/24 23:50

> そこで、GetIMEInputDataが返すIMEINPUTDATA.SelectClauseの値を、 > DrawKeyInputString内部で使用している情報通り返すことはできないのでしょうか? すみません、手元では『環境依存文字が含まれているために SelectClause の値が正常ではない』状況が 再現できずにいます( 環境依存文字でも shift-jis が対応している文字があるため ) お手数お掛けして申し訳ありませんが件の現象が確認できる入力文字列と、変換時にどの文節を選択したら 現象を確認できるか教えていただけないでしょうか? m(_ _;m
メンテ
Re: KeyInputを使用したIME入力時の時の挙動 ( No.8 )
名前:naru 日時:2022/10/25 22:38

お返事ありがとうございます。 再現できてなかったのですね。それでは対応しにくいですね。 試した環境は、DXライブラリのVer3.24、VisualStudio2022(x64) で文字セットを『マルチバイト文字セットを使用する』にしてshift-jisを使用しています。 キー入力状態にして、『MicroSoftIME』(問題の文字が出る設定なら他のIMEでもなるかと思います)を使用してたとえば「えーえふけーえす」と入力します。 ここでスペースを押して(確定はさせません)、「えー &#9403; ケー エス」となったとします。 ここで「えー &#9403; ケー エス」それぞれにカーソルを移動したときの文節インデックスはそれぞれ「0 3 3 3」となります。 &#9403;をたとえば「エフ」に変えると、「0 1 2 3」とDrawKeyInputStringの見た目と一致してくれます。 この「&#9403;」のような文字が、問題になっている文字だと思われます。
メンテ
Re: KeyInputを使用したIME入力時の時の挙動 ( No.9 )
名前:naru 日時:2022/10/25 22:39

化けちゃいましたね。 「&#9403;」は「Fが丸で囲まれた文字」です。
メンテ
Re: KeyInputを使用したIME入力時の時の挙動 ( No.10 )
名前:管理人 日時:2022/10/27 00:10

ご返答ありがとうございます、『えーえふけーえす』で手元でも現象を再現できました 件の『えふ』の文字は shift-jis では長さ0の文節、という扱いで処理するようにして 他の情報が正常な値で取得できるように修正したバージョンをアップしましたので、よろしければお試しください 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 // ソース (中身を既存のライブラリのファイルに上書きして『リビルド』をして下さい)
メンテ
Re: KeyInputを使用したIME入力時の時の挙動 ( No.11 )
名前:naru 日時:2022/10/28 22:32

ご対応いただき、ありがとうございます。 IME入力中の分節に関する動作は改善されましたが、問題の文字が含まれたまま確定した場合、 確定文字列中にその文字が含まれるものの、GetKeyInputStringでは除去されて返ってくる都合上、 カーソルの位置に不整合が生じ、これを解決するためにはIME入力中に長さ0の文節の存在を監視し、 確定文字列をパーツに区切って描画する等しなければならないため、素直にUNICODEを使用するべき、という結論に至りました。 この度はお忙しい中対応してくださり、ありがとうございました。 中途半端ですが、やってみた分を貼っておきます #include "DxLib.h" #include <string> #include <sstream> #include <vector> #define white (DxLib::GetColor(255, 255, 255)) #define black (DxLib::GetColor(0, 0, 0)) #define red (DxLib::GetColor(255, 0, 0)) #define green (DxLib::GetColor(0, 255, 0)) #define blue (DxLib::GetColor(0, 0, 255)) typedef struct Point_t { // 座標、またはサイズ Point_t() : x(0), y(0) {} Point_t(int _x, int _y) : x(_x), y(_y) {} Point_t operator+(const Point_t& _rhs) const { return Point_t(x + _rhs.x, y + _rhs.y); } Point_t operator*(int _scale) const { return Point_t(x * _scale, y * _scale); } Point_t operator/(int _den) const { return Point_t(x / _den, y / _den); } public: int x, y; } Point, Size; struct Rect { // 矩形 Rect() : lt(), size() {} Rect(int _l, int _t, int _r, int _b) : lt(_l, _t), size(_r - _l, _b - _t) {} Rect(const Point& _lt, const Size& _size) : lt(_lt), size(_size) {} Rect operator+(const Size& _point) const { return Rect(lt + _point, size); } Rect operator*(int _scale) const { return Rect(lt, size * _scale); } int r() const { return l + size.x; } int b() const { return t + size.y; } public: Point lt; Size size; int& l = lt.x, & t = lt.y; }; typedef struct Position_t { // 位置情報 int bytes; int pixels; } Position, Length; struct Clause { // 文節情報 Clause(const std::string& _str, const Position& _position, const Length& _length) : str(_str), position(_position), length(_length) {} std::string str; Position position; Length length; }; struct Candidate { // 変換文字列情報 Candidate(const std::string& _str, const Length& _length) : str(_str), length(_length) {} std::string str; Length length; }; int MyDrawString(const Point& _p, const std::string& _s, unsigned _color = white, unsigned _edge_color = 0) { return DxLib::DrawString(_p.x, _p.y, _s.c_str(), _color, _edge_color); } int MyDrawStringEX(const Point& _p, float _ext, const std::string& _s, unsigned _color = white, unsigned _edge_color = 0) { return DxLib::DrawExtendString(_p.x, _p.y, _ext, _ext, _s.c_str(), _color, _edge_color); } int MyDrawBox(const Rect& _r, unsigned _color, bool _fill) { return DxLib::DrawBox(_r.l, _r.t, _r.r(), _r.b(), _color, (int)_fill); } int MyDrawStringWidth(const std::string& _s, int _len) { return DxLib::GetDrawStringWidth(_s.c_str(), _len); } VECTOR transducer(int _idx, float _phase) { constexpr float d = 400.f; constexpr float r = 800.f; float z = (float)_idx + _phase; float sign = (z < 0 ? -1.f : 1.f); z = std::fabsf(z) * r / 9.5f; if (z >= r) return { r * sign, 0.f, 0.f }; float x = std::sqrtf(r * r - (r - z) * (r - z)) * sign; return { x, 0., d / std::sqrtf(x * x + (d + z) * (d + z)) }; } /* 文字系設定値 */ constexpr int max_length = 256; // キー入力最大文字数 (byte) constexpr int font_size = 64; // フォントのサイズ constexpr int font_thick = 8; // フォントの太さ constexpr int font_edge = 4; // フォントのエッジの太さ const std::string font_name = "Meiryo UI"; // フォント名 /* 座標設定値 */ const Size screen_size = { 1280, 800 }; // バックバッファのサイズ const Point p1 = { 64, 64 }; // 確定文字列描画原点 const Point p2 = screen_size / 2; // 未確定文字列(IME入力中文字列) 描画原点 /* 処理用 */ std::string confirmed_string(max_length, 0); // 確定文字列 std::string unconfirmed_string; // 未確定文字列(IME入力中文字列) Position cursor_confirmed; // 確定文字列のカーソル位置情報 Position cursor_unconfirmed; // 未確定文字列(IME入力中文字列) のカーソル位置情報 int ki; int frames = 0; int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { DxLib::ChangeWindowMode(true); DxLib::SetGraphMode(screen_size.x, screen_size.y, 16); if (DxLib_Init() < 0) return -1; DxLib::SetDrawScreen(DX_SCREEN_BACK); DxLib::SetDefaultFontState(font_name.c_str(), font_size, font_thick, -1, -1, font_edge); ki = DxLib::MakeKeyInput(max_length, true, false, false); DxLib::SetActiveKeyInput(ki); while (0 == ProcessMessage()) { if (DxLib::CheckKeyInput(ki)) break; DxLib::ClearDrawScreen(); // 確定文字列に対する処理 DxLib::GetKeyInputString(&confirmed_string[0], ki); cursor_confirmed.bytes = DxLib::GetKeyInputCursorPosition(ki); cursor_confirmed.pixels = MyDrawStringWidth(confirmed_string, cursor_confirmed.bytes); // 確定文字列の描画 MyDrawBox(Rect(p1 + Size(cursor_confirmed.pixels, 0), Size(2, font_size)), red, true); MyDrawString(p1, confirmed_string, white); // 未確定文字列(IME入力中の文字列) に対する処理 auto imipd = GetIMEInputData(); if (imipd) { std::vector<Clause> clauses; // 文節情報 int selected_clause; // 選択中の文節インデックス std::vector<Candidate> candidates; // 変換候補情報 int selected_candidate; // 選択中の変換候補インデックス static int prev_selected_clause; // 前フレームの選択文節インデックス static int prev_selected_candidate; // 前フレームの選択変換候補インデックス static float clause_phase = 0.f; // 文節のズレ static float candidate_phase = 0.f; // 変換候補のズレ unconfirmed_string = imipd->InputString; cursor_unconfirmed.bytes = imipd->CursorPosition; cursor_unconfirmed.pixels = MyDrawStringWidth(unconfirmed_string, cursor_unconfirmed.bytes); // 文節情報を構築 selected_clause = imipd->SelectClause; for (int i = 0; i < imipd->ClauseNum; ++i) { Position pos; Length len; std::string s; pos.bytes = imipd->ClauseData[i].Position; len.bytes = imipd->ClauseData[i].Length; s = unconfirmed_string.substr(pos.bytes, len.bytes); pos.pixels = MyDrawStringWidth(unconfirmed_string, pos.bytes); len.pixels = MyDrawStringWidth(s, (int)s.size()); clauses.emplace_back(s, pos, len); } // 変換候補情報を構築 selected_candidate = imipd->SelectCandidate; for (int i = 0; i < imipd->CandidateNum; ++i) { std::string s(imipd->CandidateList[i]); Length len; len.bytes = (int)s.size(); len.pixels = MyDrawStringWidth(s, (int)s.size()); candidates.emplace_back(s, len); } // ズレの表現 if (clause_phase < 0.f) { clause_phase += 0.1f; if (0.f <= clause_phase) clause_phase = 0.f; } if (0.f < clause_phase) { clause_phase -= 0.1f; if (clause_phase <= 0.f) clause_phase = 0.f; } if (prev_selected_clause < selected_clause) clause_phase = 1.f; if (selected_clause < prev_selected_clause) clause_phase = -1.f; if (candidate_phase < 0.f) { candidate_phase += 0.1f; if (0.f <= candidate_phase) candidate_phase = 0.f; } if (0.f < candidate_phase) { candidate_phase -= 0.1f; if (candidate_phase <= 0.f) candidate_phase = 0.f; } if (prev_selected_candidate < selected_candidate) candidate_phase = 1.f; if (selected_candidate < prev_selected_candidate) candidate_phase = -1.f; // 文節情報を描画 for (int i = 0; i < clauses.size(); ++i) { if (selected_clause < 0) break; VECTOR v = transducer(i - selected_clause, clause_phase); DxLib::SetDrawBlendMode(DX_BLENDMODE_ALPHA, (int)(255.f * v.z * v.z)); MyDrawStringEX(p2 + Point((int)v.x, (int)((1.f - v.z) * (float)font_size)), v.z, clauses[i].str.c_str(), white); } DxLib::SetDrawBlendMode(DX_BLENDMODE_NOBLEND, 255); if (0 <= selected_clause && selected_clause < clauses.size()) { Rect r(Point(clauses[selected_clause].position.pixels, 0), Size(clauses[selected_clause].length.pixels + 4, font_size)); MyDrawBox(r + p1 + Size(cursor_confirmed.pixels, 0), blue, true); } MyDrawString(p1 + Size(cursor_confirmed.pixels, 0), unconfirmed_string, white); // 変換候補情報を描画 if (selected_candidate < candidates.size()) { DxLib::SetDrawBlendMode(DX_BLENDMODE_ALPHA, std::abs(((frames << 2) & 255) - 128) + 128); Rect r(Point(), Size(candidates[selected_candidate].length.pixels, font_size)); MyDrawBox(r + p2, green, true); } for (int i = 0; i < candidates.size(); ++i) { if (abs(i - selected_candidate) > 8) continue; VECTOR v = transducer(i - selected_candidate, candidate_phase); DxLib::SetDrawBlendMode(DX_BLENDMODE_ALPHA, (int)(255.f * v.z * v.z)); MyDrawStringEX(p2 + Point((int)((1.f - v.z) * .5f * (float)candidates[i].length.pixels), (int)(v.x * 0.5f)), v.z, candidates[i].str.c_str(), white); } DxLib::SetDrawBlendMode(DX_BLENDMODE_NOBLEND, 255); prev_selected_clause = selected_clause; prev_selected_candidate = selected_candidate; ++frames; } DxLib::ScreenFlip(); } DxLib::DeleteKeyInput(ki); DxLib::DxLib_End(); return 0; }
メンテ
Re: KeyInputを使用したIME入力時の時の挙動 ( No.12 )
名前:naru 日時:2022/10/28 23:09

確定文字列中に環境依存文字が含まれるときのカーソルのずれに関しましては、 IME入力から戻ったときに、GetKeyInputStringで取得した文字列を そのままSetKeyInputStringに渡して上書きすることで改善されました。 失礼致しました。
メンテ
Re: KeyInputを使用したIME入力時の時の挙動 ( No.13 )
名前:管理人 日時:2022/10/30 23:32

> IME入力中の分節に関する動作は改善されましたが、問題の文字が含まれたまま確定した場合、 > 確定文字列中にその文字が含まれるものの、GetKeyInputStringでは除去されて返ってくる都合上、 > カーソルの位置に不整合が生じ、これを解決するためにはIME入力中に長さ0の文節の存在を監視し、 > 確定文字列をパーツに区切って描画する等しなければならないため、素直にUNICODEを使用するべき、という結論に至りました。 入力文字列を確定した後に shift-jis非対応の文字が消えても、IME入力決定後に shift-jis非対応の文字が消えても どちらでも変なので、KeyInputString 系を使う場合は UNICODE を使用するのが良いですね (^_^;
メンテ
Re: KeyInputを使用したIME入力時の時の挙動(解決) ( No.14 )
名前:naru 日時:2022/11/01 00:13

そうですね。。 文字コードと内部の処理について少し知識が深まりました。 ありがとうございました、また宜しくお願い致します。
メンテ

Page: 1 |

題名
名前
コメント
パスワード (記事メンテ時に使用)

   クッキー保存