MFC实现漂亮界面之美化按钮

上次我们学习了如何美化对话框的界面,这次我们为上次的对话框添加两个按钮,一个是关闭按钮,另一个是最小化按钮,好,现在我们先看一下效果:

是不是很难看,因为我们的对话框美化了,所以我们的按钮也要美化,因为采用贴图的方式来美化,所以,我先给出这两个按钮的PNG格式的图片,该图片支持透明色,具体如下:

关闭按钮效果图:

最小化按钮效果图:

这两张效果图是我自己从网上找的,可能不是很合适,但是用来教学,完全没有问题,它们的尺寸都是108*21,每张图片都有四个小图片,第一张和第四张小图片都是透明的,所以看不见效果,我们使用这两张图片来完成按钮的美化,每张图片从左向右有四张小图片,我们只用前三张,分别对应默认状态,焦点状态,按下状态。

下面,我们来说一下如何美化按钮?

第1步,我们先在对话框上放置两个按钮,一个是关闭按钮,另一个是最小化按钮,它们对应的ID分别是IDC_BUTTON_CLOSE和IDC_BUTTON_MIN,然后将我们的按钮设置为自绘制模式,方法如下:

选择按钮,右键属性,在属性列表中找到Owner Draw选项,将其设置为True,效果图如下:

再为它们添加两个成员变量,具体如下:

CButton m_btnClose;
CButton m_btnMin;

第2步,我们新建一个类,继承自CButton,我们取名为CMyButton,为其添加3个成员变量,分别如下:

//按钮背景图像
CImage m_imgButton;
//按钮png路径,包括焦点,正常,按下3个状态
CString m_strImgPath;
//父窗口背景图片背景路径,透明png需要使用
CString m_strImgParentPath;

第3步,我们为CMyButton添加3个成员函数,分别如下:

//设置按钮背景图片路径,父窗口背景图片路径
void SetImagePath(CString strImgPath, CString strParentImgPath);
//初始化按钮,主要是调整按钮的位置,处理透明色
bool InitMyButton(int nX/*左上角X坐标*/, int nY/*左上角Y坐标*/,int nW/*图像宽*/, int nH/*图像高*/, bool bIsPng/*是否是PNG图片*/);
//自绘制函数
void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);

CMyButton的声明最终如下:

class CMyButton : public CButton
{
 DECLARE_DYNAMIC(CMyButton)

public:
 CMyButton();

 virtual ~CMyButton();

 //按钮背景图像
 CImage m_imgButton;

 //按钮png路径,包括焦点,正常,按下3个状态
 CString m_strImgPath;

 //父窗口背景图片背景路径,透明png需要使用
 CString m_strImgParentPath;

 //设置按钮背景图片路径,父窗口背景图片路径
 void SetImagePath(CString strImgPath, CString strParentImgPath);

 //初始化按钮,主要是调整按钮的位置,处理透明色
 bool InitMyButton(int nX/*左上角X坐标*/, int nY/*左上角Y坐标*/,int nW/*图像宽*/, int nH/*图像高*/, bool bIsPng/*是否是PNG图片*/);

 //自绘制函数
 void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);

protected:
 DECLARE_MESSAGE_MAP()
};

第4步,我们实现SetImagePath函数,它的功能是为按钮背景图片和父窗口背景图片成员函数初始化,具体如下:

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

第5步,我们实现InitMyButton函数,它的功能是调整按钮在对话框上的位置,其中的参数代表该按钮在父窗口的左上角X坐标,Y坐标,宽度,高度,最后一个参数是为PNG格式图片准备的,如果是PNG带透明色的图片,需要对它进行特殊处理,具体定义如下:

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;
}

其中MoveWindow函数是用来调整按钮位置的函数,其中的参数分别代表其在父窗口的左上角X坐标,左上角Y坐标,宽度,高度。

第6步,我们实现DrawItem函数,它是美化Button的核心函数,当我们将Button设置为自绘制后,每次按钮需要刷新,重新绘制的时候,MFC框架会调用它的DrawItem函数,在这个函数中,我们可以根据按钮当前的状态为其贴上相应的背景图。当我们按钮按钮的时候,为其贴上被按下的背景图;当我们的按钮获取焦点的时候,为其贴上获取焦点的背景图;当我们的按钮没有焦点,我们为其贴上默认的背景图片,它们对应的位置前面已经说过。为了避免闪烁,我们采用双缓冲的方式,具体代码如下:

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, nW*2, 0, SRCCOPY);
 }
 else if (lpDrawItemStruct->itemState & ODS_FOCUS)
 {
        //焦点状态
       m_imgButton.BitBlt(hMemDC, 0, 0, nW, nH, nW, 0, SRCCOPY);
 }
 else
 {
 //默认状态
 CImage imgParent;

 imgParent.Load(m_strImgParentPath);

 imgParent.Draw(hMemDC, 0, 0, nW, nH, rectTmp.left, rectTmp.top, nW, nH);

 m_imgButton.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;
}

这里我们重点说一下默认状态的背景图,因为它是透明的,并且我们采用的是双缓冲,所以,为了避免最终透明色变成黑色,我们先在内存DC上贴上按钮在父窗口位置的背景图,这样可以解决透明色变成黑色的问题,如果你采用GDI+,就不用这么做,但是我们采用的是GDI。

第7步,用CMyButton替代对话框头文件中的CButton。

第8步,在对话框的InitDialog中,对两个按钮进行初始化,具体如下:

m_btnMin.SetImagePath(_T("./res/btn_min.png"), _T("./res/Background.png"));
m_btnMin.InitMyButton(516, 8, 27, 21, true);
m_btnClose.SetImagePath(_T("./res/btn_close.png"),_T("./res/Background.png"));
m_btnClose.InitMyButton(545,8,27,21,true);

第9步,编译程序,最终效果图如下:

今天,我们已经为它添加了最小化,关闭按钮,下次,我们为其添加编辑框!

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • MFC自绘Button按钮分析和实现

    对于按压式的Button按钮,WM_CTLCOLOR无法完成按钮控件的背景颜色和字体颜色修改,若想要完成外观定制需要添加WM_DRAWITEM消息或者重写CButton类中的DrawItem函数完成按钮外观修改,下面逐一介绍. 自绘制知识基础 自绘制需要的两个基础步骤: 1.控件类型设置为 BS_OWNERDRAW 2.添加WM_DRAWITEM消息响应函数或者重写DrawItem函数. WM_DRAWITEM消息响应原型如下: afx_msg void OnDrawItem( int nIDC

  • MFC实现漂亮界面之美化按钮

    上次我们学习了如何美化对话框的界面,这次我们为上次的对话框添加两个按钮,一个是关闭按钮,另一个是最小化按钮,好,现在我们先看一下效果: 是不是很难看,因为我们的对话框美化了,所以我们的按钮也要美化,因为采用贴图的方式来美化,所以,我先给出这两个按钮的PNG格式的图片,该图片支持透明色,具体如下: 关闭按钮效果图: 最小化按钮效果图: 这两张效果图是我自己从网上找的,可能不是很合适,但是用来教学,完全没有问题,它们的尺寸都是108*21,每张图片都有四个小图片,第一张和第四张小图片都是透明的,所以

  • vs2019 MFC实现office界面的画图小项目

    vs2019安装MFC 有许多新手不知道MFC在vs2019里的安装选项,其实它不会在勾选工作负载时自动默认勾选,而通常需要人为勾选,具体安装步骤如下:(安装时间不是很长,网速够快几分钟就下载完毕) 1.打开vs安装程序 2.选择Visual Studio扩展开发 3.选择C++ MFC 生成工具(x86 和 x64)进行安装 4.选择修改,等待安装 5.等待安装完成 6.安装完成,我们打开vs2019 7.我们创建新项目,可以看到已经有MFC应用这个选项 说明我们的MFC安装成功~ vs201

  • 使用Bootstrap美化按钮实例代码(demo)

    在HTML5中,按钮的常用属性主要为背景颜色和大小 demo代码演示 一. input标签: <input type="button" value="按钮" class="btn"/> 二. button标签:(这里用button标签举例) <button type="button" class="btn btn-defult">提交</button> btn 表示基本样

  • 在python tkinter界面中添加按钮的实例

    tkinter是python自带的GUI库,可以实现简单的GUI交互,该例子添加了五种不同效果的Button,如图: from tkinter import * from tkinter import messagebox #python3.0的messagebox,属于tkinter的一个组件 top = Tk() top.title("button test") def callback(): messagebox.showinfo("Python command&quo

  • jquery实现界面点击按钮弹出悬浮框

    本文实例为大家分享了jquery实现界面点击按钮弹出悬浮框的具体代码,供大家参考,具体内容如下 首先定义两个div: 一个是背景,一个是悬浮窗. <input id="Button1" type="button" value="点击弹出层"/>                <!--弹出层时背景层DIV-->         <div id="fade" class="black_ove

  • Android自定义View模仿虎扑直播界面的打赏按钮功能

    前言 作为一个资深篮球爱好者,我经常会用虎扑app看比赛直播,后来注意到文字直播界面右下角加了两个按钮,可以在直播过程中送虎扑币,为自己支持的球队加油. 具体的效果如下图所示: 我个人觉得挺好玩的,所以决定自己实现下这个按钮,废话不多说,先看实现的效果吧: 这个效果看起来和popupwindow差不多,但我是采用自定义view的方式来实现,下面说说过程. 实现过程 首先从虎扑的效果可以看到,它这两个按钮时浮在整个界面之上的,所以它需要和FrameLayout结合使用,因此我让它的宽度跟随屏幕大小

  • css不用图片美化按钮

    .tb{width:100%;height:1px;overflow:hidden;background:rgb(250,100,0);margin:0 1px;} .lr{width:100%;height:20px;overflow:hidden;border-left:1px solid rgb(250,100,0);border-right:1px solid rgb(250,100,0);} .bg{width:100%;height:20px;overflow:hidden;} .b

  • MFC程序中使用QT开发界面的实现步骤

    目录 添加QT依赖 添加信号槽机制 添加qt界面 配置元编译过程 一些问题的处理 测试信号槽 使用qt designer 设计界面 如果你有一个现成的MFC项目在做维护,但是你厌倦了使用MFC繁琐的操作来做界面美化,或者你需要在这个项目中用到QT里面好用的某些功能:亦或者是你需要使用某些只能在MFC中使用的组件,但是界面这部分已经用QT做好了.那么这篇文章可能可以帮助到你 演示环境使用Visual Studio 2019 + QT5.12.8 版本 添加QT依赖 首先创建一个基于对话框的MFC工

  • python GUI库图形界面开发之PyQt5美化窗体与控件(异形窗体)实例

    在默认情况下,我们使用PyQt5创建出来的窗口和部件都是默认的样式,虽然谈不上很丑,但是也毫无美感可言.其实,在PyQt5中,我们可以有较高的自由度来自定义窗口和各种小部件的样式,通过自定义这些样式,以达到美化图形界面的目的. 本篇文章中,我们就通过一个实际的例子,使用QSS和PyQt5的配置属性,实现图形用户界面的美化工作. 首先上效果图: 一.对界面进行布局和组件的布置 在图像界面编程中,一个好的布局有助于全局把控界面的形态,而在PyQt5中,有多种布局的方式供我们选择,比较常用的布局有以下

  • 屏蔽Django admin界面添加按钮的操作

    例如,我想去掉某个Model界面的增加按钮,如下图所示: 一般的做法是修改 template,但是,有没有更简便易行的方法呢?答案是肯定的. 只需要修改admin.py中对应的 ModelAdmin 即可. 下面是本人修改的代码: 补充知识:Django admin 列表每行后面添加审核按钮 我就废话不多说了,还是直接看代码吧! def pass_audit_str(self): parameter_str = 'id={}&status={}'.format(str(self.id), str

随机推荐