AutoCAD 3DMAX C语言 Pro/E UG JAVA编程 PHP编程 Maya动画 Matlab应用 Android
Photoshop Word Excel flash VB编程 VC编程 Coreldraw SolidWorks A Designer Unity3D
 首页 > VC编程

在VC中透明浮动按键的实现

51自学网 2015-08-30 http://www.wanshiok.com

 

  接着就是绘制按键的各种状态:由于按键必须“透明”,所以在按下和释放时只在按键区域的四周加上一个3D边框就行了。而在正常状态下,则必须去掉边框恢复背景。但如何恢复背景图象呢?我是这样做的:在按键初始化时,先把被按键覆盖了的区域保存在一个CBitmap类中,以后需要重绘按键时就把这个CBitmap画在按键上就行了。
void CDrawButton::DrawItem
(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
  // TODO: Add your code to draw the specified item
  CDC dc;
  CRect rect=lpDrawItemStruct- >rcItem;
  CString sCaption;
  dc.Attach(lpDrawItemStruct->hDC);
//得到绘制的设备环境CDC
  VERIFY(lpDrawItemStruct- >CtlType==ODT_BUTTON);

  if (lpDrawItemStruct- >itemAction & ODA_DRAWENTIRE){
    //重绘控件(正常状态)
    mBtnStats=BTN_NORMAL;
    if (m_pBitmap!=0){
      CDC memDC;
      memDC.CreateCompatibleDC(&dc);
      memDC.SelectObject(m_pBitmap);
  dc.BitBlt(0, 0, rect.Width(), rect.Height(),
        &memDC, 0, 0, SRCCOPY);
      memDC.DeleteDC();
    }
    //显示按键标题
    GetWindowText(sCaption);
    dc.SetBkMode(TRANSPARENT);
    if (m_pFont!=0){
    CFont* m_pOldFont=dc.SelectObject(m_pFont);
    dc.DrawText(sCaption,&rect,
  DT_CENTER|DT_VCENTER|DT_SINGLELINE);
      dc.SelectObject(m_pOldFont);
    }
  }

if ((lpDrawItemStruct- >itemState & ODS_SELECTED) &&
(lpDrawItemStruct- >itemAction & ODA_SELECT)){
//按下鼠标
mBtnStats=BTN_DOWN;
dc.Draw3dRect(&rect,RGB(128,128,128),RGB(192,192,192));
rect.top=rect.top+1;rect.bottom=rect.bottom-1;
rect.left=rect.left+1;rect.right=rect.right-1;
dc.Draw3dRect(&rect,RGB(0,0,0),RGB(255,255,255));
  }

if(!(lpDrawItemStruct- >itemState & ODS_SELECTED) &&
(lpDrawItemStruct- >itemAction & ODA_SELECT)){
//释放鼠标或鼠标进入按键区域
mBtnStats=BTN_UP;
dc.Draw3dRect(&rect,RGB(255,255,255),RGB(0,0,0));
rect.top=rect.top+1;rect.bottom=rect.bottom-1;
rect.left=rect.left+1;rect.right=rect.right-1;
dc.Draw3dRect(&rect,RGB(192,192,192),RGB(128,128,128));
  }

  dc.Detach();
}

  接着就必须一些初始化工作,其中最关键就是把被按键覆盖了的区域保存进CBitmap类中,我们知道CDC::StretchBlt()函数可以把位图的指定区域从一个设备拷贝到另一个设备中,这样可以很方便地把窗口或对话框的某个区域保存,条件是获得其DC:
void CDrawButton::LoadBack(CWnd *pParent)
{
  ASSERT(GetStyle() & BS_OWNERDRAW);
  if (m_pBitmap!=0) return;

  CRect rect;
  GetWindowRect(&rect);
  pParent- >ScreenToClient(&rect);//获得按键区域
  CPaintDC dc(pParent);
  if (m_pBitmap==0) m_pBitmap=new CBitmap;//初始化位图
  m_pBitmap- >CreateCompatibleBitmap
(&dc,rect.Width(),rect.Height());
  CDC memDC;
  memDC.CreateCompatibleDC(&dc);
  memDC.SelectObject(m_pBitmap);
memDC.StretchBlt(0, 0, rect.Width(),rect.Height(), &dc,
  rect.left, rect.top,
rect.Width(),rect.Height(), SRCCOPY);//保存
  memDC.DeleteDC();
m_pFont=pParent- >GetFont();//获得窗口或对话框的字体

  ModifyStyle(0,WS_VISIBLE);//显示按键

  SetBitmapMode(ODA_DRAWENTIRE,0);//绘制按键
}

  而使这个类和对话框上的按键产生联系还必须调用一下SubclassDlgItem():
BOOL CDrawButton::AutoLoad(UINT nID, CWnd *pParent)
{
// first attach the CDrawButton to the dialog control

  if (m_pBitmap!=0) return FALSE;

  if (!SubclassDlgItem(nID, pParent)) return FALSE;

  LoadBack(pParent);

  return TRUE;
}


  这个类还必须具有三个成员变量:
  CFont* m_pFont;
  CBitmap* m_pBitmap;
  UINT mBtnStats;

在构造函数中初始化这些变量
  m_pBitmap=0;
  m_pFont=0;
  //赋予0是可以的
  mBtnStats=BTN_NORMAL;

在折构函数中拆除位图
  if(m_pBitmap!=0) delete m_pBitmap;

  这样,一个透明的浮动式按键类就做好了,具体实现方法以下:
  1.接管对话框的BUTTON,首先在对话框上画一个BUTTON,再加一个PICTURE图片,BUTTON的风格必须加入OWNER DRAW及去掉VISIBLE,把BUTTON移到PICTURE上适当的位置,在对话框类加入CDrawButton类成员m_myButton,由于按键初始化时必须保存对话框的图象,而对话框在运行InitDialog()或第一次运行OnPaint()时对话框的控件还没有真正显示出来,我们只好在OnMouseMove()中进行初始化:

m_myButton.AutoLoad(IDC_BUTTON1,this);
AutoLoad()只运行一次。

  2.动态建立CDrawButton,在对话框类或CxxxView类加入CDrawButton类成员m_myButton,可以在对话框的InitDialog()或CxxxView类的InitialUpdate()中加入:m_myButton.Create()函数,必须包含BS_OWNERDRAW而不能有WS_VISIBLE风格,然后在OnMouseMove()或OnDraw()中进行初始化:m_myButton.LoadBack(this);注意应加在OnDraw()的最后。

  同样地,LoadBack()只运行一次。

  (如果按键比背景的图片迟建立而具有可见(Visible)属性,则会把图片抹掉,所以必须去掉VISIBLE属性或不能加入WS_VISIBLE风格)

  ·当鼠标移到按键区域时,改变鼠标

  这个很容易实现,不在这里多说了。

 
 
说明
:本教程来源互联网或网友上传或出版商,仅为学习研究或媒体推广,wanshiok.com不保证资料的完整性。

上一篇:VC++学习:用SDK实现分隔条  下一篇:在视图中同步显示鼠标的位置