Click here to Skip to main content
15,895,011 members
Articles / Desktop Programming / MFC

XDriveBar - Display drive buttons in a fixed toolbar

Rate me:
Please Sign up or sign in to vote.
4.70/5 (17 votes)
11 Aug 2003CPOL3 min read 111.2K   2K   58  
XDriveBar implements a drive bar for the drives in a system. The demo project shows how to keep the drive bar in sync by handling the WM_DEVICECHANGE message.
// XDriveBarTestDlg.cpp : implementation file
//

#include "stdafx.h"
#include "XDriveBarTest.h"
#include "XDriveBarTestDlg.h"
#include "about.h"
#include "dbt.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

///////////////////////////////////////////////////////////////////////////////
// CXDriveBarTestDlg dialog

BEGIN_MESSAGE_MAP(CXDriveBarTestDlg, CDialog)
	//{{AFX_MSG_MAP(CXDriveBarTestDlg)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_WM_SIZE()
	ON_WM_TIMER()
	//}}AFX_MSG_MAP
	ON_WM_DEVICECHANGE()
	ON_REGISTERED_MESSAGE(WM_DRIVE_SELECTED, OnDriveSelected)
END_MESSAGE_MAP()

///////////////////////////////////////////////////////////////////////////////
// ctor
CXDriveBarTestDlg::CXDriveBarTestDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CXDriveBarTestDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CXDriveBarTestDlg)
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
	m_pDriveBarH = NULL;
	m_pDriveBarV = NULL;
}

///////////////////////////////////////////////////////////////////////////////
// dtor
CXDriveBarTestDlg::~CXDriveBarTestDlg()
{
	if (m_pDriveBarV)
		delete m_pDriveBarV;
	m_pDriveBarV = NULL;
	if (m_pDriveBarH)
		delete m_pDriveBarH;
	m_pDriveBarH = NULL;

	m_Font.DeleteObject();
}

///////////////////////////////////////////////////////////////////////////////
// DoDataExchange
void CXDriveBarTestDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CXDriveBarTestDlg)
	//}}AFX_DATA_MAP
}

///////////////////////////////////////////////////////////////////////////////
// OnInitDialog
BOOL CXDriveBarTestDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Add "About..." menu item to system menu.

	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// 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
	
	// ----------  Set up drive bars  ----------

	LOGFONT lf;
	CFont *pFont = GetFont();
	pFont->GetLogFont(&lf);

	// one size smaller
	if (lf.lfHeight < 0)
		lf.lfHeight += 1;
	else
		lf.lfHeight -= 1;

	_tcscpy(lf.lfFaceName, _T("Arial"));
	m_Font.CreateFontIndirect(&lf);

	CreateDriveBars();

	// force WM_SIZE
	CRect rectDialog;
	GetWindowRect(&rectDialog);
	SetWindowPos(NULL, 0, 0, rectDialog.Width()+1, rectDialog.Height(), 
		SWP_NOMOVE | SWP_NOZORDER);

	return TRUE;  // return TRUE  unless you set the focus to a control
}

///////////////////////////////////////////////////////////////////////////////
// CreateDriveBars
void CXDriveBarTestDlg::CreateDriveBars()
{
	// ----------  vertical  ----------
	CRect rect;
	GetDlgItem(IDC_TOOLBAR_RECT)->GetWindowRect(&rect);
	ScreenToClient(&rect);
	rect.InflateRect(-2, -2);

	if (m_pDriveBarV)
		delete m_pDriveBarV;

	m_pDriveBarV = new CXDriveBar;

	m_pDriveBarV->Create(AfxRegisterWndClass(CS_PARENTDC), 
						 _T("XDriveBar"),
						 WS_VISIBLE|WS_CHILD,
						 rect,
						 this,
						 IDC_TOOLBAR);

	m_pDriveBarV->SetFont(&m_Font);
	m_pDriveBarV->SetThemeHelper(&m_ThemeHelper);
	m_pDriveBarV->CreateDriveButtons();

	// ----------  horizontal  ----------
	GetDlgItem(IDC_TOOLBAR_RECT2)->GetWindowRect(&rect);
	ScreenToClient(&rect);
	rect.InflateRect(-2, -2);

	if (m_pDriveBarH)
		delete m_pDriveBarH;

	m_pDriveBarH = new CXDriveBar;

	m_pDriveBarH->Create(AfxRegisterWndClass(CS_PARENTDC), 
						 _T("XDriveBar"),
						 WS_VISIBLE|WS_CHILD,
						 rect,
						 this,
						 IDC_TOOLBAR2);

	m_pDriveBarH->SetFont(&m_Font);
	m_pDriveBarH->SetThemeHelper(&m_ThemeHelper);
	m_pDriveBarH->CreateDriveButtons();
}

///////////////////////////////////////////////////////////////////////////////
// OnSysCommand
void CXDriveBarTestDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}

///////////////////////////////////////////////////////////////////////////////
// OnPaint
void CXDriveBarTestDlg::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();
	}
}

///////////////////////////////////////////////////////////////////////////////
// OnQueryDragIcon
HCURSOR CXDriveBarTestDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}

///////////////////////////////////////////////////////////////////////////////
// OnDriveSelected
LRESULT CXDriveBarTestDlg::OnDriveSelected(WPARAM wParam, LPARAM)
{
	CString strDrive = (LPCTSTR) wParam;

	strDrive += _T(":\\");

	CString strMsg;
	strMsg.Format(_T("%s  button clicked\r\n\r\n")
				  _T("Use right-click menu for shell operations."), strDrive);
	AfxMessageBox(strMsg, MB_OK | MB_ICONINFORMATION);

	return 0;
}

///////////////////////////////////////////////////////////////////////////////
// OnSize
void CXDriveBarTestDlg::OnSize(UINT nType, int cx, int cy) 
{
	CDialog::OnSize(nType, cx, cy);
	
	if (!m_pDriveBarV || !::IsWindow(m_pDriveBarV->m_hWnd))
		return;

	CRect rectDialog;
	GetClientRect(&rectDialog);

	// vertical
	CRect rectToolBarV;
	m_pDriveBarV->GetWindowRect(&rectToolBarV);
	ScreenToClient(&rectToolBarV);
	rectToolBarV.bottom = rectDialog.bottom - 10;
	m_pDriveBarV->MoveWindow(&rectToolBarV);

	CRect rectFrameV = rectToolBarV;
	rectFrameV.InflateRect(2, 2);
	GetDlgItem(IDC_TOOLBAR_RECT)->MoveWindow(&rectFrameV);
	GetDlgItem(IDC_TOOLBAR_RECT)->RedrawWindow();

	// horizontal
	CRect rectToolBarH;
	m_pDriveBarH->GetWindowRect(&rectToolBarH);
	ScreenToClient(&rectToolBarH);
	rectToolBarH.right = rectDialog.right - 10;
	m_pDriveBarH->MoveWindow(&rectToolBarH);

	CRect rectFrameH = rectToolBarH;
	rectFrameH.InflateRect(2, 2);
	GetDlgItem(IDC_TOOLBAR_RECT2)->MoveWindow(&rectFrameH);
	GetDlgItem(IDC_TOOLBAR_RECT2)->RedrawWindow();
}

///////////////////////////////////////////////////////////////////////////////
// OnDeviceChange
BOOL CXDriveBarTestDlg::OnDeviceChange(UINT nEventType, DWORD /*dwData*/)
{
	// you don't really need this switch statement unless you're curious

#ifdef _DEBUG
	switch (nEventType)
	{
		case DBT_APPYBEGIN:
			TRACE(_T("DBT_APPYBEGIN\n"));
			break;
		case DBT_APPYEND:
			TRACE(_T("DBT_APPYEND\n"));
			break;
		case DBT_DEVNODES_CHANGED:
			TRACE(_T("DBT_DEVNODES_CHANGED\n"));
			break;
		case DBT_QUERYCHANGECONFIG:
			TRACE(_T("DBT_QUERYCHANGECONFIG\n"));
			break;
		case DBT_CONFIGCHANGED:
			TRACE(_T("DBT_CONFIGCHANGED\n"));
			break;
		case DBT_CONFIGCHANGECANCELED:
			TRACE(_T("DBT_CONFIGCHANGECANCELED\n"));
			break;
		case DBT_MONITORCHANGE:
			TRACE(_T("DBT_MONITORCHANGE\n"));
			break;
		case DBT_SHELLLOGGEDON:
			TRACE(_T("DBT_SHELLLOGGEDON\n"));
			break;
		case DBT_CONFIGMGAPI32:
			TRACE(_T("DBT_CONFIGMGAPI32\n"));
			break;
		case DBT_VXDINITCOMPLETE:
			TRACE(_T("DBT_VXDINITCOMPLETE\n"));
			break;
		case DBT_VOLLOCKQUERYLOCK:
			TRACE(_T("DBT_VOLLOCKQUERYLOCK\n"));
			break;
		case DBT_VOLLOCKLOCKTAKEN:
			TRACE(_T("DBT_VOLLOCKLOCKTAKEN\n"));
			break;
		case DBT_VOLLOCKLOCKFAILED:
			TRACE(_T("DBT_VOLLOCKLOCKFAILED\n"));
			break;
		case DBT_VOLLOCKQUERYUNLOCK:
			TRACE(_T("DBT_VOLLOCKQUERYUNLOCK\n"));
			break;
		case DBT_VOLLOCKLOCKRELEASED:
			TRACE(_T("DBT_VOLLOCKLOCKRELEASED\n"));
			break;
		case DBT_VOLLOCKUNLOCKFAILED:
			TRACE(_T("DBT_VOLLOCKUNLOCKFAILED\n"));
			break;
		case DBT_NO_DISK_SPACE:
			TRACE(_T("DBT_NO_DISK_SPACE\n"));
			break;
		case DBT_LOW_DISK_SPACE:
			TRACE(_T("DBT_LOW_DISK_SPACE\n"));
			break;
		case DBT_CONFIGMGPRIVATE:
			TRACE(_T("DBT_CONFIGMGPRIVATE\n"));
			break;
		case DBT_DEVICEARRIVAL:
			TRACE(_T("DBT_DEVICEARRIVAL\n"));
			break;
		case DBT_DEVICEQUERYREMOVE:
			TRACE(_T("DBT_DEVICEQUERYREMOVE\n"));
			break;
		case DBT_DEVICEQUERYREMOVEFAILED:
			TRACE(_T("DBT_DEVICEQUERYREMOVEFAILED\n"));
			break;
		case DBT_DEVICEREMOVEPENDING:
			TRACE(_T("DBT_DEVICEREMOVEPENDING\n"));
			break;
		case DBT_DEVICEREMOVECOMPLETE:
			TRACE(_T("DBT_DEVICEREMOVECOMPLETE\n"));
			break;
		case DBT_DEVICETYPESPECIFIC:
			TRACE(_T("DBT_DEVICETYPESPECIFIC\n"));
			break;
		case DBT_VPOWERDAPI:
			TRACE(_T("DBT_VPOWERDAPI\n"));
			break;
		case DBT_USERDEFINED:
			TRACE(_T("DBT_USERDEFINED\n"));
			break;
		default:
			TRACE(_T("UNRECOGNIZED =====\n"));
			break;
	}

#else

	UNUSED_ALWAYS(nEventType);

#endif // _DEBUG

	// We will get many WM_DEVICECHANGE messages, only process one.
	// Note: SetTimer resets an existing timer  After 1.5 seconds,
	// there should be no more WM_DEVICECHANGE messages.
	SetTimer(1, 1500, NULL);

	return TRUE;		// must return TRUE
}

///////////////////////////////////////////////////////////////////////////////
// OnTimer
void CXDriveBarTestDlg::OnTimer(UINT nIDEvent) 
{
	KillTimer(nIDEvent);
	CreateDriveBars();
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) Hans Dietrich Software
United States United States
I attended St. Michael's College of the University of Toronto, with the intention of becoming a priest. A friend in the University's Computer Science Department got me interested in programming, and I have been hooked ever since.

Recently, I have moved to Los Angeles where I am doing consulting and development work.

For consulting and custom software development, please see www.hdsoft.org.






Comments and Discussions