PostMessage
string handling
interprocess communication
Windows API
programming tutorial

How to send a string via PostMessage?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

With the Win32 API, PostMessage is asynchronous: it places a message in another thread's queue and returns immediately. That makes it a poor mechanism for sending an arbitrary string payload directly, because any pointer you pass may become invalid before the receiving window processes the message. For string data, the correct answer is usually SendMessage with WM_COPYDATA, not PostMessage.

Why raw string pointers are unsafe with PostMessage

PostMessage lets you send WPARAM and LPARAM, but those are just integer-sized values. If you cast a pointer to a string buffer into LPARAM and then return, the receiver may later read freed or modified memory.

That is the key issue: PostMessage does not synchronize lifetime.

Use WM_COPYDATA with SendMessage for cross-process strings

WM_COPYDATA is the standard Win32 way to send a block of data, including a string, to another window synchronously.

cpp
1#include <windows.h>
2#include <string>
3
4void SendText(HWND target, const std::wstring& text) {
5    COPYDATASTRUCT cds{};
6    cds.dwData = 1;
7    cds.cbData = static_cast<DWORD>((text.size() + 1) * sizeof(wchar_t));
8    cds.lpData = (PVOID)text.c_str();
9
10    SendMessage(target, WM_COPYDATA, 0, reinterpret_cast<LPARAM>(&cds));
11}

Receiver side:

cpp
1case WM_COPYDATA: {
2    PCOPYDATASTRUCT cds = reinterpret_cast<PCOPYDATASTRUCT>(lParam);
3    const wchar_t* text = static_cast<const wchar_t*>(cds->lpData);
4    MessageBoxW(hwnd, text, L"Received", MB_OK);
5    return TRUE;
6}

Because SendMessage is synchronous, the sender keeps the buffer alive for the duration of the call.

Use PostMessage only for lightweight identifiers or notifications

PostMessage is still useful when the message content is small and self-contained, such as an integer command code, an index, or a signal that tells the receiver to fetch data from a shared place.

cpp
PostMessage(target, WM_APP + 1, 42, 0);

In that design, the message does not carry the string itself. It carries a small token the receiver knows how to interpret safely.

Shared memory is possible, but more complex

If you truly need asynchronous cross-process transfer with larger payloads, use shared memory or another IPC mechanism. The message can then notify the receiver that data is ready in a known shared region.

That architecture is more work because it requires synchronization, ownership rules, cleanup, and security review. For ordinary window-to-window text transfer, WM_COPYDATA is simpler.

Same-process scenarios still need lifetime discipline

Even inside one process, a posted pointer can be dangerous if the originating stack frame or heap allocation goes away before the message is handled. The process boundary is not the real issue. The asynchronous queue is.

That is why code that "works on my machine" with PostMessage and a string pointer is still unsafe.

Consider higher-level IPC if text exchange is central

If your application frequently exchanges strings between components, window messages may be the wrong abstraction. Named pipes, sockets, COM, or framework-level messaging systems are often easier to maintain than a custom message protocol built on raw pointers.

Common Pitfalls

  • Passing a pointer to a temporary or stack-allocated string through PostMessage.
  • Assuming same-process communication makes posted string pointers safe.
  • Using PostMessage when the real need is synchronous payload transfer.
  • Forgetting that WPARAM and LPARAM do not manage ownership or lifetime.
  • Rebuilding a fragile custom shared-memory protocol when WM_COPYDATA would solve the immediate problem.

Summary

  • Do not send raw string pointers through PostMessage unless lifetime is guaranteed by another mechanism.
  • Use SendMessage with WM_COPYDATA for normal Win32 string transfer.
  • Use PostMessage for small codes or notifications, not arbitrary text payloads.
  • Treat asynchronous messaging as a lifetime problem first, not a casting problem.
  • Consider higher-level IPC if string exchange is a core part of the design.

Course illustration
Course illustration

All Rights Reserved.