IPaper::Load

O código de exemplo C++ a seguir mostra como abrir o fluxo existente no armazenamento, ler novas propriedades de papel no e defini-las como os valores atuais para COPaper.

Veja a seguir o método IPaper::Load de Paper.cpp.

STDMETHODIMP COPaper::CImpIPaper::Load(
                 SHORT nLockKey,
                 IStorage* pIStorage)
  {
    HRESULT hr = E_FAIL;
    IStream* pIStream;
    INKDATA* paInkData;
    ULONG ulToRead, ulReadIn;
    LONG lNewArraySize;
    PAPER_PROPERTIES NewProps;

    if (OwnThis())
    {
      if (m_bLocked && m_cLockKey == nLockKey && NULL != pIStorage)
      {
       // Open the "PAPERDATA" stream where the paper data is stored.
        hr = pIStorage->OpenStream(
               STREAM_PAPERDATA_USTR,
               0,
               STGM_READ | STGM_DIRECT | STGM_SHARE_EXCLUSIVE,
               0,
               &pIStream);
        if (SUCCEEDED(hr))
        {
          // Obtained paper data stream. Read the Paper Properties.
          ulToRead = sizeof(PAPER_PROPERTIES);
          hr = pIStream->Read(
                           &NewProps,
                           ulToRead,
                           &ulReadIn);
          if (SUCCEEDED(hr) && ulToRead != ulReadIn)
            hr = E_FAIL;
          if (SUCCEEDED(hr))
          {
            // Handle the different versions of ink data format.
            switch (NewProps.lInkDataVersion)
            {
              case INKDATA_VERSION10:
                // Allocate an ample-sized ink data array.
                lNewArraySize = NewProps.lInkArraySize + 
                                               INKDATA_ALLOC;
                paInkData = new INKDATA[(LONG) lNewArraySize];
                if (NULL != paInkData)
                {
                  // Delete the old ink data array.
                  delete [] m_paInkData;

                  // Assign the new array.
                  m_paInkData = paInkData;
                  m_lInkDataMax = lNewArraySize;

                  // Read the complete array of Ink Data.
                  ulToRead = NewProps.lInkArraySize * sizeof(INKDATA);
                  hr = pIStream->Read(m_paInkData, 
                                      ulToRead, &ulReadIn);
                  if (SUCCEEDED(hr) && ulToRead != ulReadIn)
                    hr = E_FAIL;
                  if (SUCCEEDED(hr))
                  {
                    // Set COPaper to use the new PAPER_PROPERTIES
                    // data.
                    m_lInkDataEnd = NewProps.lInkArraySize-1;
                    m_crWinColor = NewProps.crWinColor;
                    m_WinRect.right = NewProps.WinRect.right;
                    m_WinRect.bottom = NewProps.WinRect.bottom;

                    // Copy the new properties into current 
                    // properties.
                    memcpy(
                      &m_PaperProperties,
                      &NewProps,
                      sizeof(PAPER_PROPERTIES));
                  }
                }
                else
                  hr = E_OUTOFMEMORY;
                break;
              default:
                hr = E_FAIL;  // Bad version.
                break;
            }
          }

          // Release the stream.
          pIStream->Release();
        }
      }

      UnOwnThis();
    }

    // Notify other connected clients that Paper is now loaded.
    // If Paper not loaded, then erase to a safe, empty ink data 
    // array.
    if (SUCCEEDED(hr))
      m_pBackObj->NotifySinks(PAPER_EVENT_LOADED, 0, 0, 0, 0);
    else
      Erase(nLockKey);

    return hr;
  }

Agora, o método IStorage::OpenStream é chamado para abrir o fluxo existente no armazenamento chamado "PAPERDATA". Os sinalizadores de modo de acesso são para acesso exclusivo somente leitura, direto e não compartilhado. Quando o fluxo é aberto, o método IStream::Read é chamado para ler a estrutura PAPER_PROPERTIES. Se o valor realmente lido não for igual ao valor solicitado, a operação de carregamento será anulada e E_FAIL será retornado. Se a versão de formato na PAPER_PROPERTIES recém-lida não for reconhecida, a operação de carga será anulada e Carregar retornará E_FAIL.

Com uma versão válida de formato de dados de tinta, o tamanho da nova matriz de dados de tinta do PAPER_PROPERTIES que foi lido é usado para alocar uma nova matriz de dados de tinta do tamanho necessário. Os dados de tinta existentes são excluídos e seus dados são perdidos. Se esses dados eram valiosos, eles deveriam ter sido salvos antes de Load ser chamado. Depois que a nova matriz é alocada, IStream::Read é chamado novamente para ler os dados na matriz do fluxo. Se essa chamada for bem-sucedida, os valores nas propriedades de papel recém-lidas serão adotados como os valores atuais para COPaper.

Durante essa operação de carregamento, uma estrutura de PAPER_PROPERTIES temporária, NewProps, foi usada para manter as novas propriedades lidas. Se todos tiverem êxito com a carga, NewProps será copiado para a estrutura PAPER_PROPERTIES, m_PaperProperties. Como antes, depois que Load for concluído e o IStream não for mais necessário, o ponteiro IStream será liberado.

Se houver um erro no final do Carregamento, a matriz de dados de tinta será apagada, pois pode conter dados danificados.

Se não houver nenhum erro no final de Load, o método IPaperSink::Loaded do cliente será chamado, no método NotifySinks interno do COPaper, para notificar o cliente de que a operação de carregamento foi concluída. Essa é uma notificação importante para o cliente, pois ele deve exibir esses novos dados de tinta carregados. Essa notificação faz uso significativo de recursos de objeto conectáveis no COPaper.