一个用户绘制按钮,支持透明的PNG文件,用于Visual c++ 6.0和VS2005

介绍 在这个网站上有几个所有者绘制按钮,但是我找不到一个容易支持PNG文件透明,所以我创建了这个类。由于这个类使用GDI+,它实际上支持许多图像格式,但是现在可用的质量更好的按钮是PNG而不是ICO,所以这是这里突出显示的一个。 更新:我的Style工具包中有这个类的扩展版本。如果您只是想在按钮上使用图像,那么这个类可能更容易使用。 背景 GDI+是Microsoft Windows SDK的一部分,需要在应用程序启动时对其进行初始化。如果您以前没有使用过GDI+,请查看演示项目的源代码并阅读本文: 从GDI + 特性 灰度图像 这个类将从加载的资源自动创建一个灰度图像。当按钮被设置为禁用状态时,将显示灰度图像。 突出的形象 该类将自动从加载的资源创建突出显示的图像。当鼠标悬停在按钮边界上时,将显示突出显示的图像。 替代图像 您可以选择添加一个替代图像。当通过函数调用设置时,或者当单击按钮并启用切换模式时,将显示备用图像。 切换模式 启用后,该按钮每次按下时都会在标准图像和备用图像之间切换。 按下状态 当按下按钮时,图像向右下移1像素。 工具提示 工具提示可以随意添加。 页面顶部的图像显示了播放按钮的三种不同状态。从左到右分别是:正常、高亮和禁用。另外两个按钮只是看起来很酷的例子。 从图片上看,第二个按钮处于高亮显示的状态可能不太明显。这是设计,我不想明显改变图像。高亮状态只是增加了一点亮度和对比度。当您将鼠标移到它上面时,这就足够明显了。这个类优先考虑图像质量,所以它不会拉伸或收缩图像,这通常会降低图像质量,它只绘制适合的部分。如果你需要调整你的图像大小,使用像Photoshop这样的图像编辑器。 下面的图片显示了处于切换状态的播放按钮,这应该是很明显的为什么你想要这样一个功能。退出按钮处于高亮显示状态,工具提示显示在此图像中。 使用GDI+不会造成性能损失(假设存在这种损失),因为它只在初始化期间使用。在创建时,图像被转换为位图,当需要重新绘制控件时使用位图。 使用的代码 步骤1 -将这些文件添加到您的项目中 GdipButton.hGdipButton.cppMemDC.hCGdiPlusBitmap。hCMemDC来自Keith Rule, CGdiPlusBitmap.h来自Joe Woodbury。这些都包含在源代码和演示包中。 步骤2 -添加资源、成员变量和图像 使用资源编辑器在对话框中添加一个按钮,设置资源ID,并擦除标题框中的文本。您可以将样式设置为Owner Draw,但您不需要这样做,因为代码将自动设置此样式。 使用类向导,向刚刚创建的ID添加一个变量。在本例中,我将ID设置为IDC_PLAY,变量名设置为m_cPlay。编辑对话框的.h文件,并将控件从CButton更改为CGdiButton。不要忘记包含文件“GdipButton.h”。 在资源编辑器中,从res文件夹导入. PNG文件,并将资源类型设置为PNG。使用PNG只是惯例,它可以是任何东西,只要代码匹配你的名字。右键单击IDR_PNG1,选择Properties,并将其重命名为一些有用的东西,在本例中为IDR_PLAY。 步骤3 -添加LoadStdImage()函数 现在,我们只需要在初始化时将图像加载到按钮。在OnInitDialg()函数中,在底部添加以下代码: 隐藏,复制Code

BOOL CTestGdipButtonDlg::OnInitDialog()
{
    CDialog::OnInitDialog();

    /// a bunch of stuff here

    m_cPlay.LoadStdImage(IDR_PLAY, _T("PNG"));

    return TRUE; 
}

步骤4 -建立和运行 您现在应该能够运行它并看到新的PNG按钮!如果它在这里崩溃了,可能是因为您没有初始化GDI+。回顾本文的背景部分。 演示项目 这是在测试程序中创建按钮所需要的全部代码: 隐藏,复制Code

// load the standard image and alternate image
m_cPlay.LoadStdImage(IDR_PLAY, _T("PNG"));
m_cPlay.LoadAltImage(IDR_PAUSE, _T("PNG"));
m_cPlay.EnableToggle(TRUE);

// just to show highlight state for article
m_cPlayHi.LoadStdImage(IDR_PLAY, _T("PNG"));

// set as disabled
m_cPlayDis.LoadStdImage(IDR_PLAY, _T("PNG"));
m_cPlayDis.EnableButton(FALSE);

// show a larger button type
m_cGear.LoadStdImage(IDR_GEAR, _T("PNG"));

// replace the OK button with something
m_cShutDn.LoadStdImage(IDR_EXIT, _T("PNG"));
m_cShutDn.SetToolTipText(_T("Close Program"));

演示项目中包括VC6和VS2005版本。 透明图像的问题 按钮控件不知道它下面的背景应该是什么;它从与当前DC相关联的位图中获取这些信息。在大多数情况下,这工作得很好,背景是在控件被绘制之前屏幕上的东西。然而,应用程序在启动时可能不是最顶端的。一个总是在顶部的应用程序,比如任务管理器,可能会出现问题,所以当它得到背景图像时,它是错误的数据。这可以通过调用SetBkGnd()函数b来克服y实际创建背景的代码。 在父级的OnEraseBkgnd()函数中设置所有按钮的背景。演示程序用下面的代码实现了这一点: 隐藏,复制Code

BOOL CTestGdipButtonDlg::OnEraseBkgnd(CDC* pDC)
{
    CDialog::OnEraseBkgnd(pDC);
    CRect rect;
    GetClientRect(rect);

    CMemDC pDevC(pDC, rect);

    // fill in the back ground with something

    SetButtonBackGrounds(pDevC);

    return TRUE;
}

void CTestGdipButtonDlg::SetButtonBackGrounds(CDC *pDC)
{
    m_cPlay.SetBkGnd(pDC);
    m_cPlayHi.SetBkGnd(pDC);
    m_cPlayDis.SetBkGnd(pDC);
    m_cShutDn.SetBkGnd(pDC);
}

由于传递的DC是内存DC,所以其他应用程序正在做什么并不重要。上面的代码假设你想使用的不是糟糕的默认背景;否则,你可能只会使用默认的糟糕按钮。 机器构建问题 VC6需要一些额外的东西来正确编译,添加以下到您的stdafx.h文件。还要将SDK include和lib路径添加到您的环境中。 隐藏,复制Code

// VC6
#if defined(_MSC_VER) && _MSC_VER == 1200

#ifndef ULONG_PTR
#define ULONG_PTR unsigned long*
#endif
#include <span class="code-keyword"><Specstrings.h></span>
#include <span class="code-keyword"><gdiplus.h></span>

#pragma comment(lib, "gdiplus.lib")
using namespace Gdiplus;

// VS2005
#else 

#include <span class="code-keyword"><gdiplus.h></span>
#pragma comment(lib, "gdiplus.lib")
using namespace Gdiplus;

#endif

历史 版本1.0(6月10 / / 2008) 第一个版本。 本文转载于:http://www.diyabc.com/frontweb/news989.html

原文地址:https://www.cnblogs.com/Dincat/p/13456199.html