I am trying to detect when a USB drive is inserted. Right now, I’m creating a dummy window and RegisterDeviceNotificationing it. However, I don’t think my approach is correct, as the window doesn’t seem to be receiving messages.
#include <iostream>
#define WINVER 0x501
#include <windows.h>
#include <dbt.h>
#include "devicehandler.h"
#include "remover.h"
DeviceHandler::DeviceHandler(Remover* remover)
{
this->remover = remover;
this->hWnd = this->createHandleWindow();
this->registerDeviceHandler();
this->messageLoop(this->hWnd);
}
DeviceHandler::~DeviceHandler()
{
this->unregisterDeviceHandler();
}
void DeviceHandler::messageLoop(HWND hWnd)
{
std::cerr << "Entering message loop." << std::endl; // Gets here!
MSG msg;
while (GetMessage(&msg, this->hWnd, 0, 0)) {
std::cerr << "Loop!" << std::endl; // Does not get here!
switch (msg.message) {
case WM_DEVICECHANGE:
{
PDEV_BROADCAST_HDR pHdr = (PDEV_BROADCAST_HDR) msg.lParam;
switch(msg.wParam) {
case DBT_DEVICEARRIVAL:
std::cerr << "Device added!" << std::endl;
break;
default:
std::cerr << "Other device event." << std::endl;
break;
}
break;
}
default:
break;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
HWND DeviceHandler::createHandleWindow()
{
std::cerr << "Creating handle window... ";
HWND hWnd = CreateWindow(NULL, NULL, WS_ICONIC, 0, 0, CW_USEDEFAULT, 0,
NULL, NULL, GetModuleHandle(NULL), NULL);
ShowWindow(hWnd, SW_HIDE);
std::cerr << "done!" << std::endl;
return hWnd;
}
void DeviceHandler::registerDeviceHandler()
{
std::cerr << "Device notification handling... ";
// GUID guid = { 0xa5dcbf10, 0x6530, 0x11d2, { 0x90, 0x1f, 0x00, 0xc0, 0x4f, 0xb9, 0x51, 0xed } };
GUID guid = { 0x25dbce51, 0x6c8f, 0x4a72, { 0x8a, 0x6d, 0xb5, 0x4c, 0x2b, 0x4f, 0xc8, 0x35 } };
DEV_BROADCAST_DEVICEINTERFACE notificationFilter;
ZeroMemory(¬ificationFilter, sizeof(notificationFilter));
notificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
notificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
notificationFilter.dbcc_classguid = guid;
this->deviceNotifier = RegisterDeviceNotification(this->hWnd,
¬ificationFilter,
DEVICE_NOTIFY_WINDOW_HANDLE);
std::cerr << "done!" << std::endl;
}
void DeviceHandler::unregisterDeviceHandler()
{
UnregisterDeviceNotification(this->deviceNotifier);
}
I’m guessing that this is not the right place to put the message loop, but I’m not very good with WinAPI. How do I get my program to enter the message loop? (And also preferably register device notifications.)
You should be creating a message only Window. It can receive messages it registers like device notification and power events, but it will never be shown.
Message only window must be registered with RegisterClassEx.
With you window class registered, you then pass your window class name to CreateWindowEx along with HWND_MESSAGE as a parent. Your CreateWindow should use
CreateWindowExinstead to look like this :You will still use GetMessage along with TranslateMessage and DispathMessage which will call your WNDPROC like a callback. Nothing wrong with that, but you loose the pointer to your DeviceHandler class in your windows procedure.
This is why you pass
thisas the last parameter ofCreateWindowEx. You can retreive it when you receive theWM_CREATEmessage and set it to your windows class user data withSetWindowLongPtrandGWLP_USERDATA. Every call after that will retreive the pointer withGetWindowLongPtrand cast it to a DeviceHandler object.Here is a good example of the technique.
To play by the rules, you should register your own window class to use
GWLP_USERDATA, although it should still work using theSTATICwindow class.Final note : be sure to call DefWindowProc for messages you don’t handle.