实现MFC自定义按钮功能的完整指南

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:在MFC框架中创建自定义按钮通常涉及扩展CButton类以支持图像显示。文章将详细说明如何通过派生类和消息处理来创建支持图像的按钮,包括加载和设置图像、重写绘制函数以及响应鼠标事件。最终,将介绍如何在对话框中应用这些自定义按钮,并提供代码示例来实现这些功能。 mfc自定义按钮

1. MFC CButton类简介

MFC(Microsoft Foundation Classes)是微软公司提供的一套C++类库,用于简化Windows应用程序的开发。其中的 CButton 类是MFC中用于创建和管理按钮控件的类,它封装了Windows API中关于按钮的各种操作。

1.1 CButton类的作用和特点

CButton 类在MFC中被广泛使用,用于设计用户界面中的按钮元素。开发者可以通过创建 CButton 对象并指定按钮的类型和样式来生成普通按钮、复选框或单选按钮。CButton类支持诸如设置文本、改变样式、处理消息等多种功能,并且可以很容易地与其他MFC类进行交互,实现更复杂的用户界面功能。

1.2 按钮控件的种类和属性

MFC中的按钮控件具有多种类型,包括但不限于:

  • 普通按钮(BS_PUSHBUTTON)
  • 默认按钮(BS_DEFPUSHBUTTON)
  • 复选框(BS_CHECKBOX)
  • 单选按钮(BS_AUTORADIOBUTTON 和 BS RADIOBUTTON)

每种按钮类型都有其特定的属性和样式,开发者可以通过设置这些属性来定制按钮的外观和行为。例如,可以设置按钮的尺寸、颜色、字体以及特定状态(如按下、鼠标悬停)下的视觉效果。

在下面的章节中,我们将详细探讨如何创建和继承自定义按钮类,以及如何优化按钮控件以提升用户体验。

2. 自定义按钮类的创建和继承

2.1 MFC中的按钮控件概述

2.1.1 CButton类的作用和特点

MFC(Microsoft Foundation Classes)为开发者提供了一个丰富的类库,用以构建Windows应用程序。在MFC中, CButton 类是用来创建和管理Windows按钮控件的。按钮控件作为用户界面的一部分,承担着接收用户输入和反馈系统状态的重要职责。

CButton 类的特点包括: - 封装性 :将Windows API中的按钮操作封装成面向对象的形式。 - 灵活性 :支持多种按钮样式和行为,如命令按钮、复选框、单选按钮等。 - 扩展性 :开发者可以通过继承 CButton 类来创建自定义按钮控件。

2.1.2 按钮控件的种类和属性

在MFC中,按钮控件有多种类型,每种类型都对应不同的用途和属性: - 命令按钮 :执行命令或操作。 - 复选框 :允许用户通过勾选或清除来选择多个选项。 - 单选按钮 :在一个分组中只允许用户选择一个选项。 - 位图按钮 :显示自定义的位图图像。 - Owner Drawn Button :允许开发者自定义按钮的绘制方式。

每种按钮类型都拥有不同的属性和状态,例如是否被选中、是否可用、鼠标悬停时的视觉反馈等。

2.2 创建自定义按钮类

2.2.1 类的声明和成员变量设置

创建自定义按钮类首先需要声明一个继承自 CButton 的类,并添加必要的成员变量来存储按钮状态和配置信息。例如:

class CCustomButton : public CButton
{
protected:
    // 按钮文本颜色、背景色等成员变量
    COLORREF m_textColor;
    COLORREF m_bgColor;

public:
    // 构造函数、析构函数
    CCustomButton();
    virtual ~CCustomButton();

    // 更多自定义函数和消息映射
    // ...
};
2.2.2 构造函数和析构函数的编写

在自定义按钮类的构造函数中,我们可以初始化成员变量,并且设置按钮的基本属性。析构函数则用于进行必要的清理工作。

CCustomButton::CCustomButton()
{
    m_textColor = RGB(255, 255, 255); // 默认白色文本
    m_bgColor = RGB(0, 128, 0); // 默认绿色背景
    // 初始化其他成员变量
}

CCustomButton::~CCustomButton()
{
    // 清理资源
}

2.3 继承自CButton类

2.3.1 继承机制与多态性的应用

继承是面向对象编程中的核心概念之一,它允许我们基于现有的 CButton 类创建新类,从而获得按钮的所有基本功能,并在此基础上添加新的行为或属性。

通过继承 CButton 类,我们可以在子类中重写(override)虚函数,如 OnPaint OnClick 等,来实现自定义的行为。这种多态性允许同一接口能够根据对象的不同执行不同的操作。

// 示例:重写OnPaint函数以实现自定义绘制
void CCustomButton::OnPaint()
{
    // 自定义绘制逻辑
    // ...
}
2.3.2 如何处理继承中的消息映射

在MFC中,消息映射是处理Windows消息的关键。我们需要在子类中添加消息映射宏,以便处理继承自 CButton 的消息,或添加新的消息处理函数。

BEGIN_MESSAGE_MAP(CCustomButton, CButton)
    // 消息映射宏
    ON_WM_PAINT()
    // 添加更多消息映射
END_MESSAGE_MAP()

通过以上步骤,我们已经创建了一个简单的自定义按钮类,并通过继承机制增加了其功能和表现。接下来的章节将深入探讨如何利用重写 OnPaint 函数来自定义按钮的绘制方式。

3. 重写OnPaint消息映射函数

3.1 OnPaint函数的作用和必要性

3.1.1 GDI绘图基础

在Windows应用程序中,GDI(图形设备接口)是一个重要的库,用于处理图形输出到屏幕或打印机等输出设备。GDI提供了大量的API函数来执行诸如绘图、渲染文本以及处理位图和图标等操作。

使用GDI,开发者可以绘制线条、矩形、圆形、椭圆等基本图形。同时,GDI支持复杂图形操作,如区域填充、裁剪以及颜色转换。在MFC框架中,GDI通常与CDC类一起使用,CDC是设备上下文类,是与具体设备相关的类,例如屏幕或打印机。

3.1.2 OnPaint在按钮绘制中的角色

按钮控件通常需要根据不同的状态(如正常、悬停、按下、禁用等)显示不同的外观。 OnPaint 函数扮演的角色是负责根据按钮的当前状态绘制其外观。

当按钮的状态发生变化时,Windows操作系统会发送一个WM_PAINT消息给按钮控件,这时按钮控件需要调用 OnPaint 函数来重绘其界面。开发者可以通过重写 OnPaint 函数,利用GDI和CDC类来绘制自定义的按钮图形,从而实现按钮状态的视觉反馈。

3.2 实现自定义绘制

3.2.1 使用CDC进行绘制

在MFC中,CDC类负责处理所有的绘图操作。重写 OnPaint 函数时,将得到一个指向CDC对象的指针,通过该对象可以访问所有GDI绘图功能。下面是一个基本的 OnPaint 函数重写的示例代码:

void CMyButton::OnPaint()
{
    CPaintDC dc(this); // device context for painting

    // TODO: 在此处添加消息处理程序代码
    // 不要调用 CWnd::OnPaint() 对此消息进行处理。
}

上述代码中, CPaintDC 对象 dc 是当前按钮的设备上下文,它提供了多种绘图方法。在 OnPaint 函数中,应当使用 CPaintDC 实例来完成所有绘图操作。

3.2.2 重写OnPaint函数的具体步骤

自定义绘制按钮时,首先需要了解按钮在不同状态下的外观需求,然后根据这些需求来编写绘制逻辑。以下是重写 OnPaint 函数的步骤:

  1. 检查按钮状态并获取相关状态信息。
  2. 创建GDI对象,如画刷、字体或位图,根据状态定制绘制外观。
  3. 使用CDC类的绘图函数进行绘制,例如 CDC::Rectangle 绘制边框、 CDC::FillSolidRect 填充颜色等。
  4. 在绘制完成后,清理并释放所有GDI资源。

这是一个更具体的 OnPaint 函数重写示例:

void CMyButton::OnPaint()
{
    CPaintDC dc(this);
    CRect rect;
    GetClientRect(&rect); // 获取按钮客户区大小

    // 设置按钮背景颜色
    CBrush myBrush(RGB(255, 255, 0)); // 黄色背景
    dc.FillSolidRect(&rect, myBrush);

    // 绘制边框
    dc.Rectangle(&rect);

    // 绘制文本
    dc.TextOut(20, 10, _T("Button Text"));
}

这段代码实现了按钮的简单自定义绘制,为按钮绘制了黄色背景、边框和文本。开发者可以根据需求继续添加更复杂的图形绘制逻辑。

3.3 美化按钮外观

3.3.1 使用位图和图标

为了进一步美化按钮外观,开发者可以使用位图(Bitmaps)或图标(Icons)作为按钮的背景或者装饰。在MFC中,可以通过 CBitmap 类加载位图资源,并在 OnPaint 函数中将其绘制到按钮上。

例如,加载并绘制一个位图的操作过程如下:

void CMyButton::OnPaint()
{
    CPaintDC dc(this);
    CRect rect;
    GetClientRect(&rect);

    // 加载位图
    CBitmap bitmap;
    bitmap.LoadBitmap(IDB_MYBITMAP); // 假设IDB_MYBITMAP是位图资源标识

    // 创建兼容DC和CBitmap的CPaintDC
    CDC memDC;
    memDC.CreateCompatibleDC(&dc);
    CBitmap* pOldBitmap = memDC.SelectObject(&bitmap);

    // 设置透明颜色
    bitmap.SetTransparencyColor(RGB(255, 0, 255)); // 设置紫色透明

    // 将位图绘制到按钮
    BITMAP bmpInfo;
    bitmap.GetBitmap(&bmpInfo);
    dc.BitBlt(0, 0, bmpInfo.bmWidth, bmpInfo.bmHeight, &memDC, 0, 0, SRCCOPY);

    // 恢复兼容DC的原始位图
    memDC.SelectObject(pOldBitmap);

    // 释放DC
    dc.DeleteDC();
}

上述代码段展示了如何加载一个位图资源并将其绘制到按钮上,同时设置了一个透明颜色,使得该颜色在按钮上显示为透明。

3.3.2 应用透明效果和渐变色

为了进一步提升视觉效果,可以在按钮绘制中应用透明效果和渐变色。透明效果可以通过修改位图的透明色来实现,而渐变色则需要使用到更高级的GDI+技术。

透明效果已在上面的示例中展示。渐变色可以使用 CLinearGradientBrush 类实现,它提供了创建线性渐变填充的接口。下面是一个简单的渐变填充示例:

void CMyButton::OnPaint()
{
    CPaintDC dc(this);
    CRect rect;
    GetClientRect(&rect);

    // 创建一个线性渐变画刷
    CLinearGradientBrush lgbBrush(
        ***Left(), // 渐变起始点
        rect.BottomRight(), // 渐变终点
        RGB(255, 255, 0), // 起始颜色
        RGB(255, 0, 0) // 终止颜色
    );

    // 使用渐变画刷填充按钮背景
    dc.FillSolidRect(&rect, &lgbBrush);
    // ... 继续绘制边框和文本
}

上述代码段创建了一个从左上角到右下角的黄到红的线性渐变,并填充到按钮的客户区,从而增加了按钮的视觉层次感。

在实现渐变效果时,需要注意选择合适的渐变方向和颜色,以便和按钮的整体设计风格相匹配。开发者还可以根据实际需求调整渐变的详细参数,如渐变的中心位置、颜色以及透明度等。通过这样的视觉优化,可以使按钮的外观更加吸引用户,提升整个应用界面的质感。

4. 加载和设置按钮图像的方法

4.1 图像资源的准备和管理

4.1.1 利用资源编辑器创建和导入图像

在MFC应用程序中,资源编辑器是一个非常强大的工具,它允许开发者轻松地创建和管理各种资源。图像资源是按钮自定义外观的重要组成部分,通常情况下,你需要准备多种分辨率和大小的图像以适应不同屏幕和设备。

  1. 打开你的项目资源视图,右键点击资源中的“Resource”文件夹,选择“Add” -> “Resource”。
  2. 在弹出的资源类型列表中选择“Bitmap”来创建一个新的位图资源。
  3. 使用资源编辑器中的工具来绘制或导入你的图像。对于按钮来说,一般需要准备正常、按下和鼠标悬停时的图像状态。
  4. 图像可以是位图文件(.bmp),图标文件(.ico),甚至是JPEG或GIF格式的图像。但出于效率和兼容性的考虑,推荐使用位图文件。

对于图像资源的管理,当涉及到多个按钮或多个窗口使用相同图像时,你可以将图像资源保存为一个资源文件,并在需要时通过资源ID来访问它。这样可以避免重复存储相同的数据,节省内存空间。

// 示例:在CButton派生类中,如何加载资源ID为IDB_BUTTON_IMAGE的图像
BOOL CCustomButton::SetBitmap(CString strImageName, HINSTANCE hInst)
{
    BITMAP bmp;
    if (GetBitmap(hInst, MAKEINTRESOURCE(strImageName), &bmp))
    {
        m_Bmp.LoadBitmap(bmp.bmWidth, bmp.bmHeight, (BYTE*)&bmp.bmBits);
        return TRUE;
    }
    return FALSE;
}

4.1.2 图像资源的内存管理

管理图像资源的内存是一个重要课题,尤其是在资源有限的移动设备或嵌入式系统中。在MFC中,图像资源(如位图)可以通过Windows API来加载和释放,确保资源被有效地管理。

  1. 当一个图像加载到应用程序中时,Windows操作系统会将图像数据载入内存。对于动态创建和更新的按钮图像,要确保图像资源在使用后能够被正确地释放。
  2. 在MFC中,使用 CBitmap 类来管理GDI(图形设备接口)对象是一个良好的实践。当 CBitmap 对象被销毁时,它会自动释放与之关联的资源。
  3. 在按钮图像更新时,应避免在消息循环中频繁加载和卸载大量图像资源。相反,应该在资源充足时预加载所有需要的图像资源,并在不再需要时统一释放它们。
void CCustomButton::ReleaseBitmaps()
{
    if (m_Bmp.GetSafeHandle() != NULL)
    {
        m_Bmp.DeleteObject();
    }
}

4.2 加载图像到按钮

4.2.1 使用LoadBitmap和LoadImage函数

在MFC中, CButton 类提供了一些函数来加载图像到按钮上。最常用的是 LoadBitmap LoadImage 函数。

  1. LoadBitmap 函数用于加载一个位图资源到按钮上。位图资源通常是在资源编辑器中创建并保存在项目资源文件中的。
  2. LoadImage 函数更为通用,它不仅可以加载位图资源,还可以加载图标(.ico文件)和光标(.cur文件)。它还可以指定加载时的标志来控制图像的尺寸调整行为。
// 示例:在CButton派生类中,如何使用LoadBitmap加载位图资源
BOOL CCustomButton::LoadButtonBitmap(HINSTANCE hInst, UINT nIDResource)
{
    HBITMAP hBitmap = (HBITMAP)::LoadImage(hInst, MAKEINTRESOURCE(nIDResource), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);
    if (hBitmap == NULL)
        return FALSE;

    m_Bmp.Attach(hBitmap);
    Invalidate();
    return TRUE;
}

// 示例:在CButton派生类中,如何使用LoadImage加载图像资源
BOOL CCustomButton::LoadButtonImage(HINSTANCE hInst, UINT nIDResource, UINT nType)
{
    HICON hIcon = (HICON)::LoadImage(hInst, MAKEINTRESOURCE(nIDResource), nType, 0, 0, LR_SHARED | LR_DEFAULTSIZE);
    if (hIcon == NULL)
        return FALSE;

    m_Icon.Attach(hIcon);
    Invalidate();
    return TRUE;
}

4.2.2 处理图像的拉伸和适应

在加载图像到按钮时,经常会遇到需要调整图像尺寸以适应按钮大小的情况。MFC允许开发者在加载图像时就指定拉伸或裁剪图像的标志。

  1. 当使用 LoadBitmap LoadImage 函数时,你可以指定图像拉伸模式。例如,使用 LR_CREATEDIBSECTION 标志可以创建一个DIB(设备独立位图),这样可以避免图像在缩放时出现模糊。
  2. 另外,可以使用 SetBitmap SetIcon 等方法来设置按钮图像,并手动调整图像的大小,使其匹配按钮的尺寸。
// 示例:调整图像尺寸以适应按钮大小
void CCustomButton::ResizeImageToButton()
{
    BITMAP bmp;
    m_Bmp.GetBitmap(&bmp);
    CDC dcMemory;
    dcMemory.CreateCompatibleDC(GetDC());
    CBitmap* pOldBitmap = dcMemory.SelectObject(&m_Bmp);

    // 获取按钮的尺寸
    CRect rcButton;
    GetClientRect(&rcButton);
    // 这里可以添加自定义的图像调整逻辑
    // ...

    dcMemory.SelectObject(pOldBitmap); // 恢复原来选中的位图
    dcMemory.DeleteDC(); // 删除临时的内存DC
}

4.3 按钮图像的动态更新

4.3.1 通过消息映射响应图像更新

动态更新按钮图像通常需要响应外部事件或用户操作。MFC的消息映射机制非常适合用于处理这种情况。

  1. 你可以通过重写按钮的 OnCommand OnLButtonDown 等消息处理函数来响应相应的消息,并触发图像更新。
  2. 通常情况下,图像更新会与某些特定的事件相关联。例如,在一个游戏应用程序中,按钮可能在游戏状态改变时更新其图像。
// 示例:重写OnCommand消息处理函数以响应图像更新
void CCustomButton::OnCommand(UINT nID, UINT nCode)
{
    // 当按钮接收到特定ID的命令时更新图像
    if (nID == MY_BUTTON_UPDATE_COMMAND)
    {
        UpdateButtonImage();
    }
}

void CCustomButton::UpdateButtonImage()
{
    // 更新图像的逻辑代码
    // ...
}

4.3.2 实现按钮图像的动态变化效果

实现动态变化效果,如动画或渐变效果,可以增加按钮的视觉吸引力。这通常涉及到定时器和多帧图像处理。

  1. 使用MFC的 SetTimer 函数来创建一个定时器,然后在 OnTimer 消息处理函数中更新按钮图像。
  2. 可以准备一组图像资源,每一帧代表动画的一个步骤,然后在 OnTimer 消息中循环更换这些图像。
UINT_PTR CCustomButton::m_nTimerID = 0;

void CCustomButton::StartButtonAnimation()
{
    if (m_nTimerID == 0)
    {
        // 设置定时器,第一个参数为定时器ID,第二个为时间间隔
        m_nTimerID = SetTimer(1, 200, NULL);
    }
}

void CCustomButton::StopButtonAnimation()
{
    if (m_nTimerID != 0)
    {
        KillTimer(m_nTimerID);
        m_nTimerID = 0;
    }
}

void CCustomButton::OnTimer(UINT_PTR nIDEvent)
{
    if (nIDEvent == 1)
    {
        // 更新按钮图像到下一帧
        UpdateButtonImageFrame();
        // 触发重绘消息,以便图像更改被渲染
        Invalidate();
    }
    CButton::OnTimer(nIDEvent);
}

void CCustomButton::UpdateButtonImageFrame()
{
    // 更新图像帧的逻辑代码
    // ...
}

这样,通过结合资源管理和消息映射,以及定时器和图像帧更换的逻辑,你就可以实现按钮图像的动态更新和视觉效果的增强。

5. 鼠标事件的处理

5.1 鼠标事件的种类和触发机制

5.1.1 理解鼠标事件和消息

鼠标事件是用户与图形界面交互的基本方式之一,常见的鼠标事件包括鼠标移动( WM_MOUSEMOVE )、左键按下( WM_LBUTTONDOWN )、左键释放( WM_LBUTTONUP )、右键按下( WM_RBUTTONDOWN )、右键释放( WM_RBUTTONUP )等。这些事件通过消息的形式传递给应用程序,应用程序通过处理这些消息来响应用户的操作。

在MFC中,鼠标事件消息会触发对应的函数。例如, WM_LBUTTONDOWN 事件会触发 OnLButtonDown 函数。开发者可以通过重写这些函数来实现自定义的鼠标处理逻辑。

5.1.2 如何捕获和处理鼠标事件

捕获和处理鼠标事件通常涉及以下几个步骤:

  1. 为按钮控件添加消息映射宏,关联到相应的鼠标处理函数。
  2. 在鼠标处理函数中编写事件响应代码。
  3. 更新按钮的状态或界面,以提供视觉反馈。

以下是一个简单的例子,展示如何为一个按钮添加鼠标事件处理:

// 类声明中的消息映射宏
BEGIN_MESSAGE_MAP(CMyButton, CButton)
    // ... 其他消息映射
    ON_WM_LBUTTONDOWN()
    ON_WM_LBUTTONUP()
END_MESSAGE_MAP()

// 鼠标左键按下事件处理函数
void CMyButton::OnLButtonDown(UINT nFlags, CPoint point)
{
    // 在这里处理鼠标左键按下事件
    CButton::OnLButtonDown(nFlags, point);
}

// 鼠标左键释放事件处理函数
void CMyButton::OnLButtonUp(UINT nFlags, CPoint point)
{
    // 在这里处理鼠标左键释放事件
    CButton::OnLButtonUp(nFlags, point);
}

5.2 响应鼠标事件的方法

5.2.1 重写鼠标事件相关函数

通过重写鼠标事件相关的函数,可以实现对鼠标事件的自定义响应。除了前面提到的左右键按下和释放事件,还可以处理鼠标移动和双击事件。

// 鼠标移动事件处理函数
void CMyButton::OnMouseMove(UINT nFlags, CPoint point)
{
    // 更新鼠标悬停时的按钮状态
    CButton::OnMouseMove(nFlags, point);
}

// 鼠标双击事件处理函数
void CMyButton::OnLButtonDblClk(UINT nFlags, CPoint point)
{
    // 在这里处理鼠标双击事件
    CButton::OnLButtonDblClk(nFlags, point);
}

5.2.2 实现自定义的鼠标响应逻辑

在重写的函数中,可以根据鼠标事件的不同进行相应的逻辑处理。例如,可以在鼠标按下时改变按钮的外观,鼠标释放时执行某个动作等。

5.3 鼠标事件与视觉反馈

5.3.1 鼠标悬停、按下和释放的视觉效果

为了提高用户体验,对鼠标的不同状态进行视觉反馈是很重要的。例如,当鼠标悬停在按钮上时,可以通过改变按钮的背景色或边框来表示焦点。当鼠标按下按钮时,可以通过改变按钮的大小或形状来给予反馈。

void CMyButton::OnMouseMove(UINT nFlags, CPoint point)
{
    // 仅当鼠标按下时,改变按钮的样式
    if (m_bMouseDown)
    {
        // 改变按钮的绘制样式,例如边框或背景
        Invalidate(); // 标记按钮为无效,需要重绘
    }
    CButton::OnMouseMove(nFlags, point);
}

void CMyButton::OnLButtonDown(UINT nFlags, CPoint point)
{
    m_bMouseDown = true; // 标记鼠标已经被按下
    // 其他按下时的处理代码
    CButton::OnLButtonDown(nFlags, point);
}

void CMyButton::OnLButtonUp(UINT nFlags, CPoint point)
{
    m_bMouseDown = false; // 标记鼠标释放
    // 其他释放时的处理代码
    CButton::OnLButtonUp(nFlags, point);
}

5.3.2 提升用户体验的设计思路

为了提升用户体验,设计时应考虑以下几点:

  • 一致性 :确保应用程序的视觉反馈风格一致。
  • 明确性 :视觉反馈应清晰明确,让用户知道他们的动作已经得到应用程序的响应。
  • 简洁性 :不要过多地打扰用户,视觉反馈应简单而不干扰主要操作。
  • 及时性 :视觉反馈需要及时,以便用户能立即意识到他们的操作已被处理。

通过以上的步骤和思路,可以有效地将鼠标事件和视觉反馈结合起来,创建出直观且用户友好的按钮界面。

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:在MFC框架中创建自定义按钮通常涉及扩展CButton类以支持图像显示。文章将详细说明如何通过派生类和消息处理来创建支持图像的按钮,包括加载和设置图像、重写绘制函数以及响应鼠标事件。最终,将介绍如何在对话框中应用这些自定义按钮,并提供代码示例来实现这些功能。

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值