Click here to Skip to main content
15,892,269 members
Articles / Desktop Programming / MFC

Double Buffered DC Class

Rate me:
Please Sign up or sign in to vote.
3.93/5 (15 votes)
15 Jan 20041 min read 72.8K   1.7K   25  
CDC descendant with double buffering abilities
// PiranhaMessage.cpp : implementation file
//

#include "stdafx.h"
#include "akBufferedDC.h"
#include ".\MessageWnd.h"

#include "akBufferedDC\akBufferedDC.h"


// CMessageWnd
const UINT CMessageWnd::WM_CLOSECLICKED = RegisterWindowMessage(_T("msgwnd{AE66E755-AEC8-4455-89DA-CD7E61C4F726}"));

IMPLEMENT_DYNAMIC(CMessageWnd, CWnd)
CMessageWnd::CMessageWnd()
    : m_MouseOver(false)
    , m_MouseDown(false)
{
    m_CloseBtn.SetRectEmpty();
    //  Create font
    LOGFONT lf;
    ::GetObject(::GetStockObject(DEFAULT_GUI_FONT), sizeof(LOGFONT), &lf);
    strcpy(lf.lfFaceName, _T("Tahoma"));
    m_Font.CreateFontIndirect(&lf);
}

CMessageWnd::~CMessageWnd()
{
}


BEGIN_MESSAGE_MAP(CMessageWnd, CWnd)
    ON_WM_PAINT()
    ON_WM_MOUSEMOVE()
    ON_MESSAGE(WM_MOUSELEAVE, OnMouseLeave)
    ON_WM_ERASEBKGND()
    ON_WM_LBUTTONDOWN()
    ON_WM_LBUTTONUP()
    ON_WM_SIZE()
END_MESSAGE_MAP()



// CMessageWnd message handlers

void CMessageWnd::OnPaint()
{
//    CPaintDC dc(this);                                      // device context for painting
    CakBufferedDC dc(this);                                 // device context for painting

    //  Get client rectangle
    CRect Client;
    GetClientRect(&Client);

    CBrush BkBrush(GetSysColor(COLOR_BTNFACE));
    dc.FillRect(&Client, &BkBrush);

    CPen *oldPen;

    //  Fill message background
    CPen DarkPen(PS_SOLID, 1, GetSysColor(COLOR_3DSHADOW));
    oldPen = dc.SelectObject(&DarkPen);
    CBrush InfoBk(GetSysColor(COLOR_INFOBK)), *oldBrush;
    oldBrush = dc.SelectObject(&InfoBk);
    Client.DeflateRect(2, 2, 2, 2);
    dc.Rectangle(&Client);
    dc.SelectObject(oldBrush);
    dc.SelectObject(oldPen);

    //  Setup font
    COLORREF oldFntColor = dc.SetTextColor(COLOR_INFOTEXT);
    CFont *oldFnt = dc.SelectObject(&m_Font);
    int oldBkMode = dc.SetBkMode(TRANSPARENT);
    Client.DeflateRect(2, 2);
    Client.left += 4;
    Client.right -= 4;
    dc.DrawText(m_Message, &Client, DT_WORDBREAK | DT_VCENTER);
    dc.SelectObject(oldFnt);
    dc.SetTextColor(oldFntColor);
    dc.SetBkMode(oldBkMode);

    //  Draw close button if mouse is over window
    RepaintCloseButton(&dc);
}

void CMessageWnd::OnMouseMove(UINT nFlags, CPoint point)
{
    if (!m_MouseOver)
    {
        m_MouseOver = true;
        m_MouseDown = false;
        //  Track mouse movement
        TRACKMOUSEEVENT tme = { 0 };
        tme.cbSize = sizeof(TRACKMOUSEEVENT);
        tme.dwFlags = TME_LEAVE;
        tme.hwndTrack = this->m_hWnd;
        TrackMouseEvent(&tme);
    }
    RepaintCloseButton();

    CWnd::OnMouseMove(nFlags, point);
}

LRESULT CMessageWnd::OnMouseLeave(WPARAM, LPARAM)
{
    if (m_MouseOver)
    {
        m_MouseOver = false;
        m_MouseDown = false;
        //  Stop tracking mouse movement
        TRACKMOUSEEVENT tme = { 0 };
        tme.cbSize = sizeof(TRACKMOUSEEVENT);
        tme.dwFlags = TME_LEAVE | TME_CANCEL;
        tme.hwndTrack = this->m_hWnd;
        TrackMouseEvent(&tme);
        //  Repaint
        RedrawWindow();
    }

    return 0;
}

int CMessageWnd::GetHeight()
{
    CClientDC dc(this);
    //  Get height of the font
    CFont *old = dc.SelectObject(&m_Font);
    TEXTMETRIC tm;
    dc.GetTextMetrics(&tm);
    int Result = tm.tmHeight * 5 + 10;
    dc.SelectObject(old);

    return Result;
}

void CMessageWnd::SetMessage(const CString &Message)
{
    m_Message = Message;
    RedrawWindow();
}

BOOL CMessageWnd::OnEraseBkgnd(CDC* pDC)
{
    return TRUE;
}

void CMessageWnd::OnLButtonDown(UINT nFlags, CPoint point)
{
    if (m_MouseOver)
    {
        m_MouseDown = true;
        RepaintCloseButton();
        return;
    }

    CWnd::OnLButtonDown(nFlags, point);
}

void CMessageWnd::OnLButtonUp(UINT nFlags, CPoint point)
{
    if (m_MouseOver)
    {
        m_MouseDown = false;
        RepaintCloseButton();
        if (m_CloseBtn.PtInRect(Mouse()))
            GetParent()->PostMessage(WM_CLOSECLICKED);
        return;
    }

    CWnd::OnLButtonUp(nFlags, point);
}

POINT CMessageWnd::Mouse()
{
    POINT pt;
    GetCursorPos(&pt);
    ScreenToClient(&pt);

    return pt;
}

void CMessageWnd::RepaintCloseButton(CDC *pPaintDC/* = 0*/)
{
    if (!m_MouseOver)
        return;

    CClientDC dc(this);
    CDC *pdc = (pPaintDC) ? pPaintDC : &dc;

    UINT State = DFCS_CAPTIONCLOSE;
    if (m_CloseBtn.PtInRect(Mouse()))
    {
        if (m_MouseDown)
            State |= DFCS_PUSHED;
    }
    pdc->DrawFrameControl(&m_CloseBtn, DFC_CAPTION, State);
}

void CMessageWnd::OnSize(UINT nType, int cx, int cy)
{
    CWnd::OnSize(nType, cx, cy);

    CRect Client;
    GetClientRect(&Client);
    m_CloseBtn = Client;
    m_CloseBtn.left = m_CloseBtn.right - 16;
    m_CloseBtn.bottom = m_CloseBtn.top + 16;
    m_CloseBtn.OffsetRect(-6, 6);
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Software Developer (Senior)
United States United States
Started professional career in software development back in 2000, in Ukraine. Founder and owner of a boutique software company called ByteGems.com Software. Worked for 6 years at w2bi, Inc in New Jersey USA, currently work in a large multinational company based in Redmond, WA.

My buzzwords at the moment: .NET, C#, ASP.NET, MVC, LINQ, TypeScript, JavaScript, AngularJS, HTML, JSON, services.

Still buzzing: C++, Win32, ATL, MFC, SQL, WinForms, WebForms, EF, Sockets, TCP/IP, Remoting.

Comments and Discussions