MFC 之菜单、工具栏和状态栏

菜单、工具栏和状态栏


  • 菜单是管理菜单命令的控件,工具栏是管理工具按钮的控件,菜单的菜单项可以和工具栏的按钮关联起来,状态栏用于显示运行时的提示信息。

一、菜单

  • 菜单是应用程序中常用的命令接口,为用户提供触发事件的方式,并可以响应用户事件。
  • 菜单分为弹出式菜单和普通菜单,存放菜单的地方称之为菜单栏。

1、菜单的种类及开发步骤

  • 普通菜单是停靠在菜单栏上的菜单;弹出式菜单是当用户右击某区域时弹出的菜单,也称为快捷菜单。

  • 在 Windows 系统中,菜单资源使用 HMENU 句柄标识;可用 HMENU 句柄通过 Windows API 对菜单进行编程,也可通过菜单编辑器进行可视化编辑菜单;前者过程繁琐,后者直观。

  • 通过菜单编辑器使用可视化方式编辑菜单的步骤:

    (1)使用菜单编辑器,增加、删除或修改菜单栏上的菜单以及菜单上的菜单项。

    (2)使用菜单消息处理机制,完成对菜单命令消息和菜单更新消息的处理。菜单消息用于处理对菜单命令的响应,使用菜单消息可以根据程序条件改变更新菜单项的启用、禁用状态。

2、创建和编辑菜单

  • 在菜单编辑器可直接对菜单栏中的菜单以及菜单项进行编辑,“所见即所得”,即菜单编辑器当前的样式就是程序运行时的样式。步骤如下:

    (1)为工程增加菜单资源,并打开要编辑的菜单栏。

    (2)在菜单栏上选择新选项框,即空的矩形区域,或者使用右箭头按键和左箭头按键将选择框移动到新项框。

    (3)输入菜单名称。

  • 创建菜单项的步骤:

    (1)打开创建好的菜单;

    (2)选择菜单的新项框或者选择已存在的菜单项,按下Insert键,就会在菜单项前增加新菜单项。

    (3)输入菜单项名称。

    (4)在“属性”对话框中,选择使用的菜单项样式;

    (5)在“属性”对话框中的 Prompt 文本框输入要在状态栏中显示的提示字符串。

    (6)按下 Enter 键完成菜单项的添加。

3、处理菜单命令消息

  • 使用菜单命令可以完成用户触发菜单命令时执行的操作。

  • 编写一个重命名文件标题的菜单消息处理函数:

    //.h
    //{{AFX_MSG(CMFCApplication1Doc)
      afx_msg void OnMenuitemsettitle(); //声明设置标题命令处理函数
      //}}AFX_MSG
      DECLARE_MESSAGE_MAP()
     //.cpp
     BEGIN_MESSAGE_MAP(CMFCApplication1Doc, CDocument)
      //{{AFX_MSG_MAP(CMFCApplication1Doc)
      ON_COMMAND(ID_TEST_IN,OnMenuitemsettitle)  //消息映射
      //}}AFX_MSG
    END_MESSAGE_MAP()
    
    //定义设置标题命令处理函数
    void CMFCApplication1Doc::OnMenuitemsettitle()
    {
      //设置标题
      SetTitle(CTime::GetCurrentTime().Format("log %Y-%m-%d  %H:%M:%S"));
    }
    

4、处理菜单更新消息

  • 在 Windows 程序中,菜单命令是有状态的,例如是否选中菜单,菜单是否可用等;使用菜单更新消息即可实现对这些状态的控制。

  • 当用户单击菜单时,系统会发出一个 WM_INITEMUPOPUP 消息,框架的更新机制会在菜单按下前同时向所有菜单项发送更新消息;如果菜单项的更新消息处理函数存在则程序会调用此处理函数;否则进行判断消息处理函数是否存在并执行,最后根据情况启用或禁用菜单项。

  • 例:

    //要在主窗口的视图类及实现文件中
    //.h
        BOOL bToosCheck;  //菜单项当前的选择状态
      //{{AFX_MSG(CClassView)
      afx_msg void OnMenuitemStatu();  //状态命令处理函数声明
      //状态命令更新消息处理函数
      afx_msg void OnUpdateMenuitemStatu(CCmdUI* PCmdUI);
      //}}AFX_MSG
    DECLARE_MESSAGE_MAP()
    
    //.cpp
    BEGIN_MESSAGE_MAP(CMFCApplication1View, CView)
      //{{AFX_MSG_MAP(CClassView)
      ON_COMMAND(ID_STATU, OnMenuitemStatu)
      ON_UPDATE_COMMAND_UI(ID_STATU, OnUpdateMenuitemStatu)
      //}}AFX_MSG
    END_MESSAGE_MAP()
        
     void CMFCApplication1View::OnMenuitemStatu()
    {//状态测试命令消息处理函数
      if (bToosCheck)
          bToosCheck = FALSE;  //切换菜单项的选择状态变量值
      else
          bToosCheck = TRUE;
    }
    void CMFCApplication1View::OnUpdateMenuitemStatu(CCmdUI* pCmdUI)
    {
      //状态测试命令更新消息处理函数
      if (bToosCheck)  //判断菜单项状态变量
      {
          pCmdUI->SetCheck(1);  //如果选中,则设置菜单状态为选中
          pCmdUI->SetText(L"选择,单击取消");
      }
      else
      {
          pCmdUI->SetCheck(0);  //如果未选,则设置菜单选项状态为未选
          pCmdUI->SetText(L"未选择,单击选择");//设置菜单项文本
      }
    }
    

5、设置菜单项快捷键

  • 在菜单编辑器中设置菜单项快捷键的步骤:

    (1)在菜单编辑器中,选择要设置快捷键的菜单项,打开属性对话框

    (2)在 Caption 文本框输入:菜单项名称+转义字符\t+快捷键,如退出程序的快捷键:退出\tCtrl+Shift+X,又如重命名文档名的快捷键:重命名\t+Ctrl+R

    (3)然后在快捷键(Accelerator)编辑器中创建快捷键条目,并分配标识符为菜单项标识符。

6、创建与使用弹出式快捷菜单

  • 创建弹出式菜单分两步——创建菜单并将其连接到上下文环境;当用户单击弹出式菜单时,会发送命令消息给窗口并调用命令消息处理函数。具体步骤:

    (1)创建带有空标题的菜单栏;

    (2)移动鼠标到菜单的第一个菜单项,打开属性页,输入标题和其他信息,保存菜单资源。

    (3)在需要使用弹出式菜单的上下文环境对应的代码中,增加关联代码。

    //.h
    //{{AFX_MSG(CClassView)
      afx_msg void OnRButtonDown(UINT nFlags, CPoint point);
      //}}AFX_MSG
    //.cpp
    BEGIN_MESSAGE_MAP(CMFCApplication1View, CView)
      //{{AFX_MSG_MAP(CClassView)
      ON_WM_RBUTTONDOWN()
      //}}AFX_MSG
    END_MESSAGE_MAP()
     
    void CMFCApplication1View::OnRButtonDown(UINT  nFlags, CPoint point)
    {
      POINT screenPoint = point; //定义屏幕坐标
      ClientToScreen(&screenPoint); //将传入的客户区域坐标转换为屏幕坐标
      CMenu menu;  //定义菜单对象
      VERIFY(menu.LoadMenuW(IDR_MENU3));//验证装载的菜单项
      CMenu* pPopup = menu.GetSubMenu(0);//获取弹出菜单
      ASSERT(pPopup != NULL);//验证获取的弹出菜单
      //显示弹出式菜单
      pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, screenPoint.x, screenPoint.y, AfxGetMainWnd());
      CView::OnRButtonDown(nFlags, point);
    }
    

    (4)在对应的类中添加消息命令处理函数

    //.h
    //{{AFX_MSG(CClassView)
      //状态命令更新消息处理函数
      afx_msg void OnReName();
      afx_msg void OnCreateNewFile();
      //}}AFX_MSG
    //.cpp
    BEGIN_MESSAGE_MAP(CMFCApplication1View, CView)
      //{{AFX_MSG_MAP(CClassView)
      ON_COMMAND(ID_FIRST_INPUT,OnReName)
      ON_COMMAND(ID_FIRST_CHANGE,OnCreateNewFile)
      //}}AFX_MSG
    END_MESSAGE_MAP()
        
    //弹出式重命名菜单项处理函数
    void CMFCApplication1View::OnReName()
    {
      CDC* pDC = GetDC();  //获取设备上下文
      pDC->TextOut(0, 0, L"无边落木萧萧下,不尽长江滚滚来");
    }
    void CMFCApplication1View::OnCreateNewFile()
    {
      CDC* pDC = GetDC();
      pDC->TextOut(0, 0, L"天道无情,以万物为刍狗;人自多情,将爱恨尽演绎");
    }
    

7、菜单类CMenu

  • CMenu 类封装了 Windows 的 HMENU 句柄,提供创建菜单、跟踪菜单、更新菜单和销毁菜单的成员函数。MFC 程序中,在框架类定义和操作 CMenu 对象。代码:

    //创建框架函数
    int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
    {
        CMenu* menu = new CMenu();  //定义菜单项
      VERIFY(menu->LoadMenu(IDR_MENU3));  //验证装载的菜单项
      if (!SetMenu(menu))  //设置框架使用自定义菜单
      {
          TRACE0("创建菜单失败\n");
          return -1;
      }
    }
    
    //同时修改文档模板
    BOOL CMFCApplication1App::InitInstance()
    {
        //....
        pDocTemplate = new CMultiDocTemplate(IDR_MENU3,
          RUNTIME_CLASS(CMFCApplication1Doc),
          RUNTIME_CLASS(CChildFrame), // 自定义 MDI 子框架
          RUNTIME_CLASS(CMFCApplication1View));
      if (!pDocTemplate)
          return FALSE;
      AddDocTemplate(pDocTemplate); //增加到文档模板集合
    }
    
  • 操作菜单及菜单项的成员函数:

    成员函数 功能
    Attach() 绑定 Windows 菜单句柄到 CMenu 对象
    Detach() 撤销 Windows 菜单句柄到 CMenu 对象的绑定,并返回菜单句柄
    FromHandle() 返回菜单句柄对应的 CMenu 对象
    GetSafeHumenu() 返回 CMenu 对象对应的 m_hMenu 菜单句柄
    CreateMenu() 创建空菜单并将其绑定到 CMenu 对象
    CreatePopupMenu() 创建空的弹出式菜单并将其绑定到 CMenu 对象
    LoadMenu() 从可执行文件中装载菜单资源并将其绑定到 CMenu 对象
    LoadMenuIndirect() 从内存中的菜单模板中装载菜单并将其绑定到 CMenu 对象
    DestroyMenu() 销毁与 CMenu 绑定的菜单并释放菜单占用的内存
    DeleteMenu() 删除菜单中指定的菜单项。如果删除的菜单项有与之关联的弹出菜单,则销毁弹出式菜单并释放使用的内存
    TrackPopupMenu() 在指定位置显示浮动的弹出式菜单,并跟踪弹出菜单的选择项
    AppendMenu() 向菜单尾添加新菜单项
    CheckMenuItem() 在弹出菜单中的菜单项上标记选择标志或移除选择标志
    CheckMenuRadioItem() 选择指定菜单项,并将其分组中的其他菜单项设置为未选择
    SetDefaultItem() 为指定菜单设置默认的菜单项
    GetDefaultItem() 获取指定菜单的默认菜单项
    EnableMenuItem() 启用、关闭或变灰菜单项
    GetMenuItemCount() 获取菜单中包含的菜单项,只计算弹出菜单或顶层菜单的菜单项数目
    GetMenuItemID() 获取指定位置的菜单项的菜单项标识符
    GetMenuState() 获取指定菜单项的状态或弹出菜单的菜单项数目
    GetMenuString() 获取指定菜单项的文本
    GetMenuItemInfo() 获取菜单项信息
    GetSubMenu() 返回弹出菜单的指针
    InsertMenu() 在指定位置插入新菜单项
    ModifyMenu() 修改指定位置的菜单项
    RemoveMenu() 删除菜单上的菜单项以及与此菜单项相连的弹出菜单
    SetMenuItemBitmaps() 设置菜单项的选择图像
    GetMenuContexHelpId() 返回与菜单相连的帮助上下文ID
    SetMenuContexHelpId() 设置与菜单相连的帮助上下文ID

二、工具栏

1、创建和编辑工具栏功能按钮

  • 在工具栏编辑器中,创建与编辑工具栏的步骤:

    (1)为工程增加工具栏资源,并打开要编辑的工具栏。

    (2)在工具栏上单击新项框,双击新项框打开“属性”窗口。

    (3)在 ID 输入相应的菜单项的资源 ID 。

    (4)在程序的编写过程中,根据实际情况修改命令按钮的图片大小和对应的菜单项 ID 。


    工具栏.PNG
  • 上图的 “R”图标便是自定义的“重命名文档标题”的功能按钮。

2、设置工具栏的停靠和浮动

  • 工具栏与菜单最主要的一个区别就是工具栏可以停靠也可以浮动,而菜单的位置是固定的。实现工具栏的停靠和浮动的开发步骤:

    (1)调用 CFrameWnd::EnableDocking() 函数设置可以在框架窗口中停靠界面对象,函数的参数是 DWORD 类型,表示框架的哪几个边(上下左右或任意地方)允许停靠界面对象。

    (2)调用 CControlBar::EnableDocking() 函数设置工具栏可以停靠,参数是 DWORD 类型,用于表示工具栏可以停靠的边;若没有指定工具栏可以停靠的边,则工具栏不会停靠窗口,浮动在窗口中;当需要设置工具栏不能停靠窗口边时,则设置 EnableDocking() 函数参数为零,并调用 CFrameWnd::FloatControlBar() 函数即可。

    (3)调用 CFrameWnd::DockControlBar() 函数,使工具栏可以停靠框架对话框;调用 CFrameWnd::FloatControlBar() 函数,使工具栏可以浮动窗口上。

    (4)使用浮动工具栏时,可以设置工具栏的显示样式:水平、垂直,放大、缩小。

    if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_FIXED) ||
          !m_wndToolBar.LoadToolBar(theApp.m_bHiColorIcons ? IDR_MAINFRAME_256 : IDR_MAINFRAME))
      {
          TRACE0("未能创建工具栏\n");
          return -1;      // 未能创建
      }
      //=============================
      //设置工具栏可以停靠窗口的任意边
      m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
      EnableDocking(CBRS_ALIGN_ANY);  //框架设置允许界面对象停靠
      DockPane(&m_wndToolBar);
      //DockControlBar(&m_wndToolBar);
      UINT nStyle = m_wndToolBar.GetButtonStyle(9);  //获取第五个按钮的样式
      nStyle |= TBBS_WRAPPED;   //设置按钮样式为分隔符
      m_wndToolBar.SetButtonStyle(9, nStyle);//设置第九个按钮为分隔符
      //================================
    
浮动工具栏.PNG

3、设置工具提示

  • 工具提示是常见工具帮助的一种,当用户鼠标滑过工具栏一段时间后,系统会在状态栏中或者弹出的小窗口中显示工具栏功能按钮的功能描述文本。
  • 打开工具栏编辑器,选定要弹出提示信息的功能按钮,打开其属性对话框,在 Prompt 输入“……\n……”;

4、CToolBar 介绍

  • CToolBar 类用于表示工具栏,封装了 Windows 的工具栏句柄,包含一组位图按钮和分隔符,内置了派生自 CFrameWnd 类的窗口对象的成员函数。

  • 常见的 CToolBar 类成员函数:

    函数名称 功能
    Create() or CreateEx() 创建 Windows 工具栏,并将其附加到 CToolBar 对象
    SetSizes() 设置按钮和图片的尺寸大小
    SetHight() 设置工具栏的高度
    LoadToolBar() 装载资源编辑器创建的工具栏资源
    LoadBitmap() 装载包含按钮位图的图像
    SetBitmap() 设置位图图像
    SetButtons() 设置按钮样式和图片在图像中的索引
    CommandToIndex() 返回指定命令 ID 的命令索引
    GetItemID() 获取指定位置的按钮或分隔符的命令 ID
    GetItemRect() 返回给定索引索引处的按钮显示的矩形区域
    GetButtonStyle() 返回按钮的样式
    SetButtonStyle() 设置按钮样式
    GetButtonInfo() 返回命令 ID、命令样式和按钮的图像索引
    SetButtonInfo() 设置命令 ID、命令样式和按钮的图像索引
    GetButtonText() 获取按钮上显示的文本
    SetButtonTest() 设置按钮上显示的文本
    GetToolBarCtrl() 获取底层工具栏对象

三、状态栏

  • 状态栏是显示在界面底部的具有一个或多个面板的控件栏。
  • 状态栏为应用程序提供一种不中断用户工作而显示提示信息的方式。

1、创建状态栏

  • 状态栏通常显示在对话框底部,有“面板”,包括“指示器”和“消息行”。

  • 指示器显示 SCROLLLOCK 按键是否按下、宏记录是否打开等状态信息。

  • 消息行显示有关程序运行的消息。

  • Visual Studio 中没有提供可视的资源编辑器编辑状态栏;因此,创建状态栏必须使用代码控制。步骤:

    (1)在框架类定义 CStatusBar 对象。

    (2)在框架类的 OnCreate 中创建状态栏对象:

    if (!m_wndStatusBar.Create(this))
      {
          TRACE0("未能创建状态栏\n");
          return -1;      // 未能创建
      }
    m_wndStatusBar.SetIndicators(indicators, sizeof(indicators)/sizeof(UINT));
    
    

    (3)根据实际需求,设置状态栏面板的样式。

    (4)添加状态栏处理代码,通过 ON_UPDATE_COMMAND_UI 实现与面板之间的互动;但是因为状态栏面板不是命令按钮,所以必须手动添加处理代码。

2、状态栏实例

  • 在状态栏右边创建一个实时更新 时间的面板。

    (1)右击资源视图中的任意文件夹,在弹出菜单选择“资源符号”命令。

    (2)在资源符号对话框中选择新建命令,输入符号名称和取值,单击确定并关闭资源符号对话框。

    (3)在字符串资源编辑器中添加面板对应的 ID,并输入时间面板的默认显示信息。

    (4)将自定义面板增加到 indicators 数组中。

    static UINT indicators[] =
    {
      ID_SEPARATOR,           // 状态行指示器
      ID_INDICATOR_CAPS,  //大小写知识
      ID_INDICATOR_NUM,  //数字键知识
      ID_INDICATOR_SCRL,  //滚动建知识
      ID_INDICATOR_TIME,  //时间指示
    };
    

    (5)在框架类声明中为时间面板增加消息更新处理函数

    afx_msg void OnUpdateTime(CCmdUI* pCmdUI);
    

    (6)在框架类源文件中实现时间面板更新处理函数的定义

    ON_UPDATE_COMMAND_UI(ID_INDICATOR_TIME,OnUpdateTime)
    
    void CMainFrame::OnUpdateTime(CCmdUI* pCmdUI)
    {
      pCmdUI->Enable();  //时间面板可用
      pCmdUI->SetText(CTime::GetCurrentTime().Format("%H:%M:%S"));
    }
    

3、CStatusBar 介绍

  • CStatusBar 类封装状态栏对象 CStatusBarCtrl ,与工具栏一样,状态栏对象内置在框架对话框中。当框架对话框构造时状态栏也会被构造。

  • CStatusBar 类常用函数:

    成员函数 构造 CStatusBar 对象
    Create or CreateEx() 创建状态栏,将其附加到 CStatusBar 对象中,设置初始字体和状态栏高度
    SetIndicators() 设置指示符 ID
    CommandToIndex() 获取指定指示符 ID 的索引
    GetItemID() 获取指定索引处的指示符 ID
    GetItemRect() 获取指定索引处的显示矩形区域
    GetPaneInfo() 获取指定索引处的面板信息,包括指示符 ID、样式和宽度
    GetPaneStyle() 获取指定索引处的面板的样式
    GetPaneText() 获取指定索引处的面板的文本
    GetStatusBarCtrl() 返回状态栏对象对应的底层控件
    SetPaneStyle() 设置指定索引处的面板样式
    SetPaneText() 设置指定索引处的面板文本
    SetPaneInfo() 设置指定索引处的面板信息,包括指示符 ID、样式和宽度
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,884评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,755评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,369评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,799评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,910评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,096评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,159评论 3 411
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,917评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,360评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,673评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,814评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,509评论 4 334
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,156评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,882评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,123评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,641评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,728评论 2 351

推荐阅读更多精彩内容

  • 3.1. 介绍 现在,您已经安装了Wireshark并有可能热衷于开始捕捉您的第一个数据包。在接下来的章节中,我们...
    wwyyzz阅读 1,379评论 0 1
  • 原文地址: https://blog.csdn.net/ling_xiao007/article/details/...
    Caiaolun阅读 764评论 0 0
  • 1.1 VBA是什么 直到90年代早期,使应用程序自动化还是充满挑战性的领域.对每个需要自动化的应用程序,人们不得...
    浮浮尘尘阅读 21,728评论 6 49
  • ¥开启¥ 【iAPP实现进入界面执行逐一显】 〖2017-08-25 15:22:14〗 《//首先开一个线程,因...
    小菜c阅读 6,377评论 0 17
  • 一、误删资料恢复 一不小心删错了,还把回收站清空了,咋办啊?只要三步,你就能找回你删掉并清空回收站的东西。 步骤:...
    八爷君阅读 1,542评论 2 7