CxSkinButton是開源的換膚按鈕控件,用起來也很方便。CxSkinButton提供的皮膚設置接口如下:
void SetSkin(UINT normal,UINT down, UINT over=0, UINT disabled=0, UINT focus=0,UINT mask=0,short drawmode=1,short border=1,short margin=4)
可以看到該接口必須輸入一個個的狀態位圖ID,但是在實際中,美工將按鈕的各個狀態圖放在一張圖片中,上述接口就無法使用。針對這個問題, 可以在CxSkinButton的基礎上,擴展一個新的類,增加一個新的皮膚設置接口。
繼承類定義:
class CDvssButton :
public CxSkinButton
{
public:
CDvssButton(void);
~CDvssButton(void);
public:
//此處接口可以根據美工提供圖片適當改變
void SetSkin(UINT nIDRes,UINT nIDMask = 0,short nDrawMode = 1,short nBorder = 1,short nMargin = 4,int nSmallImages = 7);
private:
void CopyBitmap(CBitmap* pDstBitmap,int nDstX,int nDstY,int nWidth,int nHeight,CBitmap* pSrcBitmap,int nSrcX,int nSrcY);
};
繼承類實現函數:
void CDvssButton::SetSkin(UINT nIDRes,UINT nIDMask,short nDrawMode,short nBorder,short nMargin,int nSmallImages)
{
m_bNormal.DeleteObject();
m_bDown.DeleteObject();
m_bOver.DeleteObject();
m_bDisabled.DeleteObject();
m_bMask.DeleteObject();
m_bFocus.DeleteObject();
CBitmap bitmap;
bitmap.LoadBitmap(nIDRes);
int nWidth = GetBitmapWidth((HBITMAP)bitmap.m_hObject);
int nHeight = GetBitmapHeight((HBITMAP)bitmap.m_hObject);
//將大圖片的各種狀態圖拷貝到對應的狀態位圖對象成員中,此處需根據美工提供的圖片自己靈活調用
CopyBitmap(&m_bDisabled,0,0,nWidth/nSmallImages,nHeight,&bitmap,0,0);
CopyBitmap(&m_bNormal,0,0,nWidth/nSmallImages,nHeight,&bitmap,nWidth/nSmallImages,0);
CopyBitmap(&m_bDown,0,0,nWidth/nSmallImages,nHeight,&bitmap,nWidth/nSmallImages*2,0);
CopyBitmap(&m_bOver,0,0,nWidth/nSmallImages,nHeight,&bitmap,nWidth/nSmallImages*3,0);
bitmap.DeleteObject();
m_DrawMode=max(0,min(nDrawMode,2));
m_Border=nBorder;
m_FocusRectMargin=max(0,nMargin);
if (nIDMask>0){
m_bMask.LoadBitmap(nIDMask);
if (hClipRgn) DeleteObject(hClipRgn);
hClipRgn = CreateRgnFromBitmap(m_bMask,RGB(255,255,255));
if (hClipRgn){
SetWindowRgn(hClipRgn, TRUE);
CDC *pDC = GetDC();
if (pDC){
SelectClipRgn(pDC->GetSafeHdc(), hClipRgn);
ReleaseDC(pDC);
}
}
if (m_DrawMode==0){
SetWindowPos(NULL,0,0,GetBitmapWidth(m_bMask),
GetBitmapHeight(m_bMask),SWP_NOZORDER|SWP_NOMOVE);
}
}
}
//該函數可以實現將一張圖片位圖對象的指定位置,指定高,寬拷貝給另一位圖對象
void CDvssButton::CopyBitmap(CBitmap* pDstBitmap,int nDstX,int nDstY,int nWidth,int nHeight,CBitmap* pSrcBitmap,int nSrcX,int nSrcY)
{
CDC SrcDC;
CDC DstDC;
SrcDC.CreateCompatibleDC(NULL);
DstDC.CreateCompatibleDC(NULL);
BITMAP bitmap;
pSrcBitmap->GetBitmap(&bitmap);
bitmap.bmWidth = nWidth;
bitmap.bmHeight = nHeight;
pDstBitmap->CreateBitmapIndirect(&bitmap);
//此處不要使用如下這種方法創建兼容位圖,否則創建的位圖格式只有黑白兩色
//pDstBitmap->CreateCompatibleBitmap(&DstDC,nWidth,nHeight);
CBitmap* pOldSrcBitmap = SrcDC.SelectObject(pSrcBitmap);
CBitmap* pOldDstBitmap = DstDC.SelectObject(pDstBitmap);
DstDC.BitBlt(0,0,nWidth,nHeight,&SrcDC,nSrcX,nSrcY,SRCCOPY);
SrcDC.SelectObject(pOldSrcBitmap);
DstDC.SelectObject(pOldDstBitmap);
SrcDC.DeleteDC();
DstDC.DeleteDC();
}
如此一來,該按鈕就可以實現對一張含有多種狀態圖圖片的處理,上述代碼,測試通過,可以直接使用。這裏也可以直接修改CxSkinButton的源碼,解決此問題。但CxSkinButton類大量的成員變量,成員函數都是保護成員,提供了擴展的便利,實現起來很快。