⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 barstat.cpp

📁 vc6.0完整版
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// This is a part of the Microsoft Foundation Classes C++ library.
// Copyright (C) 1992-1998 Microsoft Corporation
// All rights reserved.
//
// This source code is only intended as a supplement to the
// Microsoft Foundation Classes Reference and related
// electronic documentation provided with the library.
// See these sources for detailed information regarding the
// Microsoft Foundation Classes product.

#include "stdafx.h"

#ifdef AFX_CORE3_SEG
#pragma code_seg(AFX_CORE3_SEG)
#endif

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

#define new DEBUG_NEW

/////////////////////////////////////////////////////////////////////////////
// CStatusBar creation, etc

#define SBPF_UPDATE 0x0001  // pending update of text

struct AFX_STATUSPANE
{
	UINT    nID;        // IDC of indicator: 0 => normal text area
	int     cxText;     // width of string area in pixels
						//   on both sides there is a 3 pixel gap and
						//   a one pixel border, making a pane 6 pixels wider
	UINT    nStyle;     // style flags (SBPS_*)
	UINT    nFlags;     // state flags (SBPF_*)
	CString strText;    // text in the pane
};

inline AFX_STATUSPANE* CStatusBar::_GetPanePtr(int nIndex) const
{
	ASSERT((nIndex >= 0 && nIndex < m_nCount) || m_nCount == 0);
	return ((AFX_STATUSPANE*)m_pData) + nIndex;
}

#ifdef AFX_INIT_SEG
#pragma code_seg(AFX_INIT_SEG)
#endif

#define CX_PANE_BORDER 6    // 3 pixels on each side of each pane

CStatusBar::CStatusBar()
{
	// setup default border/margin depending on type of system
	m_cyTopBorder = 2;
	if (afxData.bWin4)
	{
		m_cxLeftBorder = 0;
		m_cxRightBorder = 0;
		m_cyBottomBorder = 0;
	}
	else
	{
		m_cxLeftBorder = 2;
		m_cxRightBorder = 2;
		m_cyBottomBorder = 1;
	}
	// minimum height set with SB_SETMINHEIGHT is cached
	m_nMinHeight = 0;
}

CStatusBar::~CStatusBar()
{
	AllocElements(0, 0);    // destroys existing elements
}

BOOL CStatusBar::Create(CWnd* pParentWnd, DWORD dwStyle, UINT nID)
{
	return CreateEx(pParentWnd, 0, dwStyle, nID);
}

BOOL CStatusBar::CreateEx(CWnd* pParentWnd, DWORD dwCtrlStyle, DWORD dwStyle, UINT nID)
{
	ASSERT_VALID(pParentWnd);   // must have a parent

	// save the style (some of these style bits are MFC specific)
	m_dwStyle = (dwStyle & CBRS_ALL);

	// translate MFC style bits to windows style bits
	dwStyle &= ~CBRS_ALL;
	dwStyle |= CCS_NOPARENTALIGN|CCS_NOMOVEY|CCS_NODIVIDER|CCS_NORESIZE;
	if (pParentWnd->GetStyle() & WS_THICKFRAME)
		dwStyle |= SBARS_SIZEGRIP;
	dwStyle |= dwCtrlStyle;

	// initialize common controls
	VERIFY(AfxDeferRegisterClass(AFX_WNDCOMMCTL_BAR_REG));

	// create the HWND
	CRect rect; rect.SetRectEmpty();
	return CWnd::Create(STATUSCLASSNAME, NULL, dwStyle, rect, pParentWnd, nID);
}

BOOL CStatusBar::PreCreateWindow(CREATESTRUCT& cs)
{
	// in Win4, status bars do not have a border at all, since it is
	//  provided by the client area.
	if (afxData.bWin4 &&
		(m_dwStyle & (CBRS_ALIGN_ANY|CBRS_BORDER_ANY)) == CBRS_BOTTOM)
	{
		m_dwStyle &= ~(CBRS_BORDER_ANY|CBRS_BORDER_3D);
	}
	return CControlBar::PreCreateWindow(cs);
}

BOOL CStatusBar::SetIndicators(const UINT* lpIDArray, int nIDCount)
{
	ASSERT_VALID(this);
	ASSERT(nIDCount >= 1);  // must be at least one of them
	ASSERT(lpIDArray == NULL ||
		AfxIsValidAddress(lpIDArray, sizeof(UINT) * nIDCount, FALSE));
	ASSERT(::IsWindow(m_hWnd));

	// first allocate array for panes and copy initial data
	if (!AllocElements(nIDCount, sizeof(AFX_STATUSPANE)))
		return FALSE;
	ASSERT(nIDCount == m_nCount);

	// copy initial data from indicator array
	BOOL bResult = TRUE;
	if (lpIDArray != NULL)
	{
		HFONT hFont = (HFONT)SendMessage(WM_GETFONT);
		CClientDC dcScreen(NULL);
		HGDIOBJ hOldFont = NULL;
		if (hFont != NULL)
			hOldFont = dcScreen.SelectObject(hFont);

		AFX_STATUSPANE* pSBP = _GetPanePtr(0);
		for (int i = 0; i < nIDCount; i++)
		{
			pSBP->nID = *lpIDArray++;
			pSBP->nFlags |= SBPF_UPDATE;
			if (pSBP->nID != 0)
			{
				if (!pSBP->strText.LoadString(pSBP->nID))
				{
					TRACE1("Warning: failed to load indicator string 0x%04X.\n",
						pSBP->nID);
					bResult = FALSE;
					break;
				}
				pSBP->cxText = dcScreen.GetTextExtent(pSBP->strText).cx;
				ASSERT(pSBP->cxText >= 0);
				if (!SetPaneText(i, pSBP->strText, FALSE))
				{
					bResult = FALSE;
					break;
				}
			}
			else
			{
				// no indicator (must access via index)
				// default to 1/4 the screen width (first pane is stretchy)
				pSBP->cxText = ::GetSystemMetrics(SM_CXSCREEN)/4;
				if (i == 0)
					pSBP->nStyle |= (SBPS_STRETCH | SBPS_NOBORDERS);
			}
			++pSBP;
		}
		if (hOldFont != NULL)
			dcScreen.SelectObject(hOldFont);
	}
	UpdateAllPanes(TRUE, TRUE);

	return bResult;
}

BOOL CStatusBar::AllocElements(int nElements, int cbElement)
{
	// destruct old elements
	AFX_STATUSPANE* pSBP = _GetPanePtr(0);
	for (int i = 0; i < m_nCount; i++)
	{
		pSBP->strText.~CString();
		++pSBP;
	}

	// allocate new elements
	if (!CControlBar::AllocElements(nElements, cbElement))
		return FALSE;

	// construct new elements
	pSBP = _GetPanePtr(0);
	for (i = 0; i < m_nCount; i++)
	{
		memcpy(&pSBP->strText, &afxEmptyString, sizeof(CString));
		++pSBP;
	}
	return TRUE;
}

void CStatusBar::CalcInsideRect(CRect& rect, BOOL bHorz) const
{
	ASSERT_VALID(this);
	ASSERT(::IsWindow(m_hWnd));
	ASSERT(bHorz);  // vertical status bar not supported

	// subtract standard CControlBar borders
	CControlBar::CalcInsideRect(rect, bHorz);

	// subtract size grip if present
	if ((GetStyle() & SBARS_SIZEGRIP) && !::IsZoomed(::GetParent(m_hWnd)))
	{
		// get border metrics from common control
		int rgBorders[3];
		CStatusBar* pBar = (CStatusBar*)this;
		pBar->DefWindowProc(SB_GETBORDERS, 0, (LPARAM)&rgBorders);

		// size grip uses a border + size of scrollbar + cx border
		rect.right -= rgBorders[0] + ::GetSystemMetrics(SM_CXVSCROLL) +
			::GetSystemMetrics(SM_CXBORDER) * 2;
	}
}

void CStatusBar::UpdateAllPanes(BOOL bUpdateRects, BOOL bUpdateText)
{
	ASSERT_VALID(this);
	ASSERT(::IsWindow(m_hWnd));

	// update the status pane locations
	if (bUpdateRects)
	{
		// get border information and client work area
		CRect rect; GetWindowRect(rect);
		rect.OffsetRect(-rect.left, -rect.top);
		CalcInsideRect(rect, TRUE);
		int rgBorders[3];
		VERIFY((BOOL)DefWindowProc(SB_GETBORDERS, 0, (LPARAM)&rgBorders));

		// determine extra space for stretchy pane
		int cxExtra = rect.Width() + rgBorders[2];
		int nStretchyCount = 0;
		AFX_STATUSPANE* pSBP = _GetPanePtr(0);
		for (int i = 0; i < m_nCount; i++)
		{
			if (pSBP->nStyle & SBPS_STRETCH)
				++nStretchyCount;
			cxExtra -= (pSBP->cxText+CX_PANE_BORDER + rgBorders[2]);
			++pSBP;
		}

		// determine right edge of each pane
		int* rgRights = (int*)_alloca(m_nCount * sizeof(int));
		int right = rgBorders[0];
		pSBP = _GetPanePtr(0);
		for (i = 0; i < m_nCount; i++)
		{
			// determine size of the pane
			ASSERT(pSBP->cxText >= 0);
			right += pSBP->cxText+CX_PANE_BORDER;
			if ((pSBP->nStyle & SBPS_STRETCH) && cxExtra > 0)
			{
				ASSERT(nStretchyCount != 0);
				int cxAddExtra = cxExtra / nStretchyCount;
				right += cxAddExtra;
				--nStretchyCount;
				cxExtra -= cxAddExtra;
			}
			rgRights[i] = right;

			// next pane
			++pSBP;
			right += rgBorders[2];
		}

		// set new right edges for all panes
		DefWindowProc(SB_SETPARTS, m_nCount, (LPARAM)rgRights);
	}

	// update text in the status panes if specified
	if (bUpdateText)
	{
		AFX_STATUSPANE* pSBP = _GetPanePtr(0);
		for (int i = 0; i < m_nCount; i++)
		{
			if (pSBP->nFlags & SBPF_UPDATE)
				SetPaneText(i, pSBP->strText);
			++pSBP;
		}
	}
}

#ifdef AFX_CORE3_SEG
#pragma code_seg(AFX_CORE3_SEG)
#endif

/////////////////////////////////////////////////////////////////////////////
// CStatusBar attribute access

int CStatusBar::CommandToIndex(UINT nIDFind) const
{
	ASSERT_VALID(this);

	if (m_nCount <= 0)
		return -1;

	AFX_STATUSPANE* pSBP = _GetPanePtr(0);
	for (int i = 0; i < m_nCount; i++, pSBP++)
		if (pSBP->nID == nIDFind)
			return i;

	return -1;
}

UINT CStatusBar::GetItemID(int nIndex) const
{
	ASSERT_VALID(this);
	return _GetPanePtr(nIndex)->nID;
}

void CStatusBar::GetItemRect(int nIndex, LPRECT lpRect) const
{
	ASSERT_VALID(this);
	ASSERT(::IsWindow(m_hWnd));

	CStatusBar* pBar = (CStatusBar*)this;
	if (!pBar->DefWindowProc(SB_GETRECT, nIndex, (LPARAM)lpRect))
		::SetRectEmpty(lpRect);
}

UINT CStatusBar::GetPaneStyle(int nIndex) const
{
	return _GetPanePtr(nIndex)->nStyle;
}

void CStatusBar::SetPaneStyle(int nIndex, UINT nStyle)
{
	AFX_STATUSPANE* pSBP = _GetPanePtr(nIndex);
	if (pSBP->nStyle != nStyle)
	{
		// if the pane is changing SBPS_STRETCH, then...
		if ((pSBP->nStyle ^ nStyle) & SBPS_STRETCH)
		{
			// ... we need to re-layout the panes
			pSBP->nStyle = nStyle;
			UpdateAllPanes(TRUE, FALSE);
		}

		// use SetPaneText, since it updates the style and text
		pSBP->nStyle = nStyle;
		pSBP->nFlags |= SBPF_UPDATE;
		SetPaneText(nIndex, pSBP->strText);
	}
}

void CStatusBar::GetPaneInfo(int nIndex, UINT& nID, UINT& nStyle,
	int& cxWidth) const
{
	ASSERT_VALID(this);

	AFX_STATUSPANE* pSBP = _GetPanePtr(nIndex);
	nID = pSBP->nID;
	nStyle = pSBP->nStyle;
	cxWidth = pSBP->cxText;
}

void CStatusBar::SetPaneInfo(int nIndex, UINT nID, UINT nStyle, int cxWidth)
{
	ASSERT_VALID(this);

	BOOL bChanged = FALSE;
	AFX_STATUSPANE* pSBP = _GetPanePtr(nIndex);
	pSBP->nID = nID;
	if (pSBP->nStyle != nStyle)
	{
		if ((pSBP->nStyle ^ nStyle) & SBPS_STRETCH)
			bChanged = TRUE;
		else
		{
			pSBP->nStyle = nStyle;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -