1 //*******************************************************************************
4 // You may use this source code, compile or redistribute it as part of your application
5 // for free. You cannot redistribute it as a part of a software development
6 // library without the agreement of the author. If the sources are
7 // distributed along with the application, you should leave the original
8 // copyright notes in the source code without any changes.
9 // This code can be used WITHOUT ANY WARRANTIES at your own risk.
11 // For the latest updates to this code, check this site:
12 // http://www.masmex.com
15 // Copyright(C) 2000 Philip Oldaker <email: philip@masmex.com>
16 //*******************************************************************************
19 #include "UIStatusBar.h"
24 static char THIS_FILE[] = __FILE__;
27 ///////////////////////////////////
31 ///////////////////////////////////
32 IMPLEMENT_SERIAL(CUIStatusBar, CStatusBar, 0)
33 IMPLEMENT_SERIAL(CStatusBarPane, CObject, 0)
35 BEGIN_MESSAGE_MAP(CUIStatusBar, CStatusBar)
36 //{{AFX_MSG_MAP(CUIStatusBar)
43 LPCTSTR CUIStatusBar::szSection = _T("Settings\\StatusBar");
44 LPCTSTR CUIStatusBar::szPaneEntry = _T("Pane");
46 CStatusBarPane::CStatusBarPane(const CStatusBarPane &rOther)
51 CStatusBarPane &CStatusBarPane::operator=(const CStatusBarPane &rOther)
59 void CStatusBarPane::DoCopy(const CStatusBarPane &rOther)
62 m_nStyle = rOther.m_nStyle;
63 m_bActive = rOther.m_bActive;
64 // m_listImageIndex = rOther.m_listImageIndex;
67 void CStatusBarPane::Serialize(CArchive &ar)
83 void CUIStatusBar::OnContextMenu(CWnd *pWnd, CPoint point)
87 // Build the popup menu
88 Menu.CreatePopupMenu();
89 CStatusBarPane *pPane = NULL;
91 for(POSITION pos = m_PaneList.GetTailPosition();pos != NULL;)
93 pPane = m_PaneList.GetPrev(pos);
94 if (pPane->GetCommandID() != ID_SEPARATOR && pPane->GetCommandID() != ID_INDICATOR_MAIN)
96 strText.LoadString(pPane->GetCommandID());
97 Menu.AppendMenu(MF_STRING,pPane->GetCommandID(),strText);
100 // and display using main frame as message window
101 Menu.TrackPopupMenu(TPM_LEFTBUTTON | TPM_RIGHTBUTTON | TPM_LEFTALIGN,point.x,point.y,theApp.m_pMainWnd);
102 theApp.m_pMainWnd->SetFocus();
105 ////////////////////////////////////////////////////////////
107 CUIStatusBar::CUIStatusBar()
112 CUIStatusBar::~CUIStatusBar()
117 void CUIStatusBar::Reset()
123 void CUIStatusBar::Init()
125 m_nStatusPane1Width = -1;
126 m_nStatusPane1Style = SBPS_STRETCH;
127 m_bMenuSelect = FALSE;
128 m_nMinHeight = GetSystemMetrics(SM_CYSMICON)+4;
129 m_pImageList = new CImageList;
132 void CUIStatusBar::Clear()
134 CStatusBarPane *pPane;
135 while (!m_PaneList.IsEmpty())
137 pPane = m_PaneList.RemoveTail();
144 CUIStatusBar &CUIStatusBar::operator=(const CUIStatusBar &rOther)
148 for(POSITION pos=rOther.m_PaneList.GetHeadPosition();pos != NULL;)
150 CStatusBarPane *pPane = new CStatusBarPane;
151 *pPane = *rOther.m_PaneList.GetNext(pos);
152 m_PaneList.AddTail(pPane);
154 m_nStatusPane1ID = rOther.m_nStatusPane1ID;
155 m_nStatusPane1Style = rOther.m_nStatusPane1Style;
156 m_nStatusPane1Width = rOther.m_nStatusPane1Width;
157 m_bMenuSelect = rOther.m_bMenuSelect;
161 void CUIStatusBar::UpdatePane(int nIndex)
164 GetStatusBarCtrl().GetRect(nIndex,&rect);
165 InvalidateRect(rect);
169 CStatusBarPane *CUIStatusBar::GetPane(UINT nPaneID) const
173 nPaneID = ((CUIStatusBar*)this)->GetPaneID(0);
175 CStatusBarPane *pPane = NULL;
176 for (POSITION pos=m_PaneList.GetHeadPosition();pos != NULL;)
178 pPane = m_PaneList.GetNext(pos);
179 if (pPane->GetCommandID() == nPaneID)
182 return((pPane && nPaneID == pPane->GetCommandID()) ? pPane : NULL);
185 void CUIStatusBar::RemoveAllIcons(UINT nPaneID)
187 CStatusBarPane *pPane = GetPane(nPaneID);
189 pPane->RemoveAllImages();
190 UpdatePane(GetPaneIndex(nPaneID));
193 void CUIStatusBar::RemoveIcon(UINT nPaneID,UINT nImageID,bool bUpdate)
197 nPaneID = GetPaneID(0);
199 CStatusBarPane *pPane = GetPane(nPaneID);
201 RemoveIcon(nImageID,pPane,bUpdate);
204 void CUIStatusBar::RemoveIcon(UINT nImageID,CStatusBarPane *pPane,bool bUpdate)
207 if (m_mapImageIndex.Lookup(nImageID,nImageIndex))
208 pPane->RemoveImage(nImageIndex);
210 UpdatePane(nImageIndex);
213 void CUIStatusBar::AddIcon(UINT nPaneID,UINT nImageID,bool bUpdate)
216 if (!m_mapImageIndex.Lookup(nImageID,nIndex))
217 nIndex = AddIcon(nImageID);
218 // Possibly wrong id using pane index 0
221 nPaneID = GetPaneID(0);
223 AddImageIndex(nPaneID,nIndex,bUpdate);
226 // add an image to list of images that will be displayed
227 // nIndex into the image list
228 void CUIStatusBar::AddImageIndex(UINT nPaneID,int nImageIndex,bool bUpdate)
230 CStatusBarPane *pPane = GetPane(nPaneID);
232 int nPaneIndex = GetPaneIndex(nPaneID);
233 // Pane 0 can have only one icon
236 pPane->RemoveAllImages();
238 if (!pPane->FindImage(nImageIndex))
240 pPane->AddImage(nImageIndex);
244 GetPaneInfo(nPaneIndex,nPaneID,nStyle,nWidth);
245 // Make sure it's owner draw
246 if (!(nStyle & SBT_OWNERDRAW))
248 nStyle |= SBT_OWNERDRAW;
249 SetPaneInfo(nPaneIndex,nPaneID,nStyle,nWidth);
250 pPane->SetStyle(nStyle);
253 UpdatePane(GetPaneIndex(nPaneID));
256 int CUIStatusBar::AddIcon(UINT nID)
258 if (m_pImageList->m_hImageList == NULL)
260 ASSERT(m_pImageList->m_hImageList);
261 HICON hIcon = (HICON)::LoadImage(AfxGetInstanceHandle(),MAKEINTRESOURCE(nID),IMAGE_ICON,16,16,LR_DEFAULTCOLOR);
264 int nIndex = m_pImageList->Add(hIcon);
265 m_mapImageIndex[nID] = nIndex;
271 // set image list from a bitmap id
272 void CUIStatusBar::SetImageList(UINT nBitmapID)
276 m_pImageList = new CImageList;
277 m_pImageList->Create(nBitmapID,::GetSystemMetrics(SM_CXSMICON),0,::GetSysColor(COLOR_BTNFACE));
280 void CUIStatusBar::CreateImageList()
283 m_pImageList = new CImageList;
284 m_pImageList->Create(::GetSystemMetrics(SM_CXSMICON),::GetSystemMetrics(SM_CYSMICON),ILC_MASK | ILC_COLOR16,0,1);
285 m_pImageList->SetBkColor(CLR_NONE);
288 void CUIStatusBar::SetImageList(CImageList *pImageList)
291 // if one passed in copy it
294 int count = pImageList->GetImageCount();
295 for(int i=0;i < count;i++)
297 HICON hIcon = pImageList->ExtractIcon(i);
298 m_pImageList->Add(hIcon);
303 void CUIStatusBar::AddPane(UINT nID,BOOL bActive)
305 CStatusBarPane *pPane = new CStatusBarPane(nID,bActive);
306 pPane->SetStyle(SBT_OWNERDRAW);
307 m_PaneList.AddTail(pPane);
310 BOOL CUIStatusBar::SetPanes(BOOL bSave)
313 CStatusBarPane *pPane = NULL;
314 for(POSITION pos = m_PaneList.GetTailPosition();pos != NULL;)
316 pPane = m_PaneList.GetPrev(pos);
317 nSize += pPane->IsPaneActive();
319 UINT *pIndicators = new UINT[nSize];
322 for(pos = m_PaneList.GetHeadPosition();pos != NULL;)
324 pPane = m_PaneList.GetNext(pos);
325 if (pPane->IsPaneActive())
327 pIndicators[nIndex++] = pPane->GetCommandID();
330 BOOL ret = SetIndicators(pIndicators, nSize);
331 delete[] pIndicators;
335 for(pos = m_PaneList.GetTailPosition();pos != NULL;)
337 pPane = m_PaneList.GetPrev(pos);
338 if (pPane->IsPaneActive() && pPane->GetCommandID() != ID_SEPARATOR)
340 int nIndex = GetPaneIndex(pPane->GetCommandID());
341 GetPaneInfo(nIndex,nID,nStyle,nWidth);
342 SetPaneInfo(nIndex,pPane->GetCommandID(),nStyle | pPane->GetStyle(),nWidth);
343 SetPaneText(nIndex,_T(""));
346 GetPaneInfo(0,nID,nStyle,nWidth);
347 // First pane has its own style
348 SetPaneInfo(0,nID,m_nStatusPane1Style,nWidth);
357 void CUIStatusBar::Load()
359 CWinApp *pApp = AfxGetApp();
361 CStatusBarPane *pPane = NULL;
363 for(POSITION pos = m_PaneList.GetTailPosition();pos != NULL;i++)
365 pPane = m_PaneList.GetPrev(pos);
366 strPane.Format(_T("%s%d"),szPaneEntry,i);
367 pPane->SetPaneActive(pApp->GetProfileInt(szSection,strPane,pPane->IsPaneActive()));
371 void CUIStatusBar::Save()
373 CWinApp *pApp = AfxGetApp();
375 CStatusBarPane *pPane = NULL;
377 for(POSITION pos = m_PaneList.GetTailPosition();pos != NULL;i++)
379 pPane = m_PaneList.GetPrev(pos);
380 strPane.Format(_T("%s%d"),szPaneEntry,i);
381 pApp->WriteProfileInt(szSection,strPane,pPane->IsPaneActive());
385 void CUIStatusBar::TogglePane(UINT nID)
387 CStatusBarPane *pPane = GetPane(nID);
390 pPane->SetPaneActive(!pPane->IsPaneActive());
395 void CUIStatusBar::SetText(UINT nPaneID,LPCTSTR szText,bool bUpdate)
397 const CStatusBarPane *pPane = GetPane(nPaneID);
399 SetTextPane(pPane,szText,bUpdate);
402 void CUIStatusBar::SetTextPane(const CStatusBarPane *pPane,LPCTSTR szText,bool bUpdate)
404 if (!pPane->IsPaneActive())
407 int nIndex = GetPaneIndex(pPane->GetCommandID());
409 UINT nPaneID=pPane->GetCommandID();
411 GetPaneInfo(nIndex, nPaneID, nStyle, nWidth);
412 nStyle |= SBT_OWNERDRAW;
415 HGDIOBJ hOldFont = NULL;
416 HFONT hFont = (HFONT)SendMessage(WM_GETFONT);
419 hOldFont = dc.SelectObject(hFont);
420 CSize size = dc.GetTextExtent(szText);
421 if (hOldFont != NULL)
422 dc.SelectObject(hOldFont);
425 SetPaneInfo(nIndex, nPaneID, nStyle, nWidth);
426 SetPaneText(nIndex, szText, bUpdate);
431 void CUIStatusBar::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
433 CStatusBarPane *pPane = GetPane(GetPaneID(lpDrawItemStruct->itemID));
436 // Get the pane rectangle and calculate text coordinates
437 CRect rect(&lpDrawItemStruct->rcItem);
438 CDC *pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
439 COLORREF oldBkColor = pDC->SetBkColor(::GetSysColor(COLOR_BTNFACE));
441 CListImages &listImages = pPane->GetImageIndex();
442 // make sure there is an image
443 if (!listImages.IsEmpty())
445 for(POSITION pos=listImages.GetTailPosition();pos != NULL;)
447 m_pImageList->Draw(pDC,listImages.GetPrev(pos),CPoint(rect.left,rect.top),ILD_NORMAL);
448 rect.left += ::GetSystemMetrics(SM_CXSMICON);
453 LPCTSTR pszText = (LPCTSTR)lpDrawItemStruct->itemData;
454 // make sure there is text
457 UINT nFormat = DT_LEFT | DT_SINGLELINE | DT_EXPANDTABS | DT_NOPREFIX | DT_VCENTER;
458 // if (pPane->GetStyle() & SBPS_POPOUT)
459 // nFormat |= DT_VCENTER;
461 // nFormat |= DT_BOTTOM;
462 pDC->DrawText(pszText,lstrlen(pszText),rect,nFormat);
464 pDC->SetBkColor(oldBkColor);
468 void CUIStatusBar::Serialize(CArchive &ar)
470 CStatusBar::Serialize(ar);
471 m_PaneList.Serialize(ar);
474 template <> void AFXAPI SerializeElements <CStatusBarPane*> (CArchive& ar, CStatusBarPane **ppPane, int nCount)
476 for (int i=0;i < nCount;i++,ppPane++)
490 void CUIStatusBar::OnLButtonDown(UINT nFlags, CPoint point)
492 // TODO: Add your message handler code here and/or call default
493 CStatusBar::OnLButtonDown(nFlags, point);
496 BOOL CUIStatusBar::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
498 // TODO: Add your message handler code here and/or call default
499 /* if (theApp.IsLoading())
502 ::GetCursorPos(&point);
503 ScreenToClient(&point);
505 GetItemRect(4,&rect);
506 if (rect.PtInRect(point))
508 SetCursor(::LoadCursor(NULL,IDC_CROSS));
513 return CStatusBar::OnSetCursor(pWnd, nHitTest, message);
516 ////////////////////////////////////////////////////////////////////////
517 IMPLEMENT_DYNCREATE(CProgressBar, CProgressCtrl)
519 BEGIN_MESSAGE_MAP(CProgressBar, CProgressCtrl)
520 //{{AFX_MSG_MAP(CProgressBar)
525 CProgressBar::CProgressBar() : m_nPaneIndex(-1), m_pStatusBar(NULL)
529 CProgressBar::CProgressBar(int nPaneID, CUIStatusBar *pStatusBar, int MaxValue /* = 100 */)
531 Create(nPaneID, pStatusBar, MaxValue);
534 CProgressBar::~CProgressBar()
539 // Create the CProgressCtrl as a child of the status bar
540 BOOL CProgressBar::Create(int nPaneID, CUIStatusBar *pStatusBar, int MaxValue)
542 m_pStatusBar = pStatusBar;
543 m_nPaneIndex = pStatusBar->GetPaneIndex(nPaneID);
544 if (m_nPaneIndex == -1)
547 // Create the progress bar
548 if (!CProgressCtrl::Create(WS_CHILD | WS_VISIBLE | PBS_SMOOTH, CRect(0,0,0,0), pStatusBar, 1))
551 // Set range and step
552 SetRange(0, MaxValue);
555 // Resize the control to its desired width
561 void CProgressBar::Clear()
565 void CProgressBar::SetRange(int nLower, int nUpper, int nStep /* = 1 */)
567 CProgressCtrl::SetRange(nLower, nUpper);
568 CProgressCtrl::SetStep(nStep);
571 int CProgressBar::SetPos(int nPos)
575 ModifyStyle(0,WS_VISIBLE);
576 return CProgressCtrl::SetPos(nPos);
579 int CProgressBar::OffsetPos(int nPos)
583 ModifyStyle(0,WS_VISIBLE);
584 return CProgressCtrl::OffsetPos(nPos);
587 int CProgressBar::SetStep(int nStep)
591 ModifyStyle(0,WS_VISIBLE);
592 return CProgressCtrl::SetStep(nStep);
595 int CProgressBar::StepIt()
599 ModifyStyle(0,WS_VISIBLE);
600 return CProgressCtrl::StepIt();
603 void CProgressBar::Resize()
605 ASSERT(m_pStatusBar);
606 ASSERT(m_nPaneIndex != -1);
611 // Now get the rectangle in which we will draw the progress bar
613 m_pStatusBar->GetItemRect (m_nPaneIndex, rc);
615 if (::IsWindow(m_hWnd))
619 BOOL CProgressBar::OnEraseBkgnd(CDC* pDC)
622 return CProgressCtrl::OnEraseBkgnd(pDC);