Skip to content

Instantly share code, notes, and snippets.

@aliakseis
Created December 15, 2025 14:51
Show Gist options
  • Select an option

  • Save aliakseis/943fec85a5cafa3403635983c70c55fc to your computer and use it in GitHub Desktop.

Select an option

Save aliakseis/943fec85a5cafa3403635983c70c55fc to your computer and use it in GitHub Desktop.
Message only window wrapper for sending notifications to main thread
#pragma once
#include <memory>
#include <type_traits>
class MessageOnlyWindow
{
public:
MessageOnlyWindow();
~MessageOnlyWindow();
MessageOnlyWindow(const MessageOnlyWindow&) = delete;
MessageOnlyWindow& operator=(const MessageOnlyWindow&) = delete;
template<typename T>
void SendNotifyCallback(T func)
{
void (*f)(UINT_PTR) = [](UINT_PTR param) {
if constexpr (std::is_function<typename std::remove_pointer<T>::type>::value) {
auto fun = reinterpret_cast<T>(param);
(*fun)();
}
else {
auto fun = reinterpret_cast<T*>(param);
(*fun)();
delete fun;
}
};
if constexpr (std::is_function<typename std::remove_pointer<T>::type>::value) {
VERIFY(::SendNotifyMessage(hwnd_, WM_USER + 1, reinterpret_cast<WPARAM>(func), reinterpret_cast<LPARAM>(f)));
}
else {
auto callbackPtr = new T(std::move(func));
VERIFY(::SendNotifyMessage(hwnd_, WM_USER + 1, reinterpret_cast<WPARAM>(callbackPtr), reinterpret_cast<LPARAM>(f)));
}
}
template<typename T, typename L>
void SendNotifyCallback(T* ptr, L lam)
{
void (*func) (T*) = lam;
VERIFY(::SendNotifyMessage(hwnd_, WM_USER + 1, reinterpret_cast<WPARAM>(ptr), reinterpret_cast<LPARAM>(func)));
}
private:
HWND hwnd_;
};
#include "pch.h"
#include "MessageOnlyWindow.h"
static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
if (uMsg == WM_USER + 1) {
// Handle custom message
auto func = reinterpret_cast<void (*)(UINT_PTR)>(lParam);
(*func)(wParam);
return 0;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
MessageOnlyWindow::MessageOnlyWindow() {
// Register the window class
WNDCLASS wc = { 0 };
wc.lpfnWndProc = WindowProc;
wc.hInstance = GetModuleHandle(NULL);
wc.lpszClassName = TEXT("MessageOnlyWindow");
RegisterClass(&wc);
// Create the message-only window
hwnd_ = CreateWindowEx(
0, // Optional window styles
TEXT("MessageOnlyWindow"), // Window class name
NULL, // Window name
0, // Window style
0, 0, 0, 0, // Position and size (ignored)
HWND_MESSAGE, // Parent window (message-only)
NULL, // Menu
GetModuleHandle(NULL), // Instance handle
NULL // Additional application data
);
ASSERT(hwnd_ != NULL);
}
MessageOnlyWindow::~MessageOnlyWindow() {
if (hwnd_) {
DestroyWindow(hwnd_);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment