TO jennyvenus : 我的硬件在PC中有二种模式,一种显示三个设备,一种显示二个设备,我想判断期中某种设备是否存在。我知道设备的名字,有没办法查询到? 二种模式都有WM_DEVICECHANGE消息的,所以这个消息帮不上忙。TO cnzdgs: 用Createfile打开设备能详细讲一下吗? 文件名怎么设?我试了一下没成功。我只知道从“设备管理器”可以看到的名字。
抄点现成的,不知道管不管用.h// DeviceEnumeratorDlg.h : header file //#if !defined(AFX_DEVICEENUMERATORDLG_H__6A28E8D3_F1D4_44F2_9040_103D484ABD57__INCLUDED_) #define AFX_DEVICEENUMERATORDLG_H__6A28E8D3_F1D4_44F2_9040_103D484ABD57__INCLUDED_#if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000#include <winioctl.h>///////////////////////////////////////////////////////////////////////////// // CDeviceEnumeratorDlg dialogclass CDeviceEnumeratorDlg : public CDialog { // Construction public: CDeviceEnumeratorDlg(CWnd* pParent = NULL); // standard constructor// Dialog Data //{{AFX_DATA(CDeviceEnumeratorDlg) enum { IDD = IDD_DEVICEENUMERATOR_DIALOG }; // NOTE: the ClassWizard will add data members here //}}AFX_DATA // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CDeviceEnumeratorDlg) protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support //}}AFX_VIRTUAL// Implementation protected: HICON m_hIcon; // Generated message map functions //{{AFX_MSG(CDeviceEnumeratorDlg) virtual BOOL OnInitDialog(); afx_msg void OnSysCommand(UINT nID, LPARAM lParam); afx_msg void OnPaint(); afx_msg HCURSOR OnQueryDragIcon(); virtual void OnOK(); //}}AFX_MSG DECLARE_MESSAGE_MAP()private: BOOL GetDriveGeometry(const char* filename, DISK_GEOMETRY *pdg); };//{{AFX_INSERT_LOCATION}} // Microsoft Visual C++ will insert additional declarations immediately before the previous line.#endif // !defined(AFX_DEVICEENUMERATORDLG_H__6A28E8D3_F1D4_44F2_9040_103D484ABD57__INCLUDED_)
.cpp// DeviceEnumeratorDlg.cpp : implementation file //#include "stdafx.h" #include "DeviceEnumerator.h" #include "DeviceEnumeratorDlg.h"#ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif #define MEDIA_INFO_SIZE sizeof(GET_MEDIA_TYPES)+15*sizeof(DEVICE_MEDIA_INFO)///////////////////////////////////////////////////////////////////////////// // CAboutDlg dialog used for App About///////////////////////////////////////////////////////////////////////////// // CDeviceEnumeratorDlg dialogCDeviceEnumeratorDlg::CDeviceEnumeratorDlg(CWnd* pParent /*=NULL*/) : CDialog(CDeviceEnumeratorDlg::IDD, pParent) { //{{AFX_DATA_INIT(CDeviceEnumeratorDlg) // NOTE: the ClassWizard will add member initialization here //}}AFX_DATA_INIT // Note that LoadIcon does not require a subsequent DestroyIcon in Win32 m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); }void CDeviceEnumeratorDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CDeviceEnumeratorDlg) // NOTE: the ClassWizard will add DDX and DDV calls here //}}AFX_DATA_MAP }BEGIN_MESSAGE_MAP(CDeviceEnumeratorDlg, CDialog) //{{AFX_MSG_MAP(CDeviceEnumeratorDlg) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() //}}AFX_MSG_MAP END_MESSAGE_MAP()///////////////////////////////////////////////////////////////////////////// // CDeviceEnumeratorDlg message handlersBOOL CDeviceEnumeratorDlg::OnInitDialog() { CDialog::OnInitDialog(); // Set the icon for this dialog. The framework does this automatically // when the application's main window is not a dialog SetIcon(m_hIcon, TRUE); // Set big icon SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
return TRUE; // return TRUE unless you set the focus to a control }void CDeviceEnumeratorDlg::OnSysCommand(UINT nID, LPARAM lParam) { CDialog::OnSysCommand(nID, lParam); }// If you add a minimize button to your dialog, you will need the code below // to draw the icon. For MFC applications using the document/view model, // this is automatically done for you by the framework.void CDeviceEnumeratorDlg::OnPaint() { if (IsIconic()) { CPaintDC dc(this); // device context for painting SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0); // Center icon in client rectangle int cxIcon = GetSystemMetrics(SM_CXICON); int cyIcon = GetSystemMetrics(SM_CYICON); CRect rect; GetClientRect(&rect); int x = (rect.Width() - cxIcon + 1) / 2; int y = (rect.Height() - cyIcon + 1) / 2; // Draw the icon dc.DrawIcon(x, y, m_hIcon); } else { CDialog::OnPaint(); } }// The system calls this to obtain the cursor to display while the user drags // the minimized window. HCURSOR CDeviceEnumeratorDlg::OnQueryDragIcon() { return (HCURSOR) m_hIcon; }void CDeviceEnumeratorDlg::OnOK() { const char *szDevName[]= { "\\\\.\\A:", "\\\\.\\B:", "\\\\.\\PhysicalDrive0", "\\\\.\\PhysicalDrive1", "\\\\.\\PhysicalDrive2", "\\\\.\\PhysicalDrive3", "\\\\.\\PhysicalDrive4", "\\\\.\\PhysicalDrive5", "\\\\.\\PhysicalDrive6", "\\\\.\\Cdrom0", "\\\\.\\Cdrom1", }; DISK_GEOMETRY dg; ULONGLONG DiskSize; BOOL bResult; CString strMsg; CString strTmp;
for (int i = 0; i < sizeof(szDevName)/sizeof(char*); i++) { bResult = GetDriveGeometry(szDevName[i], &dg);
2、WM_DEVICECHANGE消息。
TO jennyvenus : 我的硬件在PC中有二种模式,一种显示三个设备,一种显示二个设备,我想判断期中某种设备是否存在。我知道设备的名字,有没办法查询到? 二种模式都有WM_DEVICECHANGE消息的,所以这个消息帮不上忙。TO cnzdgs: 用Createfile打开设备能详细讲一下吗? 文件名怎么设?我试了一下没成功。我只知道从“设备管理器”可以看到的名字。
//#if !defined(AFX_DEVICEENUMERATORDLG_H__6A28E8D3_F1D4_44F2_9040_103D484ABD57__INCLUDED_)
#define AFX_DEVICEENUMERATORDLG_H__6A28E8D3_F1D4_44F2_9040_103D484ABD57__INCLUDED_#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000#include <winioctl.h>/////////////////////////////////////////////////////////////////////////////
// CDeviceEnumeratorDlg dialogclass CDeviceEnumeratorDlg : public CDialog
{
// Construction
public:
CDeviceEnumeratorDlg(CWnd* pParent = NULL); // standard constructor// Dialog Data
//{{AFX_DATA(CDeviceEnumeratorDlg)
enum { IDD = IDD_DEVICEENUMERATOR_DIALOG };
// NOTE: the ClassWizard will add data members here
//}}AFX_DATA // ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CDeviceEnumeratorDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL// Implementation
protected:
HICON m_hIcon; // Generated message map functions
//{{AFX_MSG(CDeviceEnumeratorDlg)
virtual BOOL OnInitDialog();
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
virtual void OnOK();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()private:
BOOL GetDriveGeometry(const char* filename, DISK_GEOMETRY *pdg);
};//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.#endif // !defined(AFX_DEVICEENUMERATORDLG_H__6A28E8D3_F1D4_44F2_9040_103D484ABD57__INCLUDED_)
//#include "stdafx.h"
#include "DeviceEnumerator.h"
#include "DeviceEnumeratorDlg.h"#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define MEDIA_INFO_SIZE sizeof(GET_MEDIA_TYPES)+15*sizeof(DEVICE_MEDIA_INFO)/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About/////////////////////////////////////////////////////////////////////////////
// CDeviceEnumeratorDlg dialogCDeviceEnumeratorDlg::CDeviceEnumeratorDlg(CWnd* pParent /*=NULL*/)
: CDialog(CDeviceEnumeratorDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CDeviceEnumeratorDlg)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}void CDeviceEnumeratorDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CDeviceEnumeratorDlg)
// NOTE: the ClassWizard will add DDX and DDV calls here
//}}AFX_DATA_MAP
}BEGIN_MESSAGE_MAP(CDeviceEnumeratorDlg, CDialog)
//{{AFX_MSG_MAP(CDeviceEnumeratorDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()/////////////////////////////////////////////////////////////////////////////
// CDeviceEnumeratorDlg message handlersBOOL CDeviceEnumeratorDlg::OnInitDialog()
{
CDialog::OnInitDialog(); // Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
return TRUE; // return TRUE unless you set the focus to a control
}void CDeviceEnumeratorDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
CDialog::OnSysCommand(nID, lParam);
}// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.void CDeviceEnumeratorDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0); // Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2; // Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}// The system calls this to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CDeviceEnumeratorDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}void CDeviceEnumeratorDlg::OnOK()
{
const char *szDevName[]=
{
"\\\\.\\A:",
"\\\\.\\B:",
"\\\\.\\PhysicalDrive0",
"\\\\.\\PhysicalDrive1",
"\\\\.\\PhysicalDrive2",
"\\\\.\\PhysicalDrive3",
"\\\\.\\PhysicalDrive4",
"\\\\.\\PhysicalDrive5",
"\\\\.\\PhysicalDrive6",
"\\\\.\\Cdrom0",
"\\\\.\\Cdrom1",
}; DISK_GEOMETRY dg;
ULONGLONG DiskSize;
BOOL bResult;
CString strMsg;
CString strTmp;
for (int i = 0; i < sizeof(szDevName)/sizeof(char*); i++)
{
bResult = GetDriveGeometry(szDevName[i], &dg);
strTmp.Format("\r\n%s result = %s\r\n", szDevName[i], bResult ? "success" : "failure");
strMsg+=strTmp;
if (!bResult) continue;
strTmp.Format(" Media Type = %d\r\n", dg.MediaType);
strMsg+=strTmp;
strTmp.Format(" Cylinders = %I64d\r\n", dg.Cylinders);
strMsg+=strTmp;
strTmp.Format(" Tracks per cylinder = %ld\r\n", (ULONG) dg.TracksPerCylinder);
strMsg+=strTmp;
strTmp.Format(" Sectors per track = %ld\r\n", (ULONG) dg.SectorsPerTrack);
strMsg+=strTmp;
strTmp.Format(" Bytes per sector = %ld\r\n", (ULONG) dg.BytesPerSector);
strMsg+=strTmp;
DiskSize = dg.Cylinders.QuadPart * (ULONG)dg.TracksPerCylinder *
(ULONG)dg.SectorsPerTrack * (ULONG)dg.BytesPerSector;
strTmp.Format(" Disk size = %I64d (Bytes) = %I64d (Mb)\r\n", DiskSize, DiskSize / (1024 * 1024));
strMsg+=strTmp;
}
AfxMessageBox(strMsg);
}BOOL CDeviceEnumeratorDlg::GetDriveGeometry(const char* filename, DISK_GEOMETRY *pdg)
{
HANDLE hDevice; // 设备句柄
BOOL bResult; // DeviceIoControl的返回结果
GET_MEDIA_TYPES *pmt; // 内部用的输出缓冲区
DWORD dwOutBytes; // 输出数据长度
// 打开设备
hDevice = ::CreateFile(filename, // 文件名
GENERIC_READ, // 软驱需要读盘
FILE_SHARE_READ | FILE_SHARE_WRITE, // 共享方式
NULL, // 默认的安全描述符
OPEN_EXISTING, // 创建方式
0, // 不需设置文件属性
NULL); // 不需参照模板文件
if (hDevice == INVALID_HANDLE_VALUE)
{
// 设备无法打开...
return FALSE;
}
// 用IOCTL_DISK_GET_DRIVE_GEOMETRY取磁盘参数
bResult = ::DeviceIoControl(hDevice, // 设备句柄
IOCTL_DISK_GET_DRIVE_GEOMETRY, // 取磁盘参数
NULL, 0, // 不需要输入数据
pdg, sizeof(DISK_GEOMETRY), // 输出数据缓冲区
&dwOutBytes, // 输出数据长度
(LPOVERLAPPED)NULL); // 用同步I/O
// 如果失败,再用IOCTL_STORAGE_GET_MEDIA_TYPES_EX取介质类型参数
if (!bResult)
{
pmt = (GET_MEDIA_TYPES *)new BYTE[MEDIA_INFO_SIZE];
bResult = ::DeviceIoControl(hDevice, // 设备句柄
IOCTL_STORAGE_GET_MEDIA_TYPES_EX, // 取介质类型参数
NULL, 0, // 不需要输入数据
pmt, MEDIA_INFO_SIZE, // 输出数据缓冲区
&dwOutBytes, // 输出数据长度
(LPOVERLAPPED)NULL); // 用同步I/O
if (bResult)
{
// 注意到结构DEVICE_MEDIA_INFO是在结构DISK_GEOMETRY的基础上扩充的
// 为简化程序,用memcpy代替如下多条赋值语句:
// pdg->MediaType = (MEDIA_TYPE)pmt->MediaInfo[0].DeviceSpecific.DiskInfo.MediaType;
// pdg->Cylinders = pmt->MediaInfo[0].DeviceSpecific.DiskInfo.Cylinders;
// pdg->TracksPerCylinder = pmt->MediaInfo[0].DeviceSpecific.DiskInfo.TracksPerCylinder;
// ... ...
::memcpy(pdg, pmt->MediaInfo, sizeof(DISK_GEOMETRY));
}
delete pmt;
}
// 关闭设备句柄
::CloseHandle(hDevice);
return (bResult);
}