How do I call RegisterDeviceNotification on Windows

706 views
Skip to first unread message

Robert Mecklenburg

unread,
Jul 21, 2005, 12:17:25 PM7/21/05
to wx-u...@lists.wxwindows.org
I have a simple wxWidgets app that I must modify to receive device change events
on windows. It currently overrides the MSWWindowProc and gets the
DBT_DEVNODES_CHANGED event. Unfortunately, this event doesnot include
sufficient details for my task. The windows docs indicate that more information
can be gathered by registering for the event with RegisterDeviceNotification.
This api requires the handle to the top-level window.

How can I get this handle? It appears that there is a global variable
wxhInstance that may be what I require, but I can't figure out how to get to it.

Suggestions?
Thanks,
Robert


Bob Paddock

unread,
May 5, 2015, 9:09:29 AM5/5/15
to wx-u...@googlegroups.com
[Reviving an old tread.]

On Fri, Jul 22, 2005 at 9:12 AM, Chris Mellon <ark...@gmail.com> wrote:

> wxhInstance is an HINSTANCE, it's not what you want.
> RegisterDeviceNotification just takes a regular window handle,
> although the docs suggest that it must be a top level window (for no
> apparent reason). In your app, this would be the handle of your
> wxFrame. I would try, however, simply using the same window you're
> already processing the device notifications in.

I am trying to detect USB Hardware Insertion and/or Removal via
RegisterDeviceNotification as described here:

http://www.codeproject.com/Articles/14500/Detecting-Hardware-Insertion-and-or-Removal

I am having trouble getting this integrated into wxWidgets.

RegisterDeviceNotification keeps returning the error 'Invalid Data'
which I believe is because I don't have the correct parent window.

I'm using Windows 7, wx 3.02 with MINGW w64; http://nuwen.net/mingw.html

My window hierarchy is :

Dialog -> Notebook -> Notebook Tab (wxPanel).

I'm calling RegisterDeviceNotification setup in the wxPanel
constructor, that looks like the wrong place?
Also found that the constructor is called six times. Why? Not really
important to the problem at hand.

I have tried using the wxPanel's parent as well as
wxTheApp->GetTopWindow() in RegisterDeviceNotification setup, both
giving 'Invalid Data Error'.

My two questions are:

What is the correct parent?

Were should I place the initialization code so that the parent is
valid and hopefully only called once (unlike the constructor) [I know
I can use a flag to only do it once]?

Code, explanation above should be sufficient without having to look at this:

FirstPanel::FirstPanel( wxWindow* parent, wxWindowID id, const
wxPoint& pos, const wxSize& size, long style )
{
...

const GUID GUID_DEVINTERFACE_LIST[] =
{
// GUID_DEVINTERFACE_USB_DEVICE
{ 0xA5DCBF10, 0x6530, 0x11D2, { 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9,
0x51, 0xED } },

// GUID_DEVINTERFACE_DISK
{ 0x53f56307, 0xb6bf, 0x11d0, { 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e,
0xfb, 0x8b } },

// GUID_DEVINTERFACE_HID,
{ 0x4D1E55B2, 0xF16F, 0x11CF, { 0x88, 0xCB, 0x00, 0x11, 0x11, 0x00,
0x00, 0x30 } },

// GUID_NDIS_LAN_CLASS
{ 0xad498944, 0x762f, 0x11d0, { 0x8d, 0xcb, 0x00, 0xc0, 0x4f, 0xc3,
0x35, 0x8c } }

//// GUID_DEVINTERFACE_COMPORT
//{ 0x86e0d1e0, 0x8089, 0x11d0, { 0x9c, 0xe4, 0x08, 0x00, 0x3e, 0x30,
0x1f, 0x73 } },

//// GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR
//{ 0x4D36E978, 0xE325, 0x11CE, { 0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1,
0x03, 0x18 } },

//// GUID_DEVINTERFACE_PARALLEL
//{ 0x97F76EF0, 0xF883, 0x11D0, { 0xAF, 0x1F, 0x00, 0x00, 0xF8, 0x00,
0x84, 0x5C } },

//// GUID_DEVINTERFACE_PARCLASS
//{ 0x811FC6A5, 0xF728, 0x11D0, { 0xA5, 0x37, 0x00, 0x00, 0xF8, 0x75,
0x3E, 0xD1 } }
};

HDEVNOTIFY hDevNotify;
DEV_BROADCAST_DEVICEINTERFACE NotificationFilter;

ZeroMemory( &NotificationFilter, sizeof(NotificationFilter) );
NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;

for( unsigned int i=0; i<sizeof(GUID_DEVINTERFACE_LIST)/sizeof(GUID); i++ )
{
NotificationFilter.dbcc_classguid = GUID_DEVINTERFACE_LIST[i];

hDevNotify = RegisterDeviceNotification( parent,
&NotificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE );
if( !hDevNotify )
{
wxString const com_error(
_com_error(GetLastError()).ErrorMessage() );
wxString const string_wx = wxString::Format( "Can not
register device notification: '%s' times %ul", com_error, ++count_i );
wxMessageBox( string_wx, "Can not detect USB events",
wxICON_WARNING );
}
}

...
}

#ifdef __WXMSW__

void FirstPanel::DeviceUpdate( PDEV_BROADCAST_DEVICEINTERFACE pDevInf,
WPARAM wParam )
{
// pDevInf->dbcc_name:
// \\?\USB#Vid_04e8&Pid_503b#0002F9A9828E0F06#{a5dcbf10-6530-11d2-901f-00c04fb951ed}
// szDevId: USB\Vid_04e8&Pid_503b\0002F9A9828E0F06
// szClass: USB
wxASSERT(lstrlen(pDevInf->dbcc_name) > 4);
wxString szDevId = pDevInf->dbcc_name+4;
int idx = szDevId.Last('#');
wxASSERT( -1 != idx );
szDevId.Truncate(idx);
szDevId.Replace(_T('#'), _T('\\'));
szDevId.MakeUpper();

wxString string_wx;
if ( DBT_DEVICEARRIVAL == wParam ) {
string_wx.Format(_T("Adding %s\r\n"), szDevId );
}
else
{
string_wx.Format(_T("Removing %s\r\n"), szDevId );
}
wxMessageBox( string_wx, "Box" );
}

// Overwrite MSWWindowProc to receive all messages
WXLRESULT FirstPanel::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam,
WXLPARAM lParam)
{
bool processed = false;

if(
(DBT_DEVICEARRIVAL == wParam) ||
(DBT_DEVICEREMOVECOMPLETE == wParam)
)
{
PDEV_BROADCAST_HDR pHdr = (PDEV_BROADCAST_HDR)lParam;

PDEV_BROADCAST_DEVICEINTERFACE pDevInf;
// PDEV_BROADCAST_HANDLE pDevHnd;
// PDEV_BROADCAST_OEM pDevOem;
// PDEV_BROADCAST_PORT pDevPort;
// PDEV_BROADCAST_VOLUME pDevVolume;

switch( pHdr->dbch_devicetype )
{
case DBT_DEVTYP_DEVICEINTERFACE:
pDevInf = (PDEV_BROADCAST_DEVICEINTERFACE)pHdr;
DeviceUpdate(pDevInf, wParam);
processed = true;
break;

case DBT_DEVTYP_HANDLE:
// pDevHnd = (PDEV_BROADCAST_HANDLE)pHdr;
break;

case DBT_DEVTYP_OEM:
// pDevOem = (PDEV_BROADCAST_OEM)pHdr;
break;

case DBT_DEVTYP_PORT:
// pDevPort = (PDEV_BROADCAST_PORT)pHdr;
break;

case DBT_DEVTYP_VOLUME:
// pDevVolume = (PDEV_BROADCAST_VOLUME)pHdr;
break;
}
}

if( true == processed )
{
return( (WXLRESULT) 0 );
}
else
{
return wxPanel::MSWWindowProc(nMsg, wParam, lParam); // If
message was not device insert/remove, call standard handler
}
}

#endif

Dimitri Schoolwerth

unread,
May 5, 2015, 12:30:14 PM5/5/15
to wx-users
On Tue, May 5, 2015 at 5:09 PM, Bob Paddock <wxwi...@gmail.com> wrote:

> RegisterDeviceNotification keeps returning the error 'Invalid Data'
> which I believe is because I don't have the correct parent window.

Perhaps it requires a WIN32 handle instead of a pointer to a wxWindow.
Try using GetHWND() on a wxWindow (probably the top-level one) and
pass that instead.


Regards,
Dimitri

Bob Paddock

unread,
May 5, 2015, 1:44:12 PM5/5/15
to wx-u...@googlegroups.com
That was it, thank you:

hDevNotify = RegisterDeviceNotification( (HWND)
wxWindow::GetHWND(), &NotificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE
);

Works from the wxPanel level.

Remaining question is where is the best place to put this type of code?
Right now it is working from OnIdle( wxIdleEvent& event ), which
really is not the right place for it.



>
>
> Regards,
> Dimitri
>
> --
> Please read http://www.wxwidgets.org/support/mlhowto.htm before posting.
>
> To unsubscribe, send email to wx-users+u...@googlegroups.com
> or visit http://groups.google.com/group/wx-users
Reply all
Reply to author
Forward
0 new messages