Welcome

首页 / 软件开发 / Delphi / Delphi中SendMessage使用技巧

Delphi中SendMessage使用技巧2010-11-23梁云Windows系统是由消息机制驱动的,每个线程如果建立了一个窗口,则由系统 分配一个消息队列用于窗口消息的处理。另外,消息也可以不经过消息队列而利 用SendMessage函数直接发送给窗口,窗口过程将处理这个消息,但只有当消息 被处理之后,SendMessage才能返回到调用程序。下面结合两个Delphi程序,讨 论如何利用SendMessage向控件发送消息和控件对这种消息的响应。

用SendMessage向控件发送消息

在编程中,有时需要控件以特殊的风格显示,而这种要求又无法通过设置控 件属性实现。例如,读取客户列表并显示在下拉框供用户选择,如果下拉框宽度 太窄,则不能全部显示;如果将宽度定得太宽,界面又有不紧凑之感。因此希望 能在运行期动态地确定下拉框显示区域的宽度,这种要求如果不用SendMessage 函数就很难实现。

解决办法是,在读时计算字符串的显示宽度,用显示宽度的最大值确 定下拉框显示区域的宽度。再用SendMessage函数向下拉框发送 CB_SETDROPPEDWIDTH消息和宽度值,下拉框根据消息中传来的信息,就可以进行 正确显示。

部分源程序代码如下:

i:=0; //计数
MaxWidth:=0;
Query1.SQL.Clear;
Query1.SQL.Add(‘select Company from Customer’);
Query1.Open;
//读客户列表到下拉框
while not Query1.Eof do begin
ComboBox1.Items.add(Query1.FieldByName
(‘Company’).AsString);
Width:=ComboBox1.Font.Size * Length
(ComboBox1.Items[i]);
if Width>MaxWidth then
MaxWidth:=Width; //找出最大值
Query1.Next;
i:=i+1;
end;
Query1.Close;
ComboBox1.Text:=ComboBox1.Items[0];
//发送消息以确定显示区域的宽度
SendMessage(ComboBox1.Handle,
CB_SETDROPPEDWIDTH,MaxWidth,0);

利用SendMessage函数还可以实现一些有趣的效果,例如在按钮的Click事件 中加入如下语句:

SendMessage(Button.Handle,BM_SETSTYLE,

BS_RADIOBUTTON,1);

运行后点击按钮,就可以把按钮变成一个收音机按钮。

控件接收SendMessage消息

上面讨论了用SendMessage向控件发送消息的过程。但凡事有利就有弊,用 SendMessage发送的消息在处理上存在着一定困难。因为该消息不经过消息队列 ,所以无法用OnMessage方式来指定对消息的响应,甚至用HookMainWindow也不 行,因为消息直接发送到控件,绕过了主窗体。要对这种类型的消息作出响应, 需要重载控件的WndProc方法。

例如,对于一个列表框,滚动条的滚动消息就是用SendMessage方式发送的, 因此该消息不在TlistBox的事件列表中。下面是处理控件响应该滚动消息的具体 步骤。

1.首先从TlistBox继承一个TmyListBox类,并重载WndProc方法。在程序中加 入下列定义:

type
TMyListBox=class(TListBox)
private
procedure WndProc(var Msg: TMessage);
override;
//重载WndProc,处理发送到控件的消息
public
end;

其中WndProc方法指定控件对消息的响应,输入参数是TMessage类型,该数据 类型是一个记录,包含了消息代码和消息的参数,消息参数可以用Longint或 Word方式获得。