InplaceEditorで日本語を入力する時に今文字の変換中かどうかを知りたいのですが
下記の様なソースでやりますと ImeWindowProc_1 はスタックオーバーフローになってしまいます。
スタックオーバーフローにならないようにしたいのですが良い方法が思いつきません。
InplaceEditor を SGrid1GetEditText の外に出すことなども考えましたが無理のようで
何かいい方法がありましたらご教授お願いいたします。
(因みに環境は Windows8.1+Delphi6です)
type
TForm1 = class(TForm)
〜略〜
StringGrid1: TStringGrid;
〜略〜
private
{ Private 宣言 }
ImeConvStat:boolean;
ImeWndMethod_1:TWndMethod;
procedure ImeWindowProc_1(var Msg:TMessage);
public
{ Public 宣言 }
end;
〜略〜
//-----------------------------------------
// IME日本語変換状態取得 / TInplaceEdit用
procedure TForm1.ImeWindowProc_1(var Msg: TMessage);
begin
case Msg.Msg of
WM_IME_ENDCOMPOSITION:begin
ImeConvStat := False; // 変換終了
end;
WM_IME_COMPOSITION:begin
ImeConvStat := True; // 変換中
end;
end;
ImeWndMethod_1(Msg);
end;
//-----------------------------------------
// セル編集
procedure TForm1.SGrid1GetEditText(Sender: TObject; ACol,
ARow: Integer; var Value: String);
var
InpEdit:TInplaceEdit;
begin
InpEdit := TMyGrid(StringGrid1).InplaceEditor;
if (InpEdit <> nil) then begin
ImeWndMethod_1 := InpEdit.WindowProc;
InpEdit.WindowProc := ImeWindowProc_1;
end;
end;
現状だと、OnGetEditTextが発生するたびにそのイベントハンドラ全体が実行されます。
すると、2回目に問題が発生します。
1回目: Self.ImeWndMethod_1 ← InpEdit.WindowProc // これは意図どおり
2回目: Self.ImeWndMethod_1 ← TForm1.ImeWindowProc_1 // これはマズイ
この結果、TForm1.ImeWindowProc_1 の最後、
ImeWndMethod_1(Msg);
で無限に自分自身を呼び出してしまいます。
なので、何らかの方法でサブクラス化を1回限りにする必要があります。
以下はその一例です。
private
FCapturedEdit: TInplaceEdit; // 追加
type
TMyGrid = class(TStringGrid);
procedure TForm1.StringGrid1GetEditText(Sender: TObject; ACol,
ARow: Integer; var Value: String);
var
InpEdit: TInplaceEdit;
begin
InpEdit:=TMyGrid(StringGrid1).InplaceEditor;
if (InpEdit<>FCapturedEdit) and (Assigned(InpEdit)) then begin
Self.ImeWndMethod_1:=InpEdit.WindowProc;
InpEdit.WindowProc:=Self.ImeWindowProc_1;
FCapturedEdit:=InpEdit;
end;
end;
Harry さん、早速のご回答ありがとうございます。
早速試してみたのですが
スタックオーバーフローは無くなりましたが
StringGridでセルをクリックして触ろうとしますと
あちこちセルは触れるのですが固まったような感じで編集モードになりません。
(キーでもマウスダブルクリックでも編集できません、何かおかしな動きです)
そしてプログラムを終了するときに
「ウィンドウハンドルが無効です。」
と言うメッセージでシステムエラーが起きます。
せっかく良い方法を教えて頂いたと思ってたのですが
確認しましても確かに一回だけしか処理されてないのに
その後の動きがおかしいです。
うーん、どこかに何か配慮の足らない点があるのかもしれません。
まずは試しとしてアプリケーションを新規作成し、フォームにStringGridだけ置いて
やってみてください。
それで大丈夫なら、次は徐々に要素を追加していく作業を行います。
問題点はその過程で明らかになると思います。
Harry さん、ご連絡ありがとうございます。
すみません..私のやり方の問題でした。
そこでご指摘の通り新規にフォームを作りStringGridを貼ってやってみました。
結果、何の問題も無く動きました。
因みにこの状態で if (InpEdit<>FCapturedEdit) 〜 then begin / end; の部分をコメントにしますと
前と同じようにスタックオーバーフローになります。
これから実際のソースと比べながらどこが問題を起こしているのか調べてみます。
ありがとうございました、助かりました。
前進できたようで何よりです。
もうすでにやってるとは思いますが、今度は逆に現在のコードからこのサブクラス化の部分
全体を取り除く(たぶんイベントを外すだけでいいと思いますが)とどうなるか、ですね。
それで問題が発生しないなら、何かとバッティングしてるということかも。
その「何か」は mook さんの仕込んだ特別なコードか、あるいは変哲のない普通のコードの
中に相性が悪いものがあるのかもしれません。
ツイート | ![]() |