 |
|
|
 |
|
|
 |
|
 |
I apologise - I completely missed this post!
Most of the important code in this article is not MFC. Initially, MFC is really just used to give somewhere to report to. I presume your application is already there - you just want to get notifications?
In which case, you just need to add a handler for Window's WM_DEVICECHANGE message in your top window, and look at the OnDeviceChange member function in code, which calls AddDriveToList (which is where the interesting code is).
There's quite a bit added later to do with getting and showing the right image for the drive, and that's a bit MFC-ish, but the WM_DEVICECHANGE stuff is almost pure Win32.
Iain.
I am one of "those foreigners coming over here and stealing our jobs". Yay me!
|
|
|
|
 |
|
 |
MSDN[^]
it's a real shame to copy-paste code publushed 10 years ago...
|
|
|
|
 |
|
 |
I already answered your challenge on the C++ forums. I posted a link to this article, in reply to the question about how to detect drives being added / removed.
That question comes up many times. I've pointed people to my article which provides a framework showing WM_DEVICECHANGE in action. And that's why I posted this article.
As I said then also, I look forward to your article(s).
Iain.
I have now moved to Sweden for love (awwww).
If you're in Scandinavia and want an MVP on the payroll (or happy with a remote worker), or need contract work done, give me a job! http://cv.imcsoft.co.uk/[ ^]
|
|
|
|
 |
|
 |
Hi,Thanks for ur sharing first of all,it's really a cute program.
But I've found a bug here:
I plugged in U Disk A and do some read/write work on it,your program went well. But at the same time(I was operating on U Disk A),I plugged U Disk B,I found nothing in your program.I'll only get DBT_DEVICEREMOVECOMPLETE when I remove U disk B...
In fact,it's just a problem I'm facing using the WM_DEVICECHANGE msg.In this circumstance,I can't get DBT_DEVICEARRIVAL,but only DBT_DEVNODES_CHANGED...
Besides,I'm running your program on Win2000 Pro SP4.
Thansk for your conduction!
|
|
|
|
 |
|
 |
I saw your message while I was on holiday, told myself "I must reply to this when I get home", then forgot.... Grr me.
1/ Are these memory sticks? Are they the same kind of device?
2/ I assume explorer handles the two devices properly? If not, then it may not be my code at fault!
3/ I don't know what your devices are, and I don't have casual access to debug a 2000 machine anymore. If you find any useful changes, I'll be more than happy to update the program.
Thanks,
Iain.
Iain Clarke appearing by Special Request of CPallini.
|
|
|
|
 |
|
 |
Supporting DBT_DEVICEQUERYREMOVE would be a very useful addition to this project.
|
|
|
|
 |
|
 |
I'm curious...
What would DBT_DEVICEQUERYREMOVE solve that DBT_DEVICEREMOVECOMPLETE doesn't do?
If there's a benefit, I'm more than happy add to the software. And I'm even more likely to add any changes you mail me!
Iain.
|
|
|
|
 |
|
 |
Since DBT_DEVICEQUERYREMOVE is sent when the 'safe removal' icon is clicked (before stopping a USB drive), it would allow one to react to a user who is going to unplug a drive. For example if you need to flush a file, (disclaimer: in my case, unload a virtual drive loaded from the USB drive) etc.
Unlike DBT_DEVICEREMOVECOMPLETE, one has to register to receive DBT_DEVICEQUERYREMOVE notifications. Here is how I am registering for the root of a drive, though I think one could pass any file handle on the drive.
BOOL CHelperFucntions::DoRegisterDeviceInterface(HWND hWnd, HANDLE hFile, bool bRegister)
{
DEV_BROADCAST_HANDLE NotificationFilter;
if(bRegister)
{
char szMsg[80];
ZeroMemory(&NotificationFilter, sizeof(NotificationFilter));
NotificationFilter.dbch_devicetype = DBT_DEVTYP_HANDLE;
NotificationFilter.dbch_reserved = 0;
NotificationFilter.dbch_nameoffset = 0;
NotificationFilter.dbch_handle = hFile;
HDEVNOTIFY hDevNotify = NULL; NotificationFilter.dbch_hdevnotify = hDevNotify;
NotificationFilter.dbch_size = sizeof(DEV_BROADCAST_HANDLE);
hDevNotify = RegisterDeviceNotification(hWnd, &NotificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE);
if(!hDevNotify)
{
wsprintf(szMsg, "Could not register to receive notifications about drive events: %d\n",
GetLastError());
MessageBox(hWnd, szMsg, "RegisterDeviceNotification failed", MB_OK);
return FALSE;
}
return TRUE;
}
}
Once registered, I am handling it just like any other in ::OnDeviceChange.
if (wParam == DBT_DEVICEQUERYREMOVE)
{
PDEV_BROADCAST_HDR pHdr = (PDEV_BROADCAST_HDR)lParam;
switch( pHdr->dbch_devicetype )
{
case DBT_DEVTYP_VOLUME:
{
PDEV_BROADCAST_VOLUME pDevVolume;
ZeroMemory(&pDevVolume, sizeof(pDevVolume));
pDevVolume = (PDEV_BROADCAST_VOLUME)pHdr;
CString csMP = "";
csMP = cHF.FirstDriveFromMask(pDevVolume->dbcv_unitmask);
csMP = csMP + ":\\";
// This is a drive we are interested in
// because we have registered to receive notifications
// for this drive.
int iRet=0;
iRet = MessageBox("The user wants to remove the " + csMP +" drive. Allow?", "Device Removal Permission", MB_YESNO + MB_ICONEXCLAMATION);
if(iRet == IDYES || iRet == IDOK)
{
//Figure why we are interested in this drive
//Do whatever is necessary to clean up our act
//If we could not find any reason why, just return true.
lpReturn = TRUE;
}
else
{
lpReturn = BROADCAST_QUERY_DENY;//if not ready to unload USB
}
break;
}
}
}
The FirstDriveFromMask( function is something I picked off MSDN
char CHelperFucntions::FirstDriveFromMask(ULONG unitmask)
{
char i;
for (i = 0; i < 26; ++i)
{
if (unitmask & 0x1)
break;
unitmask = unitmask >> 1;
}
return (i + 'A');
}
Please note this is a work in progress for me, I have been unable to get the correct drive letter out of the drive mask yet on the DBT_DEVICEQUERYREMOVE notification, though the fact that I receive the notification while removing the correct drive I have registered for tells me that the registration is correct and hence the drive mask should be correct.
As a programmer new to VC++ (just been coding for a couple month or so, and only a week of the MS IDE) I feel these things could do with better documentation in MSDN or elsewhere. Thanks for your efforts in that direction!
--
Omne Ignotum Pro Magnifico
|
|
|
|
 |
|
 |
My bad - Registering for notification (DBT_DEVICEQUERYREMOVE or any other) will only return a DBT_DEVTYP_HANDLE or DBT_DEVTYP_DEVICEINTERFACE, and NOT a DBT_DEVTYP_VOLUME as shown in my handler. That's why I was not able to get the drive letter out of the 'mask'.
--
Omne Ignotum Pro Magnifico
|
|
|
|
 |
|
 |
i got problem while Registering for Device Notification.
getting compilation Errors as DBT_DEVTYP_DEVICEINTERFACE' : undeclared identifier.
i am using VC++ 6.0 and Windows XP.
please let me know the changes need to made to getrid off these.
Thanks in Advance.
|
|
|
|
 |
|
 |
Tried with DEV_BROADCAST_HANDLE getting same compilation Errors.
|
|
|
|
 |
|
 |
Erm, I don't use either of the constansts / structures you mention in my project.
Can you be more specific about the error? Is it one of the header files that is complaining?
I did a search, and found DEV_BROADCAST_HANDLE in a header file in the Platform SDK, rather than the header files that come with Visual C++ 6, so that may be the answer for you.
Iain.
|
|
|
|
 |
|
 |
OK, I should have waited a bit longer before answering.
I've just found DEV_BROADCAST_HANDLE in DBT.h in the Visual C directory, but it was dependent on WINVER being greater than 0x040a. I don't explicitly set WINVER myself though, so I'm not sure where it gets it's value from.
Iain.
|
|
|
|
 |
|
 |
Iain,
finally i got it by redefining WINVER as 0x0500 in stdafx.h
-Vijay
|
|
|
|
 |
|
 |
//This can be a file handle to the root of USB drive!
NotificationFilter.dbch_handle = hFile;
Do you know what handles are working (best with full CreateFile parameters etc).
I tried few but RegisterDeviceNotification always fails.
|
|
|
|
 |
|
 |
Can you suggest some WM_DEVICECHANGE analog in Linux, or some implementation for Java? Thanks.
|
|
|
|
 |
|
 |
Sorry, I have NO idea how this sort of mechanism works in Linux. It might not even fit in with their ethos. After all, people just access /devices/whatever, so its probably less of an issue.
As for Java - just handle the windows message like anyone else will. If that's really hard, then its a blessing / curse of the device independentness of Java.
Iain.
|
|
|
|
 |
|
 |
I'm trying to compile your code and it is saying the file include C:\Source\Libraries\ImageViewer.h is missing.
Xavier Rosell
|
|
|
|
 |
|
 |
Argh - you're quite correct. I'll upload a fixed copy. In the mean time, just remove the reference to that header - it was for viewing image lists while I was experimenting.
Then you'll get the odd ShowImageList / ShowIcon error too - just remove thos lines as well.
Sorry about that!
Iain.
|
|
|
|
 |
|
 |
Article Updated - the references to ImageViewer are now gone.
Thanks again for the update,
Iain.
|
|
|
|
 |
|
 |
Hi
Nice code
How 2 detect if device(like usb mouse/keyboard or barcode scanner) inserted?
Can u help?
thanx
Have a nice code day
|
|
|
|
 |
|
 |
A quick play with plugging my USB mouse shows I get
WM_DEVICECHANGE, with WPARAM=DBT_DEVNODES_CHANGED.
Looking this up on MSDN, (and checking myself) LPARAM always equals 0, so no help there.
But if you go look for the original question / answer by Matthew Faithful (see Background in article), that may give you more ideas.
Failing that, you may need to think about your core problem. Why does your software care how many mice the uses uses? etc?
Iain.
|
|
|
|
 |
|
 |
thanx 4 reply
I got same results when usb mouse plugged.
The main issue that i interested for is the BARCODE SCANNER not mouse/keyboard...etc
Okay, i'll get the DBT_DEVNODES_CHANGED notification message,but there is more data must arrives to detects the port that the device connected to and the device informations...etc
Realy, I need to learn how can i managing(Read from) the BARCODE SCANNER set .
Thanx
|
|
|
|
 |