演练:更新 MFC 随意画图应用程序(第 2 部分)

本演练的第 1 部分演示了如何将 Office Fluent 功能区添加到经典的“随意画图”应用程序。 本部分演示如何添加用户可使用的功能区面板和控件,而不是菜单和命令。

先决条件

Visual C++ 示例

章节

该演练部分包含下列内容:

向功能区添加新面板

这些步骤演示如何添加“视图”面板和“窗口”面板,前者包含两个复选框来控制工具栏和状态栏的可见性,后者包含一个垂直方向的拆分按钮来控制多文档界面 (MDI) 窗口的创建和排列。

向功能区栏添加“视图”面板和“窗口”面板

  1. 创建一个名为 View 的面板,其中包含两个复选框,它们分别用于切换状态栏和工具栏。

    1. 从“工具箱”中,将“面板”拖动到“开始”类别。 然后,将两个复选框拖动到面板。

    2. 单击面板来修改其属性。 将“标题栏”更改为 View

    3. 单击第一个复选框来修改其属性。 将“ID”更改为 ID_VIEW_TOOLBAR,将“标题栏”更改为 Toolbar

    4. 单击第二个复选框来修改其属性。 将“ID”更改为 ID_VIEW_STATUS_BAR,将“标题栏”更改为 Status Bar

  2. 创建一个名为 Window 且带有拆分按钮的面板。 当用户单击拆分按钮时,快捷菜单会显示三个已在“随意画图”应用程序中定义的命令。

    1. 从“工具箱”中,将“面板”拖动到“开始”类别。 然后,将按钮拖动到面板。

    2. 单击面板来修改其属性。 将“标题栏”更改为 Window

    3. 单击“”按钮。 将“标题栏”更改为 Windows,将“键”更改为 w,将“大型图像索引”更改为 1,并将“拆分模式”更改为 False 然后,单击“菜单项”旁边的省略号 (...) 打开“项编辑器”对话框。

    4. 单击“添加”三次,添加三个按钮。

    5. 单击第一个按钮,然后将“标题栏”更改为 New Window,将“ID”更改为 ID_WINDOW_NEW

    6. 单击第二个按钮,然后将“标题栏”更改为 Cascade,将“ID”更改为 ID_WINDOW_CASCADE

    7. 单击第三个按钮,然后将“标题栏”更改为 Tile,将“ID”更改为 ID_WINDOW_TILE_HORZ

  3. 保存更改,然后生成并运行应用程序。 此时应会显示“视图”面板和“窗口”面板。 单击这些按钮,确认它们正常运行。

向功能区添加帮助面板

现在,可将“随意画图”应用程序中定义的两个菜单项分配给名为“帮助主题”和“关于随意画图”的功能区按钮。 这些按钮会添加到一个名为“帮助”的新面板中。

添加帮助面板

  1. 从“工具箱”中,将“面板”拖动到“开始”类别。 然后,将两个按钮拖动到面板上。

  2. 单击面板来修改其属性。 将“标题栏”更改为 Help

  3. 单击第一个按钮。 将“标题栏”更改为 Help Topics,将“ID”更改为 ID_HELP_FINDER

  4. 单击第二个按钮。 将“标题栏”更改为 About Scribble...,将“ID”更改为 ID_APP_ABOUT

  5. 保存更改,然后生成并运行应用程序。 此时应会显示包含两个功能区按钮的帮助面板。

    重要

    单击“帮助主题”按钮时,“随意画图”应用程序会打开已压缩的名为 your_project_name.chm 的 HTML 帮助文件 (.chm)。 因此,如果项目未命名为 Scribble,必须将帮助文件重命名为你的项目名称。

向功能区添加笔面板

现在,添加一个面板来显示用于控制笔粗细和颜色的按钮。 此面板包含一个复选框,用于在粗笔和细笔之间切换。 其功能类似于“随意画图”应用程序中“粗线”菜单项的功能。

在原始“随意画图”应用程序中,用户可从其单击菜单上的“笔宽”时显示的对话框中选择笔宽。 功能区栏具有足够的空间来放置新控件,因此可使用功能区上的两个组合框替换该对话框。 一个组合框用于调整细笔的宽度,另一个组合框用于调整粗笔的宽度。

向功能区添加笔面板和组合框

  1. 从“工具箱”中,将“面板”拖动到“开始”类别。 然后,将复选框和两个组合框拖动到面板上。

  2. 单击面板来修改其属性。 将“标题栏”更改为 Pen

  3. 单击此复选框。 将“标题栏”更改为 Use Thick,将“ID”更改为 ID_PEN_THICK_OR_THIN

  4. 单击第一个组合框。 将“标题栏”更改为 Thin Pen,将“ID”更改为 ID_PEN_THIN_WIDTH,将“类型”更改为 Drop List将“数据”更改为 1;2;3;4;5;6;7;8;9;,并将“文本”更改为 2

  5. 单击第二个组合框。 将“标题栏”更改为 Thick Pen,将“ID”更改为 ID_PEN_THICK_WIDTH,将“类型”更改为 Drop List将“数据”更改为 5;6;7;8;9;10;11;12;13;14;15;16;17;18;19;20;,并将“文本”更改为 5

  6. 新的组合框与任何现有菜单项均不对应,因此必须为每个笔选项创建一个菜单项。

    1. 在“资源视图”窗口中,打开 IDR_SCRIBBTYPE 菜单资源。

    2. 单击“笔”以打开笔菜单。 然后,单击“在此处键入”并键入 Thi&n Pen

    3. 右键单击键入的文本来打开“属性”窗口,然后将 ID 属性更改为 ID_PEN_THIN_WIDTH

    4. 为每个笔菜单项创建一个事件处理程序。 右键单击创建的“细笔”菜单项,然后单击“添加事件处理程序”。 此时会显示事件处理程序向导。

    5. 在向导的“类列表”框中,选择“CScribbleDoc”,然后单击“添加并编辑”。 此命令创建一个名为 CScribbleDoc::OnPenThinWidth 的事件处理程序。

    6. 将以下代码添加到 CScribbleDoc::OnPenThinWidth

      // Get a pointer to the ribbon bar
      CMFCRibbonBar* pRibbon = ((CMDIFrameWndEx*) AfxGetMainWnd())->GetRibbonBar();
      ASSERT_VALID(pRibbon);
      
      // Get a pointer to the Thin Width combo box
      CMFCRibbonComboBox* pThinComboBox = DYNAMIC_DOWNCAST(
      CMFCRibbonComboBox, pRibbon->FindByID(ID_PEN_THIN_WIDTH));
      
      //Get the selected value
      int nCurSel = pThinComboBox->GetCurSel();
      if (nCurSel>= 0)
      {
          m_nThinWidth = atoi(CStringA(pThinComboBox->GetItem(nCurSel)));
      }
      
      // Create a new pen using the selected width
      ReplacePen();
      
  7. 接下来,为粗笔创建菜单项和事件处理程序。

    1. 在“资源视图”窗口中,打开 IDR_SCRIBBTYPE 菜单资源。

    2. 单击“笔”以打开笔菜单。 然后,单击“在此处键入”并键入 Thic&k Pen

    3. 右键单击键入的文本以显示“属性”窗口。 将 ID 属性更改为 ID_PEN_THICK_WIDTH

    4. 右键单击创建的“粗笔”菜单项,然后单击“添加事件处理程序”。 此时会显示事件处理程序向导。

    5. 在向导的“类列表”框中,选择“CScribbleDoc”,然后单击“添加并编辑”。 此命令创建一个名为 CScribbleDoc::OnPenThickWidth 的事件处理程序。

    6. 将以下代码添加到 CScribbleDoc::OnPenThickWidth

      // Get a pointer to the ribbon bar
      CMFCRibbonBar* pRibbon = ((CMDIFrameWndEx *) AfxGetMainWnd())->GetRibbonBar();
      ASSERT_VALID(pRibbon);
      
      CMFCRibbonComboBox* pThickComboBox = DYNAMIC_DOWNCAST(
          CMFCRibbonComboBox, pRibbon->FindByID(ID_PEN_THICK_WIDTH));
      // Get the selected value
      int nCurSel = pThickComboBox->GetCurSel();
      if (nCurSel>= 0)
      {
          m_nThickWidth = atoi(CStringA(pThickComboBox->GetItem(nCurSel)));
      }
      
      // Create a new pen using the selected width
      ReplacePen();
      
  8. 保存更改,然后生成并运行应用程序。 此时会显示新的按钮和组合框。 尝试使用不同的笔宽随意画图。

向笔面板添加颜色按钮

接下来,添加一个 CMFCRibbonColorButton 对象,用户可通过它用颜色随意画图。

向笔面板添加颜色按钮

  1. 在添加颜色按钮之前,先为其创建一个菜单项。 在“资源视图”窗口中,打开 IDR_SCRIBBTYPE 菜单资源。 单击“笔”菜单项以打开笔菜单。 然后,单击“在此处键入”并键入 &Color 右键单击键入的文本以显示“属性”窗口。 将 ID 更改为 ID_PEN_COLOR

  2. 现在,添加颜色按钮。 从“工具箱”中,将“颜色按钮”拖动到“笔”面板中。

  3. 单击颜色按钮。 将“标题栏”更改为 Color,将“ID”更改为 ID_PEN_COLOR,将“简单查找”添加为 True,将“大型图像索引”更改为 1,并将“拆分模式”更改为 False

  4. 保存更改,然后生成并运行应用程序。 新的颜色按钮会显示在“笔”面板上。 但是,无法使用它,因为它还没有事件处理程序。 后续步骤将演示如何为颜色按钮添加事件处理程序。

将颜色成员添加到文档类

原始“随意画图”应用程序没有颜色笔,因此必须为其编写实现。 要存储文档的笔颜色,请将新成员添加到文档类 CscribbleDoc

将颜色成员添加到文档类

  1. 在 scribdoc.h 中的 CScribbleDoc 中,找到 // Attributes 节。 在 m_nThickWidth 数据成员的定义后面添加以下代码行。

    // Current pen color
    COLORREF m_penColor;
    
  2. 每个文档都包含用户已绘制的笔划列表。 每个笔划由 CStroke 对象定义。 CStroke 类不包含笔颜色的相关信息,因此必须修改该类。 在 scribdoc.h 中的 CStroke 类中,在 m_nPenWidth 数据成员的定义后面添加以下代码行。

    // Pen color for the stroke
    COLORREF m_penColor;
    
  3. 在 scribdoc.h 中,添加一个新的 CStroke 构造函数,其参数指定宽度和颜色。 在 CStroke(UINT nPenWidth); 语句后面添加以下代码行。

    CStroke(UINT nPenWidth, COLORREF penColor);
    
  4. 在 scribdoc.cpp 中,添加新的 CStroke 构造函数的实现。 在 CStroke::CStroke(UINT nPenWidth) 构造函数的实现后面添加以下代码。

    // Constructor that uses the document's current width and color
    CStroke::CStroke(UINT nPenWidth, COLORREF penColor)
    {
        m_nPenWidth = nPenWidth;
        m_penColor = penColor;
        m_rectBounding.SetRectEmpty();
    }
    
  5. 更改 CStroke::DrawStroke 方法的第二行,如下所示。

    if (!penStroke.CreatePen(PS_SOLID, m_nPenWidth, m_penColor))
    
  6. 设置文档类的默认笔颜色。 在 scribdoc.cpp 中,将以下行添加至 CScribbleDoc::InitDocument,放在 m_nThickWidth = 5; 语句后面。

    // default pen color is black
    m_penColor = RGB(0, 0, 0);
    
  7. 在 scribdoc.cpp 中,将 CScribbleDoc::NewStroke 方法的第一行更改为以下内容。

    CStroke* pStrokeItem = new CStroke(m_nPenWidth, m_penColor);
    
  8. CScribbleDoc::ReplacePen 方法的最后一行更改为以下内容。

    m_penCur.CreatePen(PS_SOLID, m_nPenWidth, m_penColor);
    
  9. 你在上一步中添加了 m_penColor 成员。 现在,为颜色按钮创建一个用于设置成员的事件处理程序。

    1. 在“资源视图”窗口中,打开 IDR_SCRIBBTYPE 菜单资源。

    2. 右键单击“颜色”菜单项,然后单击“添加事件处理程序”。 此时会显示事件处理程序向导。

    3. 在向导的“类列表”框中,选择“CScribbleDoc”,然后单击“添加并编辑”按钮。 该命令创建 CScribbleDoc::OnPenColor 事件处理程序存根。

  10. CScribbleDoc::OnPenColor 事件处理程序的存根替换为以下代码。

    void CScribbleDoc::OnPenColor()
    {
        // Change pen color to reflect color button's current selection
        CMFCRibbonBar* pRibbon = ((CMDIFrameWndEx*) AfxGetMainWnd())->GetRibbonBar();
        ASSERT_VALID(pRibbon);
    
        CMFCRibbonColorButton* pColorBtn = DYNAMIC_DOWNCAST(
            CMFCRibbonColorButton, pRibbon->FindByID(ID_PEN_COLOR));
    
        m_penColor = pColorBtn->GetColor();
        // Create new pen using the selected color
        ReplacePen();
    }
    
  11. 保存更改,然后生成并运行应用程序。 现在,可按下颜色按钮并更改笔的颜色。

初始化笔并保存首选项

接下来,初始化笔的颜色和宽度。 最后,保存并加载文件中的颜色绘图。

初始化功能区栏上的控件

  1. 初始化功能区栏上的笔。

    CScribbleDoc::InitDocument 中向 scribdoc.cpp 添加以下代码,放在 m_sizeDoc = CSize(200,200) 语句后面。

    // Reset the ribbon UI to its initial values
    CMFCRibbonBar* pRibbon =
        ((CMDIFrameWndEx*) AfxGetMainWnd())->GetRibbonBar();
    ASSERT_VALID(pRibbon);
    
    CMFCRibbonColorButton* pColorBtn = DYNAMIC_DOWNCAST(
        CMFCRibbonColorButton,
        pRibbon->FindByID(ID_PEN_COLOR));
    
    // Set ColorButton to black
    pColorBtn->SetColor(RGB(0, 0, 0));
    
    CMFCRibbonComboBox* pThinComboBox = DYNAMIC_DOWNCAST(
        CMFCRibbonComboBox,
        pRibbon->FindByID(ID_PEN_THIN_WIDTH));
    
    // Set Thin pen combobox to 2
    pThinComboBox->SelectItem(1);
    
    CMFCRibbonComboBox* pThickComboBox = DYNAMIC_DOWNCAST(
        CMFCRibbonComboBox,
        pRibbon->FindByID(ID_PEN_THICK_WIDTH));
    
    // Set Thick pen combobox to 5
    pThickComboBox->SelectItem(0);
    
  2. 将颜色绘图保存到文件中。 在 CStroke::Serialize 中向 scribdoc.cpp 添加以下语句,放在 ar << (WORD)m_nPenWidth; 语句后面。

    ar << (COLORREF)m_penColor;
    
  3. 最后,加载文件中的颜色绘图。 在 CStroke::Serialize 方法中添加以下代码行,放在 m_nPenWidth = w; 语句后面。

    ar >> m_penColor;
    
  4. 现在,用颜色随意画图,然后将绘图保存到文件中。

结论

你已经更新了 MFC“随意画图”应用程序。 修改现有应用程序时,请使用本演练作为指南。

另请参阅

演练
演练:更新 MFC 随意画图应用程序(第 1 部分)