InkStart 方法

InkStartInkDrawInkStop 方法都使用 Win32 GUI 构造,例如设备上下文和笔对象。 这说明了为什么需要 CGuiPaper 作为单独的封装级别。 绘图纸的 GUI 方面在 CGuiPaper 中处理。 COPaper 对象仅发送墨迹数据。

CGuiPaper 封装级别的另一个设计原因是其 InkStartInkDrawInkStop 方法的双重性质。 他们不仅调用 COPaper 在墨迹数据发生时记录墨迹数据,还会在墨迹发生时绘制绘图的视觉图像。 CGuiPaper 保留m_bInkSaving标志来管理这种双重性质。 当m_bInkSaving为 FALSE 时,将在屏幕上绘制图像,但不会将数据发送到 COPaper 进行记录。

当用户未移动鼠标,但 COPaper 的墨迹数据被重新提交到 CGuiPaper 进行自动重新绘制时,此方案用于重新绘制。 可以通过调用其 InkSaving 方法告知 CGuiPaper 设置m_bInkSaving标志。

以下示例代码片段演示 GUIPAPER 的 InkStart 方法。CPP 和接收器。Cpp。

InkStart 方法 (GUIPAPER。CPP)

HRESULT CGuiPaper::InkStart(
                       SHORT nX,
                       SHORT nY)
  {
    HRESULT hr = E_FAIL;

    if (m_nLockKey || (!m_nLockKey && !m_bInkSaving))
    {
      // Start an ink drawing sequence only if one is not in progress.
      if (!m_bInking)
      {
        // Remember start position.
        m_OldPos.x = nX;
        m_OldPos.y = nY;

        // Delete old pen.
        if (m_hPen)
          DeleteObject(m_hPen);

        // Create and select the new drawing pen.
        m_hPen = CreatePen(PS_SOLID, m_nInkWidth, m_crInkColor);
        SelectObject(m_hDC, m_hPen);

        hr = NOERROR;

        // Ask the Paper object to mark the start of the ink drawing
        // sequence in the current ink color.
        if (m_pIPaper && m_bInkSaving)
        {
          hr = m_pIPaper->InkStart(
                            m_nLockKey,
                            nX,
                            nY,
                            m_nInkWidth,
                            m_crInkColor);
          // Capture the Mouse.
          SetCapture(m_hWnd);

          // We've modified the ink data--it is now "dirty" with
          // respect to the compound file image. Set dirty flag.
          m_bDirty = TRUE;
        }

        // Set inking flag to TRUE.
        m_bInking = TRUE;
      }
    }

    return hr;
  }

InkStart 方法 (SINK。CPP)

StoClien 以调用其 COPaperSink 对象中连接的 IPaperSink 接口的形式接收绘图数据。 这些方法对应于 CGuiPaper 中类似的 InkStartInkDrawInkStop 方法。

STDMETHODIMP COPaperSink::CImpIPaperSink::InkStart(
                                              SHORT nX,
                                              SHORT nY,
                                              SHORT nWidth,
                                              COLORREF crInkColor)
  {
    // Turn off ink saving to the COPaper object.
    m_pBackObj->m_pGuiPaper->InkSaving(FALSE);

    // Play the data back to the CGuiPaper for display only.
    m_pBackObj->m_pGuiPaper->InkWidth(nWidth);
    m_pBackObj->m_pGuiPaper->InkColor(crInkColor);
    m_pBackObj->m_pGuiPaper->InkStart(nX, nY);

    return NOERROR;
  }

在接收器中调用 InkStart 时,它会调用 CGuiPaper 以关闭将墨迹保存到 COPaper。 COPaper 不需要接收其发送的数据的回显副本。 在接收器中调用 InkDraw 时,它只是将调用传递给 CGuiPaper::InkDraw。 在接收器中调用 InkStop 时,将调用 CGuiPaper 以重新打开墨迹保存。 结果是仅将 COPaper 的墨迹数据播放到 CGuiPaper 进行显示。

通过在“接收器”菜单上选择“断开连接”选项,可以测试 StoClienIPaperSink 断开连接时的行为。 作为试验,断开接收器的连接后,从“帮助”菜单中选择“关于”。 此时将显示“关于”对话框,该对话框将涵盖 StoClien 绘图的一部分。 在“关于”对话框中单击“确定”。 请注意,所覆盖的绘图部分现在已消失。 绘图数据不会丢失,但图像的一部分已丢失。 客户端收到WM_PAINT消息并发出 IPaper::Redraw 方法。 但由于接收器未连接,因此它未收到 IPaperSink 调用以重新绘制绘图。

还可以通过最小化 StoClien 并还原它来测试此行为。 在这种情况下,整个绘图图像会丢失,需要重新绘制。 若要在这些测试之一之后重新绘制绘图图像,请使用“接收器”菜单重新连接,然后从“绘图”菜单中选择“ 重绘 ”。