Solved

broadcast messages to all open forms/controls?

Posted on 1998-10-17
17
1,084 Views
Last Modified: 2010-04-06
I need to notify all my open windows of changes in some global settings.
How do I do that? My program does not store references to all of them...
The Delphi documentation is pretty useless :-(
They tell me how to define and handle custom messages (which I knew), but not how to create and send them!!

What I have is this:
CONST WM_ViewChange=WM_APP+501;
TYPE  TWMViewChange = record
        Msg : Cardinal;
        lParam:word;
        wParam:Longint;
        Result:Longint;
    END;

TMyForm = class(TForm)
.....

  protected
    procedure WMViewChange(VAR Msg: TWMViewChange); message WM_ViewChange;
END;

I tried  PostMessage(Application.Handle, WM_VIEWCHANGE, 0,0); but it didn't work (message didn't "arrive" in my second form (modal))

Again: This message should be sent to all open windows because they might have to adjust their layout...

I hope this will be easy for most "experts" :-)))

Thanks for your help!
0
Comment
Question by:Ronald112197
  • 7
  • 5
  • 4
  • +1
17 Comments
 
LVL 5

Expert Comment

by:inter
Comment Utility
Try declaring your message with

  WM_USER+501

regards, igor
0
 
LVL 2

Author Comment

by:Ronald112197
Comment Utility
Nope, that's not the problem... I used WM_APP because the Delphi documentation told me to! (that might have been for component writers, but so what - I use it for a derived class).

I tried changing it to WM_USER+501, but that didn't help. Must be something with the dispatch mechanism --- if I post the message to one specific component, it works ok, but I need to post it to ALL components...

Any other ideas? (sorry, but I have to reopen the question, because most people don't look at the locked questions and if I wait for two days, it'll be way down the list...- also, I urgently need that answer :-( )
0
 
LVL 10

Expert Comment

by:viktornet
Comment Utility
How about using SendMessage() instead of PostMessage() or doing this....
var
  Forms : Integer;
begin
  for Forms := 0 to Application.ComponentCount - 1 do
    if Application.Components[i] is TForm then
      SendMessage(TForm(Application.Components[i]).Handle, WM_VIEWCHANGE, 0, 0);
end;

I hope this gives you an idea or something and hope this method works :-)

Regards,
Viktor Ivanov
0
 
LVL 10

Expert Comment

by:viktornet
Comment Utility
OOppps.... I use the variable "i" frequently so I've mistaken it with Forms...here is how the code is suppose to look.....

var
  Forms : Integer;
begin
  for Forms := 0 to Application.ComponentCount - 1 do
    if Application.Components[Forms] is TForm then
      SendMessage(TForm(Application.Components[Forms]).Handle,WM_VIEWCHANGE,0,0);
end;

Regards,
Viktor Ivanov
0
 
LVL 2

Author Comment

by:Ronald112197
Comment Utility
sorry, but
a) SendMessage does not behave differently from PostMessage - the only difference is that SendMessage "locks", i.e. it returns after the message is handled while PostMessage returns immediately (which is what I would prefer)

b) This code doesn't work. Give it a try - if you set a breakpoint in the handler, you'll see that Application.ComponentCount is "low" - in my application, it is 2. First one's ClassName is THintWindow, second one is TForm1. It does NOT contain all the open windows - supposedly because I create my window with TMyWindow.Create(Self); //self=Form1, so it's owned by Form1. Of course I could use FOR Ct:=1 TO Self.ComponentCount and then also override each form's event dispatching mechanism, but that's not the "nice" solution. Delphi help says that I should never have to override the event dispatching mechanism.

There must be a way to post a message in such a way that it is passed to the open forms and controls!! (i.e. all the controls on the form)
0
 
LVL 12

Accepted Solution

by:
rwilson032697 earned 50 total points
Comment Utility
Ronald,

I'm a little confused here - do you want to inform all forms of the change, or all forms AND all components that each form contains?

Anyway, some observations:

1. You should use TMessage in the declaration of your message handler and cast the TMessage to your own message structure.

2. You can use the Broadcast method of TWinControl to broadcast a message to all windowed controls contained within it (so, you could use this to spread a message around all windowed controls of a form, but not non-windowed controls (like TLabel))

3. You could send a message to every form in your app like this:

for I := 0 to Screen.Forms.Count - 1 do
  SendMessage(Screen.Forms[i].handle, WM_VIEWCHANGE, 0, 0);

4. Send the address of your message record in the fourth parameter (the LParam). Like this:

var
  MsgInfo : TMyMesgInfo;
.
// File in Msg Info
.
// Send the message
  SendMessage(Screen.Forms[i].handle, WM_VIEWCHANGE, 0, &MsgInfo);
.

I hope these help.

Cheers,
Raymond.
0
 
LVL 10

Expert Comment

by:viktornet
Comment Utility
Ronald,

I used SendMessage() because I like it better.

About the THintWindow and TForm1 it's just what should happen...... that's why I use if Application.Components[Forms] is TForm //I check if it is...if not then just continue on hunting....

I didn't also say that that's a solution.... I didn't even tried the code with Delphi so I wasn't sure if it will work anyway....

Raymond's example might work.. I have a simple suggestion for Raymond's code. He used the & operator which is the in C/C++ but you need to use the @ operator which is in Delphi(Pascal)... Someone who reads this might wonder what this symbol is so I decided to comment that....

Regards,
Viktor Ivanov
0
 
LVL 10

Expert Comment

by:viktornet
Comment Utility
Raymond:

Actually this code doesn't work in D4....

for I := 0 to Screen.Forms.Count - 1 do
     SendMessage(Screen.Forms[i].handle, WM_VIEWCHANGE, 0, 0);

Don't know why . o O

Regards,
Viktor Ivanov
0
Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

 
LVL 10

Expert Comment

by:viktornet
Comment Utility
Here is a fix for it...

for i := 0 to Screen.FormCount - 1 do
  SendMessage(Screen.Forms[i].handle, WM_VIEWCHANGE, 0, 0);
0
 
LVL 12

Expert Comment

by:rwilson032697
Comment Utility
Doh!

Serves me right for typing in code without compiling it first. Of course its screen.formcount (doesn't it annoy you when they don't do some things consistently)!

Using the & instead of @ is caused by working with C++ and Delphi at the same time, sigh :-)

Cheers,
Raymond.
0
 
LVL 10

Expert Comment

by:viktornet
Comment Utility
Ya,
I didn't say there was something wrong w/ typing text and not compiling it,... I just wanted to clear things out so everyone can use your examples efficiently... That's all... It might take someone some time to figure things out that it was just misstyping....

Regards,
Viktor Ivanov
0
 
LVL 12

Expert Comment

by:rwilson032697
Comment Utility
Viktor,

Thanks for the correction. I guess I should have added a smiley after the not compiling sentence :-)

Cheers,
Raymond.
0
 
LVL 10

Expert Comment

by:viktornet
Comment Utility
:-)
0
 
LVL 2

Author Comment

by:Ronald112197
Comment Utility
sorry for being slow, but I didn't have time to test that solution... mainly because I had already found a solution myself.
The Delphi FAQ pages (stupid me for not reading all of those first!) suggest
for f := 0 to Screen.FormCount - 1 do
     Screen.Forms[f].Perform(UM_MyGlobalMessage, 42, 42);
which is very close to your suggestion. Thanks.

Some comments about your "observations":
#1) nope. That's not true. "New" Windows API uses named parameters
#2, #3) ok :-)
#4) I would only do that if the information about my message is longer than 2 times 4 bytes, right?

viktornet: Thanks for your comments, but I didn't like "ComponentCount": That's a loop through 140 components every time - only 2 of them are forms...
0
 
LVL 12

Expert Comment

by:rwilson032697
Comment Utility
Ronald,

re: #4 - Yes, you're right. If it fits into a couple of longints then you can pass them in WParam and LParam (though I am not sure how you get them out at the end...).

Cheers,

Raymond.
0
 
LVL 2

Author Comment

by:Ronald112197
Comment Utility
well... I could pass 64 boolean parameters in 2 longints *bg* - I only need 6 ;-))

How I get them out?
procedure WMViewChange(VAR Msg: TWMViewChange); message WM_ViewChange;
  BEGIN
    IF Msg.MyFirstParameterName AND 8 >0 THEN ....
    ....
  END;

re-Cheers :-)
0
 
LVL 12

Expert Comment

by:rwilson032697
Comment Utility
Um.. No. What I meant was how you get the WParam and LParam values into that structure of yours automagically...

Raymond.
0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Objective: - This article will help user in how to convert their numeric value become words. How to use 1. You can copy this code in your Unit as function 2. than you can perform your function by type this code The Code   (CODE) The Im…
Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
In this seventh video of the Xpdf series, we discuss and demonstrate the PDFfonts utility, which lists all the fonts used in a PDF file. It does this via a command line interface, making it suitable for use in programs, scripts, batch files — any pl…
When you create an app prototype with Adobe XD, you can insert system screens -- sharing or Control Center, for example -- with just a few clicks. This video shows you how. You can take the full course on Experts Exchange at http://bit.ly/XDcourse.

772 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now