📄 multipanestatusbarex.h
字号:
/////////////////////////////////////////////////////////////////////////////////////////
//
// MultiPaneStatusBarEx.h
//
// Author: Pablo Aliskevicius.
// Copyright (C) 2004 Pablo Aliskevicius.
//
// The code and information is provided by the author and copyright holder 'as-is',
// and any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the author or copyright holders be liable for any direct, indirect,
// incidental, special, exemplary, or consequential damages (including, but not limited
// to, procurement of substitute goods or services; loss of use, data, or profits; or
// business interruption) however caused and on any theory of liability, whether in
// contract, strict liability, or tort (including negligence or otherwise) arising in
// any way out of the use of this software, even if advised of the possibility of such
// damage.
//
/////////////////////////////////////////////////////////////////////////////////////////
//
// Classes in this file:
//
// CProgressBarInPaneImpl<T> - CMPSBarWithProgress,
// CMPSBarWithProgressAndBMP,
// [CMPSBarWithProgressAndAnimation - not implemented],
// CMPSBarWithAll
// CBitmapInPaneImpl<T> - CMPSBarWithBitmaps,
// CMPSBarWithProgressAndBMP,
// [CMPSBarWithAnimAndBMP - not implemented ],
// CMPSBarWithAll
// CAnimationInPaneImpl<T> - CMPSBarWithAnimation,
// [CMPSBarWithProgressAndAnimation - not implemented],
// [CMPSBarWithAnimAndBMP - not implemented ],
// CMPSBarWithAll
// MultiPaneStatusBarWithProgress.h: interface for the CMPSBarWithProgress class.
//
// This class extends WTL::CMultiPaneStatusBarCtrl to support creating and updating a
// progress bar in one of its panes, and moving that progress bar around.
//
// Usage:
// ======
//
// Wherever you'd create a CMultiPaneStatusBarCtrl, create one of the CMPSBarWithXXXXX
// classes instead (the one which provides the functionality you'll use).
//
// Showing progress bars:
// ----------------------
//
// Show a progress bar using ProgCreate()
// Hide it using ProgDestroyWindow()
// Display progress using ProgSetPos(), or ProgStepIt() after ProgSetStep()
// All other functions of WTL::CProgressBarCtrl, version 7.1, are also exposed.
//
// Showing bitmaps:
// ----------------
//
// Use SetBitmap() to display a bitmap. There are two versions of the function.
// Use DestroyBitmap() to hide the bitmap, and optionally call DestroyObject()
// on its handle.
//
// Showing animations:
// -------------------
//
// Use AnimCreate() to display an animation.
// Use AnimDestroyWindow() to close an animation.
//
// Showing anything (I don't like it, so there's an #ifdef):
// ---------------------------------------------------------
//
// #define MULTI_PANE_WITH_ANY before including this file.
//
// Use CMPSBarWithAll as your member variable.
//
// Use AttachWindow() to attach an HWND to a pane.
// Use DetachWindow() to detach that HWND from that pane.
//
//
/////////////////////////////////////////////////////////////////////////////////////////
#if !defined(AFX_MULTIPANESTATUSBARWITHPROGRESS_H__D2F37B4C_6E3D_450D_94B5_B14D377226FA__INCLUDED_)
#define AFX_MULTIPANESTATUSBARWITHPROGRESS_H__D2F37B4C_6E3D_450D_94B5_B14D377226FA__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#ifndef __ATLCTRLS_H__
#error You have to include <ATLCTRLS.H> for CProgressBarCtrl, CStatic and CAnimateCtrl.
#endif
#ifndef __ATLCTRLX_H__
#error You have to include <ATLCTRLX.H> for CMultiPaneStatusBarCtrlImpl<T>.
#endif
/////////////////////////////////////////////////////////////////////////////////////////
// Implementation classes, meant to be inherited from (mixins).
/////////////////////////////////////////////////////////////////////////////////////////
template <class T>
class CProgressBarInPaneImpl
{
public:
typedef CProgressBarInPaneImpl<T> CThisClass;
// Constructor, destructor...
CProgressBarInPaneImpl<T>(): m_iProgressPane(-1)
{
}
virtual ~CProgressBarInPaneImpl<T>()
{
ProgDestroyWindow();
}
// UpdatePanesLayout() override, to handle resizing the progress bar whenever relevant
BOOL UpdatePanesLayout(void)
{
if (m_iProgressPane != -1)
{
T* pt = static_cast<T*>(this);
RECT rc;
pt->GetRect(m_iProgressPane, &rc);
// ::InflateRect(&rc, -1, -1);
m_Progress.MoveWindow(&rc);
}
return TRUE; // Mixed function.
}
BEGIN_MSG_MAP(CProgressBarInPaneImpl<T>)
MESSAGE_HANDLER(SB_SIMPLE, OnSimple)
END_MSG_MAP()
LRESULT OnSimple(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
if (::IsWindow(m_Progress.m_hWnd))
m_Progress.ShowWindow(wParam ? SW_HIDE: SW_SHOW);
bHandled = FALSE;
return 0;
}
//////////////////////////////////////////////////////////////////////////////////
// Prog* functions enable access to the contained CProgressBarCtrl.
// We'll expose most of its functionality, and a few additional bits.
//////////////////////////////////////////////////////////////////////////////////
BOOL ProgCreate(int iPane, // Status pane where we'll create the progress bar.
int nMin = 0, int nMax = 100, // Progress bar initial range
DWORD dwStyle = WS_CHILD | WS_VISIBLE | PBS_SMOOTH, // Progress bar styles
DWORD dwExStyle = 0
)
{
// Check there is such a pane
T* pt = static_cast<T*>(this);
ATLASSERT(::IsWindow(pt->m_hWnd));
if (iPane >= pt->m_nPanes)
return FALSE;
// Check there is not a progress bar already open.
if (::IsWindow(m_Progress.m_hWnd))
return FALSE;
// Get the pane's rectangle
RECT rc;
pt->GetRect( iPane, &rc );
// ::InflateRect(&rc, -1, -1);
// Create the window, using the status bar (this) as a parent.
m_Progress.Create ( pt->m_hWnd, rc, NULL, dwStyle, dwExStyle);
// Set the progress bar's range and position
m_Progress.SetRange ( nMin, nMax );
m_Progress.SetPos ( nMin );
m_Progress.SetStep ( 1 );
// Hold this, we'll need it to move around.
m_iProgressPane = iPane;
return TRUE;
}
// This function can be used to close a progress bar, after ending whatever
// lengthy operation justified opening it to begin with.
void ProgDestroyWindow(void)
{
if (::IsWindow(m_Progress.m_hWnd))
{
m_Progress.ShowWindow(SW_HIDE);
m_Progress.DestroyWindow();
}
m_iProgressPane = -1;
m_Progress.m_hWnd = NULL;
}
// Just in case.
int ProgGetPane() const { return m_iProgressPane; }
//////////////////////////////////////////////////////////////////////////////////
// CProgressBarCtrl functionality (WTL version 7.1):
// CWindow functionality in CProgressBarCtrl is hidden by design.
//
DWORD ProgSetRange(int nLower, int nUpper) { return m_Progress.SetRange(nLower, nUpper); }
int ProgSetPos(int nPos) { return m_Progress.SetPos(nPos); }
int ProgOffsetPos(int nPos) { return m_Progress.OffsetPos(nPos); }
int ProgSetStep(int nStep) { return m_Progress.SetStep(nStep); }
UINT ProgGetPos() const { return m_Progress.GetPos(); }
void ProgGetRange(PPBRANGE pPBRange) const { m_Progress.GetRange(pPBRange); }
int ProgGetRangeLimit(BOOL bLimit) const { return m_Progress.GetRangeLimit(bLimit); }
DWORD ProgSetRange32(int nMin, int nMax) { return m_Progress.SetRange32(nMin, nMax); }
#if (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
COLORREF ProgSetBarColor(COLORREF clr) { return m_Progress.SetBarColor(clr); }
COLORREF ProgSetBkColor(COLORREF clr) { return m_Progress.SetBkColor(clr); }
#endif //(_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
#if (_WIN32_WINNT >= 0x0501) && defined(PBM_SETMARQUEE)
BOOL ProgSetMarquee(BOOL bMarquee, UINT uUpdateTime = 0U)
{ return m_Progress.SetMarquee(bMarquee, uUpdateTime); }
#endif //(_WIN32_WINNT >= 0x0501) && defined(PBM_SETMARQUEE)
int ProgStepIt() { return m_Progress.StepIt(); }
protected:
//////////////////////////////////////////////////////////////////////////////////
// Member variables (of course, protected)
//
CProgressBarCtrl m_Progress; // This is the contained control.
int m_iProgressPane; // Pane ordinal where the progress bar resides, or -1 when off.
}; // CProgressBarInPaneImpl
// This one also handles bitmaps
template <class T> class CBitmapInPaneImpl
{
public:
// You can have up to 15 bitmaps per status bar.
enum { MAX_MANAGED = 15 };
BEGIN_MSG_MAP(CBitmapInPaneImpl<T>)
MESSAGE_HANDLER(SB_SIMPLE, OnSimple)
END_MSG_MAP()
// Show bitmaps when the status bar is in multi pane state, hide them when it's simple.
LRESULT OnSimple(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
int sw = (wParam) ? SW_HIDE: SW_SHOW;
// Hide all children (static bitmaps)
for (int i = 0; i < MAX_MANAGED; i++)
{
if (m_Manager[i].hw)
::ShowWindow(m_Manager[i].hw, sw);
}
bHandled = false;
return 0;
}
// Move bitmaps around to stay on top of their panes.
BOOL UpdatePanesLayout(void)
{
RECT rc;
T *pT = static_cast<T*>(this);
for (int i = 0; i < MAX_MANAGED; i++)
{
if (m_Manager[i].hw)
{
pT->GetRect( m_Manager[i].iPane, &rc );
// ::InflateRect(&rc, -1, -1);
CStatic cs(m_Manager[i].hw);
cs.MoveWindow(&rc);
cs.Invalidate();
}
} // for
return TRUE;
}
// Add a bitmap to the status bar, in a pane chosen by ordinal.
BOOL SetBitmap(int iPane, // Zero based ordinal (not resource ID) of the chosen pane.
HBITMAP hbmp, // Handle to a bitmap.
bool bManage = false) // If true, DestroyObject() will be called on the HBITMAP.
{
if (NULL == hbmp)
return false;
// If the pane was in use, release it.
if (!DestroyBitmap(iPane))
return FALSE;
// Use the first available array entry to put the selected bitmap.
T *pT = static_cast<T *>(this);
for (int i = 0; i < MAX_MANAGED; i++)
{
if (!m_Manager[i].hw)
{
RECT rct;
pT->GetRect( iPane, &rct);
// ::InflateRect(&rct, -1, -1);
CStatic cs;
cs.Create(pT->m_hWnd, rct, NULL,
WS_CHILDWINDOW | WS_VISIBLE | WS_DISABLED | SS_BITMAP | SS_LEFT | SS_SUNKEN,
WS_EX_NOPARENTNOTIFY, WS_EX_CLIENTEDGE | WS_EX_STATICEDGE);
cs.SetBitmap(hbmp);
m_Manager[i].hw = cs.m_hWnd;
m_Manager[i].iPane = iPane;
m_Manager[i].hbmp = hbmp;
m_Manager[i].bManage = bManage;
UpdatePanesLayout();
return TRUE;
}
}
return FALSE;
}
// Same as the former, but loads the bitmap from a resource.
BOOL SetBitmap(int iPane, int iBmpResource)
{
HBITMAP hb = ::LoadBitmap(_Module.m_hInstResource, MAKEINTRESOURCE(iBmpResource));
if (NULL == hb)
return FALSE;
// The caller has no access to the bitmap's handle, we MUST manage it from here.
return SetBitmap(iPane, hb, true);
}
// If there is a bitmap in the selected pane, destroy it.
BOOL DestroyBitmap(int iPane)
{
T *pT = static_cast<T *>(this);
// Check we're really talking about a pane.
if (iPane < 0 || iPane >= pT->m_nPanes)
return FALSE;
// Find the pane in the array.
for (int i = 0; i < MAX_MANAGED; i++)
{
if (m_Manager[i].iPane == iPane)
{
// If the pane is in use, release whatever is there.
if (m_Manager[i].bManage)
::DeleteObject(m_Manager[i].hbmp);
::DestroyWindow(m_Manager[i].hw);
// Initialize array entry to suitable values.
m_Manager[i].Clear();
break;
}
}
return TRUE; // The pane is free.
}
CBitmapInPaneImpl<T>()
{
}
virtual ~CBitmapInPaneImpl<T>()
{
// Destroy all windows, release all managed bitmaps.
for (int i = 0; i < MAX_MANAGED; i++)
{
if (m_Manager[i].hw)
::DestroyWindow(m_Manager[i].hw);
if (m_Manager[i].bManage)
::DeleteObject(m_Manager[i].hbmp);
}
}
protected:
// This class ties one bitmap/HWND/pane.
class CBmpManager
{
public:
HWND hw;
HBITMAP hbmp;
int iPane;
bool bManage;
CBmpManager(): hw(NULL), hbmp(NULL), bManage(false), iPane(-1)
{}
void Clear(void)
{
hbmp = NULL;
hw = NULL;
bManage = false;
iPane = -1;
}
}; // class CBmpManager
CBmpManager m_Manager[MAX_MANAGED]; // 15 are more than enough, I hope.
}; // class CBitmapInPaneImpl
template <class T>
class CAnimationInPaneImpl
{
public:
CAnimationInPaneImpl<T>(): m_iAnimPane(-1) {}
virtual ~CAnimationInPaneImpl<T>()
{
AnimDestroyWindow();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -