C++ class for capturing broadcast window messages In the Windows operating system, some system events are notified via broadcast window messages. DBT_DEVICEARRIVAL and DBT_DEVICEREMOVECOMPLETE are good examples of this. To receive and process these notifications, one need to have a window with an associated window procedure. Given a non-GUI application, this is a burden. So, I'm thinking about encapsulating a simple class for capturing broadcast window messages, and here it comes. The pack comes in one main class CWndMsgReceiver and two helper classes CDummyWndClass and CDummyWnd.

I hope to have my code reviewed, and get some comments and suggestions.

WndMsgReceiver.h

#pragma once
#include &lt;atomic&gt;
#include &lt;thread&gt;
#include &lt;windows.h&gt;

class CDummyWndClass {
public:
  explicit CDummyWndClass(WNDPROC wndproc);
  ~CDummyWndClass();
  operator PCWSTR() const;
private:
  ATOM atom_;
};

class CDummyWnd {
public:
  explicit CDummyWnd(WNDPROC wndproc);
  ~CDummyWnd();
  operator HWND() const;
private:
  CDummyWndClass wndcls_;
  HWND hwnd_;
};

class CWndMsgReceiver {
public:
  explicit CWndMsgReceiver(WNDPROC wndproc);
 ~CWndMsgReceiver();
  operator HWND() const;  // to use with RegisterDeviceNotification
private:
  static void MsgPump(WNDPROC wndproc, std::atomic&lt;HWND&gt;&amp; hwnd);
  std::atomic&lt;HWND&gt; hwnd_;
  std::thread thrd_;
};


WndMsgReceiver.cpp

#include "WndMsgReceiver.h"
#include &lt;cstring&gt;
#include &lt;functional&gt;
#include &lt;utility&gt;

CDummyWndClass::CDummyWndClass(WNDPROC wndproc)
    : atom_(0) {
  HMODULE hmodule = 0;
  GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
                     GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
                     (PCWSTR)wndproc, &amp;hmodule);
  WNDCLASSW wndcls = {0, wndproc, 0, 0, (HINSTANCE)hmodule, 0, 0, 0, nullptr, 
                      L"{F9F40031-F77E-4A5C-8A6C-30296B823C22}"};
  atom_ = RegisterClassW(&amp;wndcls);
}

CDummyWndClass::~CDummyWndClass() {
  UnregisterClassW((PCWSTR)*this, 0);
}

CDummyWndClass::operator PCWSTR() const {
  PCWSTR p = nullptr;
  std::memcpy(&amp;p, &amp;atom_, sizeof(atom_));
  return p;
}

////////////////////////////////////////////////////////////////////////////////

CDummyWnd::CDummyWnd(WNDPROC wndproc)
    : wndcls_(wndproc)
    , hwnd_(CreateWindowW((PCWSTR)wndcls_, nullptr, 0, 0, 
                          0, 0, 0, 0, 0, 0, nullptr)) {
}

CDummyWnd::~CDummyWnd() {
  DestroyWindow(hwnd_);
}

CDummyWnd::operator HWND() const {
  return hwnd_;
}

////////////////////////////////////////////////////////////////////////////////

CWndMsgReceiver::CWndMsgReceiver(WNDPROC wndproc)
    : hwnd_{}
    , thrd_(std::thread(MsgPump, wndproc, std::ref(hwnd_))) {
  do Sleep(0); while (!(HWND)hwnd_);
}

CWndMsgReceiver::~CWndMsgReceiver() {
  PostThreadMessageW(GetThreadId(thrd_.native_handle()), WM_QUIT, 0, 0);
  thrd_.join();
}

CWndMsgReceiver::operator HWND() const {
  return hwnd_;
}

void CWndMsgReceiver::MsgPump(WNDPROC wndproc, std::atomic&lt;HWND&gt;&amp; hwnd) {
  CDummyWnd wnd(wndproc);
  hwnd = wnd;
  MSG msg = {};
  while (GetMessageW(&amp;msg, 0, 0, 0)) {
    TranslateMessage(&amp;msg);
    DispatchMessageW(&amp;msg);
  }
}
I haven't worked with WinAPI in years, so I can't help you much with that, but I do have a few concerns regarding style and structure of your code:


What's the meaning of this GUID? Does it have any, or is it just randomly generated?


WNDCLASSW wndcls = {0, wndproc, 0, 0, (HINSTANCE)hmodule, 0, 0, 0, nullptr, 
              L"{F9F40031-F77E-4A5C-8A6C-30296B823C22}"};



A comment explaining why this specific value would be nice. Or better, make it a named constant with a self-explanatory name.
You have several instances of C-style casts in the code. Prefer using the C++ cast operators instead. They will give you warnings and diagnostics for potentially dangerous casts.
This looks very obscure:


CDummyWndClass::operator PCWSTR() const {
  PCWSTR p = nullptr;
  std::memcpy(&amp;p, &amp;atom_, sizeof(atom_));
  return p;
}



On my first look, I thought that you were trying to memcpy into a null pointer. The &amp; on p is not easily spotted without a careful look. If you really must do this, then I think a reinterpret_cast would be more clear about your intentions. I did not test this, but something along the lines of the following should do:

CDummyWndClass::operator PCWSTR() const {
    const std::uintptr_t intVal = static_cast&lt;std::uintptr_t&gt;(atom_);
    PCWSTR ptrVal = reinterpret_cast&lt;PCWSTR&gt;(intVal);
    return ptrVal;
}

It would probably look clearer if you'd lay out that loop inside CWndMsgReceiver construtor is a more spaced way, to give it emphasis. Default { } is always good too:


  do Sleep(0); while (!(HWND)hwnd_);



 do {
     Sleep(0); 
 } while (!(HWND)hwnd_);


You should also comment that this is not an infinite loop, but that it waits on an independent thread to set the variable.
This might be your personal preference, I for one I'm not a big fan of cast operator overloads. I've seen instances when they can produce some pretty obscure code. IMHO, I think your cast operators would look much nicer as plain Get*() methods.
You don't seem to use the wacky Microsoft prefixes on variable names, though you do use the C prefix for class names. Again, this is a subjective point, but I think your class names would be more readable without it.