• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1344
  • Last Modified:

How do I PostMessage (PostThreadMessage?!?) from a worker thread to a TComponent descendent?

Hi!  I want to create a custom component (derived from TComponent) that spawns a worker thread which uses PostMessage or PostThreadMessage to asynchronously report progress in a non-blocking manner back to the custom component.  I can't use synchronization as I need the worker thread to run at speed.

I've read through dozens of "answers" on the subject on this board but all of the answers are incomplete or fragmentary.  I'd appreciate a COMPLETE source-code example since there's obviously something subtle I'm missing.  Thanks....
0
lsberman
Asked:
lsberman
1 Solution
 
BlackTigerXCommented:
do you have some code and are getting stuck somewhere?

you will get better responses if you ask specific questions on something that you don't know how to implement or is not working as you would expect, rather than asking for someone to create the whole thing for you

if you have some code post it here and we can go from there...
0
 
Wim ten BrinkCommented:
Are you sending the messages to the application handle, the form handle or have you written your own, personal message handler?

Advise... Create a small application that does something similar to what you want to do: a separate thread sending messages to some component. If you don't get it to work, post the code here... The code below is tested on my system and works just fine. (But it could be that your component isn't receiving any messages!)

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;

const
  WM_ThreadMessage = WM_USER + 100;

type
  TCustomComponent = class( TWinControl )
  private
    FCount: Integer;
  protected
    procedure WMThreadMessage( var Message: TMessage ); message WM_ThreadMessage;
  public
    constructor Create( AOwner: TComponent ); override;
  end;
  TForm1 = class( TForm )
    procedure FormCreate( Sender: TObject );
  private
    CustomComponent: TCustomComponent;
  public
  end;
  TMessageThread = class( TThread )
  private
    FFormHandle: THandle;
  protected
    procedure Execute; override;
  public
    constructor Create( Handle: THandle );
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

constructor TCustomComponent.Create( AOwner: TComponent );
begin
  inherited;
  if ( AOwner is TWinControl ) then Parent := ( AOwner as TWinControl );
  TMessageThread.Create( Handle );
end;

procedure TCustomComponent.WMThreadMessage( var Message: TMessage );
begin
  Inc( FCount );
  Form1.Caption := Format( 'Time: %s, Count: %d.', [ FormatDateTime( 'HH:NN:SS.ZZZ', Now ), FCount ] );
end;

procedure TForm1.FormCreate( Sender: TObject );
begin
  CustomComponent := TCustomComponent.Create( Self );
  CustomComponent.FCount := 0;
end;

constructor TMessageThread.Create( Handle: THandle );
begin
  inherited Create( True );
  FFormHandle := Handle;
  FreeOnTerminate := True;
  Resume;
end;

procedure TMessageThread.Execute;
var
  I: Integer;
begin
  for I := 1 to 20 do begin
    Sleep( 1000 );
    PostMessage( FFormHandle, WM_ThreadMessage, 0, 0 );
  end;
end;

end.

Oh, you will need an empty new form for this... :-)
The problem you're having is that your component doesn't have any handle for it to receive messages from the system. Thus, TComponent isn't even able to handle incoming messages. To add support for messages you will have to add some message window to your component so it will receive messages.
0

Featured Post

VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now