Discussion:
Better way to send data that SendMessage(hWnd,WM_USER,IDM_XXX,lParam);
(too old to reply)
zliminator
2003-12-06 01:04:44 UTC
Permalink
I'm sending data to a modeless dialog using the WM_USER notification and
stuffing the data into the lParam for each different wParam message and then
unpacking the lParam it in the dialog. Is there a better way? I seem to
remember some example using Set/GetWindowWord/Long. Can someone give me a
hint? Thanks.

Dan
lallous
2003-12-06 07:02:50 UTC
Permalink
If you want to use Set/GetWindowLong() , I can think of the following:

enum CommActions
{
caSetTitle = 1,
caFillListBox,
.
.
.
.
};

struct CommStruct_t
{
int ActionId;
union
{
struct
{
char *Title;
} SetTitle;
struct
{
int *data;
int length;
} FillListBox; // say to fill data in your listbox
.
.
.
.
} Actions;
};

Later when you create your modeless window allocate a structure as:
CommStruct_t *t = new CommStruct_t;
// associate this communication structure w/ your window.
SetWindowLong(windowHandle, GWL_USERDATA, (LONG)t);

In your window's WndProc() you can retrieve the stucture using
GetWindowLong().

Now send your self a WM_USER+X message to notify your window that a new
commstruct is ready.

case WM_USER+X:
{
CommStruct_t *t = (CommStruct_t *)GetWindowLong(hWnd, GWL_USERDATA);

switch(t->ActionId)
{
case caSetTitle:
SetWindowTitle(hWnd, t->Actions.SetTitle.Title);
break;
case caXXXXXX:
break;
.
.
.
.
}
break;
}


HTH
Elias
Post by zliminator
I'm sending data to a modeless dialog using the WM_USER notification and
stuffing the data into the lParam for each different wParam message and then
unpacking the lParam it in the dialog. Is there a better way? I seem to
remember some example using Set/GetWindowWord/Long. Can someone give me a
hint? Thanks.
Dan
Dan
2003-12-06 10:03:28 UTC
Permalink
Thanks. And shame on me for not thinking of using a union to pack data into
a long.

Dan in FL
Tim Robinson
2003-12-06 14:40:10 UTC
Permalink
Using SetWindowLong is redundant here, and potentially dangerous. Presumably
what you're sending in lParam applies to one and only one message, so to use
SWL, your code would look like:

// Store a pointer to the data
SetWindowLong(hWnd, GWL_USERDATA, (LONG_PTR) &data);
// Tell the window about the data
SendMessage(hWnd, WM_USER, IDM_XXX, 0);
// Remove the pointer to the data
SetWindowLong(hWnd, GWL_USERDATA, 0);

Three problems with this code:
1) It uses an index in the window's data to store a pointer when there's a
perfectly good lParam parameter to SendMessage which could be used
2) It's not thread safe at all. If more than one thread was to try this
simultaneously, it's likely that the calls to SetWindowLong and SendMessage
would get jumbled up
3) If you later realised you needed to post the message, not send it, you'd
see problem (2) even in a single-threaded app

So I'd recommend carrying on using the lParam parameter to SendMessage to
pass a pointer, and forget about SetWindowLong for this.
--
Tim Robinson (MVP, Windows SDK)
http://www.themobius.co.uk/
Post by zliminator
I'm sending data to a modeless dialog using the WM_USER notification and
stuffing the data into the lParam for each different wParam message and then
unpacking the lParam it in the dialog. Is there a better way? I seem to
remember some example using Set/GetWindowWord/Long. Can someone give me a
hint? Thanks.
Dan
Sten Westerback
2004-01-29 12:50:07 UTC
Permalink
Post by zliminator
I'm sending data to a modeless dialog using the WM_USER notification and
stuffing the data into the lParam for each different wParam message and then
unpacking the lParam it in the dialog. Is there a better way? I seem to
remember some example using Set/GetWindowWord/Long. Can someone give me a
hint? Thanks.
The best thing to do if using lParam ( & wParam) isn't enough,
is to pass a pointer to a malloced struct in the lParam which,
AFAIK, will always be able to fit a pointer.

Also note that you should use WM_APP as the base for
own messages in new code. This avoids conflicts with
some new common control messages...

- Sten
Lucian Wischik
2004-01-29 13:20:23 UTC
Permalink
Post by Sten Westerback
The best thing to do if using lParam ( & wParam) isn't enough,
is to pass a pointer to a malloced struct in the lParam which,
AFAIK, will always be able to fit a pointer.
If it's SendMessage, then I'd instead recommend to just
struct data {...};

...
data x;
SendMessage(WM_USER, mycode, &x);

i.e. declare it on the stack rather than malloc. (because a stack
declaration will be faster than malloc, and will have less chance of
leaks.)

--
Lucian
Charlie Gibbs
2004-01-29 22:08:27 UTC
Permalink
Post by Sten Westerback
Post by zliminator
I'm sending data to a modeless dialog using the WM_USER notification
and stuffing the data into the lParam for each different wParam
message and then unpacking the lParam it in the dialog. Is
there a better way? I seem to remember some example using
Set/GetWindowWord/Long. Can someone give me a hint? Thanks.
The best thing to do if using lParam ( & wParam) isn't enough,
is to pass a pointer to a malloced struct in the lParam which,
AFAIK, will always be able to fit a pointer.
How about WM_COPYDATA?
Post by Sten Westerback
Also note that you should use WM_APP as the base for
own messages in new code. This avoids conflicts with
some new common control messages...
Hmmm, this is a new one to me. While prowling through winuser.h
I did get a bit nervous when I saw #defines of WM_ values greater
than WM_USER, so I suppose this is a Good Thing. In the name of
backward compatibility I could always add the following to my code:

#ifndef WM_APP
#define WM_APP WM_USER
#endif

--
/~\ ***@kltpzyxm.invalid (Charlie Gibbs)
\ / I'm really at ac.dekanfrus if you read it the right way.
X Top-posted messages will probably be ignored. See RFC1855.
/ \ HTML will DEFINITELY be ignored. Join the ASCII ribbon campaign!
Tim Robinson
2004-01-29 23:11:09 UTC
Permalink
Post by Charlie Gibbs
Hmmm, this is a new one to me. While prowling through winuser.h
I did get a bit nervous when I saw #defines of WM_ values greater
than WM_USER, so I suppose this is a Good Thing. In the name of
#ifndef WM_APP
#define WM_APP WM_USER
#endif
No, don't! WM_APP is defined in windows.h.

Messages in the WM_USER area are reserved for the standard Windows controls
and common controls. If you want to define your own messages, either use the
real WM_APP, or values returned by RegisterWindowMessage.
--
Tim Robinson (MVP, Windows SDK)
http://www.themobius.co.uk/
Charlie Gibbs
2004-01-30 00:59:10 UTC
Permalink
Post by Tim Robinson
Post by Charlie Gibbs
Hmmm, this is a new one to me. While prowling through winuser.h
I did get a bit nervous when I saw #defines of WM_ values greater
than WM_USER, so I suppose this is a Good Thing. In the name of
#ifndef WM_APP
#define WM_APP WM_USER
#endif
No, don't! WM_APP is defined in windows.h.
Messages in the WM_USER area are reserved for the standard Windows
controls and common controls. If you want to define your own
messages, either use the real WM_APP, or values returned by
RegisterWindowMessage.
You misinterpreted my code. The purpose of the #ifndef is to
ensure that I do this trick only for older systems that didn't
yet define WM_APP. I agree, if WM_APP is defined I should
use it - which is exactly what the above code does. As you
might have guessed, I'm a belt-and-suspenders kind of guy with
an eye to portability - both forwards and backwards (I still
compile stuff that runs under 3.1).

--
/~\ ***@kltpzyxm.invalid (Charlie Gibbs)
\ / I'm really at ac.dekanfrus if you read it the right way.
X Top-posted messages will probably be ignored. See RFC1855.
/ \ HTML will DEFINITELY be ignored. Join the ASCII ribbon campaign!
Loading...