📄 zbutton.cpp
字号:
// zButton.cpp : implementation file
//
#include "stdafx.h"
#include "zButton.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CzButton
CzButton::CzButton()
{
m_DrawMode=1; // normal drawing mode
m_FocusRectMargin=0; // disable focus dotted rect
hClipRgn=NULL; // no clipping region
m_TextColor=GetSysColor(COLOR_BTNTEXT); // default button text color
m_button_down = m_tracking = m_Checked = false;
}
CzButton::~CzButton()
{
if (hClipRgn) DeleteObject(hClipRgn); // free clip region
}
BEGIN_MESSAGE_MAP(CzButton, CButton)
//{{AFX_MSG_MAP(CzButton)
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_ERASEBKGND()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CzButton message handlers
void CzButton::PreSubclassWindow()
{
// TODO: Add your specialized code here and/or call the base class
ModifyStyle( 0, BS_OWNERDRAW );
CButton::PreSubclassWindow();
}
void CzButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
// TODO: Add your code to draw the specified item
ASSERT (lpDrawItemStruct);
//TRACE("* Captured: %08X\n", ::GetCapture());
//Check if the button state in not in inconsistent mode...
POINT mouse_position;
if ((m_button_down) && (::GetCapture() == m_hWnd) && (::GetCursorPos(&mouse_position))){
if (::WindowFromPoint(mouse_position) == m_hWnd){
if ((GetState() & BST_PUSHED) != BST_PUSHED) {
//TRACE("* Inconsistency up detected! Fixing.\n");
SetState(TRUE);
return;
}
} else {
if ((GetState() & BST_PUSHED) == BST_PUSHED) {
//TRACE("* Inconsistency up detected! Fixing.\n");
SetState(FALSE);
return;
}
}
}
//TRACE("* Drawing: %08x\n", lpDrawItemStruct->itemState);
CString sCaption;
CDC *pDC = CDC::FromHandle(lpDrawItemStruct->hDC); // get device context
RECT r=lpDrawItemStruct->rcItem; // context rectangle
int cx = r.right - r.left ; // get width
int cy = r.bottom - r.top ; // get height
// get text box position
RECT tr={r.left+m_FocusRectMargin+2,r.top,r.right-m_FocusRectMargin-2,r.bottom};
GetWindowText(sCaption); // get button text
pDC->SetBkMode(TRANSPARENT);
// Select the correct skin
if (lpDrawItemStruct->itemState & ODS_DISABLED){ // DISABLED BUTTON
if(m_bDisabled.m_hObject==NULL)
// no skin selected for disabled state -> standard button
pDC->FillSolidRect(&r,GetSysColor(COLOR_BTNFACE));
else // paint the skin
DrawBitmap(pDC,(HBITMAP)m_bDisabled,r,m_DrawMode);
// if needed, draw the standard 3D rectangular border
if (m_Border) pDC->DrawEdge(&r,EDGE_RAISED,BF_RECT);
// paint the etched button text
pDC->SetTextColor(GetSysColor(COLOR_3DHILIGHT));
pDC->DrawText(sCaption,&tr,DT_SINGLELINE|DT_VCENTER|DT_CENTER);
pDC->SetTextColor(GetSysColor(COLOR_GRAYTEXT));
OffsetRect(&tr,-1,-1);
pDC->DrawText(sCaption,&tr,DT_SINGLELINE|DT_VCENTER|DT_CENTER);
} else { // SELECTED (DOWN) BUTTON
if ((lpDrawItemStruct->itemState & ODS_SELECTED)||m_Checked){
if(m_bDown.m_hObject==NULL)
// no skin selected for selected state -> standard button
pDC->FillSolidRect(&r,GetSysColor(COLOR_BTNFACE));
else { // paint the skin
DrawBitmap(pDC,(HBITMAP)m_bDown,r,m_DrawMode);
}
OffsetRect(&tr,1,1); //shift text
// if needed, draw the standard 3D rectangular border
if (m_Border) pDC->DrawEdge(&r,EDGE_SUNKEN,BF_RECT);
} else { // DEFAULT BUTTON
if(m_bNormal.m_hObject==NULL)
// no skin selected for normal state -> standard button
pDC->FillSolidRect(&r,GetSysColor(COLOR_BTNFACE));
else // paint the skin
if ((m_tracking)&&(m_bOver.m_hObject!=NULL)){
DrawBitmap(pDC,(HBITMAP)m_bOver,r,m_DrawMode);
} else {
if ((lpDrawItemStruct->itemState & ODS_FOCUS)&&(m_bFocus.m_hObject!=NULL)){
DrawBitmap(pDC,(HBITMAP)m_bFocus,r,m_DrawMode);
} else {
DrawBitmap(pDC,(HBITMAP)m_bNormal,r,m_DrawMode);
}
}
// if needed, draw the standard 3D rectangular border
if (m_Border) pDC->DrawEdge(&r,EDGE_RAISED,BF_RECT);
}
// paint the focus rect
if ((lpDrawItemStruct->itemState & ODS_FOCUS)&&(m_FocusRectMargin>0)){
r.left += m_FocusRectMargin ;
r.top += m_FocusRectMargin ;
r.right -= m_FocusRectMargin ;
r.bottom -= m_FocusRectMargin ;
DrawFocusRect (lpDrawItemStruct->hDC, &r) ;
}
// paint the enabled button text
pDC->SetTextColor(m_TextColor);
pDC->DrawText(sCaption,&tr,DT_SINGLELINE|DT_VCENTER|DT_CENTER);
}
}
void CzButton::DrawBitmap(CDC *dc, HBITMAP hbmp, RECT r, int DrawMode)
{
// DrawMode: 0=Normal; 1=stretch; 2=tiled fill
if(DrawMode==2){
FillWithBitmap(dc,hbmp,r);
return;
}
if(!hbmp) return; //safe check
int cx=r.right - r.left;
int cy=r.bottom - r.top;
CDC dcBmp,dcMask;
dcBmp.CreateCompatibleDC(dc);
dcBmp.SelectObject(hbmp);
if (m_bMask.m_hObject!=NULL){
dcMask.CreateCompatibleDC(dc);
dcMask.SelectObject(m_bMask);
CDC hdcMem;
hdcMem.CreateCompatibleDC(dc);
CBitmap hBitmap;
hBitmap.CreateCompatibleBitmap(dc,cx,cy);
hdcMem.SelectObject(hBitmap);
hdcMem.BitBlt(r.left,r.top,cx,cy,dc,0,0,SRCCOPY);
if(!DrawMode){
hdcMem.BitBlt(r.left,r.top,cx,cy,&dcBmp,0,0,SRCINVERT);
hdcMem.BitBlt(r.left,r.top,cx,cy,&dcMask,0,0,SRCAND);
hdcMem.BitBlt(r.left,r.top,cx,cy,&dcBmp,0,0,SRCINVERT);
} else {
int bx=GetBitmapWidth(hbmp);
int by=GetBitmapHeight(hbmp);
hdcMem.StretchBlt(r.left,r.top,cx,cy,&dcBmp,0,0,bx,by,SRCINVERT);
hdcMem.StretchBlt(r.left,r.top,cx,cy,&dcMask,0,0,bx,by,SRCAND);
hdcMem.StretchBlt(r.left,r.top,cx,cy,&dcBmp,0,0,bx,by,SRCINVERT);
}
dc->BitBlt(r.left,r.top,cx,cy,&hdcMem,0,0,SRCCOPY);
hdcMem.DeleteDC();
hBitmap.DeleteObject();
DeleteDC(dcMask);
} else {
if(!DrawMode){
dc->BitBlt(r.left,r.top,cx,cy,&dcBmp,0,0,SRCCOPY);
} else {
int bx=GetBitmapWidth(hbmp);
int by=GetBitmapHeight(hbmp);
dc->StretchBlt(r.left,r.top,cx,cy,&dcBmp,0,0,bx,by,SRCCOPY);
}
}
DeleteDC(dcBmp);
}
void CzButton::FillWithBitmap(CDC *dc, HBITMAP hbmp, RECT r)
{
if(!hbmp) return;
CDC memdc;
memdc.CreateCompatibleDC(dc);
memdc.SelectObject(hbmp);
int w = r.right - r.left;
int h = r.bottom - r.top;
int x,y,z;
int bx=GetBitmapWidth(hbmp);
int by=GetBitmapHeight(hbmp);
for (y = r.top ; y < h ; y += by){
if ((y+by)>h) by=h-y;
z=bx;
for (x = r.left ; x < w ; x += z){
if ((x+z)>w) z=w-x;
dc->BitBlt(x, y, z, by, &memdc, 0, 0, SRCCOPY);
}
}
DeleteDC(memdc);
}
/////////////////////////////////////////////////////////////////////////////
int CzButton::GetBitmapWidth (HBITMAP hBitmap)
{ BITMAP bm; GetObject(hBitmap,sizeof(BITMAP),(PSTR)&bm); return bm.bmWidth;}
/////////////////////////////////////////////////////////////////////////////
int CzButton::GetBitmapHeight (HBITMAP hBitmap)
{ BITMAP bm; GetObject(hBitmap,sizeof(BITMAP),(PSTR)&bm); return bm.bmHeight;}
/////////////////////////////////////////////////////////////////////////////
void CzButton::SetSkin(UINT normal,UINT down,UINT over,UINT disabled, UINT focus,UINT mask,
short drawmode, short border, short margin)
{
m_bNormal.DeleteObject(); //free previous allocated bitmap
m_bDown.DeleteObject();
m_bOver.DeleteObject();
m_bDisabled.DeleteObject();
m_bMask.DeleteObject();
m_bFocus.DeleteObject();
if (normal>0) m_bNormal.LoadBitmap(normal);
if (down>0) m_bDown.LoadBitmap(down);
if (over>0) m_bOver.LoadBitmap(over);
if (focus>0) m_bFocus.LoadBitmap(focus);
if (disabled>0) m_bDisabled.LoadBitmap(disabled);
else if (normal>0) m_bDisabled.LoadBitmap(normal);
m_DrawMode=max(0,min(drawmode,2));
m_Border=border;
m_FocusRectMargin=max(0,margin);
if (mask>0){
m_bMask.LoadBitmap(mask);
if (hClipRgn) DeleteObject(hClipRgn);
hClipRgn = CreateRgnFromBitmap(m_bMask,RGB(255,255,255));
if (hClipRgn){
SetWindowRgn(hClipRgn, TRUE);
SelectClipRgn((HDC)GetDC(),hClipRgn);
}
if (m_DrawMode==0){
SetWindowPos(NULL,0,0,GetBitmapWidth(m_bMask),
GetBitmapHeight(m_bMask),SWP_NOZORDER|SWP_NOMOVE);
}
}
}
////////////////////////////////////////////////////////////////////////////
void CzButton::SetPosition(CRect RC, int pos)
{
MoveWindow(RC.left + 50 + 40 * pos, RC.bottom - 30, 30, 20);
}
/////////////////////////////////////////////////////////////////////////////
HRGN CzButton::CreateRgnFromBitmap(HBITMAP hBmp, COLORREF color)
{
if (!hBmp) return NULL;
BITMAP bm;
GetObject( hBmp, sizeof(BITMAP), &bm ); // get bitmap attributes
CDC dcBmp;
dcBmp.CreateCompatibleDC(GetDC()); //Creates a memory device context for the bitmap
dcBmp.SelectObject(hBmp); //selects the bitmap in the device context
const DWORD RDHDR = sizeof(RGNDATAHEADER);
const DWORD MAXBUF = 40; // size of one block in RECTs
// (i.e. MAXBUF*sizeof(RECT) in bytes)
LPRECT pRects;
DWORD cBlocks = 0; // number of allocated blocks
INT i, j; // current position in mask image
INT first = 0; // left position of current scan line
// where mask was found
bool wasfirst = false; // set when if mask was found in current scan line
bool ismask; // set when current color is mask color
// allocate memory for region data
RGNDATAHEADER* pRgnData = (RGNDATAHEADER*)new BYTE[ RDHDR + ++cBlocks * MAXBUF * sizeof(RECT) ];
memset( pRgnData, 0, RDHDR + cBlocks * MAXBUF * sizeof(RECT) );
// fill it by default
pRgnData->dwSize = RDHDR;
pRgnData->iType = RDH_RECTANGLES;
pRgnData->nCount = 0;
for ( i = 0; i < bm.bmHeight; i++ )
for ( j = 0; j < bm.bmWidth; j++ ){
// get color
ismask=(dcBmp.GetPixel(j,bm.bmHeight-i-1)!=color);
// place part of scan line as RECT region if transparent color found after mask color or
// mask color found at the end of mask image
if (wasfirst && ((ismask && (j==(bm.bmWidth-1)))||(ismask ^ (j<bm.bmWidth)))){
// get offset to RECT array if RGNDATA buffer
pRects = (LPRECT)((LPBYTE)pRgnData + RDHDR);
// save current RECT
pRects[ pRgnData->nCount++ ] = CRect( first, bm.bmHeight - i - 1, j+(j==(bm.bmWidth-1)), bm.bmHeight - i );
// if buffer full reallocate it
if ( pRgnData->nCount >= cBlocks * MAXBUF ){
LPBYTE pRgnDataNew = new BYTE[ RDHDR + ++cBlocks * MAXBUF * sizeof(RECT) ];
memcpy( pRgnDataNew, pRgnData, RDHDR + (cBlocks - 1) * MAXBUF * sizeof(RECT) );
delete pRgnData;
pRgnData = (RGNDATAHEADER*)pRgnDataNew;
}
wasfirst = false;
} else if ( !wasfirst && ismask ){ // set wasfirst when mask is found
first = j;
wasfirst = true;
}
}
dcBmp.DeleteDC(); //release the bitmap
// create region
/* Under WinNT the ExtCreateRegion returns NULL (by Fable@aramszu.net) */
// HRGN hRgn = ExtCreateRegion( NULL, RDHDR + pRgnData->nCount * sizeof(RECT), (LPRGNDATA)pRgnData );
/* ExtCreateRegion replacement { */
HRGN hRgn=CreateRectRgn(0, 0, 0, 0);
ASSERT( hRgn!=NULL );
pRects = (LPRECT)((LPBYTE)pRgnData + RDHDR);
for(i=0;i<(int)pRgnData->nCount;i++)
{
HRGN hr=CreateRectRgn(pRects[i].left, pRects[i].top, pRects[i].right, pRects[i].bottom);
VERIFY(CombineRgn(hRgn, hRgn, hr, RGN_OR)!=ERROR);
if (hr) DeleteObject(hr);
}
ASSERT( hRgn!=NULL );
/* } ExtCreateRegion replacement */
delete pRgnData;
return hRgn;
}
void CzButton::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
m_button_down = true;
CButton::OnLButtonDown(nFlags, point);
}
void CzButton::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
m_button_down = false;
CButton::OnLButtonUp(nFlags, point);
}
/////////////////////////////////////////////////////////////////////////////
COLORREF CzButton::SetTextColor(COLORREF new_color)
{
COLORREF tmp_color=m_TextColor;
m_TextColor=new_color;
return tmp_color; //returns the previous color
}
BOOL CzButton::OnEraseBkgnd(CDC* pDC)
{
// TODO: Add your message handler code here and/or call default
return 1;
// return CButton::OnEraseBkgnd(pDC);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -