Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

ProcessMessages to specific thread

Status
Not open for further replies.

rcloutie

Programmer
May 26, 2005
164
CA
Hi all,

Using D2007 under XPSP3.

Is there a way to execute a kind of ProcessMessages method to a specific thread?

Here is my problem:
1. From a main form, I post a message to display the status of a record.
2. Before the message to be intercepted, the main form loads another form (which has parent a groupbox located on the main, so let's call it "child form" while is it not since it is SDI app).
3. From the child form, I initialize the display of a stringgrid (that is, setup columns title and width)
4. Before to display data, I post another message from the child form to fill the stringgrid (since the sql query might be slow and I do not want the display to flicker)
5. From that point, I would like the first message (main form) to be processes and after that, process the second message (child form), but cannot figure it out...

In other words, the main form (main thread) brings back control only after ALL messages has been intercepted in the child form (child thread).

How to call something like MainForm.ProcessMessages (because Application.ProcessMessages stays within child form only)?

Thanks for help,

Rej Cloutier
 
Okay, so I should ask what it is exactly you are looking to do. You want to process things on two forms at once? In other words, be doing things on both the main form and child form of the app at the same time?

Measurement is not management.
 
Put a TApplicationEvents on your main form to trap all your messages. Process your messages in the OnMessage event.
How to handle it is best described in a demo:
First the form:
Code:
object Form4: TForm4
  Left = 525
  Top = 269
  Width = 557
  Height = 327
  Caption = 'Form4'
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'MS Sans Serif'
  Font.Style = []
  OldCreateOrder = False
  PixelsPerInch = 96
  TextHeight = 13
  object Button1: TButton
    Left = 112
    Top = 208
    Width = 129
    Height = 25
    Caption = 'Send 1st message'
    TabOrder = 0
    OnClick = Button1Click
  end
  object Button2: TButton
    Left = 264
    Top = 208
    Width = 129
    Height = 25
    Caption = 'Send 2nd message'
    TabOrder = 1
    OnClick = Button2Click
  end
  object Memo1: TMemo
    Left = 40
    Top = 24
    Width = 449
    Height = 153
    Lines.Strings = (
      'Memo1')
    TabOrder = 2
  end
  object Button3: TButton
    Left = 216
    Top = 256
    Width = 75
    Height = 25
    Caption = 'Clear wait'
    TabOrder = 3
    OnClick = Button3Click
  end
  object ApplicationEvents1: TApplicationEvents
    OnMessage = ApplicationEvents1Message
    Left = 48
    Top = 200
  end
end
And the demo code:
Code:
unit Unit13;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, AppEvnts, StdCtrls;

type
  TForm4 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Memo1: TMemo;
    ApplicationEvents1: TApplicationEvents;
    Button3: TButton;
    procedure ApplicationEvents1Message(var Msg: tagMSG;
      var Handled: Boolean);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
  private
    { Private declarations }
    WaitForFinish: boolean;
    Procedure Process1;
    Procedure Process2;
  public
    { Public declarations }
  end;

var
  Form4: TForm4;

implementation

{$R *.dfm}

procedure TForm4.Process1;
begin
  Memo1.Lines.Add('Waiting for Process 2 to finish');
  repeat
    Application.ProcessMessages
  until not WaitForFinish;
  Memo1.Lines.Add('Process 1 complete.');
end;

procedure TForm4.Process2;
begin
  Memo1.Lines.Add('Process 2 complete.');
end;

procedure TForm4.ApplicationEvents1Message(var Msg: tagMSG; var Handled: Boolean);
var
  MyMsg: integer;
begin
  MyMsg:= Msg.Message;
  case MyMsg of
    wm_user + 127:
      begin
        Memo1.Lines.Add('Message 1 recieved');
        WaitForFinish:= true;
        Process1;
      end;
    wm_user + 128:
      begin
        Memo1.Lines.Add('Message 2 recieved');
        Process2;
      end;
  end; //case
end;

procedure TForm4.Button1Click(Sender: TObject);
begin
  PostMessage(Application.Handle, wm_user + 127, 0, 0);
end;

procedure TForm4.Button2Click(Sender: TObject);
begin
  PostMessage(Application.Handle, wm_user + 128, 0, 0);
end;

procedure TForm4.Button3Click(Sender: TObject);
begin
  WaitForFinish:= false;
end;

end.
Hit the buttons in sequence (1,2,3) and watch the memo...

HTH

Roo
Delphi Rules!
 
Hi Glen, Thanks for reply.

The work of the main form is to display general status of a record (something like a msgbox 'Sorry Mr.Pink, the file you are accessing is read-only: currently in the office of Mr.Blue').

But I want the setup of the child form to be ok (that is, all controls displayed without flickering and only data is missing).

After the dialog about main status, then and only then I want to search for data to be displayed...

 
Rej - Have you looked at my solution?

Roo
Delphi Rules!
 
BTW - You can stop the flicker effect by calling 'Table.DisableControls' before iterating through the records. It should be placed before a try/finally block and call 'Table.EnableControls' between finally/end;

Note: Calls to DisableControls can be nested. Only when all calls to DisableControls is matched to a corresponding call to EnableControls does the dataset update data controls and detail datasets.

Roo
Delphi Rules!
 
Hi Roo, Thanks for help.

Actually, I'm posting to main form using PostMessage(frmMain.Handle, WM_MYSTATUS) and to child form using PostMessage(gridChild.Handle, WM_MYDATA). Each unit are independant: messages are sent to the handle of form/control and intercepted in each context.

According to your answer, I need to post messages to Application.Handle (instead of form/control handle) in both cases. So, from within the child form, I need to PostMessage(Application.Handle, WM_MYDATA) and from within the main form, intercept WM_MYDATA and return it back to the child form.

Am I right?
 
I'm not sure... Question: Are you using TApplicationEvents to trap the messages?
Where is WM_MYSTATUS and WM_MYDATA defined?
I'm only familiar with user-defined messages - hence the WM_User + 127;

Or have you defined it something like this:
Code:
//The following code handles a custom message that the application sends to itself when a file is ready for reading.

const
 WM_FILEREADY = WM_USER + 2000;
procedure TForm1.FormCreate(Sender: TObject);
begin
  Application.OnMessage := AppMessage;
end;

procedure TForm1.AppMessage(var Msg: TMsg; var Handled: Boolean);
begin
  if Msg.message = WM_FILEREADY then begin
    Memo1.Lines.LoadFromFile(StrPas(PChar(Msg.lParam)));
    Handled := True;
  end;
  { for all other messages, Handled remains False }
  { so that other message handlers can respond }
end;

I've always used WM_USER + 127 and above because I remember reading once that Delphi uses some user defined values internally , not to exceed WM_USER + 126. I'm not sure that's still valid but it still works for me. Whether you send them to Application.Handle or "form/control handle" I don't think really matters provided that the receiver (event) processes them correctly. It's always been my personal preference to keep them centrally located for simplicity and consistency.

What I was trying to demonstrate was a way to delay the processing of the 1st message until completion of the 2nd message, as I understood your request. Hopefully you ran it to see how it works. Where you put it is up to you.

I hope it helped rather than add to your confusion. I'm better at making things work than explaining how. :p


Roo
Delphi Rules!
 
Yes I'm defining constants in each forms (within the interface section). In this case, I'm using messages instead of timers, for display matters.

In fact, the main form can contains 7 other child forms. Each of them are independant and the main form is there only to display header's record and to navigate through "tabs" (child forms are loaded dynamically and individually, so, if no request, no time spent on it.

I will check it out and post my decision as soon as it will be done. Thanks again Roo.

Rej Cloutier
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top