Diese Applikationsschrift beschreibt, wie einer MFC-basierten OLE Automation Serveranwendung Unterstützung für duale Schnittstellen hinzugefügt. Die ACDUAL -Beispiel veranschaulicht Unterstützung für duale Schnittstellen und der Beispielcode in diesem Hinweis ist ACDUAL entnommen. Die Makros beschrieben in diesem Hinweis, z. B. DECLARE_DUAL_ERRORINFO , DUAL_ERRORINFO_PART , und IMPLEMENT_DUAL_ERRORINFO , sind Teil der ACDUAL-Beispiel und können in MFCDUAL gefunden werden.H.
Duale Schnittstellen
Obwohl OLE-Automatisierung können Sie implementieren eine IDispatch -Schnittstelle, eine VTBL-Schnittstelle oder eine duale Schnittstelle (die beide umfasst), empfiehlt Microsoft dringend, dass Sie für alle verfügbar gemachte OLE-Automatisierungsobjekte duale Schnittstellen implementieren. Duale Schnittstellen haben erhebliche Vorteile gegenüber IDispatch-Schnittstellen nur oder VTBL-nur:
Hinzufügen von Unterstützung für duale Schnittstellen einer Klasse CCmdTarget basierende
Eine duale Schnittstelle ist wirklich nur eine benutzerdefinierte Schnittstelle IDispatchabgeleitet. Am einfachsten implementieren der Unterstützung von dualen Schnittstellen in einen CCmdTarget-basierte Klasse ist auf die erste Umsetzung der normale Versand-Schnittstelle für die Klasse unter Verwendung der MFC und Klassen-Assistent und dann später die benutzerdefinierte Schnittstelle hinzufügen. Zum größten Teil, werden Ihre benutzerdefinierten Schnittstellenimplementierung zurück zu der MFC IDispatch -Implementierung delegieren.
Erstens ändern Sie die ODL-Datei für Ihren Server, duale Schnittstellen für Ihre Objekte zu definieren. Um eine duale Schnittstelle definieren, müssen Sie eine Interface-Anweisung anstelle der DISPINTERFACE -Anweisung, die die Visual C++-Assistenten generieren. Eher als die Beseitigung der vorhandenen DISPINTERFACE -Anweisung, fügen Sie eine neue Interface-Anweisung. Durch die Beibehaltung der DISPINTERFACE Form, können Sie Klassen-Assistenten verwenden, um Ihr Objekt Eigenschaften und Methoden hinzufügen, aber Sie müssen Ihre Interface-Anweisung die entsprechenden Eigenschaften und Methoden hinzufügen.
Eine Interface-Anweisung für eine duale Schnittstelle müssen das OLEAUTOMATION und zwei Attribute, und die Schnittstelle IDispatchabgeleitet werden muss. Sie können die GUIDGEN -Beispiel zum Erstellen einer IID für die duale Schnittstelle
[uuid(0BDD0E81-0DD7-11cf-BBA8-444553540000), / / IID_IDualAClick
&Nbsp; OleAutomation,
Dual
]
IDualAClick-Schnittstelle: IDispatch
{
}
Wenn Sie die Interface-Anweisung vorhanden ist, beginnen Sie Einträge für die Methoden und Eigenschaften. Für duale Schnittstellen, müssen Sie die Parameter-Liste neu anordnen, sodass Ihre Methoden und eine Eigenschaft Accessor-Funktionen in die duale Schnittstelle ein HRESULT zurückgeben und die Rückgabewerte als Parameter mit den Attributen übergeben [retval,out] . Beachten Sie, dass für Eigenschaften, Sie beide lesen hinzufügen müssen ( propget ) und schreiben ( propput ) Funktion mit der gleichen Id zugreifen. Zum Beispiel:
[Propput, 13-10] HRESULT Text ([in] BSTR NewText);
[Propget, 13-10] HRESULT Text ([out, Retval] BSTR * Retval)
Nachdem Ihre Methoden und Eigenschaften definiert sind, müssen Sie einen Verweis auf der Interface-Anweisung in der Co-Klasse-Anweisung hinzufügen. Zum Beispiel:
[uuid(4B115281-32F0-11cf-AC85-444553540000)]
Dokument-Co-Klasse
{
&Nbsp; Dispinterface IAClick;
[Standard]-Schnittstelle IDualAClick;
}
Sobald die ODL-Datei aktualisiert wurde, verwenden Sie MFC Schnittstelle Karte Mechanismus definieren eine Implementierungsklasse für die duale Schnittstelle in der Objektklasse und die entsprechenden Einträge im MFC QueryInterface -Mechanismus. Sie benötigen einen Eintrag in der INTERFACE_PART Block für jeden Eintrag in der Interface-Anweisung von der ODL, sowie die Einträge für eine Dispatch-Schnittstelle. Jeder Eintrag ODL mit Attributs Propput braucht eine Funktion namens put_propertyname . Jeder Eintrag mit Attributs Propget braucht eine Funktion namensget_propertyname.
Um eine Implementierungsklasse für Ihre duale Schnittstelle definieren, fügen Sie ein DUAL_INTERFACE_PART Block auf die Objekt-Klassendefinition. Zum Beispiel:
BEGIN_DUAL_INTERFACE_PART (DualAClick, IDualAClick)
STDMETHOD(put_text) (THIS_ BSTR NewText);
STDMETHOD(get_Text) (THIS_ BSTR FAR * Retval);
STDMETHOD(put_x) (THIS_ kurze NeuX);
STDMETHOD(get_X) (THIS_ kurze FAR * Retval);
STDMETHOD(put_y) (THIS_ kurze NewY);
STDMETHOD(get_Y) (THIS_ kurze FAR * Retval);
STDMETHOD(put_Position) (THIS_ IDualAutoClickPoint FAR * NewPosition);
STDMETHOD(get_Position) (THIS_ IDualAutoClickPoint FAR FAR ** Retval);
STDMETHOD(RefreshWindow)(this);
STDMETHOD(SetAllProps) (THIS_ kurze X, kurze y, BSTR Text);
STDMETHOD(ShowWindow)(this);
END_DUAL_INTERFACE_PART(DualAClick)
Die duale Schnittstelle Herstellen einer MFC QueryInterface Mechanismus, fügen Sie ein INTERFACE_PART Eintritt in die Schnittstellenzuordnung
BEGIN_INTERFACE_MAP (CAutoClickDoc, CDocument)
INTERFACE_PART (CAutoClickDoc, DIID_IAClick, Versand)
INTERFACE_PART (CAutoClickDoc, IID_IDualAClick, DualAClick)
END_INTERFACE_MAP()
Als nächstes müssen Sie die Implementierung der Schnittstelle ausfüllen. Zum größten Teil, werden Sie an die vorhandenen MFC IDispatch -Implementierung delegieren können. Zum Beispiel:
STDMETHODIMP_(ULONG) CAutoClickDoc::XDualAClick::AddRef()
{
METHOD_PROLOGUE(CAutoClickDoc, DualAClick)
return pThis->ExternalAddRef();
}
STDMETHODIMP_(ULONG) CAutoClickDoc::XDualAClick::Release()
{
METHOD_PROLOGUE(CAutoClickDoc, DualAClick)
return pThis->ExternalRelease();
}
STDMETHODIMP CAutoClickDoc::XDualAClick::QueryInterface(
REFIID iid, LPVOID* ppvObj)
{
METHOD_PROLOGUE(CAutoClickDoc, DualAClick)
return pThis->ExternalQueryInterface(&iid, ppvObj);
}
STDMETHODIMP CAutoClickDoc::XDualAClick::GetTypeInfoCount(
UINT FAR* pctinfo)
{
METHOD_PROLOGUE(CAutoClickDoc, DualAClick)
LPDISPATCH lpDispatch = pThis->GetIDispatch(FALSE);
ASSERT(lpDispatch != NULL);
return lpDispatch->GetTypeInfoCount(pctinfo);
}
STDMETHODIMP CAutoClickDoc::XDualAClick::GetTypeInfo(
UINT itinfo, LCID lcid, ITypeInfo FAR* FAR* pptinfo)
{
METHOD_PROLOGUE(CAutoClickDoc, DualAClick)
LPDISPATCH lpDispatch = pThis->GetIDispatch(FALSE);
ASSERT(lpDispatch != NULL);
return lpDispatch->GetTypeInfo(itinfo, lcid, pptinfo);
}
STDMETHODIMP CAutoClickDoc::XDualAClick::GetIDsOfNames(
REFIID riid, OLECHAR FAR* FAR* rgszNames, UINT cNames,
LCID lcid, DISPID FAR* rgdispid)
{
METHOD_PROLOGUE(CAutoClickDoc, DualAClick)
LPDISPATCH lpDispatch = pThis->GetIDispatch(FALSE);
ASSERT(lpDispatch != NULL);
return lpDispatch->GetIDsOfNames(riid, rgszNames, cNames,
lcid, rgdispid);
}
STDMETHODIMP CAutoClickDoc::XDualAClick::Invoke(
DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags,
DISPPARAMS FAR* pdispparams, VARIANT FAR* pvarResult,
EXCEPINFO FAR* pexcepinfo, UINT FAR* puArgErr)
{
METHOD_PROLOGUE(CAutoClickDoc, DualAClick)
LPDISPATCH lpDispatch = pThis->GetIDispatch(FALSE);
ASSERT(lpDispatch != NULL);
return lpDispatch->Invoke(dispidMember, riid, lcid,
wFlags, pdispparams, pvarResult,
pexcepinfo, puArgErr);
}
Für Ihr Objekts Methoden und Eigenschaft Accessor-Funktionen müssen Sie bei der Umsetzung zu füllen. Ihre Methode und Eigenschaft Funktionen können in der Regel zurück, die mit Klassen-Assistenten generierten Methoden delegieren. Jedoch, wenn Sie Eigenschaften direkt auf Variablen festlegen, müssen Sie den Code zum Get/Put den Wert in die Variable schreiben. Zum Beispiel:
STDMETHODIMP-CAutoClickDoc::XDualAClick::put_text(BSTR newText)
{
Nbsp; METHOD_PROLOGUE (CAutoClickDoc, DualAClick)
/ / MFC automatisch konvertiert Unicode-BSTR in / / Ansi CString, bei Bedarf...
pThis - > M_str = NewText;
NOERROR zurück;
}
STDMETHODIMP-CAutoClickDoc::XDualAClick::get_text(BSTR* retval)
{
METHOD_PROLOGUE (CAutoClickDoc, DualAClick)
/ / MFC automatisch konvertiert Ansi CString zu / / Unicode-BSTR, bei Bedarf...
pThis - > M_str.SetSysString(retval);
NOERROR zurück;
}
Dual-Schnittstellenzeiger übergeben
Ihre Dual-Schnittstellenzeiger übergeben, ist nicht einfach, vor allem, wenn Sie CCmdTarget::FromIDispatchaufrufen müssen. FromIDispatch funktioniert nur für MFC IDispatch -Zeiger. Eine Möglichkeit, dies zu umgehen ist Abfrage für die ursprüngliche Menge der IDispatch -Zeiger bis von MFC und übergeben diesen Zeiger auf Funktionen, die sie benötigen. Zum Beispiel
STDMETHODIMP CAutoClickDoc::XDualAClick::put_Position)
Nbsp; IDualAutoClickPoint FAR * NewPosition)
{
METHOD_PROLOGUE (CAutoClickDoc, DualAClick)
LPDISPATCH LpDisp = NULL;
NewPosition - > QueryInterface (IID_IDispatch, (LPVOID *) & LpDisp);
pThis - > SetPosition(lpDisp);
LpDisp - > Release();
NOERROR zurück;
}
Bevor Sie einen Zeiger zurück durch die duale Schnittstellen-Methode übergeben, müssen Sie es aus der MFC IDispatch -Zeiger in Ihrem Dual-Interface-Zeiger zu konvertieren. Zum Beispiel:
STDMETHODIMP CAutoClickDoc::XDualAClick::get_Position)
Nbsp; IDualAutoClickPoint FAR FAR ** Retval)
{
METHOD_PROLOGUE (CAutoClickDoc, DualAClick)
LPDISPATCH LpDisp;
LpDisp = pThis - > GetPosition();
LpDisp - > QueryInterface (IID_IDualAutoClickPoint, (LPVOID *) Retval);
NOERROR zurück;
}
Registrieren der Anwendung Typbibliothek
AppWizard generiert keine Code, um ein OLE-Automatisierung Serveranwendung Typbibliothek mit dem System registrieren. Zwar es andere Möglichkeiten gibt, um die Typbibliothek registriert, ist es sinnvoll, damit die Anwendung die Typbibliothek registriert, wenn es ihre OLE-Typinformationen, d.h. aktualisiert wird, wenn die Anwendung, Stand-Alone ausgeführt wird.
Um die Anwendung Typbibliothek registriert, wenn die Anwendung, Stand-Alone ausgeführt wird:
InitInstance Funktion, suchen Sie den Aufruf an COleObjectFactory:: UpdateRegistryAll vorliegt. Fügen Sie nach diesem Aufruf einen Aufruf an AfxOleRegisterTypeLib, die LIBID entsprechend Ihrem Typbibliothek, zusammen mit dem Namen der Typbibliothek angeben/ / Wenn eine Server-Anwendung als eigenständige gestartet wird, ist es eine gute Idee
/ / um die Systemregistrierung zu aktualisieren, falls es beschädigt wurde.
M_server.UpdateRegistry(OAT_DISPATCH_OBJECT);
COleObjectFactory::UpdateRegistryAll();
/ / DUAL_SUPPORT_START
/ / Stellen Sie sicher, dass die Typbibliothek registriert ist oder duale Schnittstelle funktioniert nicht.
AfxOleRegisterTypeLib(AfxGetInstanceHandle(), LIBID_ACDual, _T("AutoClik.TLB"));
/ / DUAL_SUPPORT_END
Ändern der Einstellungen für Projektbuild Type Library verändert
Ändern Sie ein Projekt erstellen Einstellungen, so dass von eine Header-Datei, enthält Definitionen der UUID generiert wird MkTypLib wenn Typbibliothek aufgebaut ist
Um die UUID -Definitionen aus der MkTypLib generierte Headerdatei zum Projekt hinzufügen:
/ / initIIDs.c: IIDs für duale Schnittstellen definiert
/ / Dies muss nicht mit vorkompilierten Header erstellt werden.
# include lt;ole2.h >
# include <initguid.h>
# include "acdual.h"
Den richtige Objekt-Klassennamen angeben in der Typbibliothek
Die falsch im Lieferumfang von Visual C++-Assistenten verwenden den Klassennamen für die Umsetzung der Co-Klasse in ODL-Datei des Servers für OLE-erstellbar Klassen angeben. Während dies funktionieren wird, ist der Klassenname Umsetzung wahrscheinlich nicht den Klassennamen, den Sie Benutzern des Objekts verwenden möchten. Geben den korrekten Namen, öffnen Sie die ODL-Datei, suchen jede Co-Klasse-Anweisung und der Umsetzung Klassenname mit der richtigen externen Namen ersetzen.
Beachten Sie, dass wenn die Co-Klasse-Anweisung geändert wird, die Variablen Namen der CLSIDs in der MkTypLib generierte Headerdatei entsprechend geändert werden. Sie müssen aktualisieren Sie Ihren Code die neuen Variablen Namen verwenden.
Behandeln von Ausnahmen und die Automatisierungsfehler-Schnittstellen
Des Automatisierungsobjekt Methoden und Eigenschaft Accessor-Funktionen möglicherweise Ausnahmen auslösen. Wenn ja, sollten sie in Ihrer Implementierung der duale Schnittstellen behandeln und übergeben von Informationen über die Ausnahme zurück an den Controller über die OLE-Automatisierung Fehlerbehandlung Schnittstelle IErrorInfo. Diese Schnittstelle bietet detaillierte, kontextabhängige Fehler Informationen über sowohl IDispatch als auch VTBL-Schnittstellen. Um anzugeben, dass ein Fehlerhandler verfügbar ist, sollten Sie die ISupportErrorInfo -Schnittstelle implementieren.
Zur Veranschaulichung den Fehlerbehandlung Mechanismus davon gehen Sie aus, dass die Klassen-Assistenten generierten Funktionen verwendet, um die standard Versand-Unterstützung implementieren Ausnahmen auslösen. Die MFC-Implementierung von IDispatch:: Invoke fängt in der Regel diese Ausnahmen und konvertiert sie in eine EXCEPTINFO ist Struktur durch die Invoke -Aufruf zurückgegeben. Jedoch wenn VTBL-Schnittstelle verwendet wird, sind Sie für die Ausnahmen abfangen, selbst verantwortlich. Als Beispiel zum Schutz Ihres Dual-Interface-Methoden
STDMETHODIMP-CAutoClickDoc::XDualAClick::put_text(BSTR newText)
{
Nbsp; METHOD_PROLOGUE (CAutoClickDoc, DualAClick)
TRY_DUAL(IID_IDualAClick)
{
/ / MFC automatisch konvertiert Unicode-BSTR in / / Ansi CString, bei Bedarf...
pThis - > M_str = NewText;
NOERROR zurück;
}
CATCH_ALL_DUAL
}
CATCH_ALL_DUALsorgt für den richtigen Fehlercode zurück, wenn eine Ausnahme auftritt. CATCH_ALL_DUALkonvertiert eine MFC-Ausnahme in OLE-Automatisierung Fehlerbehandlung Informationen mithilfe der ICreateErrorInfo -Schnittstelle. (Ein Beispiel CATCH_ALL_DUAL Makro ist in der Datei MFCDUAL.H in der ACDUAL -Beispiel. Die Funktion ruft es behandeln von Ausnahmen, DualHandleException , ist in der Datei MFCDUAL.CPP.) CATCH_ALL_DUALbestimmt den Fehlercode zurück basierend auf den Typ der Ausnahme, die aufgetreten sind
hR = MAKE_HRESULT (SEVERITY_ERROR, FACILITY_ITF, Nbsp; (e - > M_wCode + 0 x 200))
Dies erstellt ein HRESULT spezifisch für die Schnittstelle, die die Ausnahme verursacht hat. Der Fehlercode ist 0 x 200, alle Konflikte mit System definierte HRESULTs für standard-OLE-Schnittstellen zu vermeiden gegenüber.
E_OUTOFMEMORY wird zurückgegeben.E_UNEXPECTED wird zurückgegeben.Um anzugeben, dass der OLE-Automatisierung Fehler-Handler verwendet wird, sollten Sie auch die ISupportErrorInfo -Schnittstelle implementieren.
Zunächst fügen Sie Code hinzu der Automatisierung-Klassendefinition zu zeigen, dass es ISupportErrorInfo unterstützt.
Zweitens fügen Sie Code hinzu der Automatisierung Klasse Schnittstelle Karte MFC QueryInterface Mechanismus die ISupportErrorInfo -Implementierungsklasse zugeordnet. Die INTERFACE_PART -Anweisung entspricht die Klasse definiert für ISupportErrorInfo.
Schließlich implementieren Sie die Klasse definiert, um die ISupportErrorInfo unterstützt.
(Die ACDUAL -Beispiel enthält drei Makros helfen, diese drei Schritte, DECLARE_DUAL_ERRORINFO , DUAL_ERRORINFO_PART , und IMPLEMENT_DUAL_ERRORINFO , alle enthaltenen im MFCDUAL.H.)
Das folgende Beispiel implementiert eine Klasse definiert, um die ISupportErrorInfounterstützt. CAutoClickDocist der Name der Klasse Automatisierung und IID_IDualAClick ist die IID für die Schnittstelle, die die Quelle von Fehlern berichtet über die OLE-Automatisierung-Error-Objekt:
STDMETHODIMP_(ULONG) CAutoClickDoc::XSupportErrorInfo::AddRef() {}
Nbsp; METHOD_PROLOGUE (CAutoClickDoc, SupportErrorInfo) zurückgeben pThis - > ExternalAddRef();
} STDMETHODIMP_(ULONG) CAutoClickDoc::XSupportErrorInfo::Release() {METHOD_PROLOGUE (CAutoClickDoc, SupportErrorInfo) return pThis - > ExternalRelease();
} STDMETHODIMP CAutoClickDoc::XSupportErrorInfo::QueryInterface (REFIID Iid, LPVOID * PpvObj) {METHOD_PROLOGUE (CAutoClickDoc, SupportErrorInfo) return pThis - > ExternalQueryInterface (& Iid, PpvObj);
} STDMETHODIMP CAutoClickDoc::XSupportErrorInfo::InterfaceSupportsErrorInfo (REFIID Iid) {METHOD_PROLOGUE (CAutoClickDoc, SupportErrorInfo) zurück (Iid == IID_IDualAClick)? S_OK: S_FALSE;
}
Technische Hinweise von &Nummer |nbsp; Technische Hinweise nach Kategorie