#pragma once
#include <GdiPlus.h>
using namespace Gdiplus;
enum EPopupShowState
{
pssShowing,
pssShowed,
pssHidding,
pssHidden
};
typedef CWinTraits<WS_POPUP, WS_EX_TOPMOST | WS_EX_TOOLWINDOW | WS_EX_LAYERED> myHistoryPopupWinType;
class CHistoryPopupWnd : public CWindowImpl<CHistoryPopupWnd, CWindow, myHistoryPopupWinType>
{
public:
CHistoryPopupWnd()
{
clrBack = ::GetSysColor(COLOR_INFOBK);
clrBorder = ::GetSysColor(COLOR_ACTIVEBORDER);
clrTitleBack = ::GetSysColor(COLOR_ACTIVECAPTION);
clrTitleText = ::GetSysColor(COLOR_CAPTIONTEXT);
strFontFace = _T("Tahoma");
uiFontSize = 10;
bShowTitle = true;
nMaxWidth = 640;
nMinWidth = 200;
nPreferedHeight = 120;
epssShowState = pssHidden;
uiTimerDrawChart = uiTimerFadding = 0;
nOpacity = 0;
}
~CHistoryPopupWnd()
{
}
DECLARE_WND_CLASS(NULL)
BEGIN_MSG_MAP(CHistoryPopupWnd)
MSG_WM_CREATE(OnCreate)
MSG_WM_PAINT(OnPaint)
MSG_WM_TIMER(OnTimer)
END_MSG_MAP()
LRESULT OnCreate(LPCREATESTRUCT)
{
cmChartMan.SetTarget(m_hWnd);
uiTimerDrawChart = SetTimer(1, 500);
return 0;
}
void OnPaint(HDC hDC)
{
CPaintDC pdc(m_hWnd);
DrawAll(pdc);
}
void OnTimer(UINT uiID)
{
if(!IsWindowVisible())
{
return;
}
if(uiID == uiTimerDrawChart)
{
cmChartMan.Render();
}
if(uiID == uiTimerFadding)
{
switch(epssShowState)
{
case pssHidden:
// KillTimer(uiTimerFadding);
// uiTimerFadding = 0;
nOpacity = 0;
break;
case pssShowed:
// KillTimer(uiTimerFadding);
// uiTimerFadding = 0;
nOpacity = 255;
break;
case pssHidding:
nOpacity -= 80;
if(nOpacity < 0)
nOpacity = 0;
::SetLayeredWindowAttributes(m_hWnd, 0, nOpacity, LWA_ALPHA);
if(nOpacity <= 0)
{
ShowWindow(SW_HIDE);
epssShowState = pssHidden;
}
break;
case pssShowing:
nOpacity += 80;
if(nOpacity > 255)
nOpacity = 255;
::SetLayeredWindowAttributes(m_hWnd, 0, nOpacity, LWA_ALPHA);
if(nOpacity >= 255)
epssShowState = pssShowed;
break;
}
}
}
HWND CreateMe(HWND hParent)
{
CRect rect;
CalculatePos(hParent, rect);
return Create(hParent, _U_RECT(&rect));
}
bool ShowPopup(HWND hParent, CStrSegment * pss)
{
if(!::IsWindow(m_hWnd)) // not yet create
{
if(CreateMe(hParent))
{
::SetLayeredWindowAttributes(m_hWnd, 0, 0, LWA_ALPHA);
epssShowState = pssShowing;
uiTimerFadding = SetTimer(2, 100);
}
else
return false;
}
if(epssShowState == pssHidden || epssShowState == pssHidding)
epssShowState = pssShowing;
CRect rect;
CalculatePos(hParent, rect);
MoveWindow(&rect);
cmChartMan.SetSource(pss);
GetChartRect(rect);
cmChartMan.SetDisplayRect(rect);
ShowWindow(SW_SHOW);
InvalidateRect(NULL, FALSE);
UpdateWindow();
return true;
}
void HidePopup(bool bimmediately = false)
{
if(!::IsWindow(m_hWnd))
return;
if(bimmediately)
{
::SetLayeredWindowAttributes(m_hWnd, 0, 0, LWA_ALPHA);
nOpacity = 0;
ShowWindow(SW_HIDE);
epssShowState = pssHidden;
}
else
epssShowState = pssHidding;
}
protected:
COLORREF clrBack, clrBorder, clrTitleBack, clrTitleText;
CString strFontFace;
UINT uiFontSize;
bool bShowTitle;
int nMaxWidth, nMinWidth;
int nPreferedHeight;
EPopupShowState epssShowState;
UINT uiTimerDrawChart, uiTimerFadding;
int nOpacity;
CChartMan cmChartMan;
void CalculatePos(HWND hParent, CRect & rect)
{
CWindow pwnd(hParent);
pwnd.GetWindowRect(&rect);
int nsw = ::GetSystemMetrics(SM_CXSCREEN);
int nsh = ::GetSystemMetrics(SM_CYSCREEN);
int n1, n2;
n1 = rect.top;
n2 = nsh - rect.bottom;
if(n1 >= n2) // show top of parent window
{
rect.OffsetRect(0, -rect.Height());
rect.top = rect.bottom - nPreferedHeight;
}
else // show bottom of parent window
{
rect.OffsetRect(0, rect.Height());
rect.bottom = rect.top + nPreferedHeight;
}
if(rect.Width() < nMinWidth)
rect.right = rect.left + nMinWidth;
if(rect.Width() > nMaxWidth)
rect.right = rect.left + nMaxWidth;
}
void GetChartRect(CRect & rect)
{
GetClientRect(&rect);
if(bShowTitle)
{
CSize sz;
HDC hdc = GetDC();
GetTitleSize(hdc, sz);
ReleaseDC(hdc);
rect.top += sz.cy;
}
rect.DeflateRect(8, 8, 8, 8);
}
void GetTitleSize(HDC hdc, CSize & sz)
{
USES_CONVERSION;
CRect rect;
GetClientRect(&rect);
Graphics g(hdc);
Gdiplus::Font font(&FontFamily(T2W(strFontFace.GetBuffer(1))),
(REAL)uiFontSize);
RectF layoutRect(0, 0, (REAL)rect.Width(), (REAL)rect.Height());
RectF boundRect;
CString str = cmChartMan.GetSource()->GetDesc();
g.MeasureString(T2W(str.GetBuffer(1)), str.GetLength(), &font,
layoutRect, &boundRect);
sz.cx = (LONG)boundRect.Width;
sz.cy = (LONG)boundRect.Height + 4;
}
void DrawBack(HDC hdc)
{
CRect rClient;
Graphics g(hdc);
SolidBrush sb(Color(GetRValue(clrBack), GetGValue(clrBack),
GetBValue(clrBack)));
Pen pen(Color(GetRValue(clrBorder), GetGValue(clrBorder),
GetBValue(clrBorder)));
GetClientRect(&rClient);
rClient.DeflateRect(0, 0, 1, 1);
g.FillRectangle(&sb, 0, 0, rClient.Width(), rClient.Height());
g.DrawRectangle(&pen, 0, 0, rClient.Width(), rClient.Height());
if(bShowTitle)
{
CSize sz;
GetTitleSize(hdc, sz);
rClient.DeflateRect(1, 1, 0, 0);
rClient.bottom = rClient.top + sz.cy;
sb.SetColor(Color(GetRValue(clrTitleBack), GetGValue(clrTitleBack),
GetBValue(clrTitleBack)));
g.FillRectangle(&sb, rClient.left, rClient.top, rClient.Width(),
rClient.Height());
g.DrawLine(&pen, rClient.left, rClient.bottom, rClient.right,
rClient.bottom);
rClient.DeflateRect(0, 0, 0, 1);
Gdiplus::Font font(&FontFamily(T2W(strFontFace.GetBuffer(1))),
(REAL)uiFontSize);
sb.SetColor(Color(GetRValue(clrTitleText), GetGValue(clrTitleText),
GetBValue(clrTitleText)));
PointF pt;
pt.X = (REAL)(rClient.Width() - sz.cx) / 2;
pt.Y = (REAL)(rClient.top + 2);
Rect rClip(rClient.left, rClient.top, rClient.Width(),
rClient.Height());
g.SetClip(rClip);
g.DrawString(T2W(cmChartMan.GetSource()->GetDesc().GetBuffer(1)),
cmChartMan.GetSource()->GetDesc().GetLength(), &font, pt, &sb);
g.ResetClip();
}
}
void DrawChart(void)
{
cmChartMan.Render();
}
void DrawAll(HDC hdc)
{
DrawBack(hdc);
DrawChart();
}
};