TN041: Přenesení MFC/OLE1 MFC 2 technologie OLE
[!POZNÁMKA]
Následující technické poznámce nebyly aktualizovány od byla poprvé zahrnuta v dokumentaci online.Proto některé postupy a témata mohou být nesprávné nebo zastaralé.Nejnovější informace je vhodné vyhledat téma zájmu v dokumentaci online index.
Obecné poznámky týkající se migrace
Jedním z cílů pro OLE 2 tříd MFC 2.5 (a vyšší) bylo zachovat většinu stejnou architekturu zavedou MFC 2.0 pro podporu OLE 1.0.Výsledkem mnoha stejné třídy OLE 2.0 MFC stále existují v této verzi MFC (COleDocument, COleServerDoc, COleClientItem, COleServerItem).Navíc mnoho rozhraní API v těchto tříd se přesně shodují.OLE 2 je však významně liší od OLE 1.0 tak můžete očekávat, že některé údaje se změnily.Pokud jste obeznámeni s podporou OLE1 MFC 2.0, budete domníváte doma s podporou 2.0 a MFC.
Pokud převzetí existující aplikace MFC/OLE1 a přidání funkce OLE 2 ji měli byste přečíst tuto poznámku.Tato poznámka se vztahuje na některé obecné problémy setkat při portování své funkce OLE1 MFC/OLE 2 a pak popisuje problémů zjištěných při portování dvou aplikací v MFC 2.0: vzorky MFC OLE OCLIENT a HIERSVR.
Je důležité architektury MFC/zobrazení dokumentu
Pokud chcete přidat do aplikace OLE 2 podporu aplikace nepoužívá architektury MFC v dokumentu zobrazit, je nyní čas na přechod na dokumentu nebo zobrazení.Jakmile je aplikace pomocí vestavěné architektury a součásti MFC jsou pouze realizované výhody tříd MFC na OLE 2.
Implementace serveru nebo kontejner bez použití architektury MFC je možné, ale není doporučeno.
Použijte namísto vlastní implementace MFC
Třídy MFC "konzervované provádění" jako CToolBar, CStatusBar, a CScrollView vestavěné zvláštní případ kód pro podporu OLE 2.Ano Pokud tyto třídy můžete použít v aplikaci budete mít výhodu úsilí, které do nich informovat je OLE.Opět je možné "konstrukce your vlastní" zde tříd pro tyto účely však není navrhne.Pokud potřebujete provádět podobné funkce, zdrojový kód MFC je výborným obchodování s některými jemnější body OLE (zejména pokud jde o místní aktivace).
Prozkoumejte ukázkový kód MFC
Existuje několik vzorků MFC, které obsahují funkce OLE.Každý z těchto aplikací implementuje OLE z jiného úhlu:
HIERSVR určeny převážně pro použití jako aplikační server.Byla zahrnuta do MFC 2.0 jako aplikace MFC/OLE1 a bylo přenést MFC/OLE 2 a pak se rozšíří tak, že implementuje mnoho funkce OLE OLE 2 k dispozici.
OCLIENT je aplikace kontejneru samostatný znamenalo prokázat mnohé funkce OLE z hlediska kontejneru.To byl z MFC 2.0 příliš přenést a pak se rozšíří na podporu mnoha pokročilejší funkce OLE, jako jsou například formáty schránky vlastní a odkazy na vložené položky.
DRAWCLI této aplikace implementuje podporu OLE kontejneru mnohem jako OCLIENT, s výjimkou, že se tak v rámci existujícího výkresu programu objektově orientované.Zobrazuje jak implementovat podporu OLE kontejneru a integrovat do existující aplikace.
SUPERPAD této aplikace, přičemž jemné samostatná aplikace je také OLE server.Podpora serveru, který implementuje je tichý minimalist.Zvláštního zájmu je jak používá služby OLE schránky zkopírovat data do schránky, ale používá schránky Vložit funkci k funkci zabudovanou do ovládacího prvku pro úpravy"Windows".Zobrazuje zajímavé mix tradičního používání rozhraní Windows API, jakož i integrace se nové OLE API.
Další informace o ukázkové aplikace v nápovědě "MFC vzorku".
Případová studie: OCLIENT z MFC 2.0
Jak je popsáno výše, OCLIENT byla zahrnuta do MFC 2.0 a implementovány s MFC/OLE1 OLE.Níže jsou popsány kroky, kterými původně převést tuto aplikaci pomocí tříd MFC/OLE 2.Počet funkcí byly přidány po dokončení počátečního portu lépe ilustrují tříd MFC/OLE.Tyto funkce nebudou uvedena zde; naleznete další informace o těchto rozšířených funkcí sám vzorku.
[!POZNÁMKA]
Visual C++ 2.0 byl vytvořen podrobný proces a chyby kompilátoru.Konkrétní chybové zprávy a umístění pravděpodobně změněn Visual C++ 4.0, ale zůstane platné rámcové informace.
Získání a systémem
Přístup k portu OCLIENT vzorku MFC/OLE je vytvářením a stanovení kompilátor zjevné chyby, které způsobí spuštění.Odebere vzorek OCLIENT 2.0 MFC a zkompilovat v této verzi MFC, zjistíte, nejsou to mnoho chyb vyřešit.Chyby v pořadí, ve kterém došlo k jsou popsány níže.
Kompilace a oprava chyb
\oclient\mainview.cpp(104) : error C2660: 'Draw' : function does not take 4 parameters
První chyba se týká COleClientItem::Draw.MFC/OLE1 trvalo více parametrů, než trvá verze MFC/OLE.Další parametry nebyly často nezbytné a obvykle hodnotu NULL (v tomto příkladu).Tato verze MFC automaticky hodnoty lpWBounds určit, kdy je Nemocnosti, který je nakresleno metasoubor DC.Kromě toho pFormatDC parametr již není nutné od jeden z "atributu DC" PDC předané v rámci vytvoří.Chcete-li tento problém vyřešit, jednoduše odebrat dva extra NULL parametrů volání kreslit.
\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 '
Chyby nad výsledkem skutečnosti, všechny COleClientItem::CreateXXXX požadované funkce v MFC/OLE1 předat jedinečný název představující zboží.To byl požadavek podkladové OLE API.To není nutné MFC/OLE 2 od OLE 2 nepoužívá DDE jako základní mechanismus komunikace (název byl použit jako konverzace DDE).Chcete-li tento problém vyřešit, odeberte CreateNewName fungovat stejně jako všechny odkazy na ni.Je snadné zjistit, jaké funkce MFC/OLE očekává v této verzi pouhým umístěním kurzoru na volání a stisknutím klávesy F1.
Jiné oblasti, které se výrazně liší, je zpracování schránky OLE 2.S OLE1 používá schránky systému Windows, které rozhraní API komunikovat pomocí schránky.OLE 2 důvodem je různé mechanismem.Rozhraní API MFC/OLE1 předpokládá, že schránka byla otevřena před zkopírováním COleClientItem objektu do schránky.To již není nutné a způsobí, že všechny operace schránky MFC/OLE se nezdaří.Při úpravě kódu odebrání závislostí na CreateNewName, měli také odebrat kód, který otevírá a zavírá schránky systému Windows.
\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'
Výsledkem těchto chyb CMainView::OnInsertObject popisovač.Zpracování příkazu "Vložit nový objekt" je jiné oblasti, kde se věci změnily odlišují.V tomto případě je nejsnadnější jednoduše původní implementace sloučit s AppWizard stanovená nové aplikace OLE kontejneru.Ve skutečnosti je technika, která lze použít pro portování aplikací jiných.V MFC/OLE1 zobrazí dialogové okno "Vložit objekt" voláním AfxOleInsertDialog funkce.Tato verze sestavení COleInsertObject objektu dialogu a volání DoModal.Kromě toho jsou vytvořeny nové položky OLE s CLSID namísto řetězce classname.Výsledek by měl vypadat přibližně takto
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();
[!POZNÁMKA]
Vložit nový objekt může být různé aplikace):
Je rovněž nezbytné zahrnout <afxodlgs.h>, který obsahuje prohlášení COleInsertObject třída dialogu, stejně jako standardní dialogy poskytované MFC.
\oclient\mainview.cpp(367) : error C2065: 'OLEVERB_PRIMARY' : undeclared identifier
\oclient\mainview.cpp(367) : error C2660: 'DoVerb' : function does not take 1 parameters
Tyto chyby jsou způsobeny skutečnost, že některé konstanty OLE1 změnily v OLE 2, i když v konceptu se shodují.V tomto případě OLEVERB_PRIMARY na OLEIVERB_PRIMARY.OLE1 a OLE 2 primární sloveso je obvykle spustit kontejneru při poklepání na položku.
Kromě toho DoVerb nyní přebírá parametr navíc – ukazatel zobrazení (CView*).Tento parametr slouží pouze pro provádění "Vizuální úpravy" (nebo aktivaci na místě).Nyní nastavit tento parametr na hodnotu NULL, protože tato funkce prováděcími není v tomto okamžiku.
Chcete-li se ujistit, že rámci nikdy pokusy o místní aktivace, by měl potlačit COleClientItem::CanActivate takto:
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
V MFC/OLE1 COleClientItem::GetBounds a SetBounds byly použity k dotazování a manipulaci v rozsahu položku ( levé a horní členy byly vždy nula).MFC/OLE 2 to je přímo podporován COleClientItem::GetExtent a SetExtent, které zabývat velikosti nebo CSize místo.
Kód pro vaše nové SetItemRectToServer a UpdateItemRectFromServer volání vypadat takto:
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
MFC/OLE1 rozhraní API synchronní volání z kontejneru na server byly simulované, protože v mnoha případech dědičně asynchronní OLE1.Bylo nezbytné zkontrolovat zbývající asynchronní volání v průběhu zpracování příkazů od uživatele.MFC/OLE1 poskytnuty COleClientItem::InWaitForRelease funkce pro to.MFC/OLE 2 není nezbytné, takže můžete odebrat přepsání OnCommand v CMainFrame společně.
V tomto okamžiku bude OCLIENT kompilace a propojit.
Další nezbytné změny.
Existuje několik věcí, které nejsou v zachováte OCLIENT spuštění, však.Je lepší řešení těchto problémů nyní namísto později.
Nejprve je nutné Inicializace knihoven OLE.Důvodem je voláním AfxOleInit z InitInstance:
if (!AfxOleInit())
{
AfxMessageBox("Failed to initialize OLE libraries");
return FALSE;
}
Je také vhodné zkontrolovat změny seznamu parametr virtuálních funkcí.Jedna funkce je COleClientItem::OnChange, lokálně v každé aplikaci MFC/OLE kontejneru.Pohledem na online Nápověda zobrazí přidaná extra "DWORD dwParam".Nový CRectItem::OnChange vypadá takto:
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
}
V MFC/OLE1 aplikace kontejneru odvozené třídy dokumentu z COleClientDoc.MFC/OLE 2 byla tato třída odebrán a nahrazen COleDocument (této nové organizace usnadňuje vytváření aplikací kontejneru server).Je #define mapuje COleClientDoc na COleDocument zjednodušit portování aplikací MFC/OLE1 2 MFC/OLE, jako je například OCLIENT.Jednou z funkcí v COleDocument , od COleClientDoc je zpráva standardní příkaz položek mapování.Důvodem je tak serverové aplikace, které používají také COleDocument (nepřímo) nesmí provádět s nimi režie tyto popisovače příkazu Pokud aplikace kontejneru server.Potřebujete mapu zprávu CMainDoc přidejte následující položky:
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)
Provedení těchto příkazů je v COleDocument, což je základní třída pro dokument.
V tomto okamžiku je OCLIENT funkčnosti aplikace OLE kontejneru.Je možné vložit položky všech typů (OLE1 nebo OLE 2).Protože není implementována nezbytný kód Povolit aktivaci na místě, jsou v samostatném okně velmi podobně jako s OLE1 upravovat položky.Další část se zabývá nezbytné změny povolit úpravy na místě (někdy nazývané "Vizuální úpravy").
Přidávání "Vizuální úpravy"
Jednou z nejzajímavějších funkcí OLE je místní aktivace (nebo "Vizuální úpravy").Tato funkce umožňuje aplikace serveru převzít části uživatelského rozhraní kontejneru poskytovány bezproblémové úpravy rozhraní pro uživatele.Provedení aktivace na místě OCLIENT třeba přidán, jakož i některé další kód některé zvláštní prostředky.Tyto prostředky a kód jsou obvykle poskytovány AppWizard – ve skutečnosti mnohem zde kód byl půjčený přímo z čerstvého AppWizard aplikace s podporou "Kontejner".
Nejprve je nutné přidat zdroj nabídky použito, pokud je položka, která je aktivní v místě.Extra nabídce zdroj v jazyce C++ můžete vytvořit zkopírováním IDR_OCLITYPE prostředků a odebrání všech kromě souboru a okno automaticky otevíraná okna.Mezi soubor a okna překryvná okna k označení oddělení skupin jsou vloženy dva oddělovacích pruhů (by měla vypadat: soubor || Okno).Další informace o rozumí tyto oddělovače a jak jsou sloučené nabídky serveru a kontejner naleznete v části "Nabídek a prostředky: nabídka slučování" v OLE 2 třídy.
Jakmile tyto nabídky vytvořeny, je třeba dát rámec o nich vědí.Důvodem je voláním CDocTemplate::SetContainerInfo pro šablonu dokumentu můžete přidat k seznamu Šablona dokumentu ve vaší InitInstance.Šablona dokumentu zaregistrovat nový kód vypadá takto:
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);
IDR_OLECLITYPE_INPLACE prostředek je zvláštní místní zdroje vytvořené v jazyce Visual C++.
Chcete-li aktivaci na místě, jsou některé kroky, které je třeba změnit v obou CView (CMainView) odvozené třídy jakož i COleClientItem odvozené třídy (CRectItem).Všechny tyto změny podle AppWizard a většina provedení budou pocházet přímo z výchozí aplikace AppWizard.
V prvním kroku tohoto portu bylo zakázáno aktivaci na místě zcela přepsáním COleClientItem::CanActivate.Povolit aktivaci na místě by odebrat toto přepsání.Kromě toho byla předána veškerá volání NULL DoVerb (existují dvě z nich) protože poskytující zobrazení pouze nezbytné pro aktivaci na místě.K provedení plně aktivaci na místě, je nutné předat správné zobrazení DoVerb volání.Je jedním z těchto v CMainView::OnInsertObject:
pItem->DoVerb(OLEIVERB_SHOW, this);
Druhý je v CMainView::OnLButtonDblClk:
m_pSelection->DoVerb(OLEIVERB_PRIMARY, this);
Je nutné přepsat COleClientItem::OnGetItemPosition.To říká server umístění okna vzhledem ke kontejneru okno při zboží je místo aktivován.Pro OCLIENT je triviální provádění:
void CRectItem::OnGetItemPosition(CRect& rPosition)
{
rPosition = m_rect;
}
Většina serverů také implementovat takzvané "místní změny velikosti." To umožňuje serveru okno velikosti a uživatel je úpravách položky přesunuty.Kontejner musí být součástí této akce, protože přesouvání nebo změně velikosti okna obvykle ovlivňuje polohu a velikost samotného dokumentu kontejneru.Provádění OCLIENT synchronizuje vnitřní obdélník udržovaný m_rect s novou pozici a velikost.
BOOL CRectItem::OnChangeItemPosition(const CRect& rectPos)
{
ASSERT_VALID(this);
if (!COleClientItem::OnChangeItemPosition(rectPos))
return FALSE;
Invalidate();
m_rect = rectPos;
Invalidate();
GetDocument()->SetModifiedFlag();
return TRUE;
}
V tomto okamžiku existuje dostatek kód povolit položku místo aktivován a řešení pro změnu velikosti a přesunutí položky, když je aktivní, ale žádný kód umožňuje ukončit relace úprav.Ačkoli některé servery bude tato funkce samy zpracováním klávesy ESC, doporučuje, že kontejnery nabízejí dva způsoby deaktivovat položky: (1) klepnutím mimo zboží a (2) stisknutím klávesy ESC.
Klávesy ESC Přidat akcelerátor s Visual C++ mapující VK_ESCAPE klíč k příkazu, ID_CANCEL_EDIT je do zdroje.Popisovač pro tento příkaz takto:
// 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);
}
Zpracování případu, kdy uživatel klepne na položku mimo přidejte následující kód na začátek CMainView::SetSelection:
if (pNewSel != m_pSelection || pNewSel == NULL)
{
COleClientItem* pActiveItem =
GetDocument()->GetInPlaceActiveItem(this);
if (pActiveItem != NULL && pActiveItem != pNewSel)
pActiveItem->Close();
}
Pokud je položka aktivní v místě, měl by mít fokus.Zda že případě zpracování OnSetFocus fokus vždy převedeno na aktivní položku při zobrazení vybrán tak, aby:
// 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);
}
Při změně velikosti zobrazení je třeba upozornit na aktivní položku změněné Obdélník ořezu.K tomu poskytnout popisovač pro OnSize:
void CMainView::OnSize(UINT nType, int cx, int cy)
{
CView::OnSize(nType, cx, cy);
COleClientItem* pActiveItem =
GetDocument()->GetInPlaceActiveItem(this);
if (pActiveItem != NULL)
pActiveItem->SetItemRects();
}
Případová studie: HIERSVR z MFC 2.0
HIERSVR také součástí MFC 2.0 a implementovány s MFC/OLE1 OLE.Tato poznámka stručně popisuje kroky, kterými původně převést tuto aplikaci pomocí tříd MFC/OLE 2.Počet funkcí byly přidány po dokončení počátečního portu lépe ilustrují tříd MFC/OLE 2.Tyto funkce nebudou uvedena zde; naleznete další informace o těchto rozšířených funkcí sám vzorku.
[!POZNÁMKA]
Visual C++ 2.0 byl vytvořen podrobný proces a chyby kompilátoru.Konkrétní chybové zprávy a umístění pravděpodobně změněn Visual C++ 4.0, ale zůstane platné rámcové informace.
Získání a systémem
Přístup k portu HIERSVR vzorku MFC/OLE je vytvářením a stanovení kompilátor zjevné chyby, které způsobí spuštění.Odebere vzorek HIERSVR 2.0 MFC a zkompilovat v této verzi MFC, zde nejsou mnoho chyb řešení (i když existují více než s OCLIENT vzorku).Chyby v pořadí, v jakém se obvykle objevují jsou popsány níže.
Kompilace a oprava chyb
\hiersvr\hiersvr.cpp(83) : error C2039: 'RunEmbedded' : is not a member of 'COleTemplateServer'
První chyba poukazuje mnohem větší problém s InitInstance funkce pro servery.Inicializace pro OLE server je pravděpodobně jeden z největších provedené změny budete muset provést aplikace MFC/OLE1 ho systémem.Nejlepší legálnosti je prohlédněte AppWizard vytvoří pro OLE server a kód podle potřeby změnit.Zde jsou některé body nezapomeňte:
Je nezbytné Inicializace knihoven OLE voláním AfxOleInit
Volání objektu šablony dokumentu nastavení popisovače prostředku serveru a informace třídy runtime nelze nastavit s SetServerInfo CDocTemplate konstruktoru.
Nezobrazovat hlavní okno aplikace, pokud je /Embedding na příkazovém řádku.
Budete potřebovat GUID dokumentu.Toto je jedinečný identifikátor pro typ dokumentu (128 bitů).AppWizard můžete vytvořit, tak pokud použijete zde popsanou techniku kopírování nového kódu z nové aplikace server generován AppWizard, si můžete jednoduše "ukrást" GUID z aplikace.Pokud tomu tak není, můžete použít GUIDGEN.EXE nástroj v adresáři BIN.
Je nezbytné "připojit" vaše COleTemplateServer šablonu dokumentu voláním objektu COleTemplateServer::ConnectTemplate.
Při spuštění aplikace samostatné aktualizace systémového registru.Jestliže uživatel přesune.EXE aplikace spuštěné z nového umístění bude aktualizovat registrační databáze systému Windows do nového umístění.
Po použití všech těchto změn na základě AppWizard vytvoří pro InitInstance, InitInstance (a související GUID) pro HIERSVR vypadat takto:
// 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;
}
Zjistíte výše uvedený kód odkazuje nové ID zdroje IDR_HIERSVRTYPE_SRVR_EMB.Toto je nabídka zdrojů použitých při úpravě dokumentu, který je vložen do jiného kontejneru.V MFC/OLE1 byly upraveny zvláštní úpravy vložené položky položky nabídky průběžně.Při úpravách vložené položky namísto úprav dokumentu souboru pomocí struktury zcela jiné nabídky velmi snadno poskytovat různé uživatelské rozhraní pro tyto dva samostatné režimy.Jak uvidíte dále, používá se při Úpravy vloženého objektu místní prostředek zcela zvláštní nabídky.
Chcete-li vytvořit prostředek načíst zdroj skriptu do jazyka Visual C++ a zkopírovat existující zdroj nabídky IDR_HIERSVRTYPE.Nový prostředek přejmenujte na IDR_HIERSVRTYPE_SRVR_EMB (to je stejné pojmenování, která používá AppWizard).Další změna "Uložit soubor" na "Aktualizace souboru"; Pojmenujte ji ID příkazu ID_FILE_UPDATE."Uložit jako" také změňte na "Uložit kopii jako"; Pojmenujte ji ID příkazu ID_FILE_SAVE_COPY_AS.Poskytuje rámci provádění oba tyto příkazy.
\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
Počet chyby vyplývající z vyřazení z OnSetData, protože je týkající OLESTATUS typu.OLESTATUS byl způsobem OLE1 vráceny chyby.To byl změněn na HRESULT 2 OLE, ačkoli obvykle převede MFC HRESULT do COleException obsahující chybu.V tomto konkrétním případě vyřazení z OnSetData již není nutné, takže je nejsnazší je odebrat.
\hiersvr\svritem.cpp(30) : error C2660: 'COleServerItem::COleServerItem' : function does not take 1 parameters
COleServerItem Konstruktoru bere další parametr "BOOL".Tento příznak určuje, jak se provádí správa paměti COleServerItem objektů.Nastavením na hodnotu TRUE, zpracovává rámci správy paměti tyto objekty – jejich odstranění, pokud již nejsou potřeba.Používá HIERSVR CServerItem (odvozené z COleServerItem) objekty jako součást nativní data, takže tento příznak bude nastavena na hodnotu FALSE.To umožňuje určit při odstranění položky každého serveru HIERSVR.
\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
Jak tyto chyby neznamená, nejsou čisté virtuální"funkce, které nebyly přepsány v CServerItem.Nejpravděpodobnější příčinou je skutečnost, že byl změněn seznam parametrů a OnDraw.Chcete-li tuto chybu opravit, změnit CServerItem::OnDraw takto (stejně jako prohlášení v 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);
}
Nový parametr je "parametru rSize".To umožňuje vyplnit velikost výkresu, pokud je to vhodné.Tato velikost musí být v HIMETRIC.V tomto případě není vhodné vyplnit tuto hodnotu, takže volání v rámci OnGetExtent načíst v rozsahu.Pro danou práci, budete muset implementovat OnGetExtent:
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 *'
Funkce CServerItem::CalcNodeSize je velikost položky převedeny na HIMETRIC a m_rectBounds.Undocumented 'm_rectBounds"člen COleServerItem neexistuje (jej byla částečně nahrazena m_sizeExtent, ale trochu jiné využití než má tento člen OLE 2 m_rectBounds v OLE1).Namísto nastavení HIMETRIC velikost do této proměnné členů bude opět ji.Tuto hodnotu používá v OnGetExtent, dříve implementováno.
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;
}
Rovněž přepíše CServerItem COleServerItem::OnGetTextData.Tato funkce je zastaralá v MFC/OLE a nahrazuje jiný mechanismus.Verze MFC 3.0 vzorku MFC OLE HIERSVR plní tuto funkci potlačení COleServerItem::OnRenderFileData.Tato funkce není pro tento port základní důležité tedy odebrat přepis OnGetTextData.
Existuje mnoho další chyby v svritem.cpp, které nejsou uvedeny.Nejsou chyby "reálný" – pouze chyby způsobené předchozí chyby.
\hiersvr\svrview.cpp(325) : error C2660: 'CopyToClipboard' : function does not take 2 parameters
COleServerItem::CopyToClipboardjiž nepodporuje příznak 'bIncludeNative'.Nativní data (data vytvořené položky server Serialize funkce) vždy zkopírována, takže odebrat první parametr.Kromě toho CopyToClipboard vyvolají výjimku, když dojde k chybě nevrací hodnotu FALSE.Změňte kód pro CServerView::OnEditCopy takto:
void CServerView::OnEditCopy()
{
if (m_pSelectedNode == NULL)
AfxThrowNotSupportedException();
TRY
{
m_pSelectedNode->CopyToClipboard(TRUE);
}
CATCH_ALL(e)
{
AfxMessageBox("Copy to clipboard failed");
}
END_CATCH_ALL
}
Ačkoli by další chyby vyplývající z kompilace HIERSVR verze MFC 2.0, než byly stejné verze OCLIENT, byly ve skutečnosti méně změn.
V tomto okamžiku HIERSVR bude kompilace a propojení a fungovat jako OLE server, ale bez funkce úprav na místě, která bude provedena další.
Přidávání "Vizuální úpravy"
Chcete-li přidat server aplikace "Vizuální úpravy" (nebo aktivaci na místě), jsou pouze několik věcí, které musí starat o:
Potřebujete speciální nabídky zdrojů použitých při zboží je aktivní v místě.
Tato aplikace má nástrojů, tak budete potřebovat nástrojů s pouze podmnožiny běžných nástrojů odpovídající příkazy k dispozici na serveru (odpovídá výše uvedené zdroje nabídky).
Potřebujete nové třídy odvozené od COleIPFrameWnd , který poskytuje přímo v uživatelském rozhraní (podobně jako CMainFrame z CMDIFrameWnd, poskytuje uživatelské rozhraní MDI).
Je třeba informovat o těchto zvláštních prostředků a třídy rozhraní.
Je snadné vytvořit zdroj nabídky.Spusťte aplikaci Visual C++, Kopírovat zdroj nabídky IDR_HIERSVRTYPE k nabídce zdroj s názvem IDR_HIERSVRTYPE_SRVR_IP.V nabídce upravte, aby zůstaly pouze popups nabídky Úpravy a nápovědy.Přidat do nabídky nabídky Úpravy a Nápověda mezi dva oddělovače (by měla vypadat: úpravy || Nápověda).Další informace o tyto oddělovače znamená a jak jsou sloučené nabídky serveru a kontejner naleznete v části "Nabídek a prostředky: nabídka slučování" v OLE 2 třídy.
Rastrový obrázek pro dílčí sadu nástrojů lze snadno vytvořit zkopírováním z čerstvého AppWizard generované aplikací "Server" možnost zkontrolovat.Tento rastrový obrázek pak lze importovat do aplikace Visual C++.Nezapomeňte poskytnout bitmapu Identifikátor IDR_HIERSVRTYPE_SRVR_IP.
Třída odvozená od COleIPFrameWnd lze zkopírovat z aplikace s podporou serveru také generovány AppWizard.Zkopírování obou souborů IPFRAME.CPP a IPFRAME.H a do projektu přidat.Ujistěte se, že LoadBitmap volání odkazuje na IDR_HIERSVRTYPE_SRVR_IP rastrový obrázek vytvořený v předchozím kroku.
Nyní, když jsou vytvářeny nové zdroje a tříd, přidáte nezbytný kód tak, aby v rámci ví o těchto (a ví, že aplikaci nyní podporuje úpravy na místě).To se provádí přidáním další parametry, které mají SetServerInfo volání v InitInstance funkce:
pDocTemplate->SetServerInfo(IDR_HIERSVRTYPE_SRVR_EMB,
IDR_HIERSVRTYPE_SRVR_IP, RUNTIME_CLASS(CInPlaceFrame));
Nyní je připravena ke spuštění v místě v kontejneru, který také podporuje aktivaci na místě.Je, ale jeden menší chyba stále skrývá v kódu.HIERSVR podporuje místní nabídka zobrazí, když uživatel stiskne tlačítko myši.Tato nabídka pracuje při plně otevřené HIERSVR, ale nefunguje při vkládání místní úpravy.Důvod lze přichytit na tento jediný řádek kódu v CServerView::OnRButtonDown:
pMenu->TrackPopupMenu(TPM_CENTERALIGN | TPM_RIGHTBUTTON,
point.x, point.y, AfxGetApp()->m_pMainWnd);
Odkaz na oznámení AfxGetApp() - > m_pMainWnd.Místo aktivována při server má hlavní okno a m_pMainWnd je nastavena, ale je obvykle neviditelný.Navíc toto okno odkazuje hlavní okno aplikace se v případě, že server je plně okno MDI rámečku otevřít nebo spustit samostatný.Neodkazuje na snímek aktivního okna, které při místní aktivaci je snímek okna odvozené z COleIPFrameWnd.I když místní úpravy, tato verze MFC přidává nové funkce získat správné aktivní okno AfxGetMainWnd.Obecně je použít namísto této funkce AfxGetApp() - > m_pMainWnd.Tento kód je potřeba změnit takto:
pMenu->TrackPopupMenu(TPM_CENTERALIGN | TPM_RIGHTBUTTON,
point.x, point.y, AfxGetMainWnd());
Nyní máte povoleno minimální funkční místní aktivace serveru OLE.Ale stále nejsou k dispozici MFC/OLE 2, které nebyly k dispozici v MFC/OLE1 mnoho funkcí.Viz HIERSVR vzorku pro další nápady na funkce, které chcete implementovat.Níže jsou uvedeny některé funkce, které implementuje HIERSVR:
Zvětšování true WYSISYG chování ke kontejneru.
Přetáhněte / drop a schránky vlastní formát.
Posouvání okna kontejneru jako výběr změnit.
HIERSVR vzorku v MFC 3.0 používá také mírně odlišné návrhu své položky na serveru.To pomáhá šetřit paměť a odkazů umožňuje flexibilnější.S HIERSVR verze 2.0 každý uzel ve stromu je vCOleServerItem.COleServerItemnese větší nároky, než je nezbytně nutné pro každý z těchto uzlů, ale COleServerItem je vyžadována pro každé aktivní odkaz.Ale z větší části jsou velmi málo aktivních odkazů v daném okamžiku.Chcete-li to účinnější, HIERSVR v této verzi MFC odděluje uzlu z COleServerItem.Má i CServerNode a CServerItem třídy.CServerItem (odvozené z COleServerItem) je vytvořen pouze podle potřeby.Jakmile kontejneru (nebo kontejnery) zastavit tento určitý odkaz na příslušném uzlu, přidružené CServerNode objektu CServerItem se zrušuje.Tento návrh je efektivnější a flexibilnější.Jeho flexibilita při obchodování s více odkazů na výběr.Ani jeden z těchto dvou verzí HIERSVR podporovat více výběrů, ale je jednodušší přidat (a odkazy na tyto výběry podporují) verze MFC 3.0 HIERSVR, protože COleServerItem je oddělen od nativní data.