How to send a message to a specific control on a TForm #105
You can send a message to any TControl descendant, whether it has a window handle or not, by using the Perform method.
Any control owned by a form can be found by searching through the form's Components property.
The following method can be added to a form (or frame) to let you send a message to a named control. It will return true if the control was found.
function TForm1.SendMessageToCtrl(const Name: string; const Msg: Cardinal; WParam, LParam: Integer): Boolean; var Idx: Integer; Ctrl: TControl; begin Result := False; // scan all components owned by the form for Idx := 0 to Pred(ComponentCount) do begin if Components[Idx] is TControl then begin // we have a TControl: check its name (case insensitive) Ctrl := Components[Idx] as TControl; if AnsiSameText(Ctrl.Name, Name) then begin // found it: send message and bail out Ctrl.Perform(Msg, WParam, LParam); Result := True; Exit; end; end; end; end;
Demo code
A ready made project containing this demo code is available. View the project.
To see SendMessageToCtrl in action start a new Delphi VCL application then:
- Add a few components to the form, making sure you include at least one of each of a TCheckBox, TLabel, TEdit and TButton. Keep the default names.
- Create an OnClick event handler for Button1.
-
Name the form "Form1", save the form unit as
Unit1.pas
and code the unit as follows:
unit Unit1; interface uses SysUtils, Forms, StdCtrls, Controls, Classes, Messages, Windows; type TForm1 = class(TForm) Label1: TLabel; Edit1: TEdit; Button1: TButton; CheckBox1: TCheckBox; procedure Button1Click(Sender: TObject); private function SendMessageToCtrl(const Name: string; const Msg: Cardinal; WParam, LParam: Integer): Boolean; end; var Form1: TForm1; implementation {$R *.dfm} function TForm1.SendMessageToCtrl(const Name: string; const Msg: Cardinal; WParam, LParam: Integer): Boolean; var Idx: Integer; Ctrl: TControl; begin Result := False; // scan all components owned by the form for Idx := 0 to Pred(ComponentCount) do begin if Components[Idx] is TControl then begin // we have a TControl: check its name (case insensitive) Ctrl := Components[Idx] as TControl; if AnsiSameText(Ctrl.Name, Name) then begin // found it: send message and bail out Ctrl.Perform(Msg, WParam, LParam); Result := True; Exit; end; end; end; end; procedure TForm1.Button1Click(Sender: TObject); const AText: PChar = 'I got a message'; begin // send a click to the checkbox: this will check it SendMessageToCtrl('CheckBox1', WM_LBUTTONDOWN, MK_LBUTTON, 0); SendMessageToCtrl('CheckBox1', WM_LBUTTONUP, MK_LBUTTON, 0); // set the text of the label SendMessageToCtrl('Label1', WM_SETTEXT, 0, Integer(AText)); SendMessageToCtrl('Label1', CM_TEXTCHANGED, 0, 0); // set the text of the edit control SendMessageToCtrl('Edit1', WM_SETTEXT, 0, Integer(AText)); end; end.
When you click Button1 you will see the text of the label named "Label1" and the edit control named "Edit1" change. The checkbox named "CheckBox1" will become checked. The comments in TForm1.Button1Click explain what's happening.
Author: | Peter Johnson |
---|---|
Added: | 2009/09/14 |
Last updated: | 2010/03/16 |