MFC 自绘按钮 改变按钮形状问题

嘻嘻666 2017-03-03 04:00:53
如下图怎么将红色 全圈 的按钮 改成和插入的图片大小一样,去掉直角


代码如下:
void CMyButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
if (!lpDrawItemStruct)
return;
HDC hMemDC;
HBITMAP bmpMem;
HGDIOBJ hOldObj;
bmpMem = CreateCompatibleBitmap(lpDrawItemStruct->hDC, lpDrawItemStruct->rcItem.right - lpDrawItemStruct->rcItem.left, lpDrawItemStruct->rcItem.bottom - lpDrawItemStruct->rcItem.top);
if (!bmpMem)
return;
hMemDC = CreateCompatibleDC(lpDrawItemStruct->hDC);
if (!hMemDC)
{
if (bmpMem)
{
::DeleteObject(bmpMem);
bmpMem = NULL;
}
return;
}

hOldObj = ::SelectObject(hMemDC, bmpMem);

RECT rectTmp = { 0 };

rectTmp = lpDrawItemStruct->rcItem;

MapWindowPoints(GetParent(), &rectTmp);

int nW = lpDrawItemStruct->rcItem.right - lpDrawItemStruct->rcItem.left;

int nH = lpDrawItemStruct->rcItem.bottom - lpDrawItemStruct->rcItem.top;

if (lpDrawItemStruct->itemState & ODS_SELECTED)
{
//按钮被选择
m_imgButton.BitBlt(hMemDC, 0, 0, nW, nH, 0, 0, SRCCOPY);
}
else if (lpDrawItemStruct->itemState & ODS_FOCUS)
{
//焦点状态
m_imgButton.BitBlt(hMemDC, 0, 0, nW, nH, 0, 0, SRCCOPY);
}
else
{
//默认状态
CImage imgParent;
imgParent.Load(m_strImgParentPath);
imgParent.BitBlt(hMemDC, 0, 0, nW, nH, 0, 0, SRCCOPY);
imgParent.AlphaBlend(hMemDC, 0, 0, nW, nH, 0, 0, nW, nH);//显示有透明度的图片
imgParent.Destroy();

}

::BitBlt(lpDrawItemStruct->hDC, 0, 0, nW, nH, hMemDC, 0, 0, SRCCOPY);

SelectObject(hMemDC, hOldObj);

if (bmpMem)
{
::DeleteObject(bmpMem);
bmpMem = NULL;
}

if (hMemDC)
{
::DeleteDC(hMemDC);
hMemDC = NULL;
}
return;
}
...全文
868 14 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
醒醒◟ 2019-08-06
  • 打赏
  • 举报
回复
lwb198576 2017-12-20
  • 打赏
  • 举报
回复
请问你这个背景是用什么控件弄上去的阿
worldy 2017-03-06
  • 打赏
  • 举报
回复
定义一个按钮形状的多边形,调用SetWindowRgn函数
向立天 2017-03-06
  • 打赏
  • 举报
回复
引用 7 楼 qq_33179570 的回复:
[quote=引用 6 楼 xianglitian 的回复:] 要做不规则窗口就要SetWindowRgn 参考http://www.codefans.net/articles/1455.shtml
//限制按钮大小 void CMyButton::PreSubclassWindow() { // TODO: 在此添加专用代码和/或调用基类 CButton::PreSubclassWindow(); CRgn rgn; CRect rc; GetClientRect(&rc); rgn.CreateRoundRectRgn(rc.left, rc.top, rc.right, rc.bottom, 5, 5); SetWindowRgn(rgn, TRUE); rgn.DeleteObject(); } BOOL CMyButton::OnEraseBkgnd(CDC* pDC) { // TODO: 在此添加消息处理程序代码和/或调用默认值 //禁止绘制底色  return TRUE; }[/code]
没反应 [/quote]把rgn作为类的成员变量处理
psp7456 2017-03-05
  • 打赏
  • 举报
回复 1
你可偷个懒,直接用皮肤就行,推荐SkinSharp
zgl7903 2017-03-04
  • 打赏
  • 举报
回复
SetWindowRgn 的帮助文档 After a successful call to SetWindowRgn, the system owns the region specified by the region handle hRgn. The system does not make a copy of the region. Thus, you should not make any further function calls with this region handle. In particular, do not close this region handle. 因此不能使用局部Rgn, 而且不能关闭 绘制时 SelectClipRgn 裁剪区域也可以

LRESULT CMyButton::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) 
{
  // TODO: Add your specialized code here and/or call the base class
  switch(message)
  {
  case(WM_MOUSEMOVE):
    {
      //鼠标移入时注册离开
      if(IsWindowEnabled() && m_bMouseMovingFlag == 0)
      {
        TRACKMOUSEEVENT tackEvent = 
        {
          sizeof(TRACKMOUSEEVENT),
          TME_LEAVE,
          m_hWnd,
          0
        };
        
        if(TrackMouseEvent(&tackEvent))
        {
          m_bMouseMovingFlag = -1;
          Invalidate(FALSE);
        }
      }

      break;
    }
  case(WM_MOUSELEAVE):
    {
      //鼠标离开时取消注册的离开事件
      if(m_bMouseMovingFlag)
      {
        TRACKMOUSEEVENT tackEvent = 
        {
          sizeof(TRACKMOUSEEVENT),
            TME_CANCEL,
            m_hWnd,
            0
        };
        
        if(TrackMouseEvent(&tackEvent))
        {
        }

        m_bMouseMovingFlag = 0;
        Invalidate(FALSE);
      }

      break;
    }
  case(WM_ERASEBKGND):
    {
      return 1; //不操作背景
    }
  case(WM_PAINT):
    {
      PAINTSTRUCT ps;
      CDC *pDC = BeginPaint(&ps);

      {
        int nSaveDC = pDC->SaveDC(); //保存DC现场
        
        CRect rcRect;
        GetClientRect(&rcRect);

        //圆角矩形
        CRgn rgRound;
        rgRound.CreateRoundRectRgn(rcRect.left, rcRect.top, rcRect.right, rcRect.bottom, 30, 30);
        //选择裁剪区域
        pDC->SelectClipRgn(&rgRound);
        
        //填充背景色 / 贴图
        COLORREF rcBack;
        if(IsWindowEnabled())
        {
          if(m_bMouseMovingFlag)
            rcBack = RGB(0, 0, 255);
          else
            rcBack = RGB(255, 0, 0);
        }
        else
        {
          rcBack = RGB(100, 100, 100);
        }
        pDC->FillSolidRect(&rcRect, rcBack);
        
        //绘制字体
        CString strText;
        GetWindowText(strText);        
        pDC->SetBkMode(TRANSPARENT); //背景透明
        //设置字体颜色
        COLORREF txColor = IsWindowEnabled()? RGB(0, 255, 0) : RGB(200, 200, 200);
        pDC->SetTextColor(txColor);
        pDC->DrawText(strText, rcRect, DT_VCENTER|DT_CENTER|DT_SINGLELINE); 
        
        //恢复裁剪区域
        pDC->SelectClipRgn(NULL);
        
        pDC->RestoreDC(nSaveDC); //恢复DC现场
      }

      EndPaint(&ps);

      return 0;
    }
  default:
    {
      break;
    }

  }

  return CButton::WindowProc(message, wParam, lParam);
}
嘻嘻666 2017-03-04
  • 打赏
  • 举报
回复
设置是成功的但是 按钮形状没变 是不是有函数先后调用问题
嘻嘻666 2017-03-04
  • 打赏
  • 举报
回复
引用 6 楼 xianglitian 的回复:
要做不规则窗口就要SetWindowRgn 参考http://www.codefans.net/articles/1455.shtml
//限制按钮大小 void CMyButton::PreSubclassWindow() { // TODO: 在此添加专用代码和/或调用基类 CButton::PreSubclassWindow(); CRgn rgn; CRect rc; GetClientRect(&rc); rgn.CreateRoundRectRgn(rc.left, rc.top, rc.right, rc.bottom, 5, 5); SetWindowRgn(rgn, TRUE); rgn.DeleteObject(); } BOOL CMyButton::OnEraseBkgnd(CDC* pDC) { // TODO: 在此添加消息处理程序代码和/或调用默认值 //禁止绘制底色  return TRUE; }[/code]
没反应
向立天 2017-03-04
  • 打赏
  • 举报
回复
要做不规则窗口就要SetWindowRgn 参考http://www.codefans.net/articles/1455.shtml
嘻嘻666 2017-03-04
  • 打赏
  • 举报
回复
引用 2 楼 zgl7903 的回复:
SetWindowRgn 裁剪窗口
自绘类的 全部函数
// MyButton.cpp : 实现文件
//

#include "stdafx.h"
#include "TPUD_SHEN.h"
#include "MyButton.h"


// CMyButton

IMPLEMENT_DYNAMIC(CMyButton, CButton)

CMyButton::CMyButton()
{
  
}

CMyButton::~CMyButton()
{
}


BEGIN_MESSAGE_MAP(CMyButton, CButton)
	ON_WM_ERASEBKGND()
END_MESSAGE_MAP()



// CMyButton 消息处理程序

void CMyButton::SetImagePath(CString strImgPath, CString strParentImgPath)
{
	m_strImgPath = strImgPath;
	m_strImgParentPath = strParentImgPath;
}

bool CMyButton::InitMyButton(int nX, int nY, int nW, int nH, bool bIsPng)
{

	HRESULT hr = 0;
	if (m_strImgPath.IsEmpty())
		return false;
	hr = m_imgButton.Load(m_strImgPath);

	if (FAILED(hr))
		return false;

	if (bIsPng)
	{
		if (m_imgButton.GetBPP() == 32)
		{
			int i = 0;
			int j = 0;
			for (i = 0; i < m_imgButton.GetWidth(); i++)
			{
				for (j = 0; j < m_imgButton.GetHeight(); j++)
				{
					byte * pbyte = (byte *)m_imgButton.GetPixelAddress(i, j);
					pbyte[0] = pbyte[0] * pbyte[3] / 255;
					pbyte[1] = pbyte[1] * pbyte[3] / 255;
					pbyte[2] = pbyte[2] * pbyte[3] / 255;
				}
			}
		}
	}

	//设置按钮的有效区域

	MoveWindow(nX, nY, nW, nH);


	return true;
}

void CMyButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{

	ModifyStyle(0, BS_OWNERDRAW);
	
	if (!lpDrawItemStruct)
		return;
	HDC hMemDC;
	HBITMAP bmpMem;
	HGDIOBJ hOldObj;
	CRect rect;
	GetClientRect(rect);
	CDC dc;
	dc.Attach(lpDrawItemStruct->hDC);

	bmpMem = CreateCompatibleBitmap(lpDrawItemStruct->hDC, lpDrawItemStruct->rcItem.right - lpDrawItemStruct->rcItem.left, lpDrawItemStruct->rcItem.bottom - lpDrawItemStruct->rcItem.top);
	if (!bmpMem)
		return;
	hMemDC = CreateCompatibleDC(lpDrawItemStruct->hDC);
	if (!hMemDC)
	{
		if (bmpMem)
		{
			::DeleteObject(bmpMem);
			bmpMem = NULL;
		}
		return;
	}

	hOldObj = ::SelectObject(hMemDC, bmpMem);

	RECT rectTmp = { 0 };

	rectTmp = lpDrawItemStruct->rcItem;

	MapWindowPoints(GetParent(), &rectTmp);

	int nW = lpDrawItemStruct->rcItem.right - lpDrawItemStruct->rcItem.left;

	int nH = lpDrawItemStruct->rcItem.bottom - lpDrawItemStruct->rcItem.top;

	

	if (lpDrawItemStruct->itemState & ODS_SELECTED)
	{
		//按钮被选择  
		m_imgButton.BitBlt(hMemDC, 0, 0, nW, nH, 0, 0, SRCCOPY);
	}
	else if (lpDrawItemStruct->itemState & ODS_FOCUS)
	{
		//焦点状态  
		m_imgButton.BitBlt(hMemDC, 0, 0, nW, nH, 0, 0, SRCCOPY);
	//	m_imgButton.AlphaBlend(hMemDC, 0, 0, nW, nH, 0, 0, nW, nH);//显示有透明度的图片
	}
	else
	{
		//默认状态  
		CImage imgParent;
		imgParent.Load(m_strImgParentPath);
	//	imgParent.BitBlt(hMemDC, 0, 0, nW, nH, 0, 0, SRCCOPY);	
		imgParent.AlphaBlend(hMemDC, 0, 0, nW, nH, 0, 0, nW, nH);//显示有透明度的图片
	
		imgParent.Destroy();
	

	}

	::BitBlt(lpDrawItemStruct->hDC, 0, 0, nW, nH, hMemDC, 0, 0, SRCCOPY);
	dc.SetBkMode(TRANSPARENT);
	dc.DrawText(TEXT("实时显示"), rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
	SelectObject(hMemDC, hOldObj);

	if (bmpMem)
	{
		::DeleteObject(bmpMem);
		bmpMem = NULL;
	}

	if (hMemDC)
	{
		::DeleteDC(hMemDC);
		hMemDC = NULL;
	}


	return;
}

void CMyButton::PreSubclassWindow()
{
	// TODO: 在此添加专用代码和/或调用基类
	CButton::PreSubclassWindow();

	CRgn rgn;
	CRect rc;
	GetClientRect(&rc);
	rgn.CreateRoundRectRgn(rc.left, rc.top, rc.right, rc.bottom, 5, 5);
	SetWindowRgn(rgn, TRUE);
	rgn.DeleteObject();
	
}


BOOL CMyButton::OnEraseBkgnd(CDC* pDC)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	//禁止绘制底色 
	
	return TRUE;

	
}
嘻嘻666 2017-03-04
  • 打赏
  • 举报
回复
引用 2 楼 zgl7903 的回复:
SetWindowRgn 裁剪窗口

//限制按钮大小
void CMyButton::PreSubclassWindow()
{
	// TODO: 在此添加专用代码和/或调用基类
	CButton::PreSubclassWindow();

	CRgn rgn;
	CRect rc;
	GetClientRect(&rc);
	rgn.CreateRoundRectRgn(rc.left, rc.top, rc.right, rc.bottom, 5, 5);
	SetWindowRgn(rgn, TRUE);
	rgn.DeleteObject();
	
}


BOOL CMyButton::OnEraseBkgnd(CDC* pDC)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	//禁止绘制底色 
	
	return TRUE;

	
}
上面为何不行
schlafenhamster 2017-03-03
  • 打赏
  • 举报
回复

void CCustomButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
    if (!lpDrawItemStruct) return;
    HDC hMemDC;
    HGDIOBJ hOldObj;

	HDC hDC=lpDrawItemStruct->hDC;
    hMemDC = CreateCompatibleDC(hDC);
// 
    RECT rectTmp = { 0 };
 
    rectTmp = lpDrawItemStruct->rcItem;
    int nW = lpDrawItemStruct->rcItem.right - lpDrawItemStruct->rcItem.left;// 96 49
    int nH = lpDrawItemStruct->rcItem.bottom - lpDrawItemStruct->rcItem.top;
// 0,0,0x60,0x31
	if (lpDrawItemStruct->itemState & ODS_SELECTED)
    {
	    hOldObj = ::SelectObject(hMemDC, m_hBt1);// red lbtdown
    }
    else if (lpDrawItemStruct->itemState & ODS_FOCUS)
    {
	    hOldObj = ::SelectObject(hMemDC, m_hBt2);// green
    }
    else
    {
	    hOldObj = ::SelectObject(hMemDC, m_hBt3);// blue
    }
// copy to DC
	COLORREF crTrans = GetPixel(hMemDC, 0, 0);// 255,255,255
	if(!::TransparentBlt(hDC,0,0,nW,nH,hMemDC,0,0,nW,nH,crTrans))
	{// bmp and bt has same size!
		DWORD err=GetLastError();
	}
//
    SelectObject(hMemDC, hOldObj);
// 
    if (hMemDC)
    {
        ::DeleteDC(hMemDC);
        hMemDC = NULL;
    }
    return;
}
zgl7903 2017-03-03
  • 打赏
  • 举报
回复
schlafenhamster 2017-03-03
  • 打赏
  • 举报
回复
按钮style owner draw

15,980

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 界面
社区管理员
  • 界面
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧