模仿QQ左侧的工具栏(QQBar)

  发现QQ的左侧的工具栏挺酷的,今天自己模仿了一个.直接用的QQ的图片资源文件.

  开始的时候呢,想用N个按钮来组合成那样的工具栏,但是发现显示的层次总是控制不好.比如当鼠标在第二个按钮上时,它竟然把上面的按钮盖住了一部分,很难看.

  后来索性把它们弄成一个按钮,通过鼠标所在的位置来判断所按的"按钮"(并非真正的按钮),并通过自己添加的BindMessage函数来为每个"按钮"来"绑定"一个消息.比如为第一个"按钮"绑定WM_MY_MESSAGE,这样就可以在主窗口中用ON_MESSAGE(WM_MY_MESSAGE,OnMyMessage)来处理了.

  添加一个按钮也很简单InsertButton(LPSTR szIcon),参数是按钮图标的文件名.

完整代码如下:

//XToolbar.h

struct BitmapInfo
{
 BOOL bHover;
 BOOL bPushed;
 HBITMAP hBitmapNormal;
 HBITMAP hBitmapHover;
 HBITMAP hBitmapPush;
 HICON hIcon;
 BitmapInfo * pNext;
};

class CXToolbar : public CButton
{
 DECLARE_DYNAMIC(CXToolbar)
public:
 CXToolbar();
 virtual ~CXToolbar();
 virtual void DrawItem(LPDRAWITEMSTRUCT lpDIS);
 BOOL InsertButton(LPSTR szIcon);
 BOOL SetCursor(HCURSOR hCursor);
 BOOL BindMessage(UINT message, WPARAM wParam = 0, LPARAM lParam = 0);
 BOOL Create(CWnd * pParentWnd, UINT nID,int x, int y, LPCTSTR szIocn);
protected:
 DECLARE_MESSAGE_MAP()
 virtual void PreSubclassWindow();
 afx_msg LRESULT OnMouseLeave(WPARAM wParam, LPARAM lParam);
 afx_msg LRESULT OnMouseHover(WPARAM wParam, LPARAM lParam);
 afx_msg void OnMouseMove(UINT nFlags, CPoint point);
 afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
 afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message);
private:
 UINT m_uTypeStyle;
 BOOL m_bCheckBox;
 HCURSOR m_hCursor;
 BOOL m_bTracking;
 HRGN m_hRgn;
 COLORREF m_clrTransparent;
 int m_nWidth;
 int m_nHeight;
 BitmapInfo * m_pbiHead;
 BitmapInfo * m_pbiTail;
 UINT m_uMessage;
 WPARAM m_wParam;
 LPARAM m_lParam;
};

//XToolbar.cpp

#include "XToolbar.h"

BOOL TransBlt(HDC hdcDest,int nXDest,int nYDest, int nWidth, int nHeight, HDC hdcSrc, int nXSrc, int nYSrc,COLORREF crColour)
{
 COLORREF crOldBack = SetBkColor(hdcDest,RGB(255,255,255));
 COLORREF crOldText = SetTextColor(hdcDest,0);
 HDC dcTrans;
 dcTrans = CreateCompatibleDC(hdcDest);
 HBITMAP bitmapTrans;
 bitmapTrans = CreateBitmap(nWidth, nHeight, 1, 1, NULL);
 HBITMAP OldBitmapTrans = (HBITMAP)SelectObject(dcTrans,bitmapTrans);
 COLORREF crOldBackSrc = SetBkColor(hdcSrc,crColour);
 BitBlt(dcTrans,0, 0, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, SRCCOPY);
 BitBlt(hdcDest,nXDest, nYDest, nWidth, nHeight, hdcSrc, 0, 0, SRCINVERT);
 BitBlt(hdcDest,nXDest, nYDest, nWidth, nHeight, dcTrans, 0, 0, SRCAND);
 BitBlt(hdcDest,nXDest, nYDest, nWidth, nHeight, hdcSrc, 0, 0, SRCINVERT);
 SelectObject(dcTrans,OldBitmapTrans);
 DeleteDC(dcTrans);
 DeleteObject(bitmapTrans);
 SetBkColor(hdcDest,crOldBack);
 SetBkColor(hdcSrc,crOldBackSrc);
 SetTextColor(hdcDest,crOldText);
 return TRUE;
}


HBITMAP LoadBitmapFromFile(LPCTSTR szBitmapName)
{
 return (HBITMAP)LoadImage(NULL, szBitmapName, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
}

HICON LoadIconFromFile(LPCTSTR szIconName)
{
 return (HICON)LoadImage(NULL, szIconName, IMAGE_ICON, 0, 0, LR_LOADFROMFILE);
}

IMPLEMENT_DYNAMIC(CXToolbar, CButton)
CXToolbar::CXToolbar()
{
 m_hCursor = NULL;
 m_bCheckBox = FALSE;
 m_uTypeStyle = BS_TYPEMASK; //???
 m_bTracking = FALSE;
 m_clrTransparent = RGB(255,0,255);
 m_hRgn = NULL;
 m_nWidth = 27;
 m_nHeight = 37;
 m_uMessage = 0;
 m_wParam = 0;
 m_lParam = 0;
 m_pbiHead = new BitmapInfo;
 
 m_pbiHead->hBitmapNormal = LoadBitmapFromFile("Skin//4.bmp");
 m_pbiHead->hBitmapHover = LoadBitmapFromFile("Skin//5.bmp");
 m_pbiHead->hBitmapPush = LoadBitmapFromFile("Skin//3.bmp");
 
 m_pbiHead->bPushed = TRUE;
 m_pbiHead->bHover = FALSE;
 m_pbiHead->pNext = NULL;

 m_pbiTail = m_pbiHead;
}

CXToolbar::~CXToolbar()
{
 while(m_pbiHead)
 {
  BitmapInfo * pTemp = m_pbiHead;
  m_pbiHead = m_pbiHead->pNext;
  if(pTemp->hBitmapNormal)
   DeleteObject(pTemp->hBitmapNormal);
  if(pTemp->hBitmapHover)
   DeleteObject(pTemp->hBitmapHover);
  if(pTemp->hBitmapPush)
   DeleteObject(pTemp->hBitmapPush);
  delete pTemp;
 }
}


BEGIN_MESSAGE_MAP(CXToolbar, CButton)
 ON_MESSAGE(WM_MOUSEHOVER,OnMouseHover)
 ON_MESSAGE(WM_MOUSELEAVE,OnMouseLeave)
 ON_WM_MOUSEMOVE()
 ON_WM_LBUTTONUP()
 ON_WM_SETCURSOR()
END_MESSAGE_MAP()

void CXToolbar::PreSubclassWindow()
{
 UINT nBS;
 nBS = GetButtonStyle();
 if (nBS & BS_CHECKBOX) m_bCheckBox = TRUE;
 if (m_uTypeStyle == BS_DEFPUSHBUTTON)
  m_uTypeStyle = BS_PUSHBUTTON;
 ASSERT(m_uTypeStyle != BS_OWNERDRAW);
 ModifyStyle(BS_TYPEMASK, BS_OWNERDRAW, SWP_FRAMECHANGED);
 SetWindowPos(NULL,0,0,m_nWidth,m_nHeight,SWP_NOMOVE | SWP_NOZORDER);
 CButton::PreSubclassWindow();
}

void CXToolbar::DrawItem(LPDRAWITEMSTRUCT lpDIS)
{
 CDC * pDC = CDC::FromHandle(lpDIS->hDC);
 CDC * pMemDC = new CDC;
 pMemDC->CreateCompatibleDC(pDC);
 CBitmap * pOldBitmap = NULL;
 BitmapInfo * pTemp = m_pbiHead;
 int y = 0;
 while(pTemp)
 {
  if(pTemp->bPushed)
   pOldBitmap = (CBitmap*)pMemDC->SelectObject(CBitmap::FromHandle(pTemp->hBitmapPush));
  else if(pTemp->bHover)
   pOldBitmap = (CBitmap*)pMemDC->SelectObject(CBitmap::FromHandle(pTemp->hBitmapHover));
  else
   pOldBitmap = (CBitmap*)pMemDC->SelectObject(CBitmap::FromHandle(pTemp->hBitmapNormal));
  TransBlt(pDC->GetSafeHdc(),0,y,27,37,pMemDC->GetSafeHdc(),0,0,RGB(255,0,255));
  if(pTemp->hIcon)
   DrawIconEx(pDC->GetSafeHdc(), 3, 3 + y, pTemp->hIcon,24,24,NULL,NULL,DI_NORMAL);
  pMemDC->SelectObject(pOldBitmap);
  y += 33;
  pTemp = pTemp->pNext;
 }
 delete pMemDC;
}

LRESULT CXToolbar::OnMouseLeave(WPARAM wParam, LPARAM lParam)
{
 m_bTracking = FALSE;
 BitmapInfo * pTemp = m_pbiHead;
 while(pTemp)
 {
  pTemp->bHover = FALSE; 
  pTemp = pTemp->pNext;
 }
 Invalidate(0);
 return 0;
}

LRESULT CXToolbar::OnMouseHover(WPARAM wParam, LPARAM lParam)
{
 return 0;
}

void CXToolbar::OnMouseMove(UINT nFlags, CPoint point)
{
 BOOL bRedraw = FALSE;
 if (!m_bTracking)
 {
  TRACKMOUSEEVENT tme;
  tme.cbSize = sizeof(tme);
  tme.hwndTrack = m_hWnd;
  tme.dwFlags = TME_LEAVE|TME_HOVER;
  tme.dwHoverTime = 1;
  m_bTracking = _TrackMouseEvent(&tme);
 }
 CRect rect;
 rect.left = 0;
 rect.right = 26;
 int i = 0;
 BitmapInfo * pTemp = m_pbiHead;
 while(pTemp)
 {
  rect.top = i * 33;
  rect.bottom = i * 33 + 32;
  if(rect.PtInRect(point))
  {
   if(!pTemp->bHover)
   {
    pTemp->bHover = TRUE;
    bRedraw = TRUE;
   }
  }
  else
  {
   if(pTemp->bHover)
   {
    pTemp->bHover = FALSE;
    bRedraw = TRUE;
   }
  }
  pTemp = pTemp->pNext;
  i++;
 }
 if(bRedraw)
  Invalidate(0);
 TRACE("bRedraw = %d/n",bRedraw);
 CButton::OnMouseMove(nFlags, point);
}

void CXToolbar::OnLButtonUp(UINT nFlags, CPoint point)
{
 BOOL bRedraw = FALSE;
 CRect rect;
 rect.left = 0;
 rect.right = 26;
 int i = 0;
 BitmapInfo * pTemp = m_pbiHead;
 while(pTemp)
 {
  rect.top = i * 33;
  rect.bottom = i * 33 + 32;
  if(rect.PtInRect(point))
  {
   if(!pTemp->bPushed)
   {
    pTemp->bPushed = TRUE;
    bRedraw = TRUE;
    if(m_wParam == 0 && m_lParam == 0)
     GetParent()->PostMessage(m_uMessage,0,(LPARAM)i);
    else
     GetParent()->PostMessage(m_uMessage,m_wParam,m_lParam);
   }
  }
  else
  {
   if(pTemp->bPushed)
   {
    pTemp->bPushed = FALSE;
    bRedraw = TRUE;
   }
  }
  pTemp = pTemp->pNext;
  i++;
 }
 if(bRedraw)
  Invalidate(0);
 CButton::OnLButtonUp(nFlags, point);
}

BOOL CXToolbar::InsertButton(LPSTR szIcon)
{
 BitmapInfo * pTemp = new BitmapInfo;
 pTemp->hBitmapNormal = LoadBitmapFromFile("Skin//barback2_normal.bmp");
 pTemp->hBitmapHover = LoadBitmapFromFile("Skin//barback2_over.bmp");
 pTemp->hBitmapPush = LoadBitmapFromFile("Skin//barback_disabled.bmp");
 pTemp->hIcon = LoadIconFromFile(szIcon);
 pTemp->bPushed = FALSE;
 pTemp->bHover = FALSE;
 pTemp->pNext = NULL;
 m_pbiTail->pNext = pTemp;
 m_pbiTail = pTemp;
 m_nHeight += 33;
 SetWindowPos(NULL,0,0,m_nWidth,m_nHeight,SWP_NOMOVE | SWP_NOZORDER);
 return 0;
}

BOOL CXToolbar::SetCursor(HCURSOR hCursor)
{
 m_hCursor = hCursor;
 return TRUE;
}
BOOL CXToolbar::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
 if(m_hCursor)
 {
  ::SetCursor(m_hCursor);
  return 1;
 }
 return CButton::OnSetCursor(pWnd, nHitTest, message);
}

BOOL CXToolbar::BindMessage(UINT message, WPARAM wParam , LPARAM lParam )
{
 if(message <= 0)
  return FALSE;
 m_uMessage = message;
 m_wParam = wParam;
 m_lParam = lParam;
 return TRUE;
}

BOOL CXToolbar::Create(CWnd * pParentWnd, UINT nID,int x, int y, LPCTSTR szIocn)
{
 RECT rect;
 rect.left = x; rect.right = x + 1; rect.top = y; rect.bottom = y + 1;
 CButton::Create("", WS_CHILD | WS_VISIBLE, rect, pParentWnd, nID);
 m_pbiHead->hIcon = LoadIconFromFile(szIocn);
 return TRUE;
}

使用方法:

 m_tb = new CXToolbar; //m_tb 的类型是 CXToolbar *

 m_tb->Create(this, 8888,10,10,"Skin//FriendButton.ico"); //8888是它的ID
 m_tb->InsertButton("Skin//CustomButton.ico");
 m_tb->InsertButton("Skin//EaseButton.ico");
 m_tb->InsertButton("Skin//SBuddyButton.ico");
 m_tb->SetCursor(LoadCursor(NULL,MAKEINTRESOURCE(32649)));
 m_tb->BindMessage(WM_MY_MESSAGE);

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值