【自绘控件之按钮类】

准备制作自己的控件类,按钮是第一个,我会将我在其中遇到困难和大家分享一些,只要实现下面的功能,按钮类就可以满足大部分的需求

 

按钮类功能:

1、正常

这个状态可以设置为光离开按钮,需要添加变量,然后在OnMouseLeave中获取状态

2、光标在按钮区域上

光标在按钮上OnMouseMove和OnMouseHover

3、按下

 

4、当前按钮为活动按钮

5、按钮不可用

6、位图按钮上显示名称

7、制作圆角矩形、圆形按钮

 

其中前三个都很好实现,下面是响应函数;

OnMouseLeave()//光标离开按钮区域

OnMouseHover()//光标在按钮区域

OnLButtonDown//按下

OnLButtonUp//松开

 

 

//以下4个问题都是在DrawItem(DRAWITEMSTRUCT  lpdrawitemstruct)中添加代码

第四个问题的解决方式:

 

函数:DrawItem(DRAWITEMSTRUCT  lpdrawitemstruct)
lpdrawitemstruct->itemState();//itemState:指定了当前绘制操作完成后,所绘项的可见状态。例如,如果菜单项应该被灰色显示,则可以指定ODS_GRAYED状态标志。其取值可以为下表中所示值的一个或者多个的联合。
【ODS_FOCUS=H8:如果菜单项将被选中,则可设置该值。该值只对菜单项有用。】

所以只要通过判断lpdrawitemstruct->itemState();是否等于ODS_FOCUS=H8:就可以设置按钮为当前活动按钮时的响应了。

 

第五个问题

函数:DrawItem(DRAWITEMSTRUCT  lpdrawitemstruct)
lpdrawitemstruct->itemState();//itemState:指定了当前绘制操作完成后,所绘项的可见状态。例如,如果菜单项应该被灰色显示,则可以指定ODS_GRAYED状态标志。其取值可以为下表中所示值的一个或者多个的联合。
【ODS_DISABLED=H4:如果控件将被禁止,则设置该值。】

所以只要通过判断lpdrawitemstruct->itemState();是否等于ODS_DISABLED=H4:就可以设置按钮为不可用按钮时的响应了。

 

第六个问题:按钮上的名称怎么显示(我的按钮的几个状态都是位图切换)

CString add;

CDC ButtonDC;

ButtonDC.Attach(lpdrawitemstruct->hDC);//获取DC

ButtonDC.SetBkMode(TRANSPARENT);//字体背景透明

GetWindowText(add);

.DrawText(add,CRect(5,5,10,10),DT_CENTER | DT_VCENTER | DT_SINGLELINE);

 

第七个问题:怎么制作圆形按钮或者是圆角按钮

CRng rc;

rc.CreateRoundRect(0,0,rect.Width(),rect.Heignt(),50,50);//获取一个圆角矩形区域

::GetWindowRgn(lpdrawitemstruct->hwndItem,rc);

ButtonDC.SelectClipRng(&rc);

SetWindowRgn(rc,true)//有效区域

 

 

 

最后记得释放内存

ButtonDC.DeleteDC();

 

2019-07-25

按钮一共设置四个状态,正常、光标在上面、按钮按下、不可用

函数:DrawItem(DRAWITEMSTRUCT  lpdrawitemstruct)中

1、if (lpDrawItemStruct->itemState & ODS_SELECTED)//为按钮的按下

2、if (state&ODS_DISABLED)//按钮被禁用的状态
 

正常状态和光标在按钮上面的状态需要用到

在头文件添加一个move_button的变量

//添加自绘功能
void MyButton::PreSubclassWindow()
{
	ModifyStyle(0, BS_OWNERDRAW);
	CButton::PreSubclassWindow();
}

//
void MyButton::OnMouseMove(UINT nFlags, CPoint point)
{
    //添加才能响应OnMouseLeave和OnMouseHover函数
	TRACKMOUSEEVENT   tme;
	tme.cbSize = sizeof(TRACKMOUSEEVENT);
	tme.dwFlags = TME_HOVER | TME_LEAVE;
	tme.dwHoverTime = HOVER_DEFAULT;
	tme.hwndTrack = m_hWnd;
	_TrackMouseEvent(&tme);
	
    //刷新才能响应DrawItem函数
	if (!move_button)
		Invalidate();
    //这个状态添加在move中是因为在这里响应的速度比OnMouseHover要快
	move_button = true;

	CButton::OnMouseMove(nFlags, point);
}



//光标离开
void MyButton::OnMouseLeave()
{
    //状态改变就调用DrawItem
	if (move_button)
		Invalidate();

	move_button = false;	
	CButton::OnMouseLeave();
}

//光标在按钮上
void MyButton::OnMouseHover(UINT nFlags, CPoint point)
{
	/*if (!move_button)
		Invalidate();


	move_button = true;*/
	
	CButton::OnMouseHover(nFlags, point);
}

//在切换位图的时候按钮背景会闪烁,添加后就没有这个问题了
BOOL MyButton::OnEraseBkgnd(CDC* pDC)
{
	return true;

	//return CButton::OnEraseBkgnd(pDC);
}

3、if (move_button == true)//光标移动到上面

4、if (move_button == false)//正常按钮

 

当获取完这些状态后在其中使用

if (lpDrawItemStruct->CtlID == IDC_BUTTON1)//判断当前状态是那个按钮

 

 

例子:在DrawItem中添加

    CDC ButtonDC;
	CBitmap bitmapTrans;
	BITMAP bmp;
	CDC mem;
	CRect rc;
	//得到用于绘制按钮的DC
	ButtonDC.Attach(lpDrawItemStruct->hDC);
	ButtonDC.SetBkMode(TRANSPARENT);
	//准备用于向按钮区域传输位图
	mem.CreateCompatibleDC(&ButtonDC);
	//获取按钮所占的矩形大小
	rc = lpDrawItemStruct->rcItem;
	//获取按钮目前所处的状态,根据不同的状态绘制不同的按钮
	int state = lpDrawItemStruct->itemState;
	//如果按钮已经得到焦点,绘制选中状态下的按钮
	//if (state&ODS_FOCUS)//选中
	if (lpDrawItemStruct->itemState & ODS_SELECTED)//按下
	{		
		if (lpDrawItemStruct->CtlID == IDC_BUTTON12)//官网
			bitmapTrans.LoadBitmap(IDB_BITMAP1);
        //按钮多久继续添加按钮判断

        bitmapTrans.GetBitmap(&bmp);
		CBitmap *old = mem.SelectObject(&bitmapTrans);
		//向按钮所在位置传输位图
		//使用StretcnBlt的目的是为了让位图随按钮的大小而改变
		ButtonDC.StretchBlt(rc.left, rc.top, rc.right, rc.bottom, &mem, 0, 0,                 bmp.bmWidth, bmp.bmHeight, SRCCOPY);
		mem.SelectObject(old);
    }
    else if(move_button)//光标在按钮上
    {
        if (lpDrawItemStruct->CtlID == IDC_BUTTON12)//官网
			bitmapTrans.LoadBitmap(IDB_BITMAP2);
        //按钮多久继续添加按钮判断

        bitmapTrans.GetBitmap(&bmp);
		CBitmap *old = mem.SelectObject(&bitmapTrans);
		//向按钮所在位置传输位图
		//使用StretcnBlt的目的是为了让位图随按钮的大小而改变
		ButtonDC.StretchBlt(rc.left, rc.top, rc.right, rc.bottom, &mem, 0, 0,                 bmp.bmWidth, bmp.bmHeight, SRCCOPY);
		mem.SelectObject(old);
    }
    else.....等等

    //设置文字背景为透明
	ButtonDC.SetBkMode(TRANSPARENT);
	bitmapTrans.DeleteObject();


	mem.DeleteDC();
	ButtonDC.DeleteDC();

 

 

VC6 CListCtrl继承例子 oid CListCtrlCl::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) { // TODO: 添加您的代码以绘制指定项 TCHAR lpBuffer[256]; LV_ITEM lvi; lvi.mask = LVIF_TEXT | LVIF_PARAM ; lvi.iItem = lpDrawItemStruct->itemID ; lvi.iSubItem = 0; lvi.pszText = lpBuffer ; lvi.cchTextMax = sizeof(lpBuffer); VERIFY(GetItem(&lvi)); LV_COLUMN lvc, lvcprev ; ::ZeroMemory(&lvc, sizeof(lvc)); ::ZeroMemory(&lvcprev, sizeof(lvcprev)); lvc.mask = LVCF_WIDTH | LVCF_FMT; lvcprev.mask = LVCF_WIDTH | LVCF_FMT; CDC* pDC; pDC = CDC::FromHandle(lpDrawItemStruct->hDC); CRect rtClient; GetClientRect(&rtClient); for ( int nCol=0; GetColumn(nCol, &lvc); nCol++) { if ( nCol > 0 ) { // Get Previous Column Width in order to move the next display item GetColumn(nCol-1, &lvcprev) ; lpDrawItemStruct->rcItem.left += lvcprev.cx ; lpDrawItemStruct->rcItem.right += lpDrawItemStruct->rcItem.left; } CRect rcItem; if (!GetSubItemRect(lpDrawItemStruct->itemID,nCol,LVIR_LABEL,rcItem)) continue; ::ZeroMemory(&lvi, sizeof(lvi)); lvi.iItem = lpDrawItemStruct->itemID; lvi.mask = LVIF_TEXT | LVIF_PARAM; lvi.iSubItem = nCol; lvi.pszText = lpBuffer; lvi.cchTextMax = sizeof(lpBuffer); VERIFY(GetItem(&lvi)); CRect rcTemp; rcTemp = rcItem; if (nCol==0) { rcTemp.left -=2; } if ( lpDrawItemStruct->itemState & ODS_SELECTED ) { pDC->FillSolidRect(&rcTemp, GetSysColor(COLOR_HIGHLIGHT)) ; pDC->SetTextColor(GetSysColor(COLOR_HIGHLIGHTTEXT)) ; } else { COLORREF color; color = GetBkColor(); pDC->FillSolidRect(rcTemp,color); if (FindColColor(nCol,color)) { pDC->FillSolidRect(rcTemp,color); } if (FindItemColor(nCol,lpDrawItemStruct->itemID,color)) { pDC->FillSolidRect(rcTemp,color); } //pDC->SetTextColor(m_color); } pDC->SelectObject(GetStockObject(DEFAULT_GUI_FONT)); UINT uFormat = DT_CENTER ; if (m_Header.m_Format[nCol]=='0') { uFormat = DT_LEFT; } else if (m_Header.m_Format[nCol]=='1') { uFormat = DT_CENTER; } else if (m_Header.m_Format[nCol]=='2') { uFormat = DT_RIGHT; } TEXTMETRIC metric; pDC->GetTextMetrics(&metric); int ofst; ofst = rcItem.Height() - metric.tmHeight; rcItem.OffsetRect(0,ofst/2); pDC->SetTextColor(m_color); COLORREF color; if (FindColTextColor(nCol,color)) { pDC->SetTextColor(color); } if (FindItemTextColor(nCol,lpDrawItemStruct->itemID,color)) { pDC->SetTextColor(color); } CFont nFont ,* nOldFont; nFont.CreateFont(m_fontHeight,m_fontWith,0,0,0,FALSE,FALSE,0,0,0,0,0,0,_TEXT("宋体"));//创建字体 nOldFont = pDC->SelectObject(&nFont); DrawText(lpDrawItemStruct->hDC, lpBuffer, strlen(lpBuffer), &rcItem, uFormat) ; pDC->SelectStockObject(SYSTEM_FONT) ; } }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值