// PopupWnd.cpp : implementation file
//

#include "stdafx.h"
//#include "Error Demo.h"
#include "LocalErrors.h"
#include "PopupWnd.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CPopupWnd

CPopupWnd::CPopupWnd()
{
	m_csMessage.Empty();
				// 0x02xxxxxx forces color match to system palette
//	m_dwColor = 0x02A0FFFF;		// gray
	m_dwColor = 0x0200FFFF;		// yellow
	m_wAlign = 0;
	m_nTimeout = 0;
	m_nIDTimer = 0;
}

CPopupWnd::~CPopupWnd()
{
}

BEGIN_MESSAGE_MAP(CPopupWnd, CWnd)
	//{{AFX_MSG_MAP(CPopupWnd)
	ON_WM_PAINT()
	ON_WM_KEYDOWN()
	ON_WM_LBUTTONDOWN()
	ON_WM_NCLBUTTONDOWN()
	ON_WM_NCRBUTTONDOWN()
	ON_WM_RBUTTONDOWN()
	ON_WM_SYSKEYDOWN()
	ON_WM_TIMER()
	ON_WM_MBUTTONDOWN()
	ON_WM_NCMBUTTONDOWN()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CPopupWnd message handlers

BOOL CPopupWnd::Create( LPCTSTR lpszTitle, DWORD dwStyle, 
						CPoint cPoint, CWnd* pParentWnd ) 
{
	CBrush	cBrush;
	UINT		nResult;
	CSize		cSize;
	CRect		cRect;

	cRect.top = cPoint.y;					// get the window position
	cRect.left = cPoint.x;
	cSize = GetMessageSize();				// get a size for the message string
	cRect.right =  cSize.cx + 15;			// size the window to fit the text
	cRect.bottom = cSize.cy + 15;
	if( m_wAlign & POPUP_RIGHT )
		cRect.left -= cRect.right;			// position window to right of point
	if( m_wAlign & POPUP_BOTTOM )
		cRect.top -= cRect.bottom;			// position window above point
	cBrush.CreateSolidBrush( m_dwColor );	// and set a window color
	// Register a custom WndClass and create a window.
	// This must be done because CPopupWnd has no icon.
	LPCTSTR lpszPopupClass =
		AfxRegisterWndClass( CS_HREDRAW | CS_VREDRAW, ::LoadCursor(NULL,IDC_ARROW), 
							 HBRUSH(cBrush), NULL );
	nResult = CWnd::CreateEx( WS_EX_NOPARENTNOTIFY | WS_EX_TOPMOST | WS_EX_WINDOWEDGE,  
							  lpszPopupClass, lpszTitle, WS_POPUPWINDOW | WS_VISIBLE,
							  cRect.left,  cRect.top, 
							  cRect.right, cRect.bottom,
							  GetSafeHwnd(), 0 );
	SetCapture();			// === note: using WS_CHILD style does not support capture ===
	if( m_nTimeout > 0 )
		m_nIDTimer = SetTimer( m_nIDTimer, m_nTimeout*1000, NULL );
	return nResult;
}

void CPopupWnd::OnPaint() 
{
	CRect	cRect;

	CPaintDC dc(this); // device context for painting
	GetClientRect( cRect );
	cRect.DeflateRect( 5, 5, 5, 5 );
	dc.SetBkColor( m_dwColor );
	dc.DrawText( m_csMessage, &cRect, DT_LEFT | DT_WORDBREAK );		//	| DT_NOCLIP 
}

CSize	CPopupWnd::GetMessageSize()
{
	CDC		cDC;
	CSize	cSize, cSizeFinal;
	CString	csTemp;
	int		nLen, nLenTrim, nLines;

	cDC.CreateIC(_T("DISPLAY"), NULL, NULL, NULL);
//	=== these two functions only work for simple strings w/o line breaks ===

//	cSize = cDC.GetTextExtent( m_csMessage );		// get a size for the string
//	cSize = cDC.GetOutputTextExtent( m_csMessage );

//	=== this routine will calculate a rectangle for a formatted display ===
	nLines = 0;
	nLenTrim = 0;
	cSizeFinal.cx = 0;
	cSizeFinal.cy = 0;
	csTemp = m_csMessage;
	do
	{
		nLen = csTemp.Find( "\r\n" );
		if( nLen >= 0 )
		{
			csTemp = csTemp.Left( nLen );
			nLenTrim += ( nLen + 2 );
			nLines++;
			cSize = cDC.GetTextExtent( csTemp );
			csTemp = m_csMessage.Right( m_csMessage.GetLength() - nLenTrim );
		}
		else
		{
			nLines++;
			cSize = cDC.GetTextExtent( csTemp );
		}
		cSizeFinal.cy = cSize.cy;						// all heights should be the same
		cSizeFinal.cx = max( cSizeFinal.cx, cSize.cx );	// keep the longest string
	}
	while( nLen >= 0 );
	cSizeFinal.cy = cSizeFinal.cy * nLines;
	return cSizeFinal;
}

void CPopupWnd::OnTimer(UINT nIDEvent) 
{
	Shutdown();
	CWnd::OnTimer(nIDEvent);
}

void CPopupWnd::Shutdown()
{
	if( m_nIDTimer )
		KillTimer( m_nIDTimer );
	PostMessage( WM_CLOSE );
	ReleaseCapture();
}

void CPopupWnd::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 
{
	Shutdown();
	CWnd::OnKeyDown(nChar, nRepCnt, nFlags);
}

void CPopupWnd::OnSysKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 
{
	Shutdown();
	CWnd::OnSysKeyDown(nChar, nRepCnt, nFlags);
}

void CPopupWnd::OnLButtonDown(UINT nFlags, CPoint point) 
{
	Shutdown();
	CWnd::OnLButtonDown(nFlags, point);
}

void CPopupWnd::OnNcLButtonDown(UINT nHitTest, CPoint point) 
{
	Shutdown();
	CWnd::OnNcLButtonDown(nHitTest, point);
}

void CPopupWnd::OnMButtonDown(UINT nFlags, CPoint point) 
{
	Shutdown();
	CWnd::OnMButtonDown(nFlags, point);
}

void CPopupWnd::OnNcMButtonDown(UINT nHitTest, CPoint point) 
{
	Shutdown();
	CWnd::OnNcMButtonDown(nHitTest, point);
}

void CPopupWnd::OnRButtonDown(UINT nFlags, CPoint point) 
{
	Shutdown();
	CWnd::OnRButtonDown(nFlags, point);
}

void CPopupWnd::OnNcRButtonDown(UINT nHitTest, CPoint point) 
{
	Shutdown();
	CWnd::OnNcRButtonDown(nHitTest, point);
}

/////////////////////////////////////////////////////////////////////////////
// PopupWnd

IMPLEMENT_DYNCREATE(PopupWnd, CWinThread)

PopupWnd::PopupWnd()
{
}

PopupWnd::~PopupWnd()
{
}

BOOL PopupWnd::InitInstance()
{
	// TODO:  perform and per-thread initialization here
	return TRUE;
}

int PopupWnd::ExitInstance()
{
	// TODO:  perform any per-thread cleanup here
	return CWinThread::ExitInstance();
}

BEGIN_MESSAGE_MAP(PopupWnd, CWinThread)
	//{{AFX_MSG_MAP(PopupWnd)
		// NOTE - the ClassWizard will add and remove mapping macros here.
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// PopupWnd message handlers

