Encapsulate Win32 window message handling and provide EasyX-style messages, allowing message processing to be independent of the UI/rendering thread. The approach is based on zouhuidong/HiEasyX.
#include "HiMsg.hpp"
HiMsg::HiMsgSet messages; // The default capacity is 63 and can be changed in the constructor.
// BindWindow must be called from the window thread that owns hwnd.
HiMsg::BindOptions options;
options.closePolicy = HiMsg::ClosePolicy::Forward;
messages.BindWindow(hwnd, options);
// Worker thread: a successful GetMessage call removes the message from the queue.
while (auto message = messages.GetMessage())
{
switch (message->message)
{
case WM_LBUTTONDOWN:
// message->hwnd identifies the parent or child window that produced the message.
break;
}
}The queue uses concurrentqueue to store ExMessage* values and accepts up to 63 unprocessed messages by default. When the queue is full, existing messages are retained and new messages are discarded. The number of discarded messages is available through GetDroppedMessageCount(). HiMsg does not provide a peek API; successful calls to GetMessage and TryGetMessage always consume the returned message.
User callbacks run synchronously on the window thread. A callback can continue normal processing, discard a message only from the HiMsg queue, handle a message completely, or force a regular Win32 message into the queue as a window message. Callbacks should remain lightweight; time-consuming work should run on the thread that consumes queued messages.
Parent windows usually receive notifications such as WM_COMMAND and WM_NOTIFY from child controls, but mouse and keyboard messages sent directly to a child window are not automatically forwarded to its parent. To receive these direct messages, use:
options.bindExistingChildren = true;
options.bindFutureChildren = true;
messages.BindWindow(hwnd, options);bindExistingChildren binds all descendant windows that already exist when the function is called. bindFutureChildren uses WM_PARENTNOTIFY to bind regular child windows created afterward. A child window created with WS_EX_NOPARENTNOTIFY does not send this notification and must be bound explicitly with BindWindow after it is created.
The default close policy forwards WM_CLOSE to the original window procedure. Alternatively, select DestroyWindow to let HiMsg destroy the window or Ignore to prevent the window from closing. HiMsg does not call PostQuitMessage by default and does so only when postQuitOnDestroy is explicitly enabled.