掲示板システム
ホーム
アクセス解析
カテゴリ
ログアウト
Window10でTEditorコンポーネントのキャレットが消える問題への対応 (ID:149672)
名前
ホームページ(ブログ、Twitterなど)のURL (省略可)
本文
いろいろ考え、処理を見直しました。 IME関連のメッセージは、以下のような順番でやってきます。(一部省略) 1. WM_IME_NOTIFY ( IMN_OPENCANDIDATE ) 2. WM_IME_COMPOSITION ( GCS_RESULTSTR ) 3. WM_IME_NOTIFY ( IMN_CLOSECANDIDATE ) 古いIMEでは、変換開始時に1でCaretBeginUpdate(HideCaret)が1回実行され、 変換終了後に3でCaretEndUpdate(ShowCaret)が1回実行され、キャレットが 問題なく再表示されるという流れになっているようですが、新しいIMEでは1の メッセージが文字ごと(例えば「あ」を3文字打てば3回)きて、3のメッセージ が来ないためにキャレットが隠されてしまう様子でした。 そのため、2のメッセージを処理した後、ここの処理の最後にCaretEndUpdateを 処理してやれば、Caretが再表示されることになります。 (この段階でCaretEndUpdateを処理してしまった場合で、もし3のメッセージが 飛んできても、そこで実行されるCaretEndUpdateは、「FCaretUpdateCountが 0なので処理しません」ということで無視され、実害はありません。新旧IME どちらにも対応できるということになります。) 上記では、割と簡単に解決しようとしていましたが、今回は、「Windows10 の一時的な不具合を最小限度の回避策で対策する」という観点から、コードを 以下のように見直しました。(変換を確定して文字列が入力されるタイミングと、 IMEの変換がキャンセルされたタイミングの2つのタイミングでだけ、 CaretEndUpdateを呼ぶ仕様としました。) 今のところはこれでも違和感ある処理にはなっていませんので、自分では今後、 この処理で進めてみようと思います。au様、あなたのご助言で具体的なコードまで 考えることができました。改めて深く御礼申し上げます。このコードをしばらく 使ってみて、最終的にまた結果をご報告いたします。 procedure TEditor.WMImeComposition(var Msg: TMessage); var Imc: HIMC; L: Integer; S: String; begin inherited; if (Msg.LParam and GCS_RESULTSTR <> 0) then begin if not FReadOnly then begin // ここの条件文を分けた Imc := ImmGetContext(Handle); L := ImmGetCompositionString(Imc, GCS_RESULTSTR, nil, 0); SetLength(S, L + 1); ImmGetCompositionString(Imc, GCS_RESULTSTR, PChar(S), L + 1); ImmReleaseContext(Handle, Imc); SetLength(S, L); FImeCount := L; PutStringToLine(S); end; while FCaretUpdateCount > 0 do CaretEndUpdate; // 文字列が確定(挿入)されたタイミングでCaretを再表示(ここだけはReadOnlyか否かを問わず処理) end else if Msg.LParam = 0 then begin while FCaretUpdateCount > 0 do CaretEndUpdate; // 変換がキャンセルされたタイミングでCaretを再表示 (EscやBkspなどで) end; end;
←解決時は質問者本人がここをチェックしてください。
戻る
掲示板システム
Copyright 2021 Takeshi Okamoto All Rights Reserved.