AR也未处理,则 DefWndProc会再次发送WM_CHAR。
所以,我判断之所以会造成乱码,很有可能是OCX在非模态状态下,即接受了WM_CHAR又接收了WM_IME_CHAR消息,造成最后的wParam是三个字节的内容,造成最后的输出是三个字节的乱码内容。
经过实验,捕捉输入控件的WM_IME_CHAR事件,并将WM_IME_CHAR作为WM_CHAR事件转发出去,就可以解决这个
问题了!处理代码如下:
case Message.Msg of
WM_IME_CHAR:
begin
KeyMsg:=TWMKey(Message);
SendMessage(Edit1.handle, WM_CHAR, KeyMsg.CharCode, 0);
end;
以上实验是针对普通的Tform中的Tedit控件进行的实验,但我要解决的问题是在通用对话框中对WM_IME_CHAR消息的处理。
在通用查找对话框中的Edit输入控件根本不是标准TWinControl控件,不能像Delphi中标准控件那样直接挂接WndProc过程,所以必须通过遍历通用对话框中的输入控件,然后再挂接消息处理过程;
1、 2、 3、 首先遍历通用对话框中的控件,判断控件的ClassName,这里ClassName通过Spy++工具可以查看的到;
找到CalssName = ‘Edit’的控件,将其消息处理转到自定义的消息处理过程中;
捕捉WM_IME_CHAR消息,并作为WM_CHAR进行转发,并忽略掉默认的WM_IME_CHAR处理。
代码如下:
//遍历通用对话框中的控件,并判断ClassName
function EnumChildWndProc(AhWnd: LongInt; AlParam: lParam)
: Boolean; stdcall;
var
WndClassName: array [0 .. 254] of Char;
WndCaption: array [0 .. 254] of Char;
className, Caption: string;
begin
GetClassName(AhWnd, WndClassName, 254);
GetWindowText(AhWnd, WndCaption, 254);
className := string(WndClassName);
Caption := string(WndCaption);
if className ='Edit' then
begin
SetProp(AhWnd, GWL_WNDPROC));
//挂接到FindReplaceWndProc消息处理过程
end;
Result := True;
end;
//FindReplaceWndProc中对WM_IME_CHAR的处理
WM_IME_CHAR:
begin
SendMessage(Wnd, WM_CHAR, WParam, 0);
Result:=-1;
MakeIntAtom(WndProcPtrAtom), GetWindowLong(AhWnd,
Exit;
end;
三、总结
在Delphi实际开发中,有些在独立EXE
程序中可以正常的处理,而在ActiveX控件中则会出现一些莫名其妙的问题,究其原因都是因为在OCX控件中消息处理机制在和独立EXE程序中差异造成的,通过以上问题的解决为今后对错误的处理和判断都有很好的借鉴意义。