TN041: Migration MFC/OLE1 mit MFC/OLE 2

HinweisHinweis

Im Folgenden technischen Hinweis ist nicht aktualisiert wurde, seitdem er erstmals in der Onlinedokumentation enthalten waren.Folglich können mehrere Prozeduren und Themen veraltet oder falsch.Die aktuellsten Informationen wird empfohlen, zum Thema Onlinedokumentations im Index finden.

Allgemeine Probleme in Bezug auf die Migration

Eines der Entwurfsziele für Klassen OLE 2 in MFC 2.5 (und höher) war, viele derselben Architektur, die in MFC 2.0 unterstützt OLE 1.0 eingeführt wurde.Daher sind viele der OLE-Klassen in MFC 2.0 weiterhin in dieser Version von MFC (COleDocument, COleServerDoc, COleClientItem, COleServerItem).Darüber hinaus wurden viele der APIs in diesen Klassen genau gleich.OLE ist jedoch erheblich anders OLE 2 bis 1.0, das heißt Sie können davon ausgehen, dass einige Details geändert haben.Wenn Sie mit Unterstützung OLE1 MFC 2.0 ' s vertraut sind, fühlen sich zu Hause mit Unterstützung von MFC 2.0.

Wenn Sie eine vorhandene Anwendung MFC/OLE1 übernehmen und ihr 2 OLE Funktionalität hinzufügen, sollten Sie diesen Hinweis zum ersten Mal gelesen werden kann.Dieser Hinweis werden einige allgemeine Probleme auftreten, die Sie beim Portieren der Funktionalität OLE1 mit MFC/OLE 2 und dann die Probleme erläutert, die angezeigt werden, wenn die zwei Anwendungen portieren eingeschlossen in MFC 2.0: MFC- und HIERSVR OLE OCLIENT Samples.

MFC-Dokument-/Ansichtsarchitektur ist wichtig

Wenn die Anwendung keine Dokument-/Ansichtarchitektur verwendet MFC und 2 OLE Unterstützung Ihrer Anwendung hinzufügen möchten, ist jetzt die Zeit zur Dokument/Ansicht zu wechseln.Viele der Vorteile von OLE 2-Klassen MFC werden nur realisiert, sobald die Anwendung die integrierte Architektur und die Komponenten von MFC verwendet.

Erstellen eines Servers oder einen Container, ohne die MFC-Architektur zu verwenden, implementieren möglich ist, jedoch nicht empfohlen.

Implementierung der Verwendungs-MFC statt der eigenen

" Klasse "eingemachter Implementierung CToolBar, wie MFC und CStatusBar integriertem Code verfügen CScrollView Besonderen Falls unterstützt OLE 2.Wenn Sie diese Klassen in der Anwendung verwenden können, profitieren Sie von dem Aufwand, der in diese eingefügt wird, um sie OLE aufmerksam zu machen.Auch hier ist auf "Klasse" Rolle-Ihr-eigenen hier für folgende Zwecke möglich, jedoch nicht empfohlen.Wenn Sie ähnliche Funktionalität implementieren müssen, ist der MFC-Quellcode ein ausgezeichneter Referenz für die Verwendung von OLE Feinheiten der Reihe (insbesondere wenn es um die direkte Aktivierung steht).

Überprüfen Sie den MFC-Beispielcode

Es gibt mehrere MFC-Beispiele, die OLE-Funktionalität einschließen.Jede dieser Anwendungen implementiert OLE von einem anderen Winkel:

  • HIERSVR bedeutete meistens zur Verwendung als Serveranwendung.Sie wurde in MFC 2.0 enthalten und steht als MFC/OLE1 Anwendung mit MFC portiert wurde/OLE 2 und anschließend so, dass sie zahlreiche OLE-Funktionen erweiterte implementiert, die in OLE 2 verfügbar sind.

  • OCLIENT Hierbei handelt es sich um eine eigenständige Containeranwendung, bedeutet, um zahlreiche OLE-Funktionen von einem Container standpunkt zu veranschaulichen.Außerdem wurde von MFC 2.0 portiert und erweitert, um zahlreiche OLE-Funktionen, wie benutzerdefinierte erweiterte Formate Zwischenablage und Links zu eingebetteten Elemente zu unterstützen.

  • DRAWCLI diese Anwendung implementiert OLE-Container ähnlich wie die Unterstützung von OCLIENT ausführt, mit der Ausnahme, dass sie wird im Kontext eines vorhandenen objektorientierten zum Zeichnen programms.Es wird erläutert, wie Sie Unterstützung OLE-Container implementieren und in die vorhandene Anwendung integrierten.

  • SUPERPAD diese Anwendung sowie wobei eine feine eigenständige Anwendung ist auch ein OLE-Server.Die Server, die Unterstützung implementiert, ist recht nicht relevant.Von besonderem Interesse ist, dass es OLE-Zwischenablage Dienste verwendet, um Daten in die Zwischenablage zu kopieren, verwendet jedoch die Funktionen, die im Windows" Bearbeiten "- Steuerelement integriert ist pasten Zwischenablage, um Funktionen zu implementieren.Dadurch wird eine interessante Mischung der herkömmlichen Windows-API-Verwendung sowie die Integration mit dem neuen OLE API an.

Weitere Informationen zu Beispielanwendungen, finden Sie unter "MFC-Beispiel können".

Fallstudie: OCLIENT von MFC 2.0

Wie oben beschrieben wurden, OCLIENT in MFC 2.0 enthalten und OLE mit MFC/OLE1 implementiert.Die Schritte, durch die Anwendung zunächst die Klassen von MFC/OLE 2 zu verwendenden konvertiert wurde, sind im Folgenden beschrieben.Mehrere Funktionen wurden hinzugefügt, nachdem der ursprünglichen Port abgeschlossen wurde, um die MFC/OLE-Klassen besser zu veranschaulichen.Diese Funktionen sind hier nicht erläutert. Auch das Beispiel finden Sie weitere Informationen über diese erweiterten Features.

HinweisHinweis

Die Compilerfehler und schrittweise Prozess wurde mit Visual C++ 2.0 erstellt.Bestimmte Fehlermeldungen und Speicherorten geändert in Visual C++ 4.0, aber die grundlegenden Informationen sind gültig.

Es unternehmungslustig abrufen

Der Ansatz, der an den Anschluss das OCLIENT-Beispiel mit MFC/OLE haben, ist, starten, indem er sie erstellt und der offensichtlichen Compilerfehler korrigiert, die entstehen.Wenn Sie das OCLIENT-Beispiel von MFC 2.0 entnehmen und unterhalb dieser MFC-Version kompilieren, suchen Sie, dass keine dass viele Fehler gibt aufzulösen.Die Fehler in der Reihenfolge, in der sie ausgeführt wurden, sind im Folgenden beschrieben.

Kompilieren und Beheben von Fehlern

\oclient\mainview.cpp(104) : error C2660: 'Draw' : function does not take 4 parameters

Der erste Fehler betrifft COleClientItem::Draw.In MFC/OLE1 besteht er mehr als Parameter akzeptiert. OLE-Version/MFCDie zusätzlichen Parameter war häufig nicht erforderlich und normalerweise NULL (wie in diesem Beispiel).Diese MFC-Version kann die Werte für die lpWBounds automatisch bestimmen, ob CDC, der gezeichnet wird, ein Metadatei-DC ist.Zusätzlich wird der Parameter pFormatDC nicht mehr notwendig, da das Framework ein vom "Attribut" DC pDC erstellt, das übergeben wird.so, dieses Problem zu beheben, entfernen Sie einfach die beiden zusätzlichen fehlenden Parameter zum Zeichnen des Aufrufs.

\oclient\mainview.cpp(273) : error C2065: 'OLE_MAXNAMESIZE' : undeclared identifier
\oclient\mainview.cpp(273) : error C2057: expected constant expression
\oclient\mainview.cpp(280) : error C2664: 'CreateLinkFromClipboard' : cannot convert parameter 1 from 'char [1]' to 'enum ::tagOLERENDER '
\oclient\mainview.cpp(286) : error C2664: 'CreateFromClipboard' : cannot convert parameter 1 from 'char [1]' to 'enum ::tagOLERENDER '
\oclient\mainview.cpp(288) : error C2664: 'CreateStaticFromClipboard' : cannot convert parameter 1 from 'char [1]' to 'enum ::tagOLERENDER '

Das obige Ergebnis der Fehler vom alle diese Tatsache erforderlichem funktioniert in MFC/OLE1, dem ein eindeutiger Name übergeben wurde, um das Element dargestellt wird.Dies ist eine Anforderung des zugrunde liegenden OLE API.Dies ist in MFC nicht erforderlich, da 2 OLE/OLE 2 DDE nicht als zugrunde liegenden Kommunikationsmechanismus (der Name wurde in DDE-Konversationen verwendet).Um dieses Problem zu beheben, können Sie die CreateNewName-Funktion entfernen sowie alle Verweise auf sie.Herauszufinden ist einfach, was jede MFC/OLE-Funktion einfach in dieser Version erwartet, indem Sie den Cursor im Aufruf platziert und F1 drückt.

Ein anderer Bereich, der deutlich unterscheidet, ist die Behandlung der Zwischenablage OLE 2.Mit OLE1 haben Sie die Windows-Zwischenablage API interagieren mit der Zwischenablage.Arbeiten mit OLE 2 ist dies mit einem anderen Mechanismus durchgeführt.Das MFC/OLE1 API angenommen, dass die Zwischenablage geöffnet war, bevor ein COleClientItem-Objekt in die Zwischenablage kopierte.Dies ist nicht mehr erforderlich und wird OLE-Zwischenablage/MFC alle Vorgänge bewirken.Während Sie den Code bearbeiten, um Abhängigkeiten auf CreateNewName zu entfernen, sollten Sie auch den Code, der die Windows-Zwischenablage öffnet und schließt.

\oclient\mainview.cpp(332) : error C2065: 'AfxOleInsertDialog' : undeclared identifier
\oclient\mainview.cpp(332) : error C2064: term does not evaluate to a function
\oclient\mainview.cpp(344) : error C2057: expected constant expression
\oclient\mainview.cpp(347) : error C2039: 'CreateNewObject' : is not a member of 'CRectItem'

Ergebnis dieser Fehler vom CMainView::OnInsertObject-Handler.Ruft den neuen Befehl "EINFGs" Objekts zu behandeln ist ein anderer Bereich, in dem Elemente durchaus geringfügig geändert haben.In diesem Fall ist es am einfachsten, die ursprüngliche Implementierung mit dem einfach zusammenzuführen, das vom Anwendungs-Assistenten für eine neue OLE-Containeranwendung bereitgestellt wird.Tatsächlich handelt es sich um eine Technik, die Sie zum Portieren von anderen Anwendungen anwenden können.In MFC/OLE1 zeigten Sie das Dialogfeld" EINFG-Objekt "an, indem Sie AfxOleInsertDialog-Funktion aufgerufen haben.In dieser Version erstellen Sie ein COleInsertObject Dialogfeldobjekt, und rufen DoModal an.Darüber hinaus werden neue OLE-Elemente mit CLSID-Klassennamen anstatt einer Zeichenfolge erstellt.Das Endergebnis sollte etwa folgendermaßen aussehen

COleInsertDialog dlg;
if (dlg.DoModal() != IDOK)
    return;

BeginWaitCursor();

CRectItem* pItem = NULL;
TRY
{
    // First create the C++ object
    pItem = GetDocument()->CreateItem();
    ASSERT_VALID(pItem);

    // Initialize the item from the dialog data.
    if (!dlg.CreateItem(pItem))
        AfxThrowMemoryException();
           // any exception will do
    ASSERT_VALID(pItem);
        
    // run the object if appropriate
    if (dlg.GetSelectionType() == 
            COleInsertDialog::createNewItem)
        pItem->DoVerb(OLEIVERB_SHOW, this);
        
    // update right away
    pItem->UpdateLink();
    pItem->UpdateItemRectFromServer();
        
    // set selection to newly inserted item
    SetSelection(pItem);
    pItem->Invalidate();
}
CATCH (CException, e)
{  
    // clean up item
    if (pItem != NULL)
        GetDocument()->DeleteItem(pItem);
            
    AfxMessageBox(IDP_FAILED_TO_CREATE);
}
END_CATCH
    
EndWaitCursor();
HinweisHinweis

Ein neues Objekt EINFGs ist möglicherweise für die Anwendung) unterschiedlich:

Außerdem ist es erforderlich, <afxodlgs.h>einzuschließen, das die Deklaration für die COleInsertObject Dialogfeldklasse sowie die anderen Standarddialogfelder enthält, die von MFC bereitgestellt werden.

\oclient\mainview.cpp(367) : error C2065: 'OLEVERB_PRIMARY' : undeclared identifier
\oclient\mainview.cpp(367) : error C2660: 'DoVerb' : function does not take 1 parameters

Diese Fehler werden durch die Tatsache zurückzuführen, OLE1 jeder Konstanten in OLE 2 geändert haben, obwohl im Begriff sie identisch sind.In diesem Fall hat OLEVERB_PRIMARY zu OLEIVERB_PRIMARY geändert.in OLE1 und OLE 2 wird das primäre Verb in der Regel durch einen Container ausgeführt, wenn der Benutzer auf ein Element doppelklicken.

Außerdem akzeptiert DoVerb jetzt einen zusätzlichen Parameter:einen Zeiger auf eine Sicht CView(*).Dieser Parameter wird nur verwendet, um "visuelle Bearbeitung" (oder direkte Aktivierung) zu implementieren.Legen Sie vorerst diesem Parameter um zur TO auf, weil diese Funktion derzeit nicht implementieren.

Um sicherzustellen, dass das Framework versucht nie direktem aktivieren, müssen Sie überschreiben COleClientItem::CanActivate wie folgt:

BOOL CRectItem::CanActivate()
{
    return FALSE;
}

\oclient\rectitem.cpp(53) : error C2065: 'GetBounds' : undeclared identifier
\oclient\rectitem.cpp(53) : error C2064: term does not evaluate to a function
\oclient\rectitem.cpp(84) : error C2065: 'SetBounds' : undeclared identifier
\oclient\rectitem.cpp(84) : error C2064: term does not evaluate to a function

In MFC/OLE1 wurden COleClientItem::GetBounds und SetBounds verwendet, um den Umfang eines Elements abzufragen und zu bearbeiten ( left und die top-Member sind immer null).In MFC/OLE 2 wird SetExtent und COleClientItem::GetExtent direkt von diesem unterstützt, die SIZE stattdessen CSize oder verarbeiten.

Der Code für das neue SetItemRectToServer und UpdateItemRectFromServer-Aufrufe sehen wie folgt aus:

BOOL CRectItem::UpdateItemRectFromServer()
{
   ASSERT(m_bTrackServerSize);
   CSize size;
   if (!GetExtent(&size))
      return FALSE;    // blank

   // map from HIMETRIC to screen coordinates
   {
      CClientDC screenDC(NULL);
      screenDC.SetMapMode(MM_HIMETRIC);
      screenDC.LPtoDP(&size);
   }
   // just set the item size
   if (m_rect.Size() != size)
   {
      // invalidate the old size/position
      Invalidate();
      m_rect.right = m_rect.left + size.cx;
      m_rect.bottom = m_rect.top + size.cy;
      // as well as the new size/position
      Invalidate();
   }
   return TRUE;
}

BOOL CRectItem::SetItemRectToServer()
{
   // set the official bounds for the embedded item
   CSize size = m_rect.Size();
   {
      CClientDC screenDC(NULL);
      screenDC.SetMapMode(MM_HIMETRIC);
      screenDC.DPtoLP(&size);
   }
   TRY
   {
      SetExtent(size);  // may do a wait
   }
   CATCH(CException, e)
   {
      return FALSE;  // links will not allow SetBounds
   }
   END_CATCH
   return TRUE;
}

\oclient\frame.cpp(50) : error C2039: 'InWaitForRelease' : is not a member of 'COleClientItem'
\oclient\frame.cpp(50) : error C2065: 'InWaitForRelease' : undeclared identifier
\oclient\frame.cpp(50) : error C2064: term does not evaluate to a function

In den synchronen API-Aufrufen MFC/OLE1 von einem Container in einen Server simuliert werden, da OLE1 grundsätzlich in vielen Fällen asynchron war.Der zu überprüfende war erforderlich, für einen ausstehenden asynchronen Aufruf, bevor die Befehle vom Benutzer ausgeführt wird, verarbeitet hat.MFC/OLE1 die bereitgestellte Funktion COleClientItem::InWaitForRelease hierfür bereit.In MFC/OLE 2 ist dies nicht erforderlich. Daher können Sie die Überschreibung von CMainFrame alle in OnCommand zusammen entfernen.

An diesem Punkt OCLIENT kompiliert und verknüpft.

Andere notwendige Änderungen

Es gibt nur wenige Aufgaben, die vom OCLIENT, das nicht jedoch ausgeführt wird.Es wird empfohlen, diese Probleme statt später jetzt zu beheben.

Zunächst ist es notwendig, die OLE-Bibliotheken zu initialisieren.Hierzu wird AfxOleInit von InitInstance aufruft:

if (!AfxOleInit())
{
  AfxMessageBox("Failed to initialize OLE libraries");
  return FALSE;
}

Es ist auch eine gute Idee, Parameterlisten für virtuelle Funktionen für Änderungen zu überprüfen.Eine solche Funktion ist in jeder überschrieben, COleClientItem::OnChange MFC/OLE-Containeranwendung.Indem Sie die Onlinehilfe anschauen, sehen Sie, dass ein zusätzliches "DWORD dwParam" hinzugefügt wurde.Das neue CRectItem::OnChange sieht folgendermaßen aus:

void 
CRectItem::OnChange(OLE_NOTIFICATION wNotification, DWORD dwParam)
{
  if (m_bTrackServerSize &&
        !UpdateItemRectFromServer())
  {
    // Blank object
    if (wNotification == OLE_CLOSED)
    {
      // no data received for the object - destroy it
      ASSERT(!IsVisible());
      GetDocument()->DeleteItem(this);
      return;   // no update (item is gone now)
    }
  }
  if (wNotification != OLE_CLOSED)
      Dirty();
  Invalidate();  // any change will cause a redraw
}

In MFC/OLE1 Containeranwendungen die Dokumentklasse abgeleitet von COleClientDoc.In MFC/OLE 2 ist diese Klasse von COleDocument entfernt und ersetzt (diese neue Organisation erleichtert bin/Server-Anwendungen zu erstellen).Es gibt #define, das COleClientDoc zu COleDocument zuordnet, um Portieren von Anwendungen MFC/OLE1 mit MFC/OLE 2 zu vereinfachen, wie OCLIENT.Eine der Funktionen, die nicht von COleDocument angegeben werden, die von COleClientDoc bereitgestellt wurde, ist die Standardeinstellung meldungszuordnungs Dateisystemeinträgen Befehls.Dies geschieht, sodass Serveranwendungen, die auch COleDocument (indirekt) verwenden, nicht mit ihnen den Mehraufwand dieser Befehlshandler tragen, es sei denn, sie eine bin/Server-Anwendung sind.Sie müssen die folgenden Einträge in der CMainDoc-Meldungszuordnung hinzufügen:

ON_UPDATE_COMMAND_UI(ID_EDIT_PASTE, OnUpdatePasteMenu)
ON_UPDATE_COMMAND_UI(ID_EDIT_PASTE_LINK, OnUpdatePasteLinkMenu)
ON_UPDATE_COMMAND_UI(ID_OLE_EDIT_LINKS, OnUpdateEditLinksMenu)
ON_COMMAND(ID_OLE_EDIT_LINKS, COleDocument::OnEditLinks)
ON_UPDATE_COMMAND_UI(ID_OLE_VERB_FIRST, OnUpdateObjectVerbMenu)
ON_UPDATE_COMMAND_UI(ID_OLE_EDIT_CONVERT, OnUpdateObjectVerbMenu)
ON_COMMAND(ID_OLE_EDIT_CONVERT, OnEditConvert)

Die Implementierung von allen diesen Befehlen ist in COleDocument, die die Basisklasse für das Dokument darstellt.

An diesem Punkt OLE-Containeranwendung eine funktionale OCLIENT ist.Es ist möglich, Elemente eines beliebigen Typs einfügen (OLE1 oder OLE 2).Da der erforderliche Code, um eine direkte Aktivierung aktivieren nicht implementiert wird, werden die Elemente in einem separaten Fenster ähnlich wie mit OLE1 bearbeitet.Im nächsten Abschnitt werden die notwendigen Änderungen, um die direkte Bearbeitung zu aktivieren (gelegentlich bezeichnet "visuelle Bearbeitung").

"Hinzufügen" visuelle Bearbeitung

Eine der interessantesten Features von OLE ist die direkte Aktivierung (oder "visuelle Bearbeitung").Diese Funktion kann die Serveranwendung Teile der Benutzeroberfläche des Containers bereitgestellte Anwendung eine nahtlosere Schnittstelle für den Benutzer bearbeiten.Um die direkte Aktivierung von OCLIENT zu implementieren, müssen einige spezielle Ressourcen hinzugefügt wurden, sowie zusätzlichen Code ein.Diese Ressourcen und der Code werden in der Regel vom Anwendungs-Assistenten bereitgestellt — Tat hier Anteil am Code wurde direkt in einer neuen Anwendungs-Assistenten-Anwendung mit "bin" Unterstützung ausgeborgt.

Zuerst muss eine Menüressource verwendet werden, hinzuzufügen, wenn es ein Element vorhanden ist, das direkt aktiviert ist.Sie können diese zusätzliche Menüressource in Visual C++ erstellen, indem Sie bis auf die IDR_OCLITYPE-Ressource kopieren und die Datei, und das Fenster Knall UPS entfernen.Zwei Trennlinien werden zwischen die Datei, und das Fenster Knall UPS eingefügt, um die Trennung von Gruppen anzugeben (Gleiches sollte sie aussehen: Datei | | Windows).Weitere Informationen zur Bedeutung der Mittelwert von Trennzeichen und wie die Server- und Container Menüs zusammengeführt werden, und Ressourcen "Menüs angezeigt werden: Menüzusammenführung" in Klassen OLE 2.

Nachdem Sie diese Menüs erstellen können, müssen Sie das Framework darüber informieren.Hierzu wird CDocTemplate::SetContainerInfo für die Dokumentvorlage aufruft, bevor Sie sie der Liste Vorlagen im InitInstance hinzufügen.Der neue Code, um die Dokumentvorlage zu registrierende sieht wie folgt aus:

CDocTemplate* pTemplate = new CMultiDocTemplate(
    IDR_OLECLITYPE,
    RUNTIME_CLASS(CMainDoc),
    RUNTIME_CLASS(CMDIChildWnd),    // standard MDI child frame
    RUNTIME_CLASS(CMainView));
pTemplate->SetContainerInfo(IDR_OLECLITYPE_INPLACE);
AddDocTemplate(pTemplate);

Die IDR_OLECLITYPE_INPLACE-Ressource ist die spezielle direkte Ressource, die in Visual C++ erstellt wird.

Um die direkte Aktivierung zu aktivieren, gibt es mehrere Ursachen in der abgeleiteten Klasse CView (CMainView) sowie in der COleClientItem abgeleiteten Klasse (CRectItem) ändern.Diese Überschreibungen werden vom Anwendungs-Assistenten bereitgestellt und der Großteil der Implementierung stehen direkt von einer standardmäßigen Anwendungs-Assistenten-Anwendung.

Im ersten Schritt des Ports, wurde die direkte Aktivierung vollständig deaktiviert werden, indem COleClientItem::CanActivate überschrieb.Diese Überschreibung sollte entfernt werden, um die direkte Aktivierung zu ermöglichen.Darüber hinaus wurde NULL für alle Aufrufe von DoVerb übergeben (es gibt zwei davon), da der Ansicht bereitzustellen für die direkte Aktivierung nur erforderlich war.Um die direkte Aktivierung vollständig zu implementieren, ist es notwendig die gewünschte Ansicht im DoVerb Aufruf übergeben wird.Einer dieser Aufrufe befindet sich in CMainView::OnInsertObject:

pItem->DoVerb(OLEIVERB_SHOW, this);

Anders ist in CMainView::OnLButtonDblClk:

m_pSelection->DoVerb(OLEIVERB_PRIMARY, this);

Es ist erforderlich, COleClientItem::OnGetItemPosition zu überschreiben.Dies weist den Server an, an welcher Stelle das Fenster im Verhältnis zum Fenster des Containers befinden, wenn das Element direkt aktiviert ist.Für OCLIENT ist die Implementierung trivial:

void CRectItem::OnGetItemPosition(CRect& rPosition)
{
    rPosition = m_rect;
}

Die meisten Server implementieren, was auch direkte "bezeichnet wird." Größenanpassung Dadurch kann das zu sortierende und Fenster Server verschoben, während der Benutzer das Element verarbeitet.Der Container muss mit dieser Aktion beteiligt sind, nach dem Verschieben oder dem Größe des Fensters ändern, wirkt sich i. d. R. die Position und die Größe innerhalb des Containerdokuments selbst.Die Implementierung für OCLIENT synchronisiert das interne Rechteck, das durch m_rect der neuen Position und Größe beibehalten wird.

BOOL CRectItem::OnChangeItemPosition(const CRect& rectPos)
{
    ASSERT_VALID(this);

    if (!COleClientItem::OnChangeItemPosition(rectPos))
        return FALSE;

    Invalidate();
    m_rect = rectPos;
    Invalidate();
    GetDocument()->SetModifiedFlag();

    return TRUE;
}

An diesem Punkt gibt es ausreichend Code, um ein Element zu ermöglichen, direkt zu aktivierenden und Größenanpassung und das Verschieben des Elements zu verarbeiten, wenn sie aktiv ist, aber kein Code kann der Benutzer die Bearbeitung zu beenden.Obwohl einige Server diese Funktion selbst aus dem Behandeln der CANCEL-TASTE bereitstellen, wird empfohlen, dass Container zwei Möglichkeiten bieten, ein Element zu deaktivieren: (1), indem Sie außerhalb des Elements und (2) durch Drücken der ESC-TASTE.

Für die ESC-Taste fügen Sie eine Zugriffstaste mit Visual C++, die die VK_ESCAPE-Taste einem Befehl zuordnet, auf die Ressourcen hinzugefügt wird ID_CANCEL_EDIT hinzu.Der Handler für diesen Befehl aus:

// The following command handler provides the standard
// keyboard user interface to cancel an in-place
// editing session.void CMainView::OnCancelEdit()
{
    // Close any in-place active item on this view.
    COleClientItem* pActiveItem = 
        GetDocument()->GetInPlaceActiveItem(this);
    if (pActiveItem != NULL)
        pActiveItem->Close();
    ASSERT(GetDocument()->GetInPlaceActiveItem(this) == NULL);
}

Um den Fall zu behandeln, in dem der Benutzer außerhalb des Elements klickt, fügen Sie den folgenden Code am Anfang von CMainView::SetSelection hinzu:

if (pNewSel != m_pSelection || pNewSel == NULL)
{
    COleClientItem* pActiveItem = 
        GetDocument()->GetInPlaceActiveItem(this);
    if (pActiveItem != NULL && pActiveItem != pNewSel)
        pActiveItem->Close();
}
    

Wenn ein Element direkt aktiviert ist, sollte es den Fokus besitzt.Um dies zu vergewissern ist der Fall, den Sie für die Behandlung OnSetFocus Fokus immer zum aktuellen Element übertragen wird, wenn die Ansicht den Fokus erhält:

// Special handling of OnSetFocus and OnSize are required 
// when an object is being edited in-place.
void CMainView::OnSetFocus(CWnd* pOldWnd)
{
    COleClientItem* pActiveItem = 
        GetDocument()->GetInPlaceActiveItem(this);
    if (pActiveItem != NULL &&
    pActiveItem->GetItemState() == COleClientItem::activeUIState)
    {
        // need to set focus to this item if it is same view
        CWnd* pWnd = pActiveItem->GetInPlaceWindow();
        if (pWnd != NULL)
        {
            pWnd->SetFocus();  // don't call the base class
            return;
        }
    }

    CView::OnSetFocus(pOldWnd);
}

Wenn die Ansicht Größe geändert wird, müssen Sie das aktive Element benachrichtigt wird, dass das Auswahlrechteck geändert hat.Zu diesem Zweck erstellen Sie einen Handler für OnSize bereit:

void CMainView::OnSize(UINT nType, int cx, int cy)
{
    CView::OnSize(nType, cx, cy);
    COleClientItem* pActiveItem = 
        GetDocument()->GetInPlaceActiveItem(this);
    if (pActiveItem != NULL)
        pActiveItem->SetItemRects();
}

Fallstudie: HIERSVR von MFC 2.0

HIERSVR wurde auch in MFC 2.0 enthalten und OLE mit MFC/OLE1 implementiert.Dieser Hinweis beschreibt die Schritte, durch die Anwendung zunächst die Klassen von MFC/OLE 2 zu verwendenden konvertiert wurde.Mehrere Funktionen wurden hinzugefügt, nachdem der ursprünglichen Port abgeschlossen wurde, um die Klassen von MFC/OLE 2 besser zu veranschaulichen.Diese Funktionen sind hier nicht erläutert. Auch das Beispiel finden Sie weitere Informationen über diese erweiterten Features.

HinweisHinweis

Die Compilerfehler und schrittweise Prozess wurde mit Visual C++ 2.0 erstellt.Bestimmte Fehlermeldungen und Speicherorten geändert in Visual C++ 4.0, aber die grundlegenden Informationen sind gültig.

Es unternehmungslustig abrufen

Der Ansatz, der an den Anschluss das HIERSVR-Beispiel mit MFC/OLE haben, ist, starten, indem er sie erstellt und der offensichtlichen Compilerfehler korrigiert, die entstehen.Wenn Sie das HIERSVR-Beispiel von MFC 2.0 entnehmen und unterhalb dieser MFC-Version kompilieren, suchen Sie, dass es nicht viele Fehler gibt aufzulösen, (obwohl mehrere dem OCLIENT-Beispiel vorhanden ist).Die Fehler in der Reihenfolge, in der sie in der Regel auftreten, sind im Folgenden beschrieben.

Kompilieren und Beheben von Fehlern

\hiersvr\hiersvr.cpp(83) : error C2039: 'RunEmbedded' : is not a member of 'COleTemplateServer'

Dieser erste Fehler unterstreicht ein viel größeres Problem mit der InitInstance-Funktion zum Server.Die Initialisierung, die für einen OLE-Server erforderlich ist, ist wahrscheinlich eine der größten Änderungen, die Sie an Ihre Anwendung vornehmen müssen, sie abzurufen MFC/OLE1 ausgeführt wird.Die beste Aufgabe auszuführen ist, zu beachten, was Anwendungs-Assistent für einen OLE-Server Code erstellt und geändert werden.Im Folgenden werden einige Punkte zu beachten:

Es ist erforderlich, die OLE-Bibliotheken zu initialisieren, indem AfxOleInit aufruft

SetServerInfo Aufruf für Dokumentvorlagen für den Server festzulegen und zu den von klasseninformationen Laufzeit verarbeitet, die nicht mit dem CDocTemplate-Konstruktor festlegen können.

Zeigen Sie nicht das Hauptfenster der Anwendung an, wenn /Embedding in der Befehlszeile vorhanden ist.

Sie benötigen GUID für das Dokument.Dies ist ein eindeutiger Bezeichner für die Eingabe des Dokuments (128 Bit).Anwendungs-Assistent erstellt eine für Sie, wenn Sie die so — Methode verwenden, die hier aus dem Kopieren des neuen Codes aus einer neuer Anwendungs-Assistent generierten Serveranwendung beschrieben wird, können Sie die GUID für diese Anwendung einfach "stehlen".Wenn dies nicht der Fall, können Sie das GUIDGEN.EXE-Hilfsprogramm im Verzeichnis Bin verwenden.

Es ist "verbindet" Ihr COleTemplateServer Dokumentvorlage Objekt, das erforderlich, indem COleTemplateServer::ConnectTemplate aufruft.

Aktualisieren Sie die Systemregistrierung, wenn die Anwendung ausführen eigenständiges ist.Auf diese Weise wird, wenn der Benutzer das .EXE für die Anwendung richtet sie vom neuen Speicherort registrierungs Windows-System ausgeführt wird, aktualisiert die Datenbank, um auf den neuen Speicherort zu verweisen.

Nach dem Anwenden aller diese Änderung, anhand der Anwendungs-Assistent für InitInstance, InitInstance (und verwandtes GUID) für HIERSVR Erstellen lesen soll:

// this is the GUID for HIERSVR documents
static const GUID BASED_CODE clsid =
    { 0xA0A16360L, 0xC19B, 0x101A, { 0x8C, 0xE5, 0x00, 0xDD, 0x01, 0x11, 0x3F, 0x12 } };
    
/////////////////////////////////////////////////////////////////////////////
// COLEServerApp initialization

BOOL COLEServerApp::InitInstance()
{
    // OLE 2 initialization
    if (!AfxOleInit())
    {
        AfxMessageBox("Initialization of the OLE failed!");
        return FALSE;
    }

    // Standard initialization
    LoadStdProfileSettings(); // Load standard INI file options 

    // Register document templates
    CDocTemplate* pDocTemplate;
    pDocTemplate = new CMultiDocTemplate(IDR_HIERSVRTYPE,
        RUNTIME_CLASS(CServerDoc),   
        RUNTIME_CLASS(CMDIChildWnd),
        RUNTIME_CLASS(CServerView));
    pDocTemplate->SetServerInfo(IDR_HIERSVRTYPE_SRVR_EMB);
    AddDocTemplate(pDocTemplate);

    // create main MDI Frame window
    CMainFrame* pMainFrame = new CMainFrame;
    if (!pMainFrame->LoadFrame(IDR_MAINFRAME))
        return FALSE;
    m_pMainWnd = pMainFrame;

    SetDialogBkColor();   // gray look

    // enable file manager drag/drop and DDE Execute open
    m_pMainWnd->DragAcceptFiles();
    EnableShellOpen();
    
    m_server.ConnectTemplate(clsid, pDocTemplate, FALSE);
    COleTemplateServer::RegisterAll();

    // try to launch as an OLE server
    if (RunEmbedded())
    {
        // "short-circuit" initialization -- run as server!
        return TRUE;
    }
    m_server.UpdateRegistry();
    RegisterShellFileTypes();

    // not run as OLE server, so show the main window
    if (m_lpCmdLine[0] == '\0')
    {
        // create a new (empty) document
        OnFileNew();
    }
    else
    {
        // open an existing document
        OpenDocumentFile(m_lpCmdLine);
    }

    pMainFrame->ShowWindow(m_nCmdShow);
    pMainFrame->UpdateWindow();
    
    return TRUE;
}

Beachten Sie, dass der Code oben neuen Ressourcen-ID verweist, IDR_HIERSVRTYPE_SRVR_EMB.Dies ist die Menüressource verwendet werden soll, wenn ein Dokument, das in einem anderen Container eingebettet ist, bearbeitet wird.In MFC/OLE1 wurden die Menüelemente, die zum Bearbeiten eines eingebetteten Elements bestimmt sind, spontan geändert.Verwenden einer völlig anderen Menüstruktur, wenn das Bearbeiten eines eingebetteten Elements, anstatt ein Basisdokument zu bearbeiten, ist es viel einfacher, unterschiedliche Benutzeroberflächen für diese zwei verschiedenen Modi zur Verfügung zu stellen.Wie Sie sehen, wird eine komplett später separate Menüressource verwendet, wenn eine direkte Bearbeitung eingebettetes Objekt.

Um diese Ressource zu erstellen, laden Sie das Ressourcenskript in Visual C++ und kopieren Sie die vorhandene IDR_HIERSVRTYPE-Menüressource.Benennen Sie die neue Ressource IDR_HIERSVRTYPE_SRVR_EMB (dies ist dieselbe Namenskonvention, die Anwendungs-Assistent verwendet).Nachfolgende Änderungen an "Datei-Update "Datei-Abwehr";" Befehls-ID geben Sie ihm ID_FILE_UPDATE.Ändern Sie auch "Datei-Abwehr z. B." auf "Datei-Abwehr-Kopie z. B."; Befehls-ID geben Sie ihm ID_FILE_SAVE_COPY_AS.Das Framework stellt die Implementierung beider Befehle.

\hiersvr\svritem.h(60) : error C2433: 'OLESTATUS' : 'virtual' not permitted on data declarations
\hiersvr\svritem.h(60) : error C2501: 'OLESTATUS' : missing decl-specifiers
\hiersvr\svritem.h(60) : error C2146: syntax error : missing ';' before identifier 'OnSetData'
\hiersvr\svritem.h(60) : error C2061: syntax error : identifier 'OLECLIPFORMAT'
\hiersvr\svritem.h(60) : error C2501: 'OnSetData' : missing decl-specifiers

Es gibt eine Reihe von Fehlern, die sich aus der Überschreibung von OnSetData, da sie den OLESTATUS-Typ verweist.OLESTATUS war die zurückgegebenen Fehler der Methode OLE1.Dies weist auf HRESULT OLE in 2 geändert, obwohl MFC HRESULT normalerweise in COleException konvertiert, das den Fehler enthält.In diesem speziellen Fall ist die Überschreibung von OnSetData nicht mehr erforderlich, daher ist die einfachste Aufgabe auszuführen, sie zu entfernen.

\hiersvr\svritem.cpp(30) : error C2660: 'COleServerItem::COleServerItem' : function does not take 1 parameters

Der COleServerItem-Konstruktor akzeptiert einen zusätzlichen "BOOL-" - Parameter.Dieses Flag wird bestimmt, wie Speicherverwaltung auf den COleServerItem-Objekte ausgeführt wird.Indem er festgelegt wird, um AUSZURICHTEN, behandelt das Framework die Speicherverwaltung dieser Objekte — löschung sie, sofern sie nicht mehr benötigt werden.HIERSVR Objekte verwendet CServerItem (abgeleitet von COleServerItem) als Teil der systemeigenen Daten, sodass Legen Sie dieses Flag auf FALSE fest.Auf diese Weise können HIERSVR bestimmen, wann jedes Serverelement gelöscht wird.

\hiersvr\svritem.cpp(44) : error C2259: 'CServerItem' : illegal attempt to instantiate abstract class
\hiersvr\svritem.cpp(44) : error C2259: 'CServerItem' : illegal attempt to instantiate abstract class

Da diese Fehler führen, gibt es einige "rein-virtuelle" Funktionen, die nicht in CServerItem überschrieben wurden.Höchstwahrscheinlich wird dies durch die Tatsache zurückzuführen, OnDraws Parameterliste geändert hat.So beheben Sie diesen Fehler, CServerItem::OnDraw Änderung wie folgt (sowie die Deklaration in svritem.h):

BOOL CServerItem::OnDraw(CDC* pDC, CSize& rSize)
{
    // request from OLE to draw node
    pDC->SetMapMode(MM_TEXT); // always in pixels
    return DoDraw(pDC, CPoint(0,0), FALSE);
}

Der neue Parameter ist "rSize".Dies ermöglicht es Ihnen, die Größe der Zeichnung zu füllen, wenn schnell wie möglich.Diese Größe muss in HIMETRIC sein.In diesem Fall ist es bequem, diesen Wert nicht zu füllen. Daher ruft das Framework OnGetExtent auf, um den Block abrufen.Damit das funktioniert, müssen Sie OnGetExtent implementieren:

BOOL CServerItem::OnGetExtent(DVASPECT dwDrawAspect, CSize& rSize)
{
    if (dwDrawAspect != DVASPECT_CONTENT)
        return COleServerItem::OnGetExtent(dwDrawAspect, rSize);
        
    rSize = CalcNodeSize();
    return TRUE;
}

\hiersvr\svritem.cpp(104) : error C2065: 'm_rectBounds' : undeclared identifier
\hiersvr\svritem.cpp(104) : error C2228: left of '.SetRect' must have class/struct/union type
\hiersvr\svritem.cpp(106) : error C2664: 'void __pascal __far DPtoLP(struct ::tagPOINT __far *,int )__far const ' : cannot convert parameter 1 from 'int __far *' to 'struct ::tagPOINT __far *'

In der CServerItem::CalcNodeSize-Funktion wird die Elementgröße an HIMETRIC konvertiert und in m_rectBounds.Der nicht dokumentierte "m_rectBounds" Member COleServerItem sie ist nicht vorhanden (teilweise von m_sizeExtent ersetzt, jedoch in OLE 2 hat dieser Member eine etwas andere Verwendung als m_rectBounds in OLE1 tat).Anstatt die HIMETRIC Größe in dieser Membervariablen festzulegen, geben Sie diese zurück.Dieser Rückgabewert wird in OnGetExtent verwendet, bereits implementiert.

CSize CServerItem::CalcNodeSize()
{
    CClientDC dcScreen(NULL);

    m_sizeNode = dcScreen.GetTextExtent(m_strDescription,
      m_strDescription.GetLength());
    m_sizeNode += CSize(CX_INSET * 2, CY_INSET * 2);

    // set suggested HIMETRIC size
    CSize size(m_sizeNode.cx, m_sizeNode.cy);
    dcScreen.SetMapMode(MM_HIMETRIC);
    dcScreen.DPtoLP(&size);
    return size;
}

CServerItem überschreibt auch COleServerItem::OnGetTextData.Dieses Feature ist in MFC/OLE veraltet und wird über einen anderen Mechanismus ersetzt.In MFC Version 3.0 des Beispiels HIERSVR OLE MFC implementiert diese Funktionalität, indem sie COleServerItem::OnRenderFileData überschreibt.Diese Funktionalität ist nicht für diesen grundlegenden Port von Bedeutung. Daher können Sie die OnGetTextData-Überschreibung entfernen.

Es gibt viele weitere Fehler in svritem.cpp, die nicht behoben wurden.Sie haben keine Fehler" echten "— Fehler, die nur die von vorherigen Fehler verursacht werden.

\hiersvr\svrview.cpp(325) : error C2660: 'CopyToClipboard' : function does not take 2 parameters

COleServerItem::CopyToClipboard nicht mehr unterstützt "bIncludeNative" - Flag.Die systemeigene Daten (die Daten, die vom Serverelement geschrieben werden, serialisieren Funktion) wird immer, sodass Sie entfernen den ersten Parameter kopiert.Außerdem löst CopyToClipboard eine Ausnahme aus, wenn ein Fehler geschieht, anstatt FALSE zurückzugeben.Ändern Sie den Code für CServerView::OnEditCopy wie folgt:

void CServerView::OnEditCopy()
{
    if (m_pSelectedNode == NULL)
        AfxThrowNotSupportedException();
        
    TRY
    {
        m_pSelectedNode->CopyToClipboard(TRUE);
    }
    CATCH_ALL(e)
    {
        AfxMessageBox("Copy to clipboard failed");
    }
    END_CATCH_ALL   
}

Obwohl es mehr Fehler, die sich aus der angegebenen Version der Kompilierung MFC 2.0 von HIERSVR, in dem sie für die gleiche Version von OCLIENT ist, die tatsächlich weniger Änderungen.

An diesem Punkt HIERSVR kompiliert und verknüpft und fungiert als OLE-Server, jedoch ohne die Funktion der direkten Bearbeitung, die auf Weiter.

"Hinzufügen" visuelle Bearbeitung

Um visuelle Bearbeitung" (oder "direkte Aktivierung), die Serveranwendung hinzuzufügen, gibt es nur einige Punkte aufgeführt, mit denen Sie kümmern sich um müssen:

  • Sie benötigen eine spezielle Menüressource verwendet werden soll, wenn das Element direkt aktiviert ist.

  • Die Anwendung verfügt über eine Symbolleiste, deshalb benötigen Sie eine Symbolleiste mit nur einer Teilmenge der normalen Symbolleiste, um die Menübefehle entspricht, die auf dem Server verfügbar sind (Übereinstimmungen die Menüressource oben erwähnt).

  • Sie benötigen eine neue Klasse, die von COleIPFrameWnd abgeleitet wurde, die die direkte Benutzeroberfläche bereitstellt (ähnlich wie CMainFrame von CMDIFrameWnd abgeleitet ist, stellt die MDI-Benutzeroberfläche) bereit.

  • Sie müssen das Framework zu diesen speziellen Ressourcen und Klassen verweisen.

Die Menüressource ist einfach zu erstellen.Ausführen von Visual C++ aus, kopieren Sie die Menüressource IDR_HIERSVRTYPE auf eine Menüressource, die IDR_HIERSVRTYPE_SRVR_IP aufgerufen wird.Ändern Sie das Menü, sodass nur die Menü Bearbeiten und Hilfe-Popups werden.Fügen Sie zwei Trennzeichen zwischen dem Menü Bearbeiten und erleichtert das Menü hinzu (Gleiches sollte sie aussehen: Bearbeiten | | Hilfe).Weitere Informationen über diese Trennzeichen und den Mittelwert ermitteln, wie die Server- und Container Menüs zusammengeführt werden, "Menüs und Ressourcen: Menüzusammenführung" in Klassen OLE 2.

Die Bitmap für die Teilmengen einfache Symbolleiste kann erstellt werden, indem das von einer neuer Anwendungs-Assistent generierten Anwendung mit einer "aktivierten Option server" wurde kopiert.Diese Bitmap kann in Visual C++ anschließend importiert werden.Stellen Sie sicher, dass die ID der Bitmap IDR_HIERSVRTYPE_SRVR_IP zu vermitteln.

Die Klasse, die von COleIPFrameWnd abgeleitet ist, kann von einer Anwendung generierten Anwendungs-Assistent unterstützt Server ebenfalls kopiert werden.Kopieren Sie beide Dateien, IPFRAME.CPP und IPFRAME.H und fügen Sie sie dem Projekt hinzu.Stellen Sie sicher, dass der LoadBitmap Aufruf verweist IDR_HIERSVRTYPE_SRVR_IP, die Bitmap im vorherigen Schritt erstellt.

Nachdem alle neuen Ressourcen und Klassen erstellt werden, fügen Sie den erforderlichen Code hinzu, damit das Framework diese auskennt (und weiß, dass diese Anwendung jetzt die direkte Bearbeitung unterstützt).Dies geschieht, indem es mehr Parameter für den SetServerInfo Aufruf in der InitInstance-Funktion hinzugefügt wird:

pDocTemplate->SetServerInfo(IDR_HIERSVRTYPE_SRVR_EMB,
    IDR_HIERSVRTYPE_SRVR_IP, RUNTIME_CLASS(CInPlaceFrame));

Es ist jetzt direkt in jedem Container ausgeführt wird, der auch direkte Aktivierung unterstützt.Aber es gibt einen kleinen Fehler, der weiterhin im Code lauert.HIERSVR unterstützt, wird ein Kontextmenü angezeigt, wenn der Benutzer mit der rechten Maustaste drückt.Dieses Menü funktioniert, wenn HIERSVR vollständig geöffnet ist, aber funktioniert nicht, wenn es eine direkte Einbettung bearbeitet.Der Grund kann in dieser Zeile des Codes in CServerView::OnRButtonDown unten fixiert werden:

pMenu->TrackPopupMenu(TPM_CENTERALIGN | TPM_RIGHTBUTTON,
    point.x, point.y, AfxGetApp()->m_pMainWnd);

Beachten Sie den Verweis auf AfxGetApp()->m_pMainWnd.Wenn der Server direkt aktiviert ist, hat er ein Hauptfenster und m_pMainWnd festgelegt wird, ist jedoch in der Regel nicht sichtbar.Darüber hinaus wird dieses Fenster das Hauptfenster der Anwendung das MDI-Rahmenfenster an, das angezeigt wird, wenn der die eigenständig Server vollständig geöffnet oder auszuführen ist.Es gibt nicht das aktive Rahmenfenster an, das beim können direkt ein Rahmenfenster ist, das von COleIPFrameWnd abgeleitet ist.Um das korrekte aktive Fenster. Dies gilt auch, wenn die direkte Bearbeitung, diese MFC-Version eine neue Funktion hinzugefügt werden, AfxGetMainWnd abrufen.Im Allgemeinen sollten Sie diese Funktion anstelle AfxGetApp()->m_pMainWnd verwenden.Dieser Code muss wie folgt ändern:

pMenu->TrackPopupMenu(TPM_CENTERALIGN | TPM_RIGHTBUTTON,
    point.x, point.y, AfxGetMainWnd());

Sie haben nun einen OLE-Server, der minimale für funktionale direkte Aktivierung aktiviert ist.Es gibt jedoch trotzdem zahlreiche Features, die mit MFC/OLE 2 verfügbar sind, die nicht in MFC/OLE1 verfügbar waren.Zeigen Sie das HIERSVR-Beispiel für mehrere Ideen auf Funktionen, die Sie implementieren müssen.Einige der Funktionen, die von HIERSVR implementiert, sind im Folgenden aufgeführt:

  • Bei true, WYSISYG-Verhalten in Bezug auf den Container die Ansicht.

  • Drag & Drop und ein benutzerdefiniertes Zwischenablageformat.

  • Im Fenster einen Bildlauf ausführen als die Auswahl des Containers geändert wird.

Das HIERSVR-Beispiel in MFC 3.0 verwendet auch einen etwas anderen Entwurf für seine Serverelemente.Dies hilft, Speicherplatz zu sparen und macht die Links flexibler.Mit der Version 2.0 von HIERSVR ist-ein jeder Knoten in der Struktur COleServerItem.COleServerItem trägt Art von mehr als Mehraufwand zwingend notwendig für jeden dieser Knoten ist, aber COleServerItem ist für jeden aktiver Link erforderlich.In den meisten Fällen gibt es nur sehr wenige aktive Links zu einem bestimmten Zeitpunkt.Um dieses effizientere zu machen, trennt das HIERSVR in dieser Version von MFC den Knoten aus COleServerItem.Es wurde ein CServerNode und eine CServerItem-Klasse.CServerItem (abgeleitet von COleServerItem) wird nur bei Bedarf erstellt wird.Nach dem Beenden des Containers (oder Container) mit diesem bestimmten Links zu diesem bestimmten Knoten, der CServerItem-Objekt, das dem CServerNode zugeordnet ist, gelöscht wird.Dieser Entwurf ist effizienter und flexibler.Die Flexibilität bei der Behandlung von Mehrfachauswahl erreichen.Keine dieser zwei Versionen der HIERSVR-Stütz mehrfachauswahl würden jedoch viel einfacher, (und Halterungsstangen zu dieser Auswahl) mit der Version 3.0 von HIERSVR sein- MFC hinzufügen, da COleServerItem von systemeigenen Daten getrennt wird.

Siehe auch

Weitere Ressourcen

Technische Hinweise durch Zahl

Technische Hinweise nach Kategorie