--- /dev/null
+//*******************************************************************************
+// COPYRIGHT NOTES
+// ---------------
+// You may use this source code, compile or redistribute it as part of your application
+// for free. You cannot redistribute it as a part of a software development
+// library without the agreement of the author. If the sources are
+// distributed along with the application, you should leave the original
+// copyright notes in the source code without any changes.
+// This code can be used WITHOUT ANY WARRANTIES at your own risk.
+//
+// For the latest updates to this code, check this site:
+// http://www.masmex.com
+// after Sept 2000
+//
+// Copyright(C) 2000 Philip Oldaker <email: philip@masmex.com>
+//*******************************************************************************
+
+#include "stdafx.h"
+#include "UIStatusBar.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+///////////////////////////////////
+//
+// IMStatusBar
+//
+///////////////////////////////////
+IMPLEMENT_SERIAL(CUIStatusBar, CStatusBar, 0)
+IMPLEMENT_SERIAL(CStatusBarPane, CObject, 0)
+
+BEGIN_MESSAGE_MAP(CUIStatusBar, CStatusBar)
+ //{{AFX_MSG_MAP(CUIStatusBar)
+ ON_WM_CONTEXTMENU()
+ ON_WM_LBUTTONDOWN()
+ ON_WM_SETCURSOR()
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+LPCTSTR CUIStatusBar::szSection = _T("Settings\\StatusBar");
+LPCTSTR CUIStatusBar::szPaneEntry = _T("Pane");
+
+CStatusBarPane::CStatusBarPane(const CStatusBarPane &rOther)
+{
+ DoCopy(rOther);
+}
+
+CStatusBarPane &CStatusBarPane::operator=(const CStatusBarPane &rOther)
+{
+ if (this == &rOther)
+ return *this;
+ DoCopy(rOther);
+ return *this;
+}
+
+void CStatusBarPane::DoCopy(const CStatusBarPane &rOther)
+{
+ m_nID = rOther.m_nID;
+ m_nStyle = rOther.m_nStyle;
+ m_bActive = rOther.m_bActive;
+// m_listImageIndex = rOther.m_listImageIndex;
+}
+
+void CStatusBarPane::Serialize(CArchive &ar)
+{
+ if (ar.IsStoring())
+ {
+ ar << m_nID;
+ ar << m_nStyle;
+ ar << m_bActive;
+ }
+ else
+ {
+ ar >> m_nID;
+ ar >> m_nStyle;
+ ar >> m_bActive;
+ }
+}
+
+void CUIStatusBar::OnContextMenu(CWnd *pWnd, CPoint point)
+{
+/* CMenu Menu;
+
+ // Build the popup menu
+ Menu.CreatePopupMenu();
+ CStatusBarPane *pPane = NULL;
+ CString strText;
+ for(POSITION pos = m_PaneList.GetTailPosition();pos != NULL;)
+ {
+ pPane = m_PaneList.GetPrev(pos);
+ if (pPane->GetCommandID() != ID_SEPARATOR && pPane->GetCommandID() != ID_INDICATOR_MAIN)
+ {
+ strText.LoadString(pPane->GetCommandID());
+ Menu.AppendMenu(MF_STRING,pPane->GetCommandID(),strText);
+ }
+ }
+ // and display using main frame as message window
+ Menu.TrackPopupMenu(TPM_LEFTBUTTON | TPM_RIGHTBUTTON | TPM_LEFTALIGN,point.x,point.y,theApp.m_pMainWnd);
+ theApp.m_pMainWnd->SetFocus();
+*/
+}
+////////////////////////////////////////////////////////////
+
+CUIStatusBar::CUIStatusBar()
+{
+ Init();
+}
+
+CUIStatusBar::~CUIStatusBar()
+{
+ Clear();
+}
+
+void CUIStatusBar::Reset()
+{
+ Clear();
+ Init();
+}
+
+void CUIStatusBar::Init()
+{
+ m_nStatusPane1Width = -1;
+ m_nStatusPane1Style = SBPS_STRETCH;
+ m_bMenuSelect = FALSE;
+ m_nMinHeight = GetSystemMetrics(SM_CYSMICON)+4;
+ m_pImageList = new CImageList;
+}
+
+void CUIStatusBar::Clear()
+{
+ CStatusBarPane *pPane;
+ while (!m_PaneList.IsEmpty())
+ {
+ pPane = m_PaneList.RemoveTail();
+ delete pPane;
+ }
+ delete m_pImageList;
+ m_pImageList = NULL;
+}
+
+CUIStatusBar &CUIStatusBar::operator=(const CUIStatusBar &rOther)
+{
+ if (this == &rOther)
+ return *this;
+ for(POSITION pos=rOther.m_PaneList.GetHeadPosition();pos != NULL;)
+ {
+ CStatusBarPane *pPane = new CStatusBarPane;
+ *pPane = *rOther.m_PaneList.GetNext(pos);
+ m_PaneList.AddTail(pPane);
+ }
+ m_nStatusPane1ID = rOther.m_nStatusPane1ID;
+ m_nStatusPane1Style = rOther.m_nStatusPane1Style;
+ m_nStatusPane1Width = rOther.m_nStatusPane1Width;
+ m_bMenuSelect = rOther.m_bMenuSelect;
+ return *this;
+}
+
+void CUIStatusBar::UpdatePane(int nIndex)
+{
+ CRect rect;
+ GetStatusBarCtrl().GetRect(nIndex,&rect);
+ InvalidateRect(rect);
+ UpdateWindow();
+}
+
+CStatusBarPane *CUIStatusBar::GetPane(UINT nPaneID) const
+{
+ if (nPaneID == 0)
+ {
+ nPaneID = ((CUIStatusBar*)this)->GetPaneID(0);
+ }
+ CStatusBarPane *pPane = NULL;
+ for (POSITION pos=m_PaneList.GetHeadPosition();pos != NULL;)
+ {
+ pPane = m_PaneList.GetNext(pos);
+ if (pPane->GetCommandID() == nPaneID)
+ break;
+ }
+ return((pPane && nPaneID == pPane->GetCommandID()) ? pPane : NULL);
+}
+
+void CUIStatusBar::RemoveAllIcons(UINT nPaneID)
+{
+ CStatusBarPane *pPane = GetPane(nPaneID);
+ ASSERT(pPane);
+ pPane->RemoveAllImages();
+ UpdatePane(GetPaneIndex(nPaneID));
+}
+
+void CUIStatusBar::RemoveIcon(UINT nPaneID,UINT nImageID,bool bUpdate)
+{
+ if (nPaneID == 0)
+ {
+ nPaneID = GetPaneID(0);
+ }
+ CStatusBarPane *pPane = GetPane(nPaneID);
+ ASSERT(pPane);
+ RemoveIcon(nImageID,pPane,bUpdate);
+}
+
+void CUIStatusBar::RemoveIcon(UINT nImageID,CStatusBarPane *pPane,bool bUpdate)
+{
+ int nImageIndex=-1;
+ if (m_mapImageIndex.Lookup(nImageID,nImageIndex))
+ pPane->RemoveImage(nImageIndex);
+ if (bUpdate)
+ UpdatePane(nImageIndex);
+}
+
+void CUIStatusBar::AddIcon(UINT nPaneID,UINT nImageID,bool bUpdate)
+{
+ int nIndex = -1;
+ if (!m_mapImageIndex.Lookup(nImageID,nIndex))
+ nIndex = AddIcon(nImageID);
+ // Possibly wrong id using pane index 0
+ if (nPaneID == 0)
+ {
+ nPaneID = GetPaneID(0);
+ }
+ AddImageIndex(nPaneID,nIndex,bUpdate);
+}
+
+// add an image to list of images that will be displayed
+// nIndex into the image list
+void CUIStatusBar::AddImageIndex(UINT nPaneID,int nImageIndex,bool bUpdate)
+{
+ CStatusBarPane *pPane = GetPane(nPaneID);
+ ASSERT(pPane);
+ int nPaneIndex = GetPaneIndex(nPaneID);
+ // Pane 0 can have only one icon
+ if (nPaneIndex == 0)
+ {
+ pPane->RemoveAllImages();
+ }
+ if (!pPane->FindImage(nImageIndex))
+ {
+ pPane->AddImage(nImageIndex);
+ }
+ UINT nStyle;
+ int nWidth;
+ GetPaneInfo(nPaneIndex,nPaneID,nStyle,nWidth);
+ // Make sure it's owner draw
+ if (!(nStyle & SBT_OWNERDRAW))
+ {
+ nStyle |= SBT_OWNERDRAW;
+ SetPaneInfo(nPaneIndex,nPaneID,nStyle,nWidth);
+ pPane->SetStyle(nStyle);
+ }
+ if (bUpdate)
+ UpdatePane(GetPaneIndex(nPaneID));
+}
+
+int CUIStatusBar::AddIcon(UINT nID)
+{
+ if (m_pImageList->m_hImageList == NULL)
+ CreateImageList();
+ ASSERT(m_pImageList->m_hImageList);
+ HICON hIcon = (HICON)::LoadImage(AfxGetInstanceHandle(),MAKEINTRESOURCE(nID),IMAGE_ICON,16,16,LR_DEFAULTCOLOR);
+ if (hIcon)
+ {
+ int nIndex = m_pImageList->Add(hIcon);
+ m_mapImageIndex[nID] = nIndex;
+ return nIndex;
+ }
+ return -1;
+}
+
+// set image list from a bitmap id
+void CUIStatusBar::SetImageList(UINT nBitmapID)
+{
+ delete m_pImageList;
+ m_pImageList = NULL;
+ m_pImageList = new CImageList;
+ m_pImageList->Create(nBitmapID,::GetSystemMetrics(SM_CXSMICON),0,::GetSysColor(COLOR_BTNFACE));
+}
+
+void CUIStatusBar::CreateImageList()
+{
+ delete m_pImageList;
+ m_pImageList = new CImageList;
+ m_pImageList->Create(::GetSystemMetrics(SM_CXSMICON),::GetSystemMetrics(SM_CYSMICON),ILC_MASK | ILC_COLOR16,0,1);
+ m_pImageList->SetBkColor(CLR_NONE);
+}
+
+void CUIStatusBar::SetImageList(CImageList *pImageList)
+{
+ CreateImageList();
+ // if one passed in copy it
+ if (pImageList)
+ {
+ int count = pImageList->GetImageCount();
+ for(int i=0;i < count;i++)
+ {
+ HICON hIcon = pImageList->ExtractIcon(i);
+ m_pImageList->Add(hIcon);
+ }
+ }
+}
+
+void CUIStatusBar::AddPane(UINT nID,BOOL bActive)
+{
+ CStatusBarPane *pPane = new CStatusBarPane(nID,bActive);
+ pPane->SetStyle(SBT_OWNERDRAW);
+ m_PaneList.AddTail(pPane);
+}
+
+BOOL CUIStatusBar::SetPanes(BOOL bSave)
+{
+ int nSize = 0;
+ CStatusBarPane *pPane = NULL;
+ for(POSITION pos = m_PaneList.GetTailPosition();pos != NULL;)
+ {
+ pPane = m_PaneList.GetPrev(pos);
+ nSize += pPane->IsPaneActive();
+ }
+ UINT *pIndicators = new UINT[nSize];
+
+ int nIndex = 0;
+ for(pos = m_PaneList.GetHeadPosition();pos != NULL;)
+ {
+ pPane = m_PaneList.GetNext(pos);
+ if (pPane->IsPaneActive())
+ {
+ pIndicators[nIndex++] = pPane->GetCommandID();
+ }
+ }
+ BOOL ret = SetIndicators(pIndicators, nSize);
+ delete[] pIndicators;
+
+ UINT nID, nStyle;
+ int nWidth;
+ for(pos = m_PaneList.GetTailPosition();pos != NULL;)
+ {
+ pPane = m_PaneList.GetPrev(pos);
+ if (pPane->IsPaneActive() && pPane->GetCommandID() != ID_SEPARATOR)
+ {
+ int nIndex = GetPaneIndex(pPane->GetCommandID());
+ GetPaneInfo(nIndex,nID,nStyle,nWidth);
+ SetPaneInfo(nIndex,pPane->GetCommandID(),nStyle | pPane->GetStyle(),nWidth);
+ SetPaneText(nIndex,_T(""));
+ }
+ }
+ GetPaneInfo(0,nID,nStyle,nWidth);
+ // First pane has its own style
+ SetPaneInfo(0,nID,m_nStatusPane1Style,nWidth);
+ if (bSave)
+ {
+ // save to registry
+ Save();
+ }
+ return ret;
+}
+
+void CUIStatusBar::Load()
+{
+ CWinApp *pApp = AfxGetApp();
+ CString strPane;
+ CStatusBarPane *pPane = NULL;
+ int i=0;
+ for(POSITION pos = m_PaneList.GetTailPosition();pos != NULL;i++)
+ {
+ pPane = m_PaneList.GetPrev(pos);
+ strPane.Format(_T("%s%d"),szPaneEntry,i);
+ pPane->SetPaneActive(pApp->GetProfileInt(szSection,strPane,pPane->IsPaneActive()));
+ }
+}
+
+void CUIStatusBar::Save()
+{
+ CWinApp *pApp = AfxGetApp();
+ CString strPane;
+ CStatusBarPane *pPane = NULL;
+ int i=0;
+ for(POSITION pos = m_PaneList.GetTailPosition();pos != NULL;i++)
+ {
+ pPane = m_PaneList.GetPrev(pos);
+ strPane.Format(_T("%s%d"),szPaneEntry,i);
+ pApp->WriteProfileInt(szSection,strPane,pPane->IsPaneActive());
+ }
+}
+
+void CUIStatusBar::TogglePane(UINT nID)
+{
+ CStatusBarPane *pPane = GetPane(nID);
+ if (pPane)
+ {
+ pPane->SetPaneActive(!pPane->IsPaneActive());
+ SetPanes(TRUE);
+ }
+}
+
+void CUIStatusBar::SetText(UINT nPaneID,LPCTSTR szText,bool bUpdate)
+{
+ const CStatusBarPane *pPane = GetPane(nPaneID);
+ ASSERT(pPane);
+ SetTextPane(pPane,szText,bUpdate);
+}
+
+void CUIStatusBar::SetTextPane(const CStatusBarPane *pPane,LPCTSTR szText,bool bUpdate)
+{
+ if (!pPane->IsPaneActive())
+ return;
+
+ int nIndex = GetPaneIndex(pPane->GetCommandID());
+ UINT nStyle;
+ UINT nPaneID=pPane->GetCommandID();
+ int nWidth;
+ GetPaneInfo(nIndex, nPaneID, nStyle, nWidth);
+ nStyle |= SBT_OWNERDRAW;
+ if (nIndex != 0)
+ {
+ HGDIOBJ hOldFont = NULL;
+ HFONT hFont = (HFONT)SendMessage(WM_GETFONT);
+ CClientDC dc(NULL);
+ if (hFont != NULL)
+ hOldFont = dc.SelectObject(hFont);
+ CSize size = dc.GetTextExtent(szText);
+ if (hOldFont != NULL)
+ dc.SelectObject(hOldFont);
+ nWidth = size.cx;
+ }
+ SetPaneInfo(nIndex, nPaneID, nStyle, nWidth);
+ SetPaneText(nIndex, szText, bUpdate);
+ if (bUpdate)
+ UpdateWindow();
+}
+
+void CUIStatusBar::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
+{
+ CStatusBarPane *pPane = GetPane(GetPaneID(lpDrawItemStruct->itemID));
+ if (pPane)
+ {
+ // Get the pane rectangle and calculate text coordinates
+ CRect rect(&lpDrawItemStruct->rcItem);
+ CDC *pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
+ COLORREF oldBkColor = pDC->SetBkColor(::GetSysColor(COLOR_BTNFACE));
+ // draw the image
+ CListImages &listImages = pPane->GetImageIndex();
+ // make sure there is an image
+ if (!listImages.IsEmpty())
+ {
+ for(POSITION pos=listImages.GetTailPosition();pos != NULL;)
+ {
+ m_pImageList->Draw(pDC,listImages.GetPrev(pos),CPoint(rect.left,rect.top),ILD_NORMAL);
+ rect.left += ::GetSystemMetrics(SM_CXSMICON);
+ rect.left += 5;
+ }
+ }
+ // draw the text
+ LPCTSTR pszText = (LPCTSTR)lpDrawItemStruct->itemData;
+ // make sure there is text
+ if (pszText)
+ {
+ UINT nFormat = DT_LEFT | DT_SINGLELINE | DT_EXPANDTABS | DT_NOPREFIX | DT_VCENTER;
+// if (pPane->GetStyle() & SBPS_POPOUT)
+// nFormat |= DT_VCENTER;
+// else
+// nFormat |= DT_BOTTOM;
+ pDC->DrawText(pszText,lstrlen(pszText),rect,nFormat);
+ }
+ pDC->SetBkColor(oldBkColor);
+ }
+}
+
+void CUIStatusBar::Serialize(CArchive &ar)
+{
+ CStatusBar::Serialize(ar);
+ m_PaneList.Serialize(ar);
+}
+
+template <> void AFXAPI SerializeElements <CStatusBarPane*> (CArchive& ar, CStatusBarPane **ppPane, int nCount)
+{
+ for (int i=0;i < nCount;i++,ppPane++)
+ {
+ if (ar.IsLoading())
+ {
+ ar >> *ppPane;
+ }
+ else
+ {
+ ar << *ppPane;
+ }
+ }
+}
+
+
+void CUIStatusBar::OnLButtonDown(UINT nFlags, CPoint point)
+{
+ // TODO: Add your message handler code here and/or call default
+ CStatusBar::OnLButtonDown(nFlags, point);
+}
+
+BOOL CUIStatusBar::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
+{
+ // TODO: Add your message handler code here and/or call default
+/* if (theApp.IsLoading())
+ {
+ CPoint point;
+ ::GetCursorPos(&point);
+ ScreenToClient(&point);
+ CRect rect;
+ GetItemRect(4,&rect);
+ if (rect.PtInRect(point))
+ {
+ SetCursor(::LoadCursor(NULL,IDC_CROSS));
+ return TRUE;
+ }
+ }
+*/
+ return CStatusBar::OnSetCursor(pWnd, nHitTest, message);
+}
+
+////////////////////////////////////////////////////////////////////////
+IMPLEMENT_DYNCREATE(CProgressBar, CProgressCtrl)
+
+BEGIN_MESSAGE_MAP(CProgressBar, CProgressCtrl)
+ //{{AFX_MSG_MAP(CProgressBar)
+ ON_WM_ERASEBKGND()
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+CProgressBar::CProgressBar() : m_nPaneIndex(-1), m_pStatusBar(NULL)
+{
+}
+
+CProgressBar::CProgressBar(int nPaneID, CUIStatusBar *pStatusBar, int MaxValue /* = 100 */)
+{
+ Create(nPaneID, pStatusBar, MaxValue);
+}
+
+CProgressBar::~CProgressBar()
+{
+ Clear();
+}
+
+// Create the CProgressCtrl as a child of the status bar
+BOOL CProgressBar::Create(int nPaneID, CUIStatusBar *pStatusBar, int MaxValue)
+{
+ m_pStatusBar = pStatusBar;
+ m_nPaneIndex = pStatusBar->GetPaneIndex(nPaneID);
+ if (m_nPaneIndex == -1)
+ return FALSE;
+
+ // Create the progress bar
+ if (!CProgressCtrl::Create(WS_CHILD | WS_VISIBLE | PBS_SMOOTH, CRect(0,0,0,0), pStatusBar, 1))
+ return FALSE;
+
+ // Set range and step
+ SetRange(0, MaxValue);
+ SetStep(1);
+
+ // Resize the control to its desired width
+ Resize();
+
+ return TRUE;
+}
+
+void CProgressBar::Clear()
+{
+}
+
+void CProgressBar::SetRange(int nLower, int nUpper, int nStep /* = 1 */)
+{
+ CProgressCtrl::SetRange(nLower, nUpper);
+ CProgressCtrl::SetStep(nStep);
+}
+
+int CProgressBar::SetPos(int nPos)
+{
+ if (m_hWnd == NULL)
+ return -1;
+ ModifyStyle(0,WS_VISIBLE);
+ return CProgressCtrl::SetPos(nPos);
+}
+
+int CProgressBar::OffsetPos(int nPos)
+{
+ if (m_hWnd == NULL)
+ return -1;
+ ModifyStyle(0,WS_VISIBLE);
+ return CProgressCtrl::OffsetPos(nPos);
+}
+
+int CProgressBar::SetStep(int nStep)
+{
+ if (m_hWnd == NULL)
+ return -1;
+ ModifyStyle(0,WS_VISIBLE);
+ return CProgressCtrl::SetStep(nStep);
+}
+
+int CProgressBar::StepIt()
+{
+ if (m_hWnd == NULL)
+ return -1;
+ ModifyStyle(0,WS_VISIBLE);
+ return CProgressCtrl::StepIt();
+}
+
+void CProgressBar::Resize()
+{
+ ASSERT(m_pStatusBar);
+ ASSERT(m_nPaneIndex != -1);
+
+ if (!m_pStatusBar)
+ return;
+
+ // Now get the rectangle in which we will draw the progress bar
+ CRect rc;
+ m_pStatusBar->GetItemRect (m_nPaneIndex, rc);
+ // Resize the window
+ if (::IsWindow(m_hWnd))
+ MoveWindow(&rc);
+}
+
+BOOL CProgressBar::OnEraseBkgnd(CDC* pDC)
+{
+ Resize();
+ return CProgressCtrl::OnEraseBkgnd(pDC);
+}