Solved

WM_USER message does not arrive

Posted on 1997-09-16
25
1,193 Views
Last Modified: 2010-04-04
OK. I give up.

My app does not receive my own messages (WM_USER + n) sent from
another instance of the same app.

Sample app:

------------------------------ code ----------------------------
type
  TForm1 = class(TForm)
    BitBtn1: TBitBtn;
    Label1: TLabel;
    Edit1: TEdit;
    procedure BitBtn1Click(Sender: TObject);
  protected
    procedure WMUser(var M: TMessage); message WM_User;
  end;

procedure TForm1.WMUser(var M: TMessage);
begin
  label1.caption:= 'received '+IntToStr(M.lParam);
  inherited;
end;

procedure TForm1.BitBtn1Click(Sender: TObject);
begin
  PostMessage(HWND_BROADCAST, WM_USER, 0, StrToInt(Edit1.Text));
end;
--------------------------- end code ---------------------------

Then:
start two instances of this app (one for send, one for receive)
in one instance:
  enter a number in the editbox (ex: 23),
  press the button,

the other instance does not write 'received 23'.

Why? And what to do? Thanks in advance.
0
Comment
Question by:krisz
  • 9
  • 7
  • 5
  • +3
25 Comments
 
LVL 1

Expert Comment

by:jackb022197
Comment Utility
You can not send a msg from one instance to another instance this way. You need to look at IPC to exchange info between different processes. Check the Win32 API help file for this.
0
 

Author Comment

by:krisz
Comment Utility
Why not? Delphi or windows prevents it? Please be more verbose,
this answer is not acceptable.

Using DDE or pipes requires sending messages, and I see
no reason to prevent it between two instances of an app.
0
 
LVL 1

Expert Comment

by:ygolan
Comment Utility
Notice that you should not broadcast a WM_USER. WM_USER-based messages are defined only within a window class - different applications respond differently to WM_USER. For all you know, there might be a running application that considers WM_USER to be a command to shut down, delete a file or format the hard disk :-)

I suggest that (if you wish to avoid IPC, which BTW is very easy to use) you create a hidden window with a special name, use FindWindow to find it from the other instance, and use its handle to PostMessage directly to it.
0
 

Author Comment

by:krisz
Comment Utility
Thanks for this comment. But I think it's not really the point.
Or registered messages will arrive? If so, the problem is no
more. If won't, bad. I'll try it.

Also I have to disagree about IPC.
Actually I'm trying to set up an IPC communication. I want to
train myself in the usage of unnamed pipes, the problem is I
have to tell to the other app the handles of the pipe. Messages
look the easiest way for this. Yes, I can use shared memory, but
if I do why do I need the pipe?

I can't believe that there is no way to send messages between
two instances of an app.
0
 
LVL 5

Expert Comment

by:julio011597
Comment Utility
Hello, just a guess:

procedure WMUser(var M: TMessage); message WM_User;
----------------------------------------------^^^^

should be WM_USER (all uppercase).

Does this makes any difference?

-julio
0
 

Author Comment

by:krisz
Comment Utility
Ok. I reject jackb's answer, and increase points to 150.

Note to julio: letter case is not the solution.
0
 

Author Comment

by:krisz
Comment Utility
Adjusted points to 150
0
 
LVL 1

Expert Comment

by:ygolan
Comment Utility
> Yes, I can use shared memory, but  if I do why do I need the > pipe?

You don't :-) that's the whole point.

I've got source code that makes  IPC easy. Email me for it - ygolan@hyperact.com
0
 

Author Comment

by:krisz
Comment Utility
Look!

It's NOT about IPC! I talk about _messages_.
I've used shared memory earlier. I've used pipes too.
IPC is cool, but I want messages, messages, MESSAGES!!!!!

Meanwhile I found a workaround. I still don't know what is
the problem with my code above, but the new code works, so
the 'what to do?' part of the question is no more.

I'm still waiting for somebody who can tell me what's the
problem.

(Note: this 150 points are the final offer)
0
 
LVL 12

Expert Comment

by:andrewjb
Comment Utility
Try using WM_USER + n, where n is about 100. Delphi itself uses some of the user messages in its own components. Who knows what! So the message might be being trapped by something else.
0
 
LVL 12

Expert Comment

by:andrewjb
Comment Utility
Try using WM_USER + n, where n is about 100. Delphi itself uses some of the user messages in its own components. Who knows what! So the message might be being trapped by something else.
0
 

Author Comment

by:krisz
Comment Utility
Bad.

I tried it with registered messages. Still doesn't work.
0
What Should I Do With This Threat Intelligence?

Are you wondering if you actually need threat intelligence? The answer is yes. We explain the basics for creating useful threat intelligence.

 
LVL 12

Accepted Solution

by:
andrewjb earned 150 total points
Comment Utility
Got it!

The BROADCAST message sends to all the APPLICATIONS, not the forms. So you have to trap application messages :

TForm1.FormCreate...
begin
  ......
  Application.OnMessage := TrapAppMessages;
  ....
end;

TForm1.TrapAppMessages( var Msg: TMsg; var Handled: Boolean);
begin
  if ( Msg.Message = WM_MYMSG ) then
  begin
    .... { Do your stuff }
    Handled := True;
  end;
end;

Still use WM_USER + n ( n = about 150 or so )

0
 

Author Comment

by:krisz
Comment Utility
This was a clue!

-- Win32.hlp, PostMessage ----------------------------
HWND_BROADCAST:

The message is posted to all top-level windows
in the system, including disabled or invisible
unowned windows, overlapped windows, and pop-up
windows. The message is not posted to child windows.
-- end -----------------------------------------------

But all windows including the main form are child windows
in delphi. The top-level window is hidden, and you can
get it's handle with Application.Handle.

It's not in the help, but you can see it in Forms.pas.
See TApplication.Create and TApplication.CreateHandle.

It's an inconsistency in Delphi. I think the MainWndProc
should forward all messages sent to the top-level window
to the main window.

Solutions:
- Application.OnMessage
- Application.HookMainWindow

(And still don't broadcast WM_USER+n messages, use
registered messages instead!)

Because you gave only a clue, and not a detailed description,
I offer you an 'acceptable' grading. Comment if you want more.
0
 
LVL 3

Expert Comment

by:mirek071497
Comment Utility
Hi krisz.
I have a question for you.
I try too broadcast messages (WM_USER+n) and when I set OnMessage for Application i can't get this message, Can You boadcast WM_USER now ? If You can than How ?
0
 
LVL 12

Expert Comment

by:andrewjb
Comment Utility
For mirek :

( Form with a button on it )


unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
    procedure AppMsg (var Msg: TMsg; var Handled: Boolean);
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

const
  WM_MYMSG = WM_USER + 150;

{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);
begin
  PostMessage( HWND_BROADCAST , WM_MYMSG , 0 , 0 );
end;

procedure tForm1.AppMsg (var Msg: TMsg; var Handled: Boolean);
begin
  if ( Msg.Message = WM_MYMSG ) then
  begin
      { This just prints something on the screen }
    AllocConsole;
    writeln('Hello there!');
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  Application.OnMessage := AppMsg;
end;

end.
0
 
LVL 3

Expert Comment

by:mirek071497
Comment Utility
Yes i write this in the same way but this don't working. Delphi3.
Why ?
When You try this i think so this is working. Mayby this depend of Delphi version ?
0
 
LVL 12

Expert Comment

by:andrewjb
Comment Utility
Works OK for me in Delphi 3.

0
 
LVL 3

Expert Comment

by:mirek071497
Comment Utility
It's seems as impossible, but I know so This working for You. Do you have any idea why this not working for me ?
0
 
LVL 12

Expert Comment

by:andrewjb
Comment Utility
The FormCreate and Button1Click methods are event handlers. You are attaching them to the form / button correctly, I assume ...

AJB

0
 
LVL 3

Expert Comment

by:mirek071497
Comment Utility
Yes.

In MS-SDK i found :


When SendMessage() is used to send a broadcast message (hwnd = 0xFFFF or
hwnd = -1), the message is sent to all top-level windows. A message
broadcast by PostMessage() is only sent to top-level windows that are
visible, enabled, and have no owner.

You might observe the effect of the difference when, for example, the top-
level window of your application calls DialogBox() to present a modal
dialog box. While the modal dialog box exists, its owner (your top-level
window) will be disabled. Messages broadcast using PostMessage() will not
reach the top-level window because the window is disabled, and will not
reach the dialog box because the dialog box has an owner. Messages
broadcast using SendMessage() will reach both the top-level window and the
dialog.

In Windows 3.1, PostMessage() will broadcast to invisible and disabled
windows just like SendMessage() already does.


But Send Message don't working too !!!.
0
 

Author Comment

by:krisz
Comment Utility
No differences between SendMessage and PostMessage.

----- win32.hlp -----------------------
SendMessage:
If this parameter is HWND_BROADCAST, the message is sent to all top-level windows in the system, including disabled or invisible unowned windows, overlapped windows, and pop-up windows; but the message is not sent to child windows.

PostMessage
The message is posted to all top-level windows in the system, including disabled or invisible unowned windows, overlapped windows, and pop-up windows. The message is not posted to child windows.
----- end ------------------------------

Application.OnMessage should work. If not, the problem is
something else.

andrewjb, if you agree, I won't grade your answer until this
conversation is going on, because the grading prevents
adding more comments. Tell me if you disagree.
0
 
LVL 12

Expert Comment

by:andrewjb
Comment Utility
Indeedy, I don't know why mirek is having problems. Perhaps you should post the code you're trying to execute, mirek ??


0
 
LVL 3

Expert Comment

by:mirek071497
Comment Utility
Sorry. You can grade the answer if this work for you. This is Your question not My.
0
 

Author Comment

by:krisz
Comment Utility
Mirek! Ask your question as a separate one. This thread is
going to close.
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

Creating an auto free TStringList The TStringList is a basic and frequently used object in Delphi. On many occasions, you may want to create a temporary list, process some items in the list and be done with the list. In such cases, you have to…
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…
This video shows how to remove a single email address from the Outlook 2010 Auto Suggestion memory. NOTE: For Outlook 2016 and 2013 perform the exact same steps. Open a new email: Click the New email button in Outlook. Start typing the address: …
This video explains how to create simple products associated to Magento configurable product and offers fast way of their generation with Store Manager for Magento tool.

743 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

15 Experts available now in Live!

Get 1:1 Help Now