📄 kcsidebannerwnd.cpp
字号:
/****************************************************************************
* class : CKCSideBannerWnd
* author : Peter Mares / kinkycode.com (gui@kinkycode.com)
* base class : CWnd (MFC)
* notes : A control to act as a banner to a window. More of a look'n'feel
* control.
* NOTE: Remember to link to MSIMG32.LIB to enable GradientFill()
*
* Blurb : Its free, it feels good and its from South Africa :)
****************************************************************************
* Version History:
*
* v0.1 (20-Oct-2003)
*
* - First public release
*
* v0.2 (24-Oct-2003)
*
* - Added (Set)(Get)ColTxtTitle() and (Set)(Get)ColTxtCaption() functions
* - Revised all other updates since initial release
*
* v0.3 (25-Oct-2003)
*
* - Changed the SetIcon() function to support a delete flag
* - Added SetTexture() function
* - Fixed a resource leak
*
* v0.31 (26-Oct-2003)
*
* - Added UNICODE support to the control - thanks to Abraxas23
*
* v0.32 (29-Oct-2003)
*
* - Added support for gradient drawing without the dependancy on MSIMG32.LIB
* Used John A. Johnson's GradientFill() function, and used dynamic linking
* of the MSIMG32.DLL (thanks to Irek Zielinski's code)
*
****************************************************************************/
#include "stdafx.h"
#include "KCSideBannerWnd.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CKCSideBannerWnd
CKCSideBannerWnd::CKCSideBannerWnd()
: CWndUtil(KCSB_CLASSNAME)
, m_pOwner(NULL)
, m_nSize(50)
, m_uPosFlag(0)
, m_uFillFlag(KCSB_FILL_GRADIENT)
, m_colBkg(RGB(255,255,255))
, m_colBkg2(RGB(128,128,192))
, m_colTxtTitle(RGB(0,0,0))
, m_colTxtCaption(RGB(0,0,0))
, m_colEdge(RGB(0,0,0))
, m_strTitle(_T("This is the sample title"))
, m_strCaption(_T("This is the sample caption..."))
, m_szEdgeOffset(5,3)
, m_szCaptionOffset(4, 10)
, m_uIconPos(KCSB_ICON_RIGHT)
, m_hIcon(0)
, m_bIconDelete(false)
, m_hBkgBitmap(0)
, m_bBmpDelete(false)
, m_pGradFill(NULL)
, m_hGradMod(0)
{
RegisterWndClass();
CFont font;
font.CreatePointFont(110, _T("Tahoma Bold"));
font.GetLogFont(&m_lfTitle);
font.DeleteObject();
font.CreatePointFont(85, _T("Tahoma"));
font.GetLogFont(&m_lfCaption);
font.DeleteObject();
// try and load the MSIMG32.LIB
if ( (m_hGradMod = LoadLibrary("MSIMG32.DLL")) )
m_pGradFill = (PFNGRADFILL) GetProcAddress( m_hGradMod, "GradientFill" );
}
/////////////////////////////////////////////////////////////////////////////
CKCSideBannerWnd::~CKCSideBannerWnd()
{
if ( m_hBkgBitmap && m_bBmpDelete )
::DeleteObject(m_hBkgBitmap);
if ( m_hIcon && m_bIconDelete )
::DeleteObject(m_hIcon);
if ( m_hGradMod )
::FreeLibrary(m_hGradMod);
}
/////////////////////////////////////////////////////////////////////////////
BEGIN_MESSAGE_MAP(CKCSideBannerWnd, CWnd)
//{{AFX_MSG_MAP(CKCSideBannerWnd)
ON_WM_PAINT()
ON_WM_ERASEBKGND()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
BOOL CKCSideBannerWnd::Attach(CWnd* pWnd, unsigned int uFlags, unsigned int uiID)
{
ASSERT(pWnd);
if ( !pWnd )
return FALSE;
ASSERT(pWnd->m_hWnd);
if ( !pWnd->m_hWnd )
return FALSE;
CRect rect;
m_pOwner = pWnd;
m_pOwner->GetWindowRect(&rect);
m_pOwner->ClientToScreen(&rect);
m_uPosFlag = uFlags;
// Banner LEFT
if ( uFlags & KCSB_ATTACH_LEFT )
{
rect.left -= m_nSize;
if ( rect.left < 0 )
rect.OffsetRect( -rect.left, 0 );
}
// Banner RIGHT
else if ( uFlags & KCSB_ATTACH_RIGHT )
{
rect.right += m_nSize;
}
// Banner TOP
else if ( uFlags & KCSB_ATTACH_TOP )
{
rect.top -= m_nSize;
if ( rect.top < 0 )
rect.OffsetRect( 0, -rect.top );
}
// Banner BOTTOM
else if ( uFlags & KCSB_ATTACH_BOTTOM )
{
rect.bottom += m_nSize;
}
// update the size of the owner
m_pOwner->SetWindowPos(NULL, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOMOVE | SWP_NOZORDER);
// update the positions of the child controls
UpdateLayout(m_nSize);
// attach the banner respective to its positional flag
m_pOwner->GetClientRect(&rect);
if ( uFlags & KCSB_ATTACH_LEFT )
rect.right = rect.left + m_nSize;
else if ( uFlags & KCSB_ATTACH_RIGHT )
rect.left = rect.right - m_nSize;
else if ( uFlags & KCSB_ATTACH_TOP )
rect.bottom = rect.top + m_nSize;
else if ( uFlags & KCSB_ATTACH_BOTTOM )
rect.top = rect.bottom - m_nSize;
// et voila... create the banner..
Create(WS_CHILD | WS_VISIBLE, rect, m_pOwner, uiID);
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
void CKCSideBannerWnd::SetSize(int nSize)
{
if ( m_hWnd )
{
CRect rect;
//
// offset the controls accordingly
if ( m_uPosFlag & KCSB_ATTACH_LEFT || m_uPosFlag & KCSB_ATTACH_TOP )
{
UpdateLayout( nSize - m_nSize );
}
//
// size the containing window
m_pOwner->GetWindowRect(&rect);
if ( m_uPosFlag & KCSB_ATTACH_LEFT )
{
rect.left -= (nSize-m_nSize);
if ( rect.left < 0 )
rect.OffsetRect( -rect.left, 0 );
m_pOwner->SetWindowPos(NULL, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOMOVE | SWP_NOZORDER);
}
else if ( m_uPosFlag & KCSB_ATTACH_RIGHT )
{
rect.left -= (nSize - m_nSize);
m_pOwner->SetWindowPos(NULL, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER);
}
else if ( m_uPosFlag & KCSB_ATTACH_TOP )
{
rect.top -= (nSize - m_nSize);
if ( rect.top < 0 )
rect.OffsetRect( 0, -rect.top );
m_pOwner->SetWindowPos(NULL, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOMOVE | SWP_NOZORDER);
}
else if ( m_uPosFlag & KCSB_ATTACH_BOTTOM )
{
rect.top -= (nSize - m_nSize );
m_pOwner->SetWindowPos(NULL, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER);
}
// size the banner
GetClientRect(&rect);
if ( m_uPosFlag & KCSB_ATTACH_LEFT )
rect.right = rect.left + nSize;
else if ( m_uPosFlag & KCSB_ATTACH_RIGHT )
rect.right = rect.left + nSize;
else if ( m_uPosFlag & KCSB_ATTACH_TOP )
rect.bottom = rect.top + nSize;
else if ( m_uPosFlag & KCSB_ATTACH_BOTTOM )
rect.bottom = rect.top + nSize;
MoveWindow(&rect);
m_pOwner->Invalidate();
}
m_nSize = nSize;
}
/////////////////////////////////////////////////////////////////////////////
void CKCSideBannerWnd::UpdateSize()
{
if ( !m_hWnd )
return;
CRect rect;
m_pOwner->GetClientRect(&rect);
if ( m_uPosFlag & KCSB_ATTACH_LEFT )
rect.right = rect.left + m_nSize;
else if ( m_uPosFlag & KCSB_ATTACH_RIGHT )
rect.left = rect.right - m_nSize;
else if ( m_uPosFlag & KCSB_ATTACH_TOP )
rect.bottom = rect.top + m_nSize;
else if ( m_uPosFlag & KCSB_ATTACH_BOTTOM )
rect.top = rect.bottom - m_nSize;
MoveWindow(&rect, TRUE);
}
/////////////////////////////////////////////////////////////////////////////
void CKCSideBannerWnd::SetPosFlag(unsigned int uFlags)
{
if ( (uFlags & 0xF) == (m_uPosFlag & 0xF) )
return;
CRect rect;
int nSize = m_nSize;
SetSize(0);
m_uPosFlag = uFlags;
SetSize(nSize);
m_pOwner->GetClientRect(&rect);
if ( uFlags & KCSB_ATTACH_LEFT )
rect.right = rect.left + nSize;
else if ( uFlags & KCSB_ATTACH_RIGHT )
rect.left = rect.right - nSize;
else if ( uFlags & KCSB_ATTACH_TOP )
rect.bottom = rect.top + nSize;
else if ( uFlags & KCSB_ATTACH_BOTTOM )
rect.top = rect.bottom - nSize;
MoveWindow(&rect);
m_pOwner->Invalidate();
}
/////////////////////////////////////////////////////////////////////////////
void CKCSideBannerWnd::UpdateLayout(int nOffset)
{
stEnum data;
data.pBannerWnd = this;
data.pParentWnd = m_pOwner;
data.nOffset = nOffset;
data.uFlags = m_uPosFlag;
::EnumChildWindows( m_pOwner->m_hWnd, ChildEnumProc, (LPARAM)&data );
}
/////////////////////////////////////////////////////////////////////////////
BOOL CALLBACK CKCSideBannerWnd::ChildEnumProc(HWND hWndChild, LPARAM lParam)
{
stEnum* pData = (stEnum*) lParam;
HWND hWndParent = 0;
CRect rect;
POINT topLeft, bottomRight;
// check if the hwnd is valid, and check that its not the HWND to the banner
if ( hWndChild && hWndChild != pData->pBannerWnd->m_hWnd )
{
// now we check if the parent is actually the parent of the banner..
// this check was put it to deal with composite controls like a combobox..
// NOTE: For some reason, a combobox's edit control appears to be a child
// of the parent, until you query for its parent HWND.
hWndParent = ::GetParent(hWndChild);
if ( hWndParent == pData->pParentWnd->m_hWnd )
{
// we have a valid child window which we can now reposition
::GetWindowRect(hWndChild, &rect);
topLeft.x = rect.left;
topLeft.y = rect.top;
bottomRight.x = rect.right;
bottomRight.y = rect.bottom;
::ScreenToClient( pData->pParentWnd->m_hWnd, &topLeft );
::ScreenToClient( pData->pParentWnd->m_hWnd, &bottomRight );
if ( pData->uFlags & KCSB_ATTACH_LEFT )
{
topLeft.x += pData->nOffset;
bottomRight.x += pData->nOffset;
}
else if ( pData->uFlags & KCSB_ATTACH_TOP )
{
topLeft.y += pData->nOffset;
bottomRight.y += pData->nOffset;
}
::MoveWindow( hWndChild, topLeft.x, topLeft.y, bottomRight.x - topLeft.x, bottomRight.y - topLeft.y, TRUE );
}
}
// return TRUE to continue enumerating...
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
// CKCSideBannerWnd message handlers
/////////////////////////////////////////////////////////////////////////////
BOOL CKCSideBannerWnd::Create(DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext)
{
BOOL bResult = CWnd::Create(KCSB_CLASSNAME, _T(""), dwStyle, rect, pParentWnd, nID, pContext);
return bResult;
}
/////////////////////////////////////////////////////////////////////////////
void CKCSideBannerWnd::OnPaint()
{
CPaintDC dc(this); // device context for painting
CDC memDC;
CBitmap memBMP, *pOldBmp = NULL;
CRect rect;
GetClientRect(&rect);
// create mem DC
memDC.CreateCompatibleDC(&dc);
memBMP.CreateCompatibleBitmap(&dc, rect.Width(), rect.Height());
pOldBmp = memDC.SelectObject(&memBMP);
// draw the banner
DrawBackground(&memDC, rect);
DrawTextFields(&memDC, rect);
// render the image
dc.BitBlt(0, 0, rect.Width(), rect.Height(), &memDC, 0, 0, SRCCOPY);
// deselect object
memDC.SelectObject(pOldBmp);
// delete objects
memBMP.DeleteObject();
memDC.DeleteDC();
}
/////////////////////////////////////////////////////////////////////////////
BOOL CKCSideBannerWnd::OnEraseBkgnd(CDC* pDC)
{
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
void CKCSideBannerWnd::DrawBackground(CDC* pDC, CRect rect)
{
CBrush nBrush, *pOldBrush = NULL;
CPen nPen, *pOldPen = NULL;
// Flat fill...
if ( m_uFillFlag & KCSB_FILL_FLAT || ( (m_colBkg == m_colBkg2) && (m_uFillFlag & KCSB_FILL_GRADIENT) ))
{
pDC->FillSolidRect(&rect, m_colBkg);
DrawEdge(pDC, rect);
}
// Gradient fill
else if ( m_uFillFlag & KCSB_FILL_GRADIENT )
{
TRIVERTEX vert[2];
GRADIENT_RECT gRect;
ULONG uGFlag;
if ( m_pGradFill ) // can we use the MSIMG32.DLL function?
{
if ( (m_uPosFlag & KCSB_ATTACH_LEFT) || (m_uPosFlag & KCSB_ATTACH_RIGHT) )
{
// set the gradient fill according to position
if ( m_uPosFlag & KCSB_ATTACH_LEFT )
{
vert[0].x = 0;
vert[0].y = rect.top;
vert[0].Red = GetRValue(m_colBkg2)<<8;
vert[0].Green = GetGValue(m_colBkg2)<<8;
vert[0].Blue = GetBValue(m_colBkg2)<<8;
vert[0].Alpha = 0;
vert[1].x = rect.right;
vert[1].y = rect.bottom;
vert[1].Red = GetRValue(m_colBkg)<<8;
vert[1].Green = GetGValue(m_colBkg)<<8;
vert[1].Blue = GetBValue(m_colBkg)<<8;
vert[1].Alpha = 0;
}
else
{
vert[0].x = rect.right;
vert[0].y = rect.top;
vert[0].Red = GetRValue(m_colBkg)<<8;
vert[0].Green = GetGValue(m_colBkg)<<8;
vert[0].Blue = GetBValue(m_colBkg)<<8;
vert[0].Alpha = 0;
vert[1].x = 0;
vert[1].y = rect.bottom;
vert[1].Red = GetRValue(m_colBkg2)<<8;
vert[1].Green = GetGValue(m_colBkg2)<<8;
vert[1].Blue = GetBValue(m_colBkg2)<<8;
vert[1].Alpha = 0;
}
uGFlag = GRADIENT_FILL_RECT_V;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -