MFC基于对话框程序

如果是.net的朋友则在菜单上选择新建->项目,在项目类型中选择Visual C++项目,在模板中选择MFC应用程序,在名称中输入Dialog,按确定。在应用程序类型中选择基于对话框,后按完成。

于是一个基于对话框程序就做好了。第一次使用MFC的朋友,一定会为之喳舌。自己从零开始编程许久了,也许还不习惯别人为咱们生成代码吧。“第一映象就是乱”,这就是我的同学给我的回答。没关系,我们可以一点一点来看和理解VC给我们生成的代码。毕竟,它为我们节省了很多时间来打WindowSDK框架代码。

请打开类视图(ClassView),如果无误的话,我们可以看到三个类。分别是CAboutDlg, CDialogApp, CDialogDlg这三个类。 其中,CDialogApp是最重要的一个类。双击CDialogApp,打开其定义体。我们会看到它是这么定义的:   

1. class CDialogApp : public CWinApp

我们可以看到这个类是派生于CWinApp的。在MFC编程中,这种情况很多见,继承类库类来添加自己需要的功能,然后再去使用。在MFC应用程序中,CWinApp就是这样使用的。查一查类库关于CWinApp的描述,是这样的:

MFC中的主应用程序类封装用于 Windows 操作系统的应用程序的初始化、运行和终止。基于框架生成的应用程序必须有且仅有一个从 CWinApp 派生的类的对象。在创建窗口之前先构造该对象。

CWinApp 是从 CWinThread 派生的,后者表示可能具有一个或多个线程的应用程序的主执行线程。在最新版本的 MFC 中,InitInstance、Run、ExitInstance 和 OnIdle 成员函数实际位于 CWinThread 类中。此处将这些函数作为 CWinApp 成员来探讨,因为探讨所关心的是对象作为应用程序对象而不是主线程的角色。

与用于 Windows 操作系统的任何程序一样,框架应用程序也具有 WinMain 函数。但在框架应用程序中不必编写 WinMain。它由类库提供,并在应用程序启动时调用。WinMain 执行注册窗口类等标准服务。然后它调用应用程序对象的成员函数来初始化和运行应用程序。(可通过重写由 WinMain 调用的 CWinApp 成员函数来自定义 WinMain。)

为初始化应用程序,WinMain 调用应用程序对象的 InitApplication 和 InitInstance 成员函数。为运行应用程序的消息循环,WinMain 调用 Run 成员函数。在终止时,WinMain 调用应用程序对象的 ExitInstance 成员函数。

上面这段里指的框架应用程序,包括了我们这种对话框应用程序。如MSDN所说,MFC类库已经为我们提供了WinMain函数,而不必我们添加。这就是为什么在MFC程序看不见主函数的原故。请看这句话“基于框架生成的应用程序必须有且仅有一个从 CWinApp 派生的类的对象。在创建窗口之前先构造该对象。” 打开类视图的全局(Glotbals),会发现有一个theApp全局变量(或对象,我总觉得变量与对象可以归为一类,应该有一个统一的名称来讲)。双击它,就可以看到CDialogApp theApp这样的定义。因为全局变量和对象在程序中是最先被创建的,于是保证了在创建窗口之前构造一个CWinApp对象(因为CDialogApp派生于CWinApp,所以theApp也是一个CWinApp对象)。这个全局对象是非常有用,因为CWinApp本身集成了所有的程序资源WinAPI,我们可以使用它来取得程序的资源(如图标,图像,预定义字符串等等)。一般要取得此全局对象,不直接使用theApp,而是调用::AfxGetApp()来取得这个全局对象的指针。

MFC默认的主函数,会先调用theApp对象的InitApplication和InitInstance成员函数,来进行程序的初始化,在程序中一般只重写InitInstance函数。然后,建立一个消息循环,不同的是在循环不停地调用theApp的Run成员函数。当收到WM_QUIT后,退出while循环。最后,执行theApp的ExitInstance成员函数,从而结束整个应用程序。

让我们在类视图(Class View)中展开CDialogApp类(点击那个+符号),我们可以看到CDialogApp重写了InitInstance()函数。它用于对应用程序主线程进行初始化。双击视图中的InitInstance()来查看此函数的定义。我这里的函数定义如下:   

01. 000:BOOL CDialogApp::InitInstance()
02. 001:{
03. 002: // 如果一个运行在 Windows XP 上的应用程序代码指定要
04. 003: // 使用 ComCtl32.dll 版本 6 或更高版本来启用可视化方式,
05. 004: //则需要 InitCommonControls()。否则,将无法创建窗口。
06. 005: InitCommonControls();
07. 006:
08. 007: CWinApp::InitInstance(); //调用父类的InitInstance来进行默认的初始化
09. 008:
10. 009: AfxEnableControlContainer();
11. 010:
12. 011:
13. 012: CDialogDlg dlg; //建立一个对话框对象,CDialogDlg是我们自定义的对话框类
14. 013: m_pMainWnd = &dlg; //将本线程(即程序主线程)的主窗口设置为这个对话框
15. 014: INT_PTR nResponse = dlg.DoModal(); //有模式地显示这个对话框,直到对话框关闭
16. 015: if (nResponse == IDOK) //如果对话框是用确定来关闭的,则
17. 016: {
18. 017: // TODO:在此放置处理用“确定”来关闭
19. 018: //对话框的代码
20. 019: }
21. 020: else if (nResponse == IDCANCEL) //如果对话框是用取消来关闭的,则
22. 021: {
23. 022: // TODO:在此放置处理用“取消”来关闭
24. 023: //对话框的代码
25. 024: }
26. 025:
27. 026: // 由于对话框已关闭,所以将返回 FALSE 以便退出应用程序,
28. 027: // 而不是启动应用程序的消息泵。
29. 028: return FALSE;
30. 029:}

因为InitInstance()函数的结束返回值是false,应用程序将会立即退出。也就是只显示对话框,当对话框关闭后,程序就会结束了。这时候的InitInstance函数就有点主函数的味道了。

下面,我们再来看看CDialogDlg类的定义,它是派生于CDialog的。它重写了以下函数

 
1. CDialogDlg(CWnd* pParent = NULL); 自定义的构造函数
2. virtual BOOL OnInitDialog(); 对话框初始化消息操作函数
3. afx_msg void OnSysCommand(UINT nID, LPARAM lParam); 系统菜单消息响应函数
4. afx_msg void OnPaint(); 对话框重绘响应函数
5. afx_msg HCURSOR OnQueryDragIcon(); 最小化图标询问响应函数

另外,要注意的是在CDialogDlg类的定义体中有这么一个枚举的定义:   

 

1. enum { IDD = IDD_DIALOG_DIALOG };

它表明这个CDialogDlg类使用的对话框模板是IDD_DIALOG_DIALOG。

CDialogDlg派生层次如下   

1. CDialogDlg=>CDialog=>CWnd=>CCmdTarget=>CObject

先来看看构造函数:   

 

1. CDialogDlg::CDialogDlg(CWnd* pParent /*=NULL*/)
2. : CDialog(CDialogDlg::IDD/*这个IDD就是那个枚举的值*/, pParent)
3. {
4.     m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
5. }

在这个函数中首先,调用父类CDialog的构造函数来完成默认构造操作。其次,它使用AfxGetApp函数取得全局CWinApp对象theApp的指针,并使用它的LoadIcon函数来取得程序中IDR_MAINFRAME图标资源,并赋给成员变量m_hIcon。这个图标可以在资源视图的ICON中可以的查到和设定。

在CDialogDlg的实现文件CDialogDlg.cpp中,可以找到如下一段语句

 
1. BEGIN_MESSAGE_MAP(CDialogDlg, CDialog)
2. ON_WM_SYSCOMMAND()
3. ON_WM_PAINT()
4. ON_WM_QUERYDRAGICON()
5. //}}AFX_MSG_MAP
6. END_MESSAGE_MAP()

这是一段消息映射宏定义段。表示这个对话框类可以响应WM_SYSCOMMAND ,WM_PAINT,WM_QUERYDRAGICON消息。它们的响应函数,系统默认分别为OnSysCommand,OnPaint,OnQueryDragIcon。这段的意思是说,如果CDialogDlg类的对话框接收到WM_SYSCOMMAND消息,就会调用OnSysCommand。其它消息以此为例。不过,这些响应段一般是用不着我们自己手动添写的,是由系统来管理的。你如果要分析一个MFC程序代码,这一块是一个很好的切入点,可以清楚的看到这个程序到底都可以响应什么消息,都有些什么功能。以上这些宏都可以在MSDN中查到。

下面,我们来一个对于对话框非常重要的函数OnInitDialog(),顾名思义这是一个对话框的初始化函数。在对话框创建之后,第一次显示之前调用。

 
01. BOOL CDialogDlg::OnInitDialog()
02. {
03.     CDialog::OnInitDialog(); //执行父类默认的初始化对话框操作
04.     // IDM_ABOUTBOX 必须在系统命令范围内。
05.     ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
06.     ASSERT(IDM_ABOUTBOX < 0xF000);
07.     // 将\“关于...\”菜单项添加到系统菜单中。
08.     CMenu* pSysMenu = GetSystemMenu(FALSE); //取得此对话框系统菜单的CMenu对象指针,并赋给pSysMenu;
09.     if (pSysMenu != NULL) //如果不为空,则
10.     {
11.         CString strAboutMenu; //声明一个字符串对象
12.         strAboutMenu.LoadString(IDS_ABOUTBOX); //取得资源IDS_ABOUTBOX预定义字符串,可以
13.         //在资源视图中的String Table查到和设定这个预定义字符串
14.         if (!strAboutMenu.IsEmpty()) //如果不为空,则
15.         {
16.             pSysMenu->AppendMenu(MF_SEPARATOR); //向菜单添加一个分隔符
17.             pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
18.             //向菜单添加这个字符串,并将消息ID设为IDM_ABOUTBOX
19.         }
20.     }
21.     // 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
22.     // 执行此操作
23.     SetIcon(m_hIcon, TRUE); // 设置大图标
24.     SetIcon(m_hIcon, FALSE); // 设置小图标
25.     // TODO:在此添加额外的初始化代码
26.     return TRUE; // 除非设置了控件的焦点,否则应该返回 TRUE
27. }

以上,就是这个基于对话框的MFC应用程序的基础代码。现在可以直接编译运行,来查看效果。 下面,我将在这些代码的基础上来添加功能,来实现一个复制文件的程序。 首先,我要在资源视图的Dialog中,修改IDD_DIALOG_DIALOG模板: 我首先将对话框模板上面的所有按钮和静态文本全部删掉,添加两个文本框和四个按钮。如果要修改控件的ID值,则要右击控件,点选属性,在ID框中输入任意的ID字符串即可。基本布局如下:

注:粗体字代表该控件的ID值。

如果想向CDialogDlg类添加按钮事件, 有两种简单的方法。第一种在模板设计中,双击按钮,按确定后,即添加该按钮单击事件。另一种方法是使用向导(在.NET中是在CDialog类的属性对话框中的事件栏中添加),首先在视图(View)菜单中选择类向导(ClassWizard),弹出类向导对话框,在类名(ClassName)下拉框中选择我们的要添加事件的类CDialogDlg。对象ID(Object ID)列表框中选择控件的ID,在消息(Messages)列表框中选择要添加的事件,按添加函数钮(Add Function)即可。

将四个按钮分别添加单击事件,系统会为我们自动命名成员函数。如果无误的话,分别是OnBnClickedCancel();OnBnClickedCopy();OnBnClickedSrbrowse();OnBnClickedTrbrowse();因为我用的是.NET, 可能会与6.0生成的函数名略有不同。在添加完事件后,你最好去看看上面所提到过的消息映射宏有什么变化,是否能够读懂它们。

首先在OnBnClickedCancel()函数中添加这么一行语句:

 
1. this->EndDialog(IDCANCEL);

这行语句的作用是关闭当前的对话框,并以IDCANCEL返回,表明用户是用取消来关闭对话框的。这是CDialog类的一个方法。我们期望如果点击了取消按钮,则关闭当前的对话框。

我们再来处理一下浏览按钮的功能。我期望可以弹出一个选择文件的对话框,来选择源文件和目标文件,并把文件名显示在文本框里。这个文件对话框刚好在MFC类库有所定义,我们可以直接拿来使用。首先,我们必须在CDialogDlg类的实现文件CDialogDlg.cpp的头几行添加一个含包头文件

 
1. #include

然后,在源文件浏览按钮(ID_SRBROWSE)的响应函数OnBnClickedSrbrowse里添加如下语句:

 
01. CFileDialog Open(true/*如果为真则对话框为打开对话框,为否则为保存对话框*/,
02. "" /*默认后缀名*/,
03. "" /*默认文件名*/,
04. 0 /*对话框风格*/,
05. "All File|*.*|",
06. this /*父窗口指针*/);
07.
08. CString strFilePath;
09. if (Open.DoModal() == IDOK) //有模式地显示对话框,如果返回确定则代表有文件选择,则
10. {
11.     strFilePath = Open.GetPathName(); //取得文件路径字符串
12.     SetDlgItemText (IDC_SOURCE, strFilePath); //将ID为IDC_SOURCE的控件的文本设为该字符串
13. }

要说明的,CString是MFC的字符串类,在形式上可以当成字符数组。而且还可以像VB的字符串一样使用,直接进行字符串赋值。
还有就是SetDlgItemText,这是CWnd类的一个方法,功能是将改变当前窗口的某控件的文本。这个控件可以是按钮、文本框、静态文本、下拉列表框等等。其第一个参数是该控件的ID,第二个参数是以0结尾的字符串。

以这个函数类推,可以将目标浏览按钮的功能代码写成如下:

 
01. CFileDialog Save(false /**/,
02. "" /*默认后缀名*/,
03. "" /*默认文件名*/,
04. 0 /*对话框风格*/,
05. "All File|*.*|",
06. this /*父窗口指针*/);
07. CString strFilePath;
08. if (Save.DoModal() == IDOK)
09. {
10.     strFilePath = Save.GetPathName();
11.     SetDlgItemText (IDC_TARGET, strFilePath);
12. }

最后,我们再来完成复制按钮的功能。在单击事件响应函数OnBnClickedTrbrowse中添加如下代码:

 
1. CString strSource,strTarget;
2. GetDlgItemText (IDC_SOURCE, strSource); //取得ID名为IDC_SOURCE控件的文本
3. GetDlgItemText (IDC_TARGET, strTarget); //取得ID名为IDC_TARGET控件的文本
4. if (CopyFile (strSource, strTarget, false)) //复制文件,如果返回为真表示成功,则
5. {
6.     MessageBox ("复制成功!", "报告", MB_OK); //弹出一个确定框
7. }

这里要解释的是GetDlgItemText,它也是CWnd的一个方法,是SetDlgItemText的反过程,用于取得窗口上某个控件的文本。CopyFile是WinAPI,它用于进行文件的复制,第一个参数是表示源文件名的字符串,第二个参数是表示目标文件名的字符串。如果成功的话则返回真。CWnd::MessageBox函数用于显示一个消息框,第一个参数是消息文本,第二个参数是标题文本,第三个参数是消息框种类,这里是MB_OK确定框,还可以是MB_YESNO是否框等等,以上这些可以在MSDN中查到。

  • 4
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
目 录 译者序 前言 第一部分 基础知识 第1章 窗口 2 1.1 窗口和API环境 2 1.1.1 三种类型窗口 2 1.1.2 客户区和非客户区 3 1.2 窗口和MFC环境 4 1.3 怎样应用MFC创建一个窗口 5 1.4 怎样使用MFC销毁一个窗口 9 1.4.1 捆绑到一个已有的窗口 9 1.4.2 窗口类 10 1.4.3 窗口进程 10 1.5 怎样使用MFC创建一个窗口类 11 1.5.1 使用AfxRegisterWndClass () 函数注册一个窗口类 11 1.5.2 使用AfxRegisterClass ()函数 创建一个窗口类 12 1.6 怎样销毁一个MFC窗口类 14 1.7 厂商安装的窗口类 14 1.8 其他类型窗口 15 1.9 桌面窗口 16 1.10 小结 16 第2章 类 18 2.1 基类 18 2.1.1 CObject 18 2.1.2 CCmdTarget 19 2.1.3 CWnd 19 2.2 应用程序、框架、文档和视图类 19 2.2.1 CWinApp(O/C/W) 20 2.2.2 CView (O/C/W) 21 2.3 其他用户界面类 22 2.3.1 通用控件类 23 2.3.2 菜单类 23 2.3.3 对话框类 24 2.3.4 控制条类 24 2.3.5 属性类 25 2.4 绘图类 25 2.4.1 设备环境类 25 2.4.2 图形对象类 25 2.5 文件类 26 2.6 数据库类 26 2.6.1 ODBC类 26 2.6.2 DAO类 27 2.7 数据集类 27 2.8 其他数据类 27 2.9 通信类 28 2.10 其他类 29 2.11 小结 31 第3章 消息处理 32 3.1 发送或寄送一个消息 32 3.1.1 发送一个消息 32 3.1.2 寄送一个消息 32 3.1.3 发送一个消息与寄送一个消息 的比较 32 3.2 怎样使用MFC发送一个消息 33 3.3 怎样用MFC寄送一个消息 33 3.4 三种类型的消息 34 3.4.1 窗口消息 34 3.4.2 命令消息 34 3.4.3 控件通知 34 3.5 MFC怎样接收一个寄送的消息 36 3.6 MFC怎样处理一个接收到的消息 36 3.7 处理用户界面的对象 44 3.8 创建自定义窗口消息 45 3.8.1 静态分配的窗口消息 45 3.8.2 动态分配的窗口消息 46 3.9 重定向消息 47 3.9.1 子分类和超分类 47 3.9.2 用MFC子分类窗口 48 3.9.3 重载OnCmdMsg ( ) 49 3.9.4 使用SetWindowsHookEx ( ) 49 3.9.5 使用SetCapture ( ) 49 3.9.6 专有的消息泵 50 3.10 小结 50 第4章 绘图 51 4.1 设备环境 51 4.2 在MFC环境中创建一个设备环境 52 4.2.1 屏幕 52 4.2.2 打印机 53 4.2.3 内存 54 4.2.4 信息 54 4.3 绘图例程 55 4.3.1 画点 55 4.3.2 画线 55 4.3.3 画形状 55 4.3.4 形状填充和翻转 55 4.3.5 滚动 56 4.3.6 绘制文本 56 4.3.7 绘制位图和图标 56 4.4 绘图属性 56 4.4.1 设备环境属性 57 4.4.2 画线属性 58 4.4.3 形状填充属性 58 4.4.4 文本绘制属性 58 4.4.5 映像模式 59 4.4.6 调色板属性 62 4.4.7 混合属性 62 4.4.8 剪裁属性 63 4.4.9 位图绘制属性 64 4.5 元文件和路径 65 4.5.1 元文件 65 4.5.2 路径 66 4.6 颜色和调色板 66 4.6.1 抖动色 67 4.6.2 未经抖动色 67 4.6.3 系统调色板 67 4.6.4 使用系统调色板 68 4.6.5 动画色 71 4.7 控制什么时候在哪里绘图 71 4.7.1 处理WM_PAINT 71 4.7.2 只绘制被无效化的区域 72 4.7.3 处理WM_DRAWITEM 72 4.7.4 在其他时间绘图 73 4.8 小结 74 第二部分 用户界面实例 第5章 应用程序与环境 76 5.1 例1 规划MFC应用程序 76 5.2 例2 用AppWizard创建一个MFC 应用程序 79 5.3 例3 用ClassWizard创建一个类 83 5.4 例4 初始化应用程序屏幕 84 5.5 例5 保存应用程序屏幕 86 5.6 例6 处理命令行选项 88 5.7 例7 动态改变应用程序图标 91 5.8 例8 提示用户优先选项 93 5.9 例9 保存和恢复用户优先选项 97 5.10 例10 终止应用程序 100 5.11 例11 创建一个启动窗口 101 第6章 菜单 107 6.1 例12 使用菜单编辑器 107 6.2 例13 添加一个菜单命令处理函数 109 6.3 例14 根据当前可视文档动态改 变菜单 110 6.4 例15 启用和禁用菜单命令 111 6.5 例16 复选标记菜单命令 112 6.6 例17 单选标记菜单命令 113 6.7 例18 动态修改菜单 114 6.8 例19 动态修改系统菜单 116 6.9 例20 触发一个菜单命令 117 6.10 例21 创建弹出式菜单 117 第7章 工具栏和状态栏 120 7.1 例22 使用工具栏编辑器 120 7.2 例23 启用和禁用工具栏按钮 122 7.3 例24 为工具栏按钮添加字 123 7.4 例25 非标准工具栏大小 128 7.5 例26 保持工具栏按钮按下 129 7.6 例27 保持工具栏按钮组中 一个按钮按下 130 7.7 例28 为工具栏添加非按钮控件 131 7.8 例29 修改应用程序的状态栏 136 7.9 例30 更新状态栏窗格 138 7.10 例31 为状态栏添加其他控件 139 第8章 视图 145 8.1 例32 滚动视图 145 8.2 例33 改变鼠标光标形状 147 8.3 例34 沙漏光标 148 8.4 例35 窗体视图 149 8.5 例36 列表视图 152 8.6 例37 动态分割一个视图 163 第9章 对话框和对话条 166 9.1 例38 使用对话框编辑器 166 9.2 例39 创建一个对话框类 168 9.3 例40 模式对话框 170 9.4 例41 无模式对话框 171 9.5 例42 在无模式对话框的控件间 切换焦点 172 9.6 例43 对话框中的动画 173 9.7 例44 消息框 174 9.8 例45 对话条 176 第10章 控件窗口 182 10.1 例46 在任意位置创建一个控 件窗口 182 10.2 例47 用子分类定制一个通用 控件窗口 183 10.3 例48 用超分类定制一个通用 控件窗口 188 10.4 例49 在按钮上放置位图 190 10.5 例50 动态填充一个组合框 192 10.6 例51 排序一个列表控件 194 10.7 例52 分隔线控件 196 第11章 绘图 198 11.1 例53 绘制图形 198 11.2 例54 绘制文本 201 11.3 例55 从任意位置装入一个图 标并绘制 203 11.4 例56 从任意位置装入一个位 图和绘制一个位图 204 11.5 例57 从文件中创建一个位图 206 11.6 例58 创建一个自绘位图 211 第三部分 内部处理实例 第12章 消息 215 12.1 例59 添加消息处理函数或重 载MFC类 216 12.2 例60 添加命令范围消息处理函数 219 12.3 例61 重定向命令消息 221 12.4 例62 创建自己的窗口消息 222 第13章 文件、串行化和数据库 225 13.1 例63 访问二进制文件 225 13.2 例64 访问标准I/O文件 227 13.3 例65 访问内存文件 228 13.4 例66 在数据类中实现串行化 229 13.5 例67 串行化SDI或MDI文档 235 13.6 例68 按要求串行化 240 13.7 例69 透明地更新串行化的文档 242 13.8 例70 串行化多态类 246 13.9 例71 串行化数据集 248 13.10 例72 访问ODBC数据库 252 13.11 例73 访问DAO数据库 257 第14章 杂类 263 14.1 例74 剪切、拷贝和粘贴文本 数据 263 14.2 例75 剪切、拷贝、粘贴多信 息文本数据 268 14.3 例76 剪切、拷贝和粘贴二进制 数据 273 14.4 例77 数组函数 280 14.5 例78 列表函数 281 14.6 例79 映像函数 283 14.7 例80 系统键盘输入 285 14.8 例81 时间 288 第四部分 打包实例 第15章 库 291 15.1 例82 静态链接C/C++库 291 15.2 例83 动态链接C/C++库 295 15.3 例84 动态链接MFC扩展类库 300 15.4 例85 资源库 303 第五部分 附录 附录A 控件窗口风格 305 附录B 消息、控件通知和消息映像宏 323 附录C 访问其他应用程序类 328 附录D 开发中注意事项 330 附录E MFC快速参考指南 339

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值