456 lines
12 KiB
C++
456 lines
12 KiB
C++
// **************************************************************************
|
|
|
|
// Copyright (c) 1997-2001 Microsoft Corporation, All Rights Reserved
|
|
//
|
|
// File: DiskView.cpp
|
|
//
|
|
// Description:
|
|
// This file implements the CDiskView class. This class gets several properties
|
|
// from a Win32_LogicalDisk instance and displays them.
|
|
//
|
|
// A barchart of the free and used disk space is shown on the left and an
|
|
// edit box on the right displays several other properties such as the object
|
|
// path, filesystem type, etc.
|
|
//
|
|
//
|
|
// History:
|
|
//
|
|
// **************************************************************************
|
|
|
|
|
|
#include "stdafx.h"
|
|
#include <wbemidl.h>
|
|
#include "diskview.h"
|
|
#include "barchart.h"
|
|
#include "coloredit.h"
|
|
|
|
|
|
|
|
// Colors for various things in the display.
|
|
#define COLOR_SPACE_USED RGB(255, 0, 0) // Used disk space.
|
|
#define COLOR_SPACE_AVAILABLE RGB(64, 255, 0) // Available disk space
|
|
#define COLOR_BG RGB(0, 96, 129) // Background color
|
|
#define COLOR_TEXT RGB(255, 128, 128)
|
|
#define COLOR_TEXT_BOX RGB(255, 255, 128)
|
|
#define COLOR_BLACK RGB(0, 0, 0)
|
|
#define COLOR_WHITE RGB(255, 255, 255)
|
|
#define COLOR_WARNING_TEXT RGB(96, 96, 255)
|
|
|
|
// Definitions for laying out the view.
|
|
#define CX_BAR 32
|
|
#define CX_BAR_SPACING 50
|
|
#define CX_LEFT_MARGIN 50
|
|
#define CX_RIGHT_MARGIN 50
|
|
#define CY_TOP_MARGIN 50
|
|
#define CY_BOTTOM_MARGIN 50
|
|
#define CY_LEADING 5
|
|
#define CX_CHART_MARGIN 16
|
|
#define CY_CHART_MARGIN 16
|
|
|
|
CDiskView::CDiskView()
|
|
{
|
|
m_pedit = new CColorEdit;
|
|
m_pedit->SetColor(COLOR_BG, COLOR_TEXT);
|
|
m_pchart = new CBarChart;
|
|
m_pchart->SetBarCount(1);
|
|
m_pchart->SetBgColor(COLOR_BG);
|
|
m_pchart->SetBarColor(0, COLOR_SPACE_USED, COLOR_SPACE_AVAILABLE);
|
|
m_pchart->SetLabelColor(0, COLOR_WHITE, COLOR_BG);
|
|
m_bEditNeedsRefresh = FALSE;
|
|
m_bNeedsInitialLayout = TRUE;
|
|
}
|
|
|
|
CDiskView::~CDiskView()
|
|
{
|
|
delete m_pedit;
|
|
delete m_pchart;
|
|
}
|
|
|
|
|
|
BEGIN_MESSAGE_MAP(CDiskView, CWnd)
|
|
//{{AFX_MSG_MAP(CDiskView)
|
|
ON_WM_SIZE()
|
|
ON_WM_PAINT()
|
|
//}}AFX_MSG_MAP
|
|
END_MESSAGE_MAP()
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CDiskView message handlers
|
|
|
|
|
|
|
|
|
|
|
|
BOOL CDiskView::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext)
|
|
{
|
|
BOOL bDidCreate = CWnd::Create(lpszClassName, lpszWindowName, dwStyle, rect, pParentWnd, nID, pContext);
|
|
if (!bDidCreate) {
|
|
return bDidCreate;
|
|
}
|
|
|
|
|
|
CRect rcEmpty;
|
|
rcEmpty.SetRectEmpty();
|
|
|
|
bDidCreate = m_pchart->Create(NULL, "CBarChart", WS_CHILD | WS_VISIBLE, rcEmpty, this, 100, NULL);
|
|
if (!bDidCreate) {
|
|
return FALSE;
|
|
}
|
|
|
|
bDidCreate = m_pedit->Create(WS_CHILD | WS_VISIBLE | ES_MULTILINE, rcEmpty, this, 101);
|
|
if (!bDidCreate) {
|
|
return FALSE;
|
|
}
|
|
|
|
LayoutChildren();
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
//******************************************************************
|
|
// CDiskView::SetObject
|
|
//
|
|
// This method is called to select a new instance of the CIMOM Win32_LogicalDisk
|
|
// class into this view.
|
|
//
|
|
// This method gets several properties from the object instance including
|
|
// the size, freespace, and so on.
|
|
//
|
|
// Parameters:
|
|
// [in] LPCTSTR pszObjectPath
|
|
// The CIMOM object path used used to load the object instance
|
|
// "pco" from CIMOM.
|
|
//
|
|
// [in] IWbemClassObject* pco
|
|
// A pointer to a CIMOM Win32_LogicalDisk class object.
|
|
//
|
|
// Returns:
|
|
// Nothing.
|
|
//
|
|
//**************************************************************************
|
|
void CDiskView::SetObject(LPCTSTR pszObjectPath, IWbemClassObject* pco)
|
|
{
|
|
// Clear the current values of the properties that we will load from
|
|
// from the class object.
|
|
m_sDescription.Empty();
|
|
m_sFileSystem.Empty();
|
|
m_sProviderName.Empty();
|
|
m_sDeviceID.Empty();
|
|
m_uiFreeSpace = 0;
|
|
m_uiSize = 0;
|
|
m_bEditNeedsRefresh = TRUE;
|
|
|
|
|
|
// Store the object path so that we can display it later.
|
|
m_sObjectPath = pszObjectPath;
|
|
|
|
|
|
// Load each of the properties that we're interested in from the "pco" class object.
|
|
//
|
|
// The parameters that I chose to load are rather arbitrary. I just chose
|
|
// a few to demonstrate that this custom view works with live data from CIMOM.
|
|
//
|
|
if (pco != NULL) {
|
|
long lFlags = 0;
|
|
long lFlavor = 0;
|
|
CIMTYPE cimtype;
|
|
COleVariant varPropValue;
|
|
COleVariant varPropName;
|
|
CString sValue;
|
|
|
|
|
|
// Get Property: Size
|
|
SCODE sc;
|
|
varPropName = "Size";
|
|
sc = pco->Get(varPropName.bstrVal, lFlags, &varPropValue, &cimtype, &lFlavor);
|
|
if (FAILED(sc)) {
|
|
ReportFailedToGetProperty(varPropName.bstrVal, sc);
|
|
return;
|
|
}
|
|
|
|
if (cimtype==CIM_UINT64 && varPropValue.vt==VT_BSTR) {
|
|
sValue = varPropValue.bstrVal;
|
|
m_uiSize = _atoi64(sValue);
|
|
}
|
|
|
|
|
|
// Get Property:FreeSpace
|
|
lFlags = 0;
|
|
lFlavor = 0;
|
|
varPropValue.Clear();
|
|
varPropName = "FreeSpace";
|
|
sc = pco->Get(varPropName.bstrVal, lFlags, &varPropValue, &cimtype, &lFlavor);
|
|
if (FAILED(sc)) {
|
|
ReportFailedToGetProperty(varPropName.bstrVal, sc);
|
|
return;
|
|
}
|
|
|
|
if (cimtype==CIM_UINT64 && varPropValue.vt==VT_BSTR) {
|
|
sValue = varPropValue.bstrVal;
|
|
m_uiFreeSpace = _atoi64(sValue);
|
|
}
|
|
|
|
|
|
// Get Property: Description
|
|
lFlags = 0;
|
|
lFlavor = 0;
|
|
varPropValue.Clear();
|
|
varPropName = "Description";
|
|
sc = pco->Get(varPropName.bstrVal, lFlags, &varPropValue, &cimtype, &lFlavor);
|
|
if (FAILED(sc)) {
|
|
ReportFailedToGetProperty(varPropName.bstrVal, sc);
|
|
return;
|
|
}
|
|
|
|
if (cimtype==CIM_STRING && varPropValue.vt==VT_BSTR) {
|
|
m_sDescription = varPropValue.bstrVal;
|
|
}
|
|
|
|
|
|
|
|
// Get Property: FileSystem
|
|
lFlags = 0;
|
|
lFlavor = 0;
|
|
varPropValue.Clear();
|
|
varPropName = "FileSystem";
|
|
sc = pco->Get(varPropName.bstrVal, lFlags, &varPropValue, &cimtype, &lFlavor);
|
|
if (FAILED(sc)) {
|
|
ReportFailedToGetProperty(varPropName.bstrVal, sc);
|
|
return;
|
|
}
|
|
|
|
if (cimtype==CIM_STRING && varPropValue.vt==VT_BSTR) {
|
|
m_sFileSystem = varPropValue.bstrVal;
|
|
}
|
|
|
|
|
|
// Get Property: DeviceID
|
|
lFlags = 0;
|
|
lFlavor = 0;
|
|
varPropValue.Clear();
|
|
varPropName = "DeviceID";
|
|
sc = pco->Get(varPropName.bstrVal, lFlags, &varPropValue, &cimtype, &lFlavor);
|
|
if (FAILED(sc)) {
|
|
ReportFailedToGetProperty(varPropName.bstrVal, sc);
|
|
return;
|
|
}
|
|
|
|
if (cimtype==CIM_STRING && varPropValue.vt==VT_BSTR) {
|
|
m_sDeviceID = varPropValue.bstrVal;
|
|
}
|
|
|
|
|
|
// Get Property: ProviderName
|
|
lFlags = 0;
|
|
lFlavor = 0;
|
|
varPropValue.Clear();
|
|
varPropName = "ProviderName";
|
|
sc = pco->Get(varPropName.bstrVal, lFlags, &varPropValue, &cimtype, &lFlavor);
|
|
if (FAILED(sc)) {
|
|
ReportFailedToGetProperty(varPropName.bstrVal, sc);
|
|
return;
|
|
}
|
|
|
|
if (cimtype==CIM_STRING && varPropValue.vt==VT_BSTR) {
|
|
m_sProviderName = varPropValue.bstrVal;
|
|
}
|
|
|
|
}
|
|
|
|
// Set the value of the only bar in the barchart to represent
|
|
// the total size and the amount of freespace on the disk.
|
|
m_pchart->SetValue(0, m_uiSize, m_uiSize - m_uiFreeSpace);
|
|
m_pchart->SetLabel(0, m_sDeviceID);
|
|
}
|
|
|
|
// This method is called when an attempt to get a property value fails.
|
|
void CDiskView::ReportFailedToGetProperty(BSTR bstrPropName, SCODE sc)
|
|
{
|
|
CString sPropName;
|
|
sPropName = bstrPropName;
|
|
|
|
char szMessage[256];
|
|
sprintf(szMessage, "Failed to get property \"%s\". SC = 0x%08lx", sPropName, sc);
|
|
::MessageBox(NULL, szMessage, "Property Get Error", MB_OK);
|
|
}
|
|
|
|
|
|
|
|
// Layout the positions of the child windows and move the children to
|
|
// their new positions.
|
|
void CDiskView::LayoutChildren()
|
|
{
|
|
if (!::IsWindow(m_pchart->m_hWnd) || !::IsWindow(m_pedit->m_hWnd)) {
|
|
return;
|
|
}
|
|
|
|
m_bNeedsInitialLayout = FALSE;
|
|
CRect rcClient;
|
|
GetClientRect(rcClient);
|
|
|
|
|
|
// The barchart goes on the left and consumes one third of the total width less
|
|
// the margin width.
|
|
int cxChart = rcClient.Width() / 3 - 2 * CX_CHART_MARGIN;
|
|
int cyChart = rcClient.Height() - 2 * CY_CHART_MARGIN;
|
|
|
|
if (cxChart < 0 || cyChart < 0) {
|
|
m_rcChart.SetRectEmpty();
|
|
}
|
|
else {
|
|
m_rcChart.left = rcClient.left + CX_CHART_MARGIN;
|
|
m_rcChart.top = rcClient.top + CY_CHART_MARGIN;
|
|
m_rcChart.right = m_rcChart.left + cxChart;
|
|
m_rcChart.bottom = m_rcChart.top + cyChart;
|
|
}
|
|
m_pchart->MoveWindow(m_rcChart);
|
|
|
|
|
|
// The edit box goes just inside of the legend box inset by a 5 unit
|
|
// margin.
|
|
CRect rcLegend;
|
|
GetLegendRect(rcLegend);
|
|
|
|
CRect rcEdit;
|
|
rcEdit.left = rcLegend.left + 5;
|
|
rcEdit.right = rcLegend.right - 5;
|
|
rcEdit.top = rcLegend.top + 5;
|
|
rcEdit.bottom = rcLegend.bottom - 5;
|
|
|
|
m_pedit->MoveWindow(rcEdit);
|
|
m_pedit->RedrawWindow();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get rectangle that is used to help place the chart legend and the edit box.
|
|
void CDiskView::GetLegendRect(CRect& rcLegend)
|
|
{
|
|
CRect rcClient;
|
|
GetClientRect(rcClient);
|
|
|
|
rcLegend.left = CX_LEFT_MARGIN + 2 * CX_BAR + 2 * CX_BAR_SPACING;
|
|
rcLegend.right = rcClient.right - CX_RIGHT_MARGIN;
|
|
rcLegend.top = rcClient.top + CY_TOP_MARGIN;
|
|
rcLegend.bottom = rcClient.bottom - CY_BOTTOM_MARGIN;
|
|
}
|
|
|
|
|
|
|
|
void CDiskView::OnPaint()
|
|
{
|
|
CPaintDC dc(this); // device context for painting
|
|
|
|
if (m_bNeedsInitialLayout) {
|
|
LayoutChildren();
|
|
}
|
|
|
|
// Fill the backgound with the backgound color.
|
|
CBrush brBackground(COLOR_BG);
|
|
dc.FillRect(&dc.m_ps.rcPaint, &brBackground);
|
|
|
|
// Draw the chart legend.
|
|
DrawLegend(&dc);
|
|
|
|
// The edit control is a child window, so it will redraw itself, but
|
|
// first we want to load it with the values of several properties that
|
|
// we got earlier in CDiskView::SetObject.
|
|
if (m_bEditNeedsRefresh && ::IsWindow(m_pedit->m_hWnd)) {
|
|
m_bEditNeedsRefresh = FALSE;
|
|
CString sEditText;
|
|
char szBuffer[1024];
|
|
sprintf(szBuffer, "ObjectPath = %s\r\n\r\n", m_sObjectPath);
|
|
sEditText += szBuffer;
|
|
|
|
sprintf(szBuffer, "Description = %s\r\n\r\n", m_sDescription);
|
|
sEditText += szBuffer;
|
|
|
|
sprintf(szBuffer, "FileSystem = %s\r\n\r\n", m_sFileSystem);
|
|
sEditText += szBuffer;
|
|
|
|
if (!m_sProviderName.IsEmpty()) {
|
|
sprintf(szBuffer, "ProviderName = %s\r\n\r\n", m_sProviderName);
|
|
sEditText += szBuffer;
|
|
}
|
|
|
|
m_pedit->SetWindowText(sEditText);
|
|
}
|
|
|
|
|
|
// The barchart is a child window, so it will redraw itself.
|
|
|
|
// Do not call CWnd::OnPaint() for painting messages
|
|
}
|
|
|
|
|
|
|
|
// Draw the chart legend so that the user can tell what color
|
|
// means full and what color means empty.
|
|
void CDiskView::DrawLegend(CDC* pdc)
|
|
{
|
|
if (m_bNeedsInitialLayout) {
|
|
LayoutChildren();
|
|
}
|
|
|
|
CRect rcLegend;
|
|
GetLegendRect(rcLegend);
|
|
|
|
if (m_pedit->m_hWnd) {
|
|
CRect rcEdit;
|
|
rcEdit.left = rcLegend.left + 5;
|
|
rcEdit.right = rcLegend.right - 5;
|
|
rcEdit.top = rcLegend.top + 5;
|
|
rcEdit.bottom = rcLegend.bottom - 5;
|
|
|
|
m_pedit->MoveWindow(rcEdit);
|
|
m_pedit->RedrawWindow();
|
|
}
|
|
|
|
|
|
CBrush brWhite(COLOR_WHITE);
|
|
pdc->FrameRect(rcLegend, &brWhite);
|
|
|
|
|
|
pdc->SetTextColor(COLOR_WHITE); // text foreground = black
|
|
pdc->SetBkColor(COLOR_BG); // text bkgnd = yellow
|
|
|
|
|
|
|
|
CRect rcFull;
|
|
rcFull.left = rcLegend.left;
|
|
rcFull.top = rcLegend.bottom + 10;
|
|
rcFull.right = rcFull.left + 10;
|
|
rcFull.bottom = rcFull.top + 10;
|
|
|
|
CBrush brFull(COLOR_SPACE_USED);
|
|
pdc->FillRect(rcFull, &brFull);
|
|
|
|
|
|
CSize sizeText;
|
|
CString sText;
|
|
sText = "Used";
|
|
sizeText = pdc->GetTextExtent(sText);
|
|
pdc->TextOut(rcFull.right + 10, rcFull.top, sText);
|
|
|
|
|
|
CRect rcAvailable = rcFull;
|
|
rcAvailable.OffsetRect(rcFull.Width() + sizeText.cx + 20, 0);
|
|
|
|
CBrush brAvailable(COLOR_SPACE_AVAILABLE);
|
|
pdc->FillRect(rcAvailable, &brAvailable);
|
|
|
|
sText = "Available";
|
|
sizeText = pdc->GetTextExtent(sText);
|
|
pdc->TextOut(rcAvailable.right + 10, rcAvailable.top, sText);
|
|
}
|
|
|
|
|
|
void CDiskView::OnSize(UINT nType, int cx, int cy)
|
|
{
|
|
CWnd::OnSize(nType, cx, cy);
|
|
LayoutChildren();
|
|
}
|