消息,直接挂接事件,对属性进行赋值就可以;其中最大的问题是对应的位置要比较固定,但是这些对话框基本上都是Fix固定大小的窗体,对应的位置并不需要过多的考虑。
二、通用对话框的消息处理
通用对话框的基类TcommonDialog的基类是Tcomponent,但是它并不能按照普通的TWinControl那样进行控件操作和事件的处理,查看Tdialog单元
源代码,会发现每个通用对话框,会创建一个TredirectorWindow类,代码如下:
FRedirector := TRedirectorWindow.Create(nil);
with TRedirectorWindow(FRedirector) do
begin
FFindReplaceDialog := Self;
end;
TRedirectorWindow(FRedirector).FFormHandle := GetActiveWindow;
FFindReplace.hWndOwner := FRedirector.Handle;
从以下代码可以看到FfindReplace.hWndOwner,即FfindReplace的宿主是Fredirector,再来看TredirectorWindow的定义,TRedirectorWindow = class(TWinControl),其中注释描述如下:
{ TRedirectorWindow }
{ A redirector window is used to put the find/replace dialog into the
ownership chain of a form, but intercept messages that CommDlg.dll sends
exclusively to the find/replace dialog's owner. TRedirectorWindow
creates its hidden window handle as owned by the target form, and the
find/replace dialog handle is created as owned by the redirector. The
redirector wndproc forwards all messages to the find/replace component.
}
重定向window是用来创建一个隐藏的窗口句柄,redirector的处理的Wndproc消息都被重定向到通用对话框组件上。
所以,通用对话框的处理都来自于windows系统的CommDlg.dll,TredirectorWindow用来转发
Delphi程序中的消息给通用对话框,这里也可以看出Delphi中的通用对话框是对windows标准对话框进行封装后的结果,windows标准对话框中的控件并不能当做delphi中的控件进行直接访问。
在开发电子病历编辑器控件的过程中,出现一个问题,对于Delphi的ActiveX控件在非模态窗体状态,接受输入法输入时,输入内容呈现的是乱码,如果是英文和数字输入则没有问题,而且模态窗体状态没有这种情况,在独立EXE程序中也没有。
通过跟踪对话框消息,发现在非模态窗体状态,接受的windows的WM_CHAR消息,接收到的Wparam参数内容和正常的情况不一样,在模态状态下,接受的Wparam是4位长度,而在非模态状态下的Wparam是6位长度,并且与正常情况下的内容没有规律可循,经过分析对比发现,模态和非模态对话框在DELPHI中的处理的不同在于:
? ? 非模态对话框
响应一个消息,系统处理一个消息,处理完毕后返回控制权给Windows;
模态对话框
在对话框创建后,挂起外部的消息,只是响应对话框内部的消息,而外部消息则全部"过滤"掉了,直到系统接收到WM_DESTROY或WM_CLOSE后,系统返回控制权给模态对话框创建前的线程,继续模态对话框创建前的线程将执行的代码;
在Windows中有两个接受字符的消息,WM_CHAR和WM_IME_CHAR;
1、 WM_CHAR
如果窗口是unicode(IsWindowUnicode),WM_CHAR的wParam就是unicode字符。如果窗口式ANSI,WM_CHAR的wParam是一个单字节的值。如果输入中文,则会得到2个WM_CHAR,把这两个单字节值合到一起就是输入的中文;
2、 WM_IME_CHAR
如果是unicode window,则wParam就是unicode字符,此时和WM_CHAR没有任何区别。
如果是ansi window,则wParam是双字节的mbc编码。
其中IME(Input Method Editor)的消息处理流程:
当用输入法输入时,首先发送WM_IME_COMPOSITION消息,在这个消息处理中,可以用ImmGetCompsitionString得到输入的字符串。如果不处理,则DefWndProc会针对每个字符串重新发送WM_IME_CHAR,如果WM_IME_CH