Delphi中SendMessage使用技巧

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方式获得。

时间: 2024-12-01 21:26:04

Delphi中SendMessage使用技巧的相关文章

在Delphi中的Access技巧集

1.DELPHI中操作ACCESS数据库(建立.mdb文件,压缩数据库) 以下代码在WIN2K,D6,MDAC2.6下测试通过, 编译好的程序在WIN98第二版无ACCESS环境下运行成功. //在之前uses ComObj,ActiveX //声明连接字符串 Const SConnectionString = 'Provider=Microsoft.Jet.OLEDB.4.0;Data Source=%s;' +'Jet OLEDB:Database Password=%s;'; //====

Delphi中对象解除技巧

在Delphi程序设计中,我们需要通过解除建立的所有对象来避免内存泄漏.但是,如果你在程序中不谨慎小心的话,很容易多次解除同一个对象,这将会引起很严重的错误,造成应用程序崩溃,甚至是死机. 请看下面的程序: procedure TForm1.Button1Click(Sender:TObject); var Button2,Button3:TButton; begin Button2:=TButton.Create(self); Button3:=TButton.Create(Button2);

Delphi中的线程类 - TThread详解<转>

Delphi中有一个线程类TThread是用来实现多线程编程的,这个绝大多数Delphi书藉都有说到,但基本上都是对TThread类的几个成员作一简单介绍,再说明一下Execute的实现和Synchronize的用法就完了.然而这并不是多线程编程的全部,我写此文的目的在于对此作一个补充.线程本质上是进程中一段并发运行的代码.一个进程至少有一个线程,即所谓的主线程.同时还可以有多个子线程.当一个进程中用到超过一个线程时,就是所谓的"多线程".那么这个所谓的"一段代码"

Delphi中取得系统支持的颜色数的方法

在自己的软件中经常需要得知运行本软件的系统支持的颜色数.例如有的软件在16Bits的颜色数的计算机上开发而成,程序的颜色调试得非常漂亮,但是到了一台只支持16色的计算机上,程序变得非常难看.这就需要得到系统的颜色数. Delphi中如何取得系统的颜色数呢?下面的程序就解决这个问题. function GetSysColorNum:Integer; Var ScreenDc:HDC; NumBitsPixel:Integer; begin Result:=0; ScreenDc:=GetDC(0)

Delphi中TApplication类的用法

在Delphi中TApplication是一个有着十分重要作用的类.TApplication类是用于描述Delphi编制的应用程序的一个类.通过对这个类的灵活应用可以编制许多有特点的程序.. 1) 检测当前Windows程序是否被激活: TApplication类有一个属性--Active,这个属性就可以描述当前运行的程序是否被激活,成为Windows的焦点.检 测的代码如下: If Application.Active=False then ShowMessage('当前窗口没有被激活');

Delphi中利用钩子实现QQ聊天窗口的修改

有人曾为公司不让用QQ.MSN等聊天工具而烦恼吗?看了下面的小程序你就会打消这种看法了. 当初公司做校园一卡通的项目时,里面的机房客户端需要用到系统的低级键盘钩子WH_KEYBOARD_LL,这也是我第一次接触到Windows中的Hook,因为WH_KEYBOARD_LL和其他钩子不一样,在Delphi的Windows帮助以及windows.pas文件中都没有定义,但microsoft的msdn中确有WH_KEYBOARD_LL的介绍,所以一路解决后就对Windows的系统钩子产生了兴趣.之后相

Delphi中如何取得系统支持的颜色数

在自己的软件中经常需要得知运行本软件的系统支持的颜色数.例如有的软件在16Bits的颜色数的计算机上开发而成,程序的颜色调试得非常漂亮,但是到了一台只支持16色的计算机上,程序变得非常难看.这就需要得到系统的颜色数. Delphi中如何取得系统的颜色数呢?下面的程序就解决这个问题. function GetSysColorNum:Integer; Var ScreenDc:HDC; NumBitsPixel:Integer; begin Result:=0; ScreenDc:=GetDC(0)

Delphi中的消息处理

1.windows的消息驱动体系 在windows系统中,消息传递是实现对乡间通信和控制的主要手段.可以额系统都以消息驱动的方式工作.系统中发生的用户输入操作.显示信息的改变.系统环境参数变化等所有时间都以系统定义消息的形式出现在相关的应用程序和窗口.所以程序设计的主要任务就是为这些消息的处理设计代码. 在应用程序中,发送者可以通过发送消息要求接收者完成相应的处理.当程序运行时,windows系统为每个应用程序实例建立一个消息队列,一次保存发送给该程序实例的消息,在应用程序的主控部分,需要设置一

初探Delphi中的插件编程

前言 我写Delphi程序是从MIS系统入门的,开始尝试子系统划分的时候采用的是MDI窗体的结构.随着系统功能的扩充,不断有新的子系统加入系统中,单个工程会变得非常大,每次做一点修改都要重新编译,单个工程的形式也不利于团队协作.为了提高工作效率,我希望利用DLL动态链接库的形式实现插件结构的编程. 插件结构的编程需要一个插件容器来控制各DLL的运行情况,将划分好的每个子系统安排到一个DLL库文件中.对每个DLL程序需要为容器预留接口函数,一般接口函数包括:启动调用DLL库的函数.关闭DLL库的函