commitmonitor Code
Monitor your SVN repositories and notifies you on new commits
Brought to you by:
steveking
changed | /trunk/src/StatusBarMsgWnd.cpp |
changed | /trunk/src/StatusBarMsgWnd.h |
added | /trunk/src/memdc.h |
--- a/trunk/src/StatusBarMsgWnd.cpp +++ b/trunk/src/StatusBarMsgWnd.cpp @@ -3,7 +3,16 @@ #include <ShellAPI.h> #include <assert.h> +#include "MemDC.h" + int CStatusBarMsgWnd::m_counter = 0; +vector<int> CStatusBarMsgWnd::m_slots; + +CStatusBarMsgWnd::~CStatusBarMsgWnd() +{ + if (m_icon) + ::DestroyIcon(m_icon); +} bool CStatusBarMsgWnd::RegisterAndCreateWindow() { @@ -32,13 +41,15 @@ return false; } -void CStatusBarMsgWnd::Show(LPCTSTR title, LPCTSTR text, HWND hParentWnd, UINT messageOnClick, int stay /* = 10 */) +void CStatusBarMsgWnd::Show(LPCTSTR title, LPCTSTR text, UINT icon, HWND hParentWnd, UINT messageOnClick, int stay /* = 10 */) { m_title = wstring(title); m_text = wstring(text); m_hParentWnd = hParentWnd; m_messageOnClick = messageOnClick; m_stay = stay; + m_icon = (HICON)::LoadImage(hResource, MAKEINTRESOURCE(icon), IMAGE_ICON, + STATUSBARMSGWND_ICONSIZE, STATUSBARMSGWND_ICONSIZE, LR_DEFAULTCOLOR); ::SystemParametersInfo(SPI_GETWORKAREA, 0, &m_workarea, 0); @@ -51,7 +62,20 @@ m_ShowTicks = 0; m_counter++; - m_thiscounter = m_counter; + // find an empty slot + m_thiscounter = 0; + for (vector<int>::iterator it = m_slots.begin(); it != m_slots.end(); ++it) + { + if (*it) + m_thiscounter++; + else + { + *it = 1; + break; + } + } + if (m_thiscounter >= (int)m_slots.size()) + m_slots.push_back(1); SetTimer(*this, STATUSBARMSGWND_SHOWTIMER, 10, NULL); } @@ -64,15 +88,38 @@ break; case WM_TIMER: return DoTimer(); + case WM_ERASEBKGND: + return TRUE; case WM_PAINT: { - PAINTSTRUCT ps; - HDC hdc = BeginPaint(hwnd, &ps); RECT rect; - ::GetClientRect(*this, &rect); - SetBkColor(hdc, ::GetSysColor(COLOR_WINDOW)); - ::ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rect, NULL, 0, NULL); - EndPaint(hwnd, &ps); + if (GetUpdateRect(*this, &rect, false)) + { + ::GetClientRect(*this, &rect); + // adjust the rectangle according to which part is hidden + switch (m_uEdge) + { + case ABE_BOTTOM: + rect.bottom = rect.top + m_height; + break; + case ABE_LEFT: + rect.left = rect.right - m_width; + break; + case ABE_RIGHT: + rect.right = rect.left + m_width; + break; + case ABE_TOP: + rect.top = rect.bottom - m_height; + break; + default: + break; + } + PAINTSTRUCT ps; + HDC hdc = BeginPaint(hwnd, &ps); + CMemDC memdc(hdc); + OnPaint(memdc, &rect, m_uEdge); + EndPaint(hwnd, &ps); + } } break; default: @@ -82,12 +129,84 @@ return 0; }; +void CStatusBarMsgWnd::OnPaint(HDC hDC, LPRECT pRect, UINT uEdge) +{ + // erase the background + SetBkColor(hDC, ::GetSysColor(COLOR_WINDOW)); + ::ExtTextOut(hDC, 0, 0, ETO_OPAQUE, pRect, NULL, 0, NULL); + + // draw a border + DrawEdge(hDC, pRect, EDGE_BUMP, BF_ADJUST | BF_RECT | BF_SOFT); + + // draw the icon on the left + DrawIconEx(hDC, pRect->left + 2, pRect->top + 2, m_icon, + STATUSBARMSGWND_ICONSIZE, STATUSBARMSGWND_ICONSIZE, 0, NULL, DI_NORMAL); + + // draw the title + HFONT hFont = CreateFont(-MulDiv(10, GetDeviceCaps(hDC, LOGPIXELSY), 72), 0, 0, 0, + FW_BOLD, false, false, false, ANSI_CHARSET, OUT_DEFAULT_PRECIS, + CLIP_DEFAULT_PRECIS, CLEARTYPE_QUALITY, DEFAULT_PITCH, _T("MS Shell Dlg")); + HFONT hFontOld = (HFONT)SelectObject(hDC, (HGDIOBJ)hFont); + SetTextColor(hDC, ::GetSysColor(COLOR_WINDOWTEXT)); + RECT titlerect = *pRect; + titlerect.left += (STATUSBARMSGWND_ICONSIZE + 5); + titlerect.top += 2; + titlerect.right -= 5; + TCHAR * textbuf = new TCHAR[m_title.size()+1]; + _tcscpy_s(textbuf, m_title.size()+1, m_title.c_str()); + DrawTextEx(hDC, textbuf, m_title.length(), &titlerect, DT_CALCRECT|DT_CENTER|DT_WORD_ELLIPSIS, NULL); + titlerect.right = pRect->right-5; + DrawTextEx(hDC, textbuf, m_title.length(), &titlerect, DT_CENTER|DT_WORD_ELLIPSIS, NULL); + delete [] textbuf; + SelectObject(hDC, hFontOld); + DeleteObject(hFont); + + // draw a separator line + HPEN hPen = CreatePen(PS_SOLID, 1, ::GetSysColor(COLOR_3DSHADOW)); + HPEN hOldPen = (HPEN)::SelectObject(hDC, hPen); + MoveToEx(hDC, titlerect.left, titlerect.bottom+4, NULL); + LineTo(hDC, titlerect.right, titlerect.bottom+4); + ::SelectObject(hDC, hOldPen); + DeleteObject(hPen); + hPen = CreatePen(PS_SOLID, 1, ::GetSysColor(COLOR_3DHIGHLIGHT)); + hOldPen = (HPEN)::SelectObject(hDC, hPen); + MoveToEx(hDC, titlerect.left, titlerect.bottom+5, NULL); + LineTo(hDC, titlerect.right, titlerect.bottom+5); + ::SelectObject(hDC, hOldPen); + DeleteObject(hPen); + + // draw the status text + hFont = CreateFont(-MulDiv(8, GetDeviceCaps(hDC, LOGPIXELSY), 72), 0, 0, 0, + FW_NORMAL, false, false, false, ANSI_CHARSET, OUT_DEFAULT_PRECIS, + CLIP_DEFAULT_PRECIS, CLEARTYPE_QUALITY, DEFAULT_PITCH, _T("MS Shell Dlg")); + hFontOld = (HFONT)SelectObject(hDC, (HGDIOBJ)hFont); + SetTextColor(hDC, ::GetSysColor(COLOR_GRAYTEXT)); + RECT statusrect = *pRect; + statusrect.left += (STATUSBARMSGWND_ICONSIZE + 5); + statusrect.top = (titlerect.bottom + 8); + textbuf = new TCHAR[m_text.size()+1]; + _tcscpy_s(textbuf, m_text.size()+1, m_text.c_str()); + //DrawTextEx(hDC, textbuf, m_text.length(), &statusrect, DT_CALCRECT|DT_CENTER|DT_WORD_ELLIPSIS, NULL); + DrawTextEx(hDC, textbuf, m_text.length(), &statusrect, DT_CENTER|DT_WORD_ELLIPSIS, NULL); + delete [] textbuf; + SelectObject(hDC, hFontOld); + DeleteObject(hFont); +} + LRESULT CStatusBarMsgWnd::DoTimer() { - if (m_ShowTicks >= ((m_stay+2)*m_height)) + bool finished = false; + if (((m_uEdge == ABE_TOP)||(m_uEdge == ABE_BOTTOM)) && + (m_ShowTicks >= ((m_stay+2)*m_height))) + finished = true; + if (((m_uEdge == ABE_LEFT)||(m_uEdge == ABE_RIGHT)) && + (m_ShowTicks >= ((m_stay+2)*m_width))) + finished = true; + if (finished) { ::KillTimer(*this, STATUSBARMSGWND_SHOWTIMER); DestroyWindow(*this); + m_slots[m_thiscounter] = 0; m_counter--; assert(m_counter >= 0); delete this; @@ -131,10 +250,10 @@ // expanding to the right xPos += m_ShowTicks; } - xPos += ((m_thiscounter-1)*m_width); + xPos += ((m_thiscounter)*m_width); RECT popupRect; - popupRect.left = m_workarea.left + ((m_thiscounter-1)*m_width); + popupRect.left = m_workarea.left + ((m_thiscounter)*m_width); popupRect.right = xPos; popupRect.top = m_workarea.top; popupRect.bottom = m_workarea.top + m_height; @@ -162,12 +281,12 @@ // expanding down yPos += m_ShowTicks; } - yPos += ((m_thiscounter-1)*m_height); + yPos += ((m_thiscounter)*m_height); RECT popupRect; popupRect.left = m_workarea.right - m_width; popupRect.right = m_workarea.right; - popupRect.top = m_workarea.top + ((m_thiscounter-1)*m_height); + popupRect.top = m_workarea.top + ((m_thiscounter)*m_height); popupRect.bottom = yPos; ::SetWindowPos(*this, HWND_TOPMOST, popupRect.left, popupRect.top, popupRect.right-popupRect.left, popupRect.bottom-popupRect.top, @@ -193,11 +312,11 @@ // expanding to the left xPos -= m_ShowTicks; } - xPos -= ((m_thiscounter-1)*m_width); + xPos -= ((m_thiscounter)*m_width); RECT popupRect; popupRect.left = xPos; - popupRect.right = m_workarea.right - ((m_thiscounter-1)*m_width); + popupRect.right = m_workarea.right - ((m_thiscounter)*m_width); popupRect.top = m_workarea.top; popupRect.bottom = m_workarea.top + m_height; ::SetWindowPos(*this, HWND_TOPMOST, @@ -224,13 +343,13 @@ // rising yPos -= m_ShowTicks; } - yPos -= ((m_thiscounter-1)*m_height); + yPos -= ((m_thiscounter)*m_height); RECT popupRect; popupRect.left = m_workarea.right - m_width; popupRect.right = m_workarea.right; popupRect.top = yPos; - popupRect.bottom = m_workarea.bottom - ((m_thiscounter-1)*m_height); + popupRect.bottom = m_workarea.bottom - ((m_thiscounter)*m_height); ::SetWindowPos(*this, HWND_TOPMOST, popupRect.left, popupRect.top, popupRect.right-popupRect.left, popupRect.bottom-popupRect.top, SWP_NOACTIVATE|SWP_SHOWWINDOW);
--- a/trunk/src/StatusBarMsgWnd.h +++ b/trunk/src/StatusBarMsgWnd.h @@ -1,30 +1,33 @@ #pragma once #include "BaseWindow.h" #include <string> +#include <vector> using namespace std; #define STATUSBARMSGWND_SHOWTIMER 101 - +#define STATUSBARMSGWND_ICONSIZE 32 class CStatusBarMsgWnd : public CWindow { public: CStatusBarMsgWnd(HINSTANCE hInst, const WNDCLASSEX* wcx = NULL) : CWindow(hInst, wcx) - , m_width(150) - , m_height(50) + , m_width(200) + , m_height(80) + , m_icon(NULL) { RegisterAndCreateWindow(); } - void Show(LPCTSTR title, LPCTSTR text, HWND hParentWnd, UINT messageOnClick, int stay = 10); + void Show(LPCTSTR title, LPCTSTR text, UINT icon, HWND hParentWnd, UINT messageOnClick, int stay = 10); private: // deconstructor private to prevent creating an instance on the stack // --> must be created on the heap! - ~CStatusBarMsgWnd(void) {} + ~CStatusBarMsgWnd(void); protected: + virtual void OnPaint(HDC hDC, LPRECT pRect, UINT uEdge); /** * Registers the window class and creates the window. */ @@ -41,6 +44,7 @@ private: wstring m_title; wstring m_text; + HICON m_icon; UINT m_messageOnClick; HWND m_hParentWnd; @@ -54,5 +58,6 @@ int m_thiscounter; static int m_counter; + static vector<int> m_slots; };
--- a +++ b/trunk/src/memdc.h @@ -0,0 +1,181 @@ +#pragma once + +////////////////////////////////////////////////// +// CMemDC - memory DC +// +// Author: Keith Rule +// Email: keithr@europa.com +// Copyright 1996-1997, Keith Rule +// +// You may freely use or modify this code provided this +// Copyright is included in all derived versions. +// +// History - 10/3/97 Fixed scrolling bug. +// Added print support. +// 25 feb 98 - fixed minor assertion bug +// +// This class implements a memory Device Context + +#ifdef _MFC_VER +class CMemDC : public CDC +{ +public: + // constructor sets up the memory DC + CMemDC(CDC* pDC, bool bTempOnly = false, int nOffset = 0) : CDC() + { + ASSERT(pDC != NULL); + + m_pDC = pDC; + m_pOldBitmap = NULL; + m_bMemDC = ((!pDC->IsPrinting()) && (!GetSystemMetrics(SM_REMOTESESSION))); + m_bTempOnly = bTempOnly; + + if (m_bMemDC) // Create a Memory DC + { + pDC->GetClipBox(&m_rect); + CreateCompatibleDC(pDC); + m_bitmap.CreateCompatibleBitmap(pDC, m_rect.Width() - nOffset, m_rect.Height()); + m_pOldBitmap = SelectObject(&m_bitmap); + SetWindowOrg(m_rect.left, m_rect.top); + } + else // Make a copy of the relevant parts of the current DC for printing + { + m_bPrinting = pDC->m_bPrinting; + m_hDC = pDC->m_hDC; + m_hAttribDC = pDC->m_hAttribDC; + } + + FillSolidRect(m_rect, pDC->GetBkColor()); + } + + CMemDC(CDC* pDC, const CRect* pRect) : CDC() + { + ASSERT(pDC != NULL); + + // Some initialization + m_pDC = pDC; + m_pOldBitmap = NULL; + m_bMemDC = !pDC->IsPrinting(); + m_bTempOnly = false; + + // Get the rectangle to draw + if (pRect == NULL) { + pDC->GetClipBox(&m_rect); + } else { + m_rect = *pRect; + } + + if (m_bMemDC) { + // Create a Memory DC + CreateCompatibleDC(pDC); + pDC->LPtoDP(&m_rect); + + m_bitmap.CreateCompatibleBitmap(pDC, m_rect.Width(), m_rect.Height()); + m_pOldBitmap = SelectObject(&m_bitmap); + + SetMapMode(pDC->GetMapMode()); + + SetWindowExt(pDC->GetWindowExt()); + SetViewportExt(pDC->GetViewportExt()); + + pDC->DPtoLP(&m_rect); + SetWindowOrg(m_rect.left, m_rect.top); + } else { + // Make a copy of the relevant parts of the current DC for printing + m_bPrinting = pDC->m_bPrinting; + m_hDC = pDC->m_hDC; + m_hAttribDC = pDC->m_hAttribDC; + } + + // Fill background + FillSolidRect(m_rect, pDC->GetBkColor()); + } + + // Destructor copies the contents of the mem DC to the original DC + ~CMemDC() + { + if (m_bMemDC) { + // Copy the off screen bitmap onto the screen. + if (!m_bTempOnly) + m_pDC->BitBlt(m_rect.left, m_rect.top, m_rect.Width(), m_rect.Height(), + this, m_rect.left, m_rect.top, SRCCOPY); + + //Swap back the original bitmap. + SelectObject(m_pOldBitmap); + } else { + // All we need to do is replace the DC with an illegal value, + // this keeps us from accidentally deleting the handles associated with + // the CDC that was passed to the constructor. + m_hDC = m_hAttribDC = NULL; + } + } + + // Allow usage as a pointer + CMemDC* operator->() {return this;} + + // Allow usage as a pointer + operator CMemDC*() {return this;} + +private: + CBitmap m_bitmap; // Off screen bitmap + CBitmap* m_pOldBitmap; // bitmap originally found in CMemDC + CDC* m_pDC; // Saves CDC passed in constructor + CRect m_rect; // Rectangle of drawing area. + BOOL m_bMemDC; // TRUE if CDC really is a Memory DC. + BOOL m_bTempOnly; // Whether to copy the contents on the real DC on destroy +}; +#else +class CMemDC +{ +public: + + // constructor sets up the memory DC + CMemDC(HDC hDC, bool bTempOnly = false, int nOffset = 0) + { + UNREFERENCED_PARAMETER(nOffset); + m_hDC = hDC; + m_hOldBitmap = NULL; + m_bTempOnly = bTempOnly; + + GetClipBox(m_hDC, &m_rect); + m_hMemDC = ::CreateCompatibleDC(m_hDC); + m_hBitmap = CreateCompatibleBitmap(m_hDC, m_rect.right - m_rect.left, m_rect.bottom - m_rect.top); + m_hOldBitmap = (HBITMAP)SelectObject(m_hMemDC, m_hBitmap); + SetWindowOrgEx(m_hMemDC, m_rect.left, m_rect.top, NULL); + } + + // Destructor copies the contents of the mem DC to the original DC + ~CMemDC() + { + if (m_hMemDC) { + // Copy the off screen bitmap onto the screen. + if (!m_bTempOnly) + BitBlt(m_hDC, m_rect.left, m_rect.top, m_rect.right-m_rect.left, m_rect.bottom-m_rect.top, m_hMemDC, m_rect.left, m_rect.top, SRCCOPY); + + //Swap back the original bitmap. + SelectObject(m_hMemDC, m_hOldBitmap); + DeleteObject(m_hBitmap); + DeleteDC(m_hMemDC); + } else { + // All we need to do is replace the DC with an illegal value, + // this keeps us from accidentally deleting the handles associated with + // the CDC that was passed to the constructor. + DeleteObject(m_hBitmap); + DeleteDC(m_hMemDC); + m_hMemDC = NULL; + } + } + + // Allow usage as a pointer + operator HDC() {return m_hMemDC;} +private: + HBITMAP m_hBitmap; // Off screen bitmap + HBITMAP m_hOldBitmap; // bitmap originally found in CMemDC + HDC m_hDC; // Saves CDC passed in constructor + HDC m_hMemDC; // our own memory DC + RECT m_rect; // Rectangle of drawing area. + bool m_bTempOnly; // Whether to copy the contents on the real DC on destroy +}; + +#endif +