4

I coded a programm which uses MFC and therefore WinAPI-functions like PostMessage. It's mainly just one Window-thread and a network-client-thread. I created my own Message and it works fine so far. To explain the program a bit:
I wrote a Client which gets messages over the network, decodes them and then needs to send Messages to the Window which shows the Values of the Messages. All this works - with 32 bit values. It surely is some kind of not correctly using the PostMessage-function, because lParam and wParam are Pointers normally. But I can't use just Pointers because my client-application and my Window application are two different threads and the values in the client application get deleted as soon as possible. (The client needs to call a cyclic request from the server)

#define DEVICE_INFO_DATETIME 70000
long long date;
date = (value->serverTimestamp);
PostMessage(getWindowHandle(), WM_NEW_DATA, date, DEVICE_INFO_DATETIME);

Thing is I get timestamps and other data encoded as 64 bit. And wparam and lparam are just 32 bit, so it always truncates my values. Ok I can compile it in 64 bit, then 64-bit values are used but this is not compatible to 32 bit systems (right?) and not what I want. A workaround for this kind of code is setting up an temporary 64 bit value or maybe an array of 64 bit values as a global variable but I don't want to save them all in a seperate value regarding the memory. Just passing the value would be the best solution here.

Do you have any guesses what I could do here?

sideshowbarker
  • 81,827
  • 26
  • 193
  • 197
Neto.Z
  • 41
  • 5
  • 1
    Possible duplicate of [PostMessage params from 32-bit C# to 64-bit C++](http://stackoverflow.com/questions/1086632/postmessage-params-from-32-bit-c-sharp-to-64-bit-c) –  Jan 07 '16 at 13:44
  • 1
    You simply need to pass ownership of the pointer. The worker thread allocates, the UI thread can clean up. Don't forget to check the return value of PostMessage. – Hans Passant Jan 07 '16 at 13:58
  • How do I do pass the ownership? You mean I can allocate a 64-bit variable in my worker-thread (with malloc for example), pass the Pointer via PostMessage to my UI and then after using the value free() the pointer? I know there is something like SmartPointers in C++, but I am using a bare C-Environment for my worker. – Neto.Z Jan 07 '16 at 15:07

1 Answers1

5

Use DEVICE_INFO_DATETIME as the WPARAM, pass the address of data as LPARAM. It would be safer to use SendMessage since it's passing reference to stack data.

long long date = 123;
SendMessage(getWindowHandle(), WM_NEW_DATA, DEVICE_INFO_DATETIME, (LPARAM)&date);

Also if WM_NEW_DATA is defined properly then DEVICE_INFO_DATETIME does not have to be a large random number like 70000. For example

#define WM_NEW_DATA WM_APP + 1
#define DEVICE_INFO_DATETIME 1


You can also pass long long value as two integers, this will work with PostMessage

#define WM_NEW_DATA2 WM_APP + 2

long long date = ...
int hi = date >> 32;
int lo = (int)date;
PostMessage(hwnd, WM_NEW_DATA2, (WPARAM)hi, (LPARAM)lo);

receive:

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    if (msg == WM_NEW_DATA2)
    {
        long long date = ((long long)wParam << 32) + lParam;
    }
}



Using pointers and PostMessage: The calling function allocates data, and receiver function deletes the data (it can also use malloc and free)
//call:
long long *date = new long long;
PostMessage(hwnd, WM_APP + 3, DEVICE_INFO_DATETIME, (LPARAM)date);

//receive:
if (msg == WM_APP + 3)
{
    long long *date = (long long*)lParam;
    if (!date) return 0; //insufficient error check!
    delete date;//delete pointer when finished
}

However this is error prone. For example if caller accidentally sends PostMessage(hwnd, WM_APP + 3, DEVICE_INFO_DATETIME, 1); the program will crash. There is no way the receiver can know if lParam is good or bad (as far as I know)

Barmak Shemirani
  • 30,904
  • 6
  • 40
  • 77
  • ok, thanks! that solved the problem. I had two problems. first using wParam, which is an UInt and that somehow turns the Pointer into a random number and second using PostMessage causes the message to process when the memory where the pointer is pointing to is empty. SendMessage now works correctly and does its job. that's exactly what I wanted. – Neto.Z Jan 07 '16 at 15:55
  • I am not sure about downvote reason. It seems like overkill to use memory allocation for date stamp. I added another method to pass 64 bit integer using `PostMessage` – Barmak Shemirani Jan 07 '16 at 17:45
  • yeah I wondered about the downvote too. The second version was my thought too but I needed to send the define too. Just curious: date is a local variable in this example. Using SendMessage causes the WinAPI to immediately process this message and only after this return to the SendMessage-caller and only then after processing the calling function, date will be destroyed. PostMessage caused to just process the message anytime and returns immediately to the calling function and therefore the calling function could be finished and date is lost. Did I get this right? – Neto.Z Jan 08 '16 at 07:54
  • `SendMessage` is similar to calling a regular function. It waits until the other function is finished. Whereas `PostMessage` return immediately and does not wait for the other function. The other function may try to use `date` after the caller function is already finished, and `date` is out of scope and destroyed. `SendMessage` has its own draw backs, here it can potentially cause the program to hang (even though it's multi-threaded). I added another method for `PostMessage` and pointers. But `SendMessage` is good enough as long as it's not causing problems. – Barmak Shemirani Jan 08 '16 at 09:38