MFC学习笔记

  • 个人财务管理软件设计中MFC控件的使用(List)
  • list control控件的使用
  • combo box控件的使用
  • 文件保存
  • 登录对话框的建立
  • 问题-MFC读取文件在EditControl中显示乱码
  • 添加bmp文件和ICO文件
  • 画图实现实时显示图形轨迹
  • MessageBox()的使用
  • Invalidate,UpdateWindow,UpdateDate

个人财务管理软件设计中MFC控件的使用(List)

1.添加内容

//将添加的信息在列表中显示CString sName, sDate, sPlace, sSalary, sBonus, sAlimony;ifstream addfin("adduse.txt", ios::in);string a1, a2, a3, a4, a5, a6;while(addfin >> a1>> a2 >> a3 >> a4 >> a5 >> a6){sName=a1.c_str();sDate = a2.c_str();sPlace = a3.c_str();sSalary = a4.c_str();sBonus = a5.c_str();sAlimony = a6.c_str();myList1.InsertItem(0, NULL);//插入一个行myList1.SetItemText(0, 0, sName);//填充数据myList1.SetItemText(0, 1, sDate);myList1.SetItemText(0, 2, sPlace);myList1.SetItemText(0, 3, sSalary);myList1.SetItemText(0, 4, sBonus);myList1.SetItemText(0, 5, sAlimony);}

2.删除内容

//判断列表框中是否有记录if (!myList1.GetItemCount())    {MessageBox(L"暂无记录", L"警告",  MB_OKCANCEL | MB_ICONEXCLAMATION);return;}//判断是否选中一项,若选中则删除POSITION ps;int index = 0;ps = myList1.GetFirstSelectedItemPosition();index = myList1.GetNextSelectedItem(ps);//标记行号if (-1 == index){MessageBox(L"请选中一行数据", L"警告", MB_OKCANCEL | MB_ICONEXCLAMATION);return;}else{if (IDOK == MessageBox(L"确定删除?", L"提示", MB_OKCANCEL | MB_ICONQUESTION)){myList1.DeleteItem(index);}}

3.修改内容

// 删除再添加

4.查询内容

CString str, cbsel;int nIndex = myCombo.GetCurSel();myCombo.GetLBText(nIndex, str);GetDlgItemText(IDC_CBSEL, cbsel);UpdateData(TRUE);int i,flag = 0;if (str == "姓名"){for (i = 0; i<myList1.GetItemCount(); ++i){if (cbsel == myList1.GetItemText(i, 0)){myList2.InsertItem(0, NULL);myList2.SetItemText(0, 0, myList1.GetItemText(i, 0));myList2.SetItemText(0, 1, myList1.GetItemText(i, 1));myList2.SetItemText(0, 2, myList1.GetItemText(i, 2));myList2.SetItemText(0, 3, myList1.GetItemText(i, 3));myList2.SetItemText(0, 4, myList1.GetItemText(i, 4));myList2.SetItemText(0, 5, myList1.GetItemText(i, 5));UpdateData(FALSE);flag = 1;}}}else if (str == "...")//其他查询条件的实现方法基本相同,不再赘述

5.保存到文档

USES_CONVERSION;char* save1;ofstream savefile;savefile.open("SAVEFILE.txt", ios::out);for(int j=0;j<myList1.GetItemCount();++j){save1 = W2A(myList1.GetItemText(j, 0));savefile << save1 << " ";save1 = W2A(myList1.GetItemText(j, 1));savefile << save1 << " ";save1 = W2A(myList1.GetItemText(j, 2));savefile << save1 << " ";save1 = W2A(myList1.GetItemText(j, 3));savefile << save1 << " ";save1 = W2A(myList1.GetItemText(j, 4));savefile << save1 << " ";save1 = W2A(myList1.GetItemText(j, 5));savefile << save1 << " " << endl;}savefile.close();MessageBox(L"保存成功", L"提示", MB_OKCANCEL);

这个里功能更全面:百度文库-MFC学生信息管理系统详解

list control控件的使用

1.设置listctrl 风格及扩展风格

      LONG lStyle;lStyle = GetWindowLong(m_list.m_hWnd, GWL_STYLE);//获取当前窗口stylelStyle &= ~LVS_TYPEMASK; //清除显示方式位lStyle |= LVS_REPORT; //设置styleSetWindowLong(m_list.m_hWnd, GWL_STYLE, lStyle);//设置styleDWORD dwStyle = m_list.GetExtendedStyle();dwStyle |= LVS_EX_FULLROWSELECT;//选中某行使整行高亮(只适用与report风格的listctrl)dwStyle |= LVS_EX_GRIDLINES;//网格线(只适用与report风格的listctrl)dwStyle |= LVS_EX_CHECKBOXES;//item前生成checkbox控件m_list.SetExtendedStyle(dwStyle); //设置扩展风格

2.插入数据

 m_list.InsertColumn( 0, "id", LVCFMT_LEFT, 40 );//插入列m_list.InsertColumn( 1, "name", LVCFMT_LEFT, 50 );int nRow = m_list.InsertItem(0, “”);//插入行m_list.SetItemText(nRow, 0, “12138”);//设置数据,第1列m_list.SetItemText(nRow, 1, “Jack”);//设置数据,第2列

3.选中和取消选中一行

 int nIndex = 0;//选中m_list.SetItemState(nIndex, LVIS_SELECTED|LVIS_FOCUSED, LVIS_SELECTED|LVIS_FOCUSED);//取消选中m_list.SetItemState(nIndex, 0, LVIS_SELECTED|LVIS_FOCUSED);

4.得到listctrl中所有行的checkbox的状态

      m_list.SetExtendedStyle(LVS_EX_CHECKBOXES);CString str;for(int i=0; i<m_list.GetItemCount(); i++){if( m_list.GetItemState(i, LVIS_SELECTED) == LVIS_SELECTED || m_list.GetCheck(i)){str.Format(_T("第%d行的checkbox为选中状态"), i);AfxMessageBox(str);}}

5.得到listctrl中所有选中行的序号

      POSITION pos = m_list.GetFirstSelectedItemPosition();if (pos == NULL)TRACE0("No items were selected!\n");else{while (pos){int nItem = m_list.GetNextSelectedItem(pos);TRACE1("Item %d was selected!\n", nItem);// you could do your own processing on nItem here}}

6.得到单击的listctrl的行列号

     //添加listctrl控件的NM_CLICK消息相应函数void CTest6Dlg::OnClickList1(NMHDR* pNMHDR, LRESULT* pResult){// 方法一:/*DWORD dwPos = GetMessagePos();CPoint point( LOWORD(dwPos), HIWORD(dwPos) );m_list.ScreenToClient(&point);LVHITTESTINFO lvinfo;lvinfo.pt = point;lvinfo.flags = LVHT_ABOVE;int nItem = m_list.SubItemHitTest(&lvinfo);if(nItem != -1){CString strtemp;strtemp.Format("单击的是第%d行第%d列", lvinfo.iItem, lvinfo.iSubItem);AfxMessageBox(strtemp);}*/// 方法二:/*NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;if(pNMListView->iItem != -1){CString strtemp;strtemp.Format("单击的是第%d行第%d列",pNMListView->iItem, pNMListView->iSubItem);AfxMessageBox(strtemp);}*/*pResult = 0;}

7.得到listctrl的所有列的header字符串内容

      LVCOLUMN lvcol;char  str[256];int   nColNum;CString  strColumnName[4];//假如有4列nColNum = 0;lvcol.mask = LVCF_TEXT;lvcol.pszText = str;lvcol.cchTextMax = 256;while(m_list.GetColumn(nColNum, &lvcol)){ strColumnName[nColNum] = lvcol.pszText;nColNum++;}

8.右键点击listctrl的item弹出菜单

      //添加listctrl控件的NM_RCLICK消息相应函数void CTest6Dlg::OnRclickList1(NMHDR* pNMHDR, LRESULT* pResult){NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;if(pNMListView->iItem != -1){       m_pRClickMenu = new CMenu();ASSERT(m_pRClickMenu != NULL);m_pRClickMenu->CreatePopupMenu();m_pRClickMenu->AppendMenu(MF_STRING, IDC_BTN_SEND_EMAIL, "发送邮件");m_pRClickMenu->AppendMenu(MF_STRING, IDC_BTN_COPY, "复制到剪切板");// DWORD dwPos = GetMessagePos();// CPoint point( LOWORD(dwPos), HIWORD(dwPos) );CPoint point;GetCursorPos(&point);m_pRClickMenu->TrackPopupMenu(TPM_LEFTALIGN, point.x, point.y, this, NULL);} *pResult = 0;}

combo box控件的使用

1.改变下拉框大小
  1)直接在控件上操作,先点向下的箭头,就可以调整下拉框大小;

2)为了让列表框变的更宽,可以用setdroppedwidth(int width)函数来调整列表框的宽度。

2.定义控件对应变量

假定已经创建了一个Dialog,并且从控件工具箱将Combo Box 控件拖放到上面。打开 Class Wizard,添加控件对应变量,如:CComboBox m_combo。

3.向控件添加 Items

1)在Combo Box控件属性的Data标签里面添加,一行表示Combo Box下拉列表中的一行。换行用ctrl+回车。若在VS2005中,Items间用";"隔开即可;

2)利用函数 AddString()向 Combo Box 控件添加Items,如:

m_combo.AddString(“StringData1”);

m_combo.AddString(“StringData2”);

m_combo.AddString(“StringData3”);

3) 也可以调用函数 InsertString() 将 Item 插入指定位置 nIndex,如:

m_combo.InsertString(nIndex, “StringData” );

4)int GetCount( )可以得到当前列表框中行的数量。

示例代码:程序初始化时动态添加Items

CString strTemp;

m_combo.ResetContent();//消除现有所有内容

for(inti=1;i<=100;i++)

{

strTemp.Format(“%d”,i);

m_combo.AddString(strTemp);

}

4.从控件得到选定的Item

假设在控件列表中已经选定某项,现在要得到被选定项的内容,首先要得到该项的位置,然后得到对应位置的内容。这里会用到两个函数,如:

int nIndex = m_combo.GetCurSel();

CString strText;

m_combo.GetLBText( nIndex, strText);

这样,得到的内容就保存在 strText 中。若要选取当前内容,可调用函数GetWindowText(strText)。

5.在控件中查找给定Item

这种操作一般用于在程序中动态修改控件中该项的值,可以用函数FindStringExact() 精确匹配,如:

int nIndex = m_combo.FindStringExact( nStartAfter, “value to befound”);

nStartAfter指明从哪一行开始查找。如果查找成功,返回的是该项的位置;否则,返回CB_ERR。

也可以选中包含指定字符串的项,如:

int nIndex = m_combo.SelectString( nStartAfter, “value to beselected”);

6.删除控件中的Item

该操作可以利用函数DeleteString(),需要指定被删除项的位置,如:

m_combo.DeleteString(nIndex);

也可以使用函数ResetContent(),清除目前的所有项,如:

m_combo.ResetContent();

文件保存

//法1.C++,fstream类的操作//法2.MFC的CFile操作:
CFile test;
CFileException e;
TCHAR* pszFileName = "test.txt";
if(!test.Open(pszFileName,CFile::modeCreate|CFile::modeNoTruncate|CFile::modeReadWrite, &e))//建立、打开test.txt文件
{AfxMessageBox("File could not be opened %d\n", e.m_cause);
}CString m_str;
pm_dedit=(CEdit*)GetDlgItem(IDC_edit);
pm_dedit->GetWindowText(m_str);
test.Write(m_str,m_str.GetLength());
m_str.Close();//关闭文件//法3.MFC的CStdioFile操作

CFile文件操作详见:VS2010/MFC编程入门之四十五(MFC常用类:CFile文件操作类)

登录对话框的建立

1.在资源视图中添加一个窗体资源。插入Dialog。(此处窗体的ID选用的是默认的,可根据自己的情况进行修改)

2.在对话框区域右键,选择添加类,则会弹出一个添加类的对话框,基类选择CDialog,类名自己起个名字。这里取名为CSignIn。然后确认。(新建一个对话框以后一定要添加类,否则上面的控件都不能添加变量,可能还会出现一些其他的问题。)

3.将登录对话框的名字在属性窗口中修改为“登录”。并为其添加两个静态文本框,两个文本编辑框和两个按钮控件( 登录、退出 )。

4.依次为各个控件修改属性或者添加程序。

  • a.静态文本框
    修改两个静态文本框的ID,要不相同;修改其文本内容,例如“用户名”,“密码”。
  • b.文本编辑框
    为两个编辑框分别添加变量,如 m_Name,m_Password,;方法:选中编辑框,右键,选择添加变量,输入变量的名字,且此时变量的类型为Value。并将密码文本编辑框的password属性改为Ture ( 注意此时的Multiline属性应为False,否则可能会出现password属性不能编辑的情况 )。
  • c.按钮控件
//登录按钮
void CSignIn::OnBnClickedOk1()
{// TODO: 在此添加控件通知处理程序代码UpdateData(TRUE);if (m_name!="CSDN" || m_Password!="CSDN"){MessageBox("用户名或密码错误!");return;}CDialog::OnOK();
}//要在 主窗体的OnInitDialog 中添加登录窗体显示代码如下
CSignIn dlg;
if(dlg.DoModal()!=IDOK)
{OnOK();
}
return TRUE;//这句代码一定要放在OnInitDialog的结尾。//退出按钮
OnCancel();

问题-MFC读取文件在EditControl中显示乱码

Visual Studio2008以上的版本和VC6生成的项目默认编码不同,visual studio项目默认使用的是UNICODE编码,但是我们在读取文件的时候读取的是ANSI的文本,因此直接设置到edit control中就出现乱码了。
解决这个的办法也很简单,只要在SetWindow Text的时候使用SetWindowTexeA函数,强迫使用ANSI格式就可以了。如:

添加bmp文件和ICO文件

左侧-资源视图-文件名.rc-右键-添加资源-选择资源类型-导入-窗口选择显示全部类型文件-可将res文件中的资源导入

画图实现实时显示图形轨迹


//1.在类里定义变量和消息:bool m_bClickEmpty; //判断是否点击了空白的地方,以实现拖动框选择 CPoint OldEmptyBegin;//点击空白开始的座标CPoint NowEmptyEnd;//移动时保存座标afx_msg void OnMouseMove(UINT nFlags, CPoint point);afx_msg void OnLButtonDown(UINT nFlags, CPoint point);afx_msg void OnLButtonUp(UINT nFlags, CPoint point);//2.在鼠标相关的消息里面写代码:void XX::OnLButtonDown(UINT nFlags, CPoint point){m_bClickEmpty = true;OldEmptyBegin = point;NowEmptyEnd = point;}void XX::OnMouseMove(UINT nFlags, CPoint point){if ( m_bClickEmpty )     {          CClientDC dc(this);CBrush *pBrush = CBrush::FromHandle( (HBRUSH)GetStockObject( NULL_BRUSH) );CBrush *POldBrush = dc.SelectObject( pBrush );int nOldMode = dc.SetROP2(R2_NOTXORPEN);dc.Rectangle( &CRect( OldEmptyBegin, NowEmptyEnd ) );dc.Rectangle( &CRect( OldEmptyBegin, point ) );NowEmptyEnd = point;dc.SelectObject( POldBrush );dc.SetROP2( nOldMode );}}void XX::OnLButtonUp(UINT nFlags, CPoint point){if ( m_bClickEmpty )      {           m_bClickEmpty = false;CClientDC dc(this);CBrush *pBrush = CBrush::FromHandle( (HBRUSH)GetStockObject( NULL_BRUSH) );CBrush *POldBrush = dc.SelectObject( pBrush );int nOldMode = dc.SetROP2(R2_NOTXORPEN);dc.Rectangle( &CRect( OldEmptyBegin, NowEmptyEnd ) );dc.SelectObject( POldBrush );dc.SetROP2( nOldMode );}}

MessageBox()的使用

功能: 显示一个消息对话框。
语法: MessageBox(text,title{,icon{,button{,default}}})
参数:
title:string类型,指定消息对话框的标题;
text:指定消息对话框中显示的消息,该参数可以是数值数据类型、字符串或boolean值;
icon:Icon枚举类型,可选项,指定要在该对话框左侧显示的图标;
button:Button枚举类型,可选项,指定显示在该对话框底部的按钮
default:数值型,可选项,指定作为缺省按钮的按钮编号,按钮编号自左向右依次计数,缺省值为1,如果该参数指定的编号超过了显示的按钮个数,那么MessageBox()函数将使用缺省值返回值Integer。函数执行成功时返回用户选择的按钮编号(例如1、2、3等),发生错误时返回-1。如果任何参数的值为NULL,MessageBox()函数返回NULL。
**用法:**当你的应用程序需要显示一段简短信息(比如显示出错、警告等信息)时,没有必要自己从头创建窗口、安排控件,使用MessageBox()函数既简单又方便。用户只有响应该窗口后,程序才能继续运行下去。MessageBox()函数的icon参数指定显示在窗口中的图标,它是枚举类型,可能取值为: 取值 图标Information! StopSign! Exclamation! Question! None! 无图标其中Information!是Icon参数的缺省值。Button参数指定在窗口中显示哪些按钮,有效取值为:取值中文Windows 95下显示OK!“确定”按钮OKCancel!“确定”、“取消”按钮YesNo!“是”、“否”按钮 YesNoCancel!“是”、“否”、“取消”按钮RetryCancel!“重试”、“取消”按钮AbortRetryIgnore!“终止”、“重试”、“忽略”按钮
函数功能: 该函数创建、显示、和操作一个消息框。消息框含有应用程序定义的消息和标题,加上预定义图标与Push(下按)按钮的任何组合。

Invalidate,UpdateWindow,UpdateDate

详见;Invalidate和UpdateWindow,UpdateData区别联系

Invalidate():
该函数的作用是使整个窗口客户区无效。窗口的客户区无效意味着需要重绘。例如,如果一个被其它窗口遮住的窗口变成了前台窗口,那么原来被遮住的部分就是无效的,需要重绘。这时Windows会在应用程序的消息队列中放置WM_PAINT消息。MFC为窗口类提供了WM_PAINT的消息处理函数OnPaint,OnPaint负责重绘窗口。视图类有一些例外,在视图类的OnPaint函数中调用了OnDraw函数,实际的重绘工作由OnDraw来完成。参数bErase为TRUE时,重绘区域内的背景将被擦除,否则,背景将保持不变。

InvalidateRect():
该函数的功能与Invalidate基本一样,不同的是,它是使指定的某个区域无效,需要输入一个区域,如果参数为NULL,则设置整个窗口为无效区。

UpdateData():
该函数的作用是对空间进行更新。
当你使用了ClassWizard建立了控件和变量之间的联系后,当你修改了变量的值,而希望对话框控件更新显示,就应该在修改变量后调用UpdateData(FALSE);如果你希望知道用户在对话框中到底输入了什么,就应该在访问变量前调用UpdateData(TRUE),将控件的输入映射到变量中。

UpdateWindow():
该函数的作用是使窗口立即重绘。
调用Invalidate等函数后窗口不会立即重绘(这是由于WM_PAINT消息的优先级很低,它需要等消息队列中的其它消息发送完后才能被处理)。
调用UpdateWindow函数可使WM_PAINT被直接发送到目标窗口,从而导致窗口立即重绘。

UpdateWindow:如果有无效区,则马上sending a WM_PAINT message到窗口处理过程,不进消息队列进行排队等待,立即刷新窗口,否则,什么都不做。
InvalidateRect:设置无效区,如果为NULL参数,则设置整个窗口为无效区。当应用程序的那个窗口的消息队列为空时,则sending a WM_PAINT message(即使更新区域为空).在sending a WM_PAINT message的所有InvalidateRect的更新区域会累加。

引用以下文章,侵删
list control控件:https://www.cnblogs.com/crearo-ssy/archive/2012/11/05/2754641.html
Combo Box控件:https://www.cnblogs.com/ggbailei/articles/2769504.html
登录框:https://blog.csdn.net/qq_31275519/article/details/52120910
读取文件在EditControl中显示乱码:https://blog.csdn.net/xuyangcao123/article/details/44057003
实时显示轨迹:https://blog.csdn.net/mikasoi/article/details/81415564
MessageBox()用法简介:https://blog.csdn.net/weixin_37605770/article/details/79049986
Invalidate和UpdateWindow,UpdateData区别联系:https://blog.csdn.net/komtao520/article/details/49491687

结合本科C++项目的MFC学习总结相关推荐

  1. Maven学习总结(43)——利用javadoc插件生成项目的API文档

    在进行Java学习的时候,相信大家都看过在线或者下载的java api文档,可能是html格式或者chm格式的,其实这些参考文档也是很容易生成的,这里介绍一个maven的插件来实现项目代码文档的生成. ...

  2. mfc 学习的第二天

    mfc 学习的第二天 MFC 入门 1.1 MFC是什么 微软基础类库(英语:Microsoft Foundation Classes,简称MFC)是一个微软公司提供的类库(class librari ...

  3. C++ MFC 学习笔记+小型通讯录系统实现

    MFC 最详细入门教程 [MFC常用函数总结](https://www.cnblogs.com/jiu0821/p/4606639.html) [C++ & MFC]https://www.c ...

  4. 比尔盖茨是这样审查项目的 2

    比尔盖茨是这样审查项目的  2 --选自<软件随想录:程序员部落酋长Joel谈软件> [续]http://blog.csdn.net/turingbooks/archive/2009/12 ...

  5. 参与 Apache 顶级开源项目的 N 种方式,Apache Dubbo Samples SIG 成立!

    头图来源:https://opensource.guide/ 来源 | 阿里巴巴云原生公众号 ​ 只有贡献代码才算是参与开源项目社区贡献吗? 一说到参与开源项目贡献,一般大家的反应都是代码级别的贡献, ...

  6. 参与Apache顶级开源项目的N种方式,Apache Dubbo Samples SIG 成立!

    简介:一说到参与开源项目贡献,一般大家的反应都是代码级别的贡献,总觉得我的代码被社区合并了,我才算一个贡献者,这是一个常见的错误认知.其实,在一个开源社区中有非常多的角色是 non-code cont ...

  7. 【转】MFC学习总结

    HBRUSH CAboutDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) { if ((pWnd->GetDlgCtrlID() == ...

  8. MFC学习中遇到的小问题和解决方案

    MFC学习中遇到的小问题和解决方案 1 清除combox里面的内容 ((CComboBox*)GetDlgItem(IDC_COMBO_CF))->ResetContent();//消除现有所有 ...

  9. Spring Boot 不使用默认的 parent,改用自己的项目的 parent

    前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家.点击跳转到教程. 在初学spring boot时,官方示例中,都是让我们继承一个spring的 spring-boot ...

最新文章

  1. 图像技术在上亿规模实拍图片中的应用(算法好文)
  2. 根据一个大图片自动生成相应小图片的代码
  3. C 判断 —— if...else 语句(bool变量、float变量、指针变量与“零值”进行比较)(else 到底与哪个 if 配对呢? if 语句后面的分号?)
  4. 【SSM框架系列】Mybatis基本介绍
  5. Microsoft Fluent Design System
  6. 初学者python笔记(内置函数_2)
  7. 别把可视化不当事,看完大屏模板,Excel和PPT直言比不过
  8. python调用mt4_python mt4
  9. Proteus 8.13 安装教程
  10. 自媒体月入过万的自媒体赚钱工具,免费教会你!
  11. 分享五款好用的PDF编辑工具
  12. Http Status 500
  13. sql注入学习笔记1
  14. 银河麒麟(kylin)V10桌面版
  15. 如何清理占用计算机内存,win7系统清理电脑内存的操作方法
  16. Python爬虫系列(一)环境搭建,以及简单使用,体验他的强大
  17. 如何运用VR3d模型线上展示构建博物馆展厅与展馆
  18. TOPSIS模型原理和MATLAB代码实现
  19. python测试app性能_App性能测试工具MobilePerformance
  20. mac电脑安装nvm

热门文章

  1. 【Java学习】JUC并发编程
  2. mysql2005编辑器用法,文本编辑器 - Visual Studio的隐藏功能(2005-2010)?
  3. MySQL高性能索引设计
  4. HTML 小练习(智联注册页)
  5. 【分享】如何判断个人电脑是多少位(32位?还是64位系统)
  6. 阿里云RPA(机器人流程自动化)干货系列之五:业务流程梳理方法
  7. MFC CString转ASCII字符串
  8. 算法:一只青蛙一次可以跳上1级台阶,也可以跳上2级.求该青蛙跳上一个n级的台阶总共有多少种跳法.
  9. java.lang.IllegalStateException: Underflow in restore - more restores than saves
  10. Lambda钱包API接入教程