/****************************************************************/ /* */ /* InfobarCtrl.cpp */ /* */ /* Implementation of the CInfobarCtrl class. */ /* This class imitates the outlook infobar. */ /* */ /* Programmed by LYFZ van der Meer */ /* Copyright LYFZ Software Solutions 2002 */ /* http://www.LYFZvandermeer.nl */ /* */ /* Last updated: 10 july 2002 */ /* */ /****************************************************************/ #include "stdafx.h" #include "resource.h" #include "InfobarCtrl.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif CInfobarCtrl::CInfobarCtrl() { m_bMouseInButton = FALSE; m_bMouseDown = FALSE; } CInfobarCtrl::~CInfobarCtrl() { } BEGIN_MESSAGE_MAP(CInfobarCtrl, CStatic) //{{AFX_MSG_MAP(CInfobarCtrl) ON_WM_PAINT() ON_WM_MOUSEMOVE() ON_WM_TIMER() ON_WM_LBUTTONDOWN() ON_WM_LBUTTONUP() //}}AFX_MSG_MAP END_MESSAGE_MAP() /********************************************************************/ /* */ /* Function name : OnPaint */ /* Description : This is where all the painting of our control */ /* takes place. */ /* */ /********************************************************************/ void CInfobarCtrl::OnPaint() { CPaintDC dc(this); // device context for painting CDC memDC; CBitmap memBitmap; CBitmap* pOldBitmap; CRect rcClient; GetClientRect(&rcClient); // to avoid flicker, establish a memory dc, draw to it and then BitBlt it to the client memDC.CreateCompatibleDC(&dc); memBitmap.CreateCompatibleBitmap(&dc, rcClient.Width(), rcClient.Height()); pOldBitmap = (CBitmap *)memDC.SelectObject(&memBitmap); // paint background memDC.FillSolidRect(rcClient, GetSysColor(COLOR_3DSHADOW)); // select font CFont* pOldFont = (CFont*)memDC.SelectObject(&m_TextFont); COLORREF oldTextColor; int nBkMode = memDC.SetBkMode(TRANSPARENT); // set text color to white oldTextColor = memDC.SetTextColor(RGB(255,255,255)); CRect rcItem = m_rcButton; if (rcItem.right >= rcClient.right) rcItem.right = rcClient.right-1; if (m_bMouseInButton) { if (m_bMouseDown) memDC.Draw3dRect(rcItem, RGB(0,0,0), RGB(255,255,255)); else memDC.Draw3dRect(rcItem, RGB(255,255,255), RGB(0,0,0)); } rcItem.DeflateRect(5, 0); rcItem.right -= 12; // draw text ::DrawTextEx(memDC.m_hDC, m_strText.GetBuffer (0), m_strText.GetLength(), &rcItem, DT_SINGLELINE | DT_VCENTER | DT_LEFT | DT_PATH_ELLIPSIS, NULL); // draw a arrow rcItem.right += 12; rcItem.left = rcItem.right-8; rcItem.top += rcItem.Height() / 2 - 1; CPoint pt[3]; pt[0] = rcItem.TopLeft(); pt[1] = CPoint(rcItem.right, rcItem.top); pt[2] = CPoint(rcItem.left + rcItem.Width()/2, rcItem.top + rcItem.Width()/2); memDC.SelectStockObject(WHITE_BRUSH); memDC.SelectStockObject(NULL_PEN); memDC.Polygon(pt, 3); // finally send the result to the display dc.BitBlt(0, 0, rcClient.Width(), rcClient.Height(), &memDC, 0, 0, SRCCOPY); // restore old values memDC.SelectObject(pOldFont); memDC.SetTextColor(oldTextColor); memDC.SetBkMode(nBkMode); memDC.SelectObject(pOldBitmap); } /********************************************************************/ /* */ /* Function name : OnLButtonDown */ /* Description : Handle WM_LBUTTONDOWN message */ /* */ /********************************************************************/ void CInfobarCtrl::OnLButtonDown(UINT nFlags, CPoint point) { if (m_bMouseInButton) { if (!m_bMouseDown) m_bMouseDown = TRUE; Invalidate(); } CStatic::OnLButtonDown(nFlags, point); } /********************************************************************/ /* */ /* Function name : OnLButtonUp */ /* Description : Handle WM_LBUTTONUP message */ /* */ /********************************************************************/ void CInfobarCtrl::OnLButtonUp(UINT nFlags, CPoint point) { if (m_bMouseInButton) { int bOldMode = m_bMouseInButton; if (m_rcButton.PtInRect(point)) m_bMouseInButton = TRUE; else m_bMouseInButton = FALSE; if (m_bMouseDown) { m_bMouseDown = FALSE; if (m_bMouseInButton == bOldMode) { Invalidate(); // do something ... if (m_bMouseInButton) { Invalidate(); // load and display popup menu CMenu menu; menu.LoadMenu(IDR_INFOBARMENU); CMenu* pPopup = menu.GetSubMenu(0); CRect rect; GetWindowRect(rect); // show and track the menu DWORD dwID = pPopup->TrackPopupMenu((TPM_LEFTALIGN|TPM_LEFTBUTTON|TPM_NONOTIFY|TPM_RETURNCMD), rect.left, rect.bottom, this); GetParent()->SendMessage(WM_COMMAND, dwID); } } else { m_bMouseInButton = FALSE; Invalidate(); } } } CStatic::OnLButtonUp(nFlags, point); } /********************************************************************/ /* */ /* Function name : OnMouseMove */ /* Description : Handle WM_MOUSEMOVE message */ /* */ /********************************************************************/ void CInfobarCtrl::OnMouseMove(UINT nFlags, CPoint point) { if (nFlags & MK_LBUTTON) m_bMouseDown = TRUE; else m_bMouseDown = FALSE; BOOL bOldState = m_bMouseInButton; if (m_rcButton.PtInRect(point)) m_bMouseInButton = TRUE; else m_bMouseInButton = FALSE; if (m_bMouseInButton != bOldState) { Invalidate(FALSE); KillTimer(1); SetTimer(1,10,NULL); } CStatic::OnMouseMove(nFlags, point); } /********************************************************************/ /* */ /* Function name : OnTimer */ /* Description : Handle WM_TIMER message -> process timer */ /* */ /********************************************************************/ void CInfobarCtrl::OnTimer(UINT nIDEvent) { if (nIDEvent == 1) { CPoint pt; if (!GetCursorPos(&pt)) return; ScreenToClient(&pt); CRect rcClient; GetClientRect(&rcClient); rcClient.bottom = rcClient.top + 22; if (!rcClient.PtInRect(pt)) { KillTimer(1); m_bMouseInButton = FALSE; m_bMouseDown = FALSE; Invalidate(); } } CStatic::OnTimer(nIDEvent); } /********************************************************************/ /* */ /* Function name : SetText */ /* Description : Set text of the control */ /* */ /********************************************************************/ void CInfobarCtrl::SetText(LPCTSTR lpszText) { m_strText = lpszText; CClientDC dc(this); CFont* pFont = (CFont*)dc.SelectObject(&m_TextFont); CRect rcClient; GetClientRect(&rcClient); // calculate new button rect CSize size = dc.GetTextExtent(m_strText); size.cx += 22; size.cy = rcClient.Height()-2; m_rcButton = CRect(CPoint(1, 1), size); dc.SelectObject(pFont); Invalidate(); } /********************************************************************/ /* */ /* Function name : PreSubclassWindow */ /* Description : Initialize control variables */ /* */ /********************************************************************/ void CInfobarCtrl::PreSubclassWindow() { m_TextFont.CreateFont(16, 0,0,0,FW_BOLD, 0,0,0, DEFAULT_CHARSET, OUT_CHARACTER_PRECIS, CLIP_CHARACTER_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, "Arial"); CStatic::PreSubclassWindow(); }