Reputation: 11467
I am trying to detect when a USB drive is inserted. Right now, I'm creating a dummy window and RegisterDeviceNotification
ing 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.)
Upvotes: 2
Views: 1364
Reputation: 10171
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 CreateWindowEx
instead to look like this :
HWND hWnd = CreateWindowEx(0, myClassName, _T("This is not the class name"),
0, 0, 0, 0, 0, HWND_MESSAGE, 0, 0, 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 this
as the last parameter of CreateWindowEx
. You can retreive it when you receive the WM_CREATE
message and set it to your windows class user data with SetWindowLongPtr
and GWLP_USERDATA
. Every call after that will retreive the pointer with GetWindowLongPtr
and 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 the STATIC
window class.
Final note : be sure to call DefWindowProc for messages you don't handle.
Upvotes: 2
Reputation: 9089
Looks like the problem is that your window is not created because you didn't specified valid class name. HWND
returned in this case is NULL
and device fails to register it and send messages to it.
As proposed in other answer you could use Message-Only Window for purpose to receive device notifications. But would like to mention that registering window class is not necessary in this case, you could use predefined class name, e.g. STATIC
(as you don't need actually to specify your own window proc):
HWND hwnd = CreateWindowEx(0, "STATIC", 0, 0, 0, 0, 0, 0, HWND_MESSAGE, 0, 0, 0);
Upvotes: 1