TN041: MFC 動作に移行する MFC および OLE 2

移行に関する一般的な問題

OLE 2 クラス MFC 2.5 に (等) の設計目標の 1 つの OLE 1.0 をサポートする MFC 2.0 の場所に、同じアーキテクチャをだった。結果として、MFC 2.0 の同じ OLE クラスの多くはまだこのバージョンでは、MFC (COleDocumentCOleServerDocCOleClientItemCOleServerItem) の存在します。に加えて、これらのクラスの Api の多くはまったく同じです。ただし、いくつかの詳細が変更されていることを期待することができます OLE 2 は OLE 1.0 から大幅に異なるです。MFC 2.0 の OLE1 サポートに精通している場合は、MFC の 2.0 サポートを自宅で感じられるでしょう。

既存の mfc/ole1 アプリケーションして OLE 2 の機能を追加する場合は、まずこのノートをお読みください。このノートを OLE1 機能を MFC および OLE 2 の移植が発生して、MFC 2.0 に含まれる 2 つのアプリケーションを移植することが明らかになった問題についてを説明しますいくつかの一般的な問題について説明: MFC OLE のサンプル OCLIENT HIERSVR

MFC のドキュメント/ビュー アーキテクチャが重要です。

アプリケーションが MFC のドキュメント/ビュー アーキテクチャを使用しないし、OLE 2 のサポートをアプリケーションに追加する場合は、ドキュメント/ビューに移動する時間になりました。組み込みのアーキテクチャとコンポーネントの MFC アプリケーションで使用すると、MFC の OLE 2 クラスの利点の多くのみ実現します。

MFC アーキテクチャを使用せず、サーバーまたはコンテナを実装可能な推奨されませんが。

MFC の実装の代わりに自分自身を使用します。

MFC"実装"缶詰など、 CToolBarCStatusBarCScrollViewクラスがある組み込みの特別なケースのコード OLE 2 のサポート。したがって、アプリケーションでこれらのクラスを使用することができる場合、OLE を認識するには努力からメリットがあります。これらの目的には、「ロール自分」のクラスをここでそれはない提案です。同様の機能を実装する必要がある場合は、(特にそれをインプレース アクティブ化) MFC ソース コードを OLE の細かい点のいくつかを扱う参照です。

MFC サンプル コードを調べる

OLE 機能が含まれる MFC サンプルの数です。これらの各アプリケーションを別の角度から OLE を実装します。:

サーバー アプリケーションとしての使用を主に意味HIERSVR -。それは mfc/ole1 アプリケーションとして MFC 2.0 に含まれていたと MFC および OLE 2 に移植して OLE 2 で利用可能な多くの OLE 機能を実装する拡張。

OCLIENT - このスタンドアロン コンテナーのアプリケーションは、OLE の機能の多くは、コンテナーの観点から説明するためのものです。それも MFC 2.0 から移植されたものと、多くのカスタム クリップボード形式や埋め込みアイテムへのリンクなどのより高度な OLE 機能をサポートする拡張。

OCLIENT のように、 DRAWCLI - このアプリケーションは既存のオブジェクト指向描画プログラムの枠組みの中でそうことを除いては OLE コンテナー サポートを実装します。それはどのように OLE コンテナー サポートを実装可能性があり、それを既存のアプリケーションに統合を示してください。

SUPERPAD - このアプリケーションとして、罰金のスタンドアロン アプリケーションも OLE サーバーです。それを実装するサーバーのサポートはかなりミニマルなです。特に興味深いはどのようにデータをクリップボードにコピーするには OLE のクリップボード サービスを使用してが機能、Windows に組み込まれたを使用して [編集] クリップボード貼り付けの機能を実装するコントロール。これは興味深いミックスの伝統的な Windows API の使用方法として、新しい OLE Api との統合を示しています。

サンプル アプリケーションの詳細については、「MFC サンプル 』 のヘルプ参照してください。

事例: OCLIENT MFC 2.0 から

上記で説明したように OCLIENT MFC 2.0 に含まれていたし、OLE 動作を実装します。このアプリケーション最初 MFC および OLE 2 クラスを使用する基本的な手順を以下に示します。最初のポートより MFC および OLE クラスを説明するために完了した後、多数の機能が追加されました。これらの機能はここで説明しません;これらの高度な機能の詳細については、サンプルそれ自体を参照してください。

特価;コンパイラ エラーおよび詳細なプロセスは Visual C 2.0 で作成されました。Visual C 4.0 では、特定のエラー メッセージおよび場所を変えるかもしれないの概念に関する情報が有効なまま(&N)。

それを取得して実行しています。

OCLIENT サンプルを移植する方法それを構築してなります明らかなコンパイラ エラーを修正することを開始することです。OCLIENT サンプル MFC 2.0 からをした場合に、この MFC のバージョンでコンパイルすると、解決するのには、多くのエラーがないことがあります。エラーの発生する順序を次に示します。

コンパイルとエラーの修正

\oclient\mainview.cpp(104): エラー c2660 エラー: '描く': 4 つのパラメーターを受け取らない関数

最初のエラー COleClientItem::Drawを懸念します。動作では、MFC および OLE のバージョンよりも多くのパラメーターだった。余分なパラメーターはありません必要と (この例では通常は NULL でした。描画されている CDC が、メタファイル DC がこのバージョンの MFC は自動的に、lpWBounds の値を判断できます。フレームワークが、「DC」の属性で渡された pDC から 1 つを構築するために加えて、情報パラメーター必要はなくなりました。この問題を解決するには、あなただけの削除 2 つに余分な描画呼び出しのパラメーターは NULL。

\oclient\mainview.cpp(273): エラー C2065: 'OLE_MAXNAMESIZE': 宣言されていない識別子\oclient\mainview.cpp(273): エラー C2057: 定数式が必要\oclient\mainview.cpp(280): エラー C2664: 'CreateLinkFromClipboard': パラメーター 1 'char [1]' から変換できません ' enum: tagOLERENDER '\oclient\mainview.cpp(286): エラー C2664: 'CreateFromClipboard': パラメーター 1 'char [1]' から変換できません ' enum: tagOLERENDER '\oclient\mainview.cpp(288): エラー C2664: 'CreateStaticFromClipboard': パラメーター 1 'char [1]' から変換できません ' enum: tagOLERENDER '

上記のエラー、 COleClientItem::CreateXXXX関数の動作のすべての項目を表す一意の名前を渡すこと必要なことに起因します。これは、基になる OLE API の要件でした。OLE 2 DDE を (名前は DDE 会話で使用された)、基になる通信メカニズムとして使用しないのでこれは、MFC および OLE 2 の必要はありません。この問題を解決するには、 CreateNewName関数と同様にすべての参照を削除できます。どのような各 MFC および OLE 関数このバージョンで単に呼び出しにカーソルを配置し、F1 キーを押すによって期待です。 見つけることは簡単です。

大幅に異なる別の領域は、ole2 におけるクリップボード処理です。OLE1 と Api を操作 Windows クリップボード、クリップボードを使用しました。OLE 2 のこれの別のメカニズムでです。MFC 動作 Api は、 COleClientItemオブジェクトをクリップボードにコピーする前に、クリップボードが開いていたことと。これが必要になったし、すべての MFC および OLE クリップボード操作が失敗する原因とされます。CreateNewNameの依存関係を削除するには、コードを編集している間、またが開き、Windows のクリップボードを終了するコードを削除する必要があります。

\oclient\mainview.cpp(332): エラー C2065: 'AfxOleInsertDialog': 宣言されていない識別子\oclient\mainview.cpp(332): エラー C2064: 用語は、関数に評価されません。\oclient\mainview.cpp(344): エラー C2057: 定数式が必要\oclient\mainview.cpp(347): エラー C2039: 'CreateNewObject': 'CRectItem' のメンバーではないです。

これらのエラーは、 CMainView::OnInsertObjectハンドラーから結果します。[新しいオブジェクトの挿入] コマンドを処理することがかなりの変更が別の領域です。この例では、単に元の実装は、AppWizard によって提供される新しい OLE コンテナー アプリケーションをマージするは簡単です。実際には、これは他のアプリケーションの移植を適用できる手法です。Mfc/ole1 では、 AfxOleInsertDialog関数を呼び出すことによって、[オブジェクトの挿入] ダイアログ ボックスを表示しました。このバージョンのCOleInsertObjectダイアログ オブジェクトを構築し、 domodal 関数を呼び出します。さらに、クラス名の文字列の代わりにCLSIDを新しい OLE アイテムが作成されます。その結果、これのようになります

COleInsertDialog ダイアログ;場合 (ダイアログ。DoModal() ! IDOK =)特価;戻る;BeginWaitCursor();CRectItem ※ pItem = NULL;してください。{//最初に C++ オブジェクトを作成します。pItem = GetDocument() - > CreateItem();ASSERT_VALID(pItem);//ダイアログ データから項目を初期化します。場合 (! ダイアログ。CreateItem(pItem))AfxThrowMemoryException();//すべての例外を行いますASSERT_VALID(pItem);・必要に応じて、オブジェクトを実行場合 (ダイアログ。GetSelectionType() = = COleInsertDialog::createNewItem)pItem - > DoVerb(OLEIVERB_SHOW, this);//今すぐ更新pItem - > UpdateLink();pItem - > UpdateItemRectFromServer();・新たに挿入された項目に選択範囲を設定SetSelection(pItem);pItem - > Invalidate();}キャッチ (CException、e){・ ・ アイテムをクリーン場合 (pItem! = NULL)GetDocument() - > DeleteItem(pItem);AfxMessageBox(IDP_FAILED_TO_CREATE);}END_CATCHEndWaitCursor()

特価;新規オブジェクトの挿入は、アプリケーションを異なる場合があります)(&N):

それも lt;afxodlgs.h する必要があります > MFC によって提供されるその他の標準的なダイアログと同様に、 COleInsertObjectダイアログ クラスの宣言が含まれています。

\oclient\mainview.cpp(367): エラー C2065: 'OLEVERB_PRIMARY': 宣言されていない識別子\oclient\mainview.cpp(367): エラー c2660 エラー: 'DoVerb': 1 のパラメーターを受け取らない関数

概念が同じであってもいくつか OLE1 定数 OLE 2 では、変更が、実際これらのエラーが原因です。この場合はOLEVERB_PRIMARY OLEIVERB_PRIMARYに変更されました。ユーザーがアイテムをダブルクリックすると両方の OLE1 および OLE 2 では、主動詞は通常、コンテナーによって実行されます。

また、 DoVerbを今、余分なパラメーターを受け取る ? ビューへのポインター (CView※)。このパラメーターは、「ビジュアル編集」(埋め込み) を実装するためにのみ使用されます。この時点でこの機能を実装していないので今のところ、そのパラメーターを NULL に、設定します。

フレームワークがない場所にしようとを有効にすることを確認するには、あなたのCOleClientItem::CanActivateとして次のようにオーバーライドする必要があります。

 BOOL CRectItem::CanActivate(){特価;FALSE を返す;}\oclient\rectitem.cpp(53): エラー C2065: 'GetBounds': 宣言されていない識別子\oclient\rectitem.cpp(53): エラー C2064: 用語は、関数に評価されません。\oclient\rectitem.cpp(84): エラー C2065: 'SetBounds': 宣言されていない識別子\oclient\rectitem.cpp(84): エラー C2064: 用語は、関数に評価されません。(&N)

、動作では、 COleClientItem::GetBoundsSetBoundsがクエリを実行し、(のメンバーは常にゼロだ)、項目の範囲を操作する際にしました。MFC および OLE 2 でこれより直接COleClientItem::GetExtentSetExtentは、サイズまたはCSizeの代わりにサポートされています。

コードは、新しい SetItemRectToServer と UpdateItemRectFromServer の呼び出しを見てこのような:

BOOL CRectItem::UpdateItemRectFromServer(){特価;ASSERT(m_bTrackServerSize);CSize サイズ;if (!。GetExtent(&size))FALSE を返す;//空白・画面座標 HIMETRIC からをマップ{CClientDC screenDC(NULL);screenDC.SetMapMode(MM_HIMETRIC);screenDC.LPtoDP(&size);}・だけ項目のサイズを設定場合 (m_rect。Size() ! サイズ =){//古いサイズ/位置を無効にします。Invalidate();m_rect.right = m_rect.left + size.cx;m_rect.bottom = m_rect.top + size.cy;・ ・と同様、新しいサイズ/位置Invalidate();}TRUE を返す;}BOOL CRectItem::SetItemRectToServer(){・公式の境界の埋め込みアイテムの設定CSize サイズ m_rect =。Size();{CClientDC screenDC(NULL);screenDC.SetMapMode(MM_HIMETRIC);screenDC.DPtoLP(&size);}してください。{SetExtent(size);//、待機を行うことができます}キャッチ (CException、e){FALSE を返す;//リンク SetBounds 許可されません}END_CATCHTRUE を返す;}\oclient\frame.cpp(50): エラー C2039: 'InWaitForRelease': 'COleClientItem' のメンバーではないです。\oclient\frame.cpp(50): エラー C2065: 'InWaitForRelease': 宣言されていない識別子\oclient\frame.cpp(50): エラー C2064: 用語は、関数に評価されません。

OLE1 が多くのケースで本質的に非同期で動作のコンテナーからサーバーへの API 呼び出しの同期シミュレーション、いた。非同期呼び出しが進行中のユーザーからのコマンドを処理する前に確認する必要があります。動作、 COleClientItem::InWaitForReleaseそうすること機能。CMainFrame のすべて一緒に OnCommand のオーバーライドを削除することができますので MFC および OLE 2 でこの必要ありません。

この時点で OCLIENT コンパイル リンクと。

その他の必要な変更

OCLIENT 実行、しかし続けることではないほとんどの事がありません。今の代わりに後で問題を解決することをお勧め。

まず、OLE ライブラリを初期化するために必要です。これは、 InitInstanceからAfxOleInitを呼び出すことによって行われます:

if (!。AfxOleInit()){AfxMessageBox (「OLE ライブラリの初期化に失敗しました」);FALSE を返す;}

また、仮想関数のパラメーター リストの変更を確認することをお勧めします。このような 1 つの関数すべて MFC および OLE コンテナー アプリケーションでオーバーライドCOleClientItem::OnChange、です。オンライン ヘルプを見ると、余分な 'DWORD dwParam」が追加されたことがわかります。新しい CRectItem::OnChange を次のように見える

void CRectItem::OnChange (OLE_NOTIFICATION wNotification、DWORD dwParam){場合 (m_bTrackServerSize amp; &!UpdateItemRectFromServer()){//オブジェクトを空にします。場合 (wNotification OLE_CLOSED = =){//データ、オブジェクトを受信しないそれを破壊アサート。IsVisible());GetDocument() - > DeleteItem(this);戻る;//更新はありません (項目はなくなった今)}}場合 (wNotification ! OLE_CLOSED =)Dirty();Invalidate();//変更、再描画が発生します}

Mfc/ole1 では、コンテナー アプリケーションのドキュメント クラスCOleClientDocから派生。MFC および OLE 2 でこのクラスの削除されているし、(この新しい組織コンテナー/サーバー アプリケーションを構築しやすくなります) COleDocumentに置き換え。COleClientDoc動作アプリケーション OCLIENT などの MFC および OLE 2 への移植を簡略化するには、 COleDocumentをマップ、 #define there ' s。COleClientDocによって提供されたCOleDocumentによって提供されない機能の 1 つは、標準コマンド メッセージ マップ エントリです。これは、コンテナー/サーバー アプリケーションでない限りまたCOleDocument (直接) 使用しない、サーバー アプリケーションにこれらのコマンド ハンドラーのオーバーヘッドしない行うようにするためです。だから、CMainDoc のメッセージ マップに次のエントリを追加する必要があります。:

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)

これらのコマンドのすべての実装でCOleDocumentはドキュメントの基本クラスです。

この時点で、OCLIENT 機能 OLE コンテナー アプリケーションです。(OLE1 または OLE 2) の任意のタイプのアイテムを挿入することが可能です。インプレース アクティブ化を有効にするに必要なコードが実装されていないので、OLE1 とような別のウィンドウでアイテムが編集されます。次のセクション (「ビジュアル編集」呼ばれます) のインプレース編集を有効にするには、必要な変更について説明します。

「ビジュアル編集」を追加

OLE の最も興味深い機能の 1 つはインプレース アクティブ化 (または「ビジュアル編集」) です。この機能では、コンテナーのユーザー インターフェイスの一部で、ユーザーにシームレスな編集インターフェイスを提供するには、サーバー アプリケーションことができます。OCLIENT にインプレース アクティベーションを実装するには、いくつかの特殊なリソースをいくつか追加のコードだけでなく、追加する必要があります。これらのリソースとコード AppWizard によって通常提供されています-実際には、多くのここのコードは、新鮮な AppWizard アプリケーションを「コンテナー」サポートから直接借りていた。

まず第一に、インプレース アクティブなアイテムがあるときに使用するメニュー リソースを追加する必要は。IDR_OCLITYPE リソースをコピーしてがすべてのファイルとウィンドウのポップアップを削除するには Visual C でこの余分のメニュー リソースを作成します。間のファイルとウィンドウのポップアップをグループの分離を示す 2 つの区分線が挿入されます (それのようになります: ファイル | |ウィンドウ)。「メニューとリソース: メニューの結合」 OLE 2 クラスでこれらの区切り文字何を意味し、、サーバー メニューとコンテナー メニューのマージ方法の詳細についてを参照してください。

これらのメニューを作成した後、それらについて知っているフレームワークを聞かせする必要があります。これは、InitInstance でに、ドキュメント テンプレートの一覧に追加する前に、ドキュメント テンプレートのCDocTemplate::SetContainerInfoを呼び出して行われます。ドキュメント テンプレートを登録するには、新しいコードを次のように見える

 CDocTemplate ※ pTemplate = 新しいそれ (特価;IDR_OLECLITYPE、RUNTIME_CLASS(CMainDoc)、RUNTIME_CLASS(CMDIChildWnd)、・ ・標準 MDI 子フレームRUNTIME_CLASS(CMainView));pTemplate - > SetContainerInfo(IDR_OLECLITYPE_INPLACE);AddDocTemplate(pTemplate)

IDR_OLECLITYPE_INPLACE リソースを Visual C で作成された特別な場所でリソースです。

インプレース アクティブ化を有効にするには、両方のCViewでを変更する必要があるいくつかある (CMainView) の派生クラスだけでなく、 COleClientItem派生クラス (CRectItem)。すべてのこれらの上書き AppWizard によって提供され、実装のほとんどはデフォルトの AppWizard アプリケーションから直接来る。

このポートの最初のステップでは、インプレース アクティブ化完全COleClientItem::CanActivateをオーバーライドすることにより無効にされました。このオーバーライドは、インプレース アクティベーションを許可する削除する必要があります。また、NULL へのすべての呼び出し (はそれらの 2 つ) DoVerbにビューのみインプレース アクティブ化の必要があるを提供するため渡されました。インプレース アクティブ化を完全に実装するには、 DoVerb呼び出しで適切なビューを渡す必要があります。これらの呼び出しのいずれかのCMainView::OnInsertObjectであります。

pItem gt; DoVerb(OLEIVERB_SHOW, this)(&G)

別のCMainView::OnLButtonDblClkであります。

m_pSelection-gt; DoVerb(OLEIVERB_PRIMARY, this)(&G)

それはCOleClientItem::OnGetItemPositionをオーバーライドする必要があります。これをインプレース アクティブ化されると、項目コンテナーのウィンドウを基準に、ウィンドウの配置場所を指示します。OCLIENT の実装は簡単です。

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

ほとんどのサーバーも」でサイズを変更するインプレース」と呼ばれるものを実装します。これがサーバ ・ ウィンドウのサイズし、ユーザー、アイテムを編集している間を移動することができます。移動または通常、ウィンドウをサイズ変更、位置とサイズ、コンテナー ドキュメント自体に影響を与えるので、コンテナーはこの操作では、参加する必要があります。OCLIENT の実装 m_rect の新しい位置とサイズによって維持、内部四角形を同期します。

 BOOL CRectItem::OnChangeItemPosition(const CRectamp; rectPos){ASSERT_VALID(this);if (!。COleClientItem::OnChangeItemPosition(rectPos))FALSE を返す;Invalidate();m_rect = rectPos;Invalidate();GetDocument() - > SetModifiedFlag();TRUE を返す;}

この時点では、インプレース アクティブ化してサイズとそれがアクティブなときのアイテムの移動を処理するアイテムを許可するには、十分なコードが、編集セッションを終了するには、ユーザーがコードはありません。一部のサーバーこの機能自体をエスケープ キーを処理することによって提供するが、容器項目を無効にするには、2 つの方法がありますを提供することをお勧め: (1) 外のアイテムをクリックして (2)、esc キーを押す。

エスケープのキー追加 Visual C は、VK_ESCAPE キーをコマンドには、マップとアクセラレータ ID_CANCEL_EDIT をリソースに追加されます。このコマンドのハンドラーに依存します。:

・次のコマンド ハンドラーを標準提供・ キーボード、インプレースをキャンセルするユーザー インターフェイス//session.void CMainView::OnCancelEdit() の編集{特価;//、インプレース アクティブな項目このビューを閉じます。COleClientItem ※ pActiveItem = GetDocument() - > GetInPlaceActiveItem(this);場合 (pActiveItem! = NULL)pActiveItem - > Close();ASSERT(GetDocument()-> GetInPlaceActiveItem(this) = = NULL);}

外の項目のユーザーを処理するには、あなたCMainView::SetSelectionの先頭に次のコードを追加します。

場合 (pNewSel ! m_pSelection = | | pNewSel = = NULL){特価;COleClientItem ※ pActiveItem = GetDocument() - > GetInPlaceActiveItem(this);場合 (pActiveItem! = NULL & & pActiveItem ! pNewSel =)pActiveItem - > Close();}& 特価
 

アイテムがアクティブのときは、フォーカスをはずです。ビューがフォーカス フォーカスは常にアクティブな項目に転送は、このかどうかを確認するには onsetfocus を使用:

・ OnSetFocus と OnSize の特別な処理は必要な・ ・ときオブジェクト編集されている場所で。void CMainView::OnSetFocus (CWnd ※ pOldWnd){特価;COleClientItem ※ pActiveItem = GetDocument() - > GetInPlaceActiveItem(this);場合 (pActiveItem! = NULL & &pActiveItem - > GetItemState() COleClientItem::activeUIState = =){・同じビューの場合、この項目にフォーカスを設定する必要がありますCWnd ※ pWnd = pActiveItem - > GetInPlaceWindow();場合 (pWnd! = NULL){pWnd - > SetFocus();//基本クラスを呼び出すことはありません戻る;}}CView::OnSetFocus(pOldWnd);}

ビューのサイズを変更すると、クリッピング四角形が変更された、アクティブな項目を通知する必要があります。これを行うに、 OnSizeのハンドラーを提供します。:

void CMainView::OnSize (UINT nType、cx、int int cy){特価;CView::OnSize (コマンドを実行して、cx, cy);COleClientItem ※ pActiveItem = GetDocument() - > GetInPlaceActiveItem(this);場合 (pActiveItem! = NULL)pActiveItem - > SetItemRects();}

事例: HIERSVR MFC 2.0 から

HIERSVRも MFC 2.0 に含まれていたし、OLE 動作を実装します。このノートではこのアプリケーション最初 MFC および OLE 2 クラスを使用して変換された手順を説明します。最初のポートより MFC および OLE 2 クラスを説明するために完了した後、多数の機能が追加されました。これらの機能はここで説明しません;これらの高度な機能の詳細については、サンプルそれ自体を参照してください。

特価;コンパイラ エラーおよび詳細なプロセスは Visual C 2.0 で作成されました。Visual C 4.0 では、特定のエラー メッセージおよび場所を変えるかもしれないの概念に関する情報が有効なまま(&N)。

それを取得して実行しています。

HIERSVR サンプルを移植する方法それを構築してなります明らかなコンパイラ エラーを修正することを開始することです。HIERSVR サンプル MFC 2.0 から取るこの MFC のバージョンでコンパイルすると、(ただし oclient の以上) を解決するのには、多くのエラーがないことがあります。エラーが通常発生順を次のとおりです。

コンパイルとエラーの修正

\hiersvr\hiersvr.cpp(83): エラー C2039: 'RunEmbedded': 'COleTemplateServer' のメンバーではないです。

サーバーので、多くの大きな問題、 InitInstance関数をしたときにこの最初のエラーが指摘しました。OLE サーバーに必要な初期化は、おそらくそれを実行するには、動作アプリケーションにする必要があります最大の変更点の 1 つです。行うには最高のものは、AppWizard の OLE サーバーに何を作成で見るし、必要に応じてコードを変更です。ここではいくつかの点を念頭に:

AfxOleInitを呼び出して、OLE ライブラリを初期化する必要があります。

SetServerInfo サーバー リソース ハンドルと、 CDocTemplateコンス トラクターで設定できないランタイム クラス情報を設定するには、ドキュメント テンプレート オブジェクトを呼び出す。

コマンドラインで/Embedding がある場合、アプリケーションのメイン ウィンドウを表示しません。

ドキュメントのGUIDを必要があります。これは、ドキュメントのタイプ (128 ビット) の一意の識別子です。AppWizard を作成する-そうここで説明したテクニックを使用する場合は、新しいコードを新しい AppWizard サーバー アプリケーションからコピー、単に「GUID はアプリケーションから盗むことができる」。そうでない場合は、GUIDGEN を使用することができます。BIN ディレクトリに EXE ユーティリティ。

COleTemplateServerオブジェクト、ドキュメント テンプレートにCOleTemplateServer::ConnectTemplateを呼び出すことによって接続するには"必要があります。

アプリケーションをスタンドアロンで実行するときは、システム レジストリを更新します。この方法は、ユーザーを移動する場合。EXE アプリケーションは、新しい場所から実行する新しい場所をポイントするには、Windows システム登録データベース更新されます。

AppWizard のinitinstance 関数を何を作成日時に基づいてこれらの変更のすべてを適用した後、HIERSVR のInitInstance (と関連の GUID) は次のとおり読み取りする必要があります。:

// 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;
}

あなたは、上記のコードが新しいリソース ID を IDR_HIERSVRTYPE_SRVR_EMB を指すことがわかります。これは別のコンテナーに埋め込まれているドキュメントを編集するときに使用するメニュー リソースです。MFC 動作で埋め込みアイテムを編集する特定のメニュー項目はその場で変更されました。ファイル ベースのドキュメントを編集するのではなく、埋め込みアイテムを編集するときに、完全に別のメニュー構造を使用してこれら 2 つのモードの別のユーザー インターフェイスを提供しやすくなります。後でわかりますは完全に別のメニュー リソース埋め込みオブジェクト インプレースを編集するときに使用されます。

このリソースを作成するには、Visual C リソース スクリプトをロードし、既存の IDR_HIERSVRTYPE メニュー リソースをコピーします。新しいリソース (これは、AppWizard を使用して、同じ名前付け規則) IDR_HIERSVRTYPE_SRVR_EMB に変更します。次に「ファイルを保存する」」にファイル更新」; 変更コマンド ID ID_FILE_UPDATEを与えます。「ファイル保存コピーとしてに「;」ファイル保存として」も変更コマンド ID ID_FILE_SAVE_COPY_ASを与えます。これらのコマンドの両方の実装フレームワークを提供します。

\hiersvr\svritem.h(60): エラー C2433: 'OLESTATUS': '仮想' できませんデータ宣言で\hiersvr\svritem.h(60): エラー C2501: 'OLESTATUS': 宣言指定子がありません\hiersvr\svritem.h(60): エラー C2146: 構文エラー: 見つからない ';' 識別子 'OnSetData' の前に\hiersvr\svritem.h(60): エラー C2061: 構文エラー: 識別子 'OLECLIPFORMAT'\hiersvr\svritem.h(60): エラー C2501: 'OnSetData': 宣言指定子がありません

それをOLESTATUS型に参照しているので、 OnSetDataのオーバーライドからエラーの数です。OLESTATUS OLE1 エラーの方法でした。MFC は、通常、エラーを含む、 COleExceptionには、 HRESULT変換しますがこのHRESULT OLE 2 に変更されました。行うには簡単なことがそれを削除するにはこの特定のケースでは、 OnSetDataのオーバーライドは、もはや必要です。

 \hiersvr\svritem.cpp(30): エラー c2660 エラー: 'COleServerItem::COleServerItem': 1 のパラメーターを受け取らない関数

COleServerItemコンス トラクターは、追加の 'BOOL' パラメーターを受け取ります。このフラグは、 COleServerItemオブジェクトのメモリ管理の方法を決定します。TRUE に設定すると、フレームワークはこれらのオブジェクトのメモリ管理処理 ? が不要になったときに削除します。このフラグを FALSE に設定されますので HIERSVR ( COleServerItemの派生) CServerItemオブジェクトは、ネイティブのデータの一部として使用します。これは hiersvr 各サーバー アイテムが削除された場合を確認します。

\hiersvr\svritem.cpp(44): エラー C2259: 'CServerItem': 抽象クラスをインスタンス化しようとする不正な\hiersvr\svritem.cpp(44): エラー C2259: 'CServerItem': 抽象クラスをインスタンス化しようとする不正な

これらのエラーを示すように、CServerItem にオーバーライドされていないいくつかの純粋な仮想関数です。最も可能性の高いこの OnDraw のパラメータ リストが変更されたという事実によって発生します。このエラーを解決するには、 CServerItem::OnDrawとして次のように (だけでなく、svritem.h で宣言) 変更します。

BOOL CServerItem::OnDraw(CDC* pDC, CSizeamp; rSize){//要求の OLE からノードを描画するにはpDC - > SetMapMode(MM_TEXT);//は、常にピクセルDoDraw (pDC、CPoint(0,0)、FALSE); を返す}

新しいパラメーター 'rSize' です。これは、便利な場合、図面のサイズを入力することができます。このサイズはHIMETRICである必要があります。この例では、フレームワーク、範囲を取得するには、 OnGetExtentを呼び出すのでこの値を入力するは不便です。あなたがそのためには、 OnGetExtentを実装する必要があります。:

BOOL CServerItem::OnGetExtent(DVASPECT dwDrawAspect, CSizeamp; rSize){場合 (dwDrawAspect ! DVASPECT_CONTENT =)COleServerItem::OnGetExtent (dwDrawAspect、rSize); を返すrSize = CalcNodeSize();TRUE を返す;}\hiersvr\svritem.cpp(104): エラー C2065: 'm_rectBounds': 宣言されていない識別子\hiersvr\svritem.cpp(104): エラー C2228: 左の '。SetRect' クラス、構造体、共用体型が必要\hiersvr\svritem.cpp(106): エラー C2664: 'void これらの関数がされており、_ DPtoLP (構造体リファレンスマニュアル:: tagPOINT されており、_ ※、int) __far const ': パラメーター 1 から変換することはできません ' int されており、_ ※ ' に' 構造体リファレンスマニュアル:: tagPOINT されており、_ ※ '(&A)

CServerItem::CalcNodeSize 関数項目のサイズをHIMETRICに変換され、 m_rectBoundsに格納されています。COleServerItemの 'm_rectBounds' の非公開メンバーは存在しません ( m_sizeExtentによって、部分的交換しますが、 m_rectBounds OLE1 でよりも OLE 2 でこのメンバーをわずかに異なる使用)。このメンバー変数にHIMETRICサイズを設定するのではなく、それを返すよ。この戻り値は以前実装OnGetExtentの使用します。

CSize CServerItem::CalcNodeSize(){特価;CClientDC dcScreen(NULL);m_sizeNode dcScreen.GetTextExtent (m_strDescription、=m_strDescription.GetLength());m_sizeNode + = CSize (CX_INSET ※ 2、CY_INSET ※ 2);・推奨 HIMETRIC サイズを設定CSize サイズ (m_sizeNode.cx、m_sizeNode.cy);dcScreen.SetMapMode(MM_HIMETRIC);dcScreen.DPtoLP(&size);サイズを返す;}

CServerItem にもCOleServerItem::OnGetTextDataをよりも優先されます。この関数は、MFC および OLE で時代遅れであり、別のメカニズムで置き換えられます。MFC OLE サンプルの MFC 3.0 バージョン HIERSVR COleServerItem::OnRenderFileDataをオーバーライドすることによってこの機能を実装します。OnGetTextData のオーバーライドを削除することは、この機能はこの基本的なポートごとに、重要ではありません。

対処されていない多くの多くのエラー svritem.cpp であります。彼らは「実質の」エラーではありません ? だけで以前のエラーにより発生、エラー。

\hiersvr\svrview.cpp(325): エラー c2660 エラー: 'CopyToClipboard': 2 つのパラメーターを受け取らない関数

COleServerItem::CopyToClipboard 'bIncludeNative' フラグをサポートされていません。ネイティブ データ (サーバー アイテムの Serialize 関数が書き出すデータ) は、最初のパラメーターを削除するので常にコピーされます。また、 CopyToClipboard FALSE を返すのではなく、エラーが発生すると例外がスローされます。コードを CServerView::OnEditCopy として次のように変更します。

void CServerView::OnEditCopy(){特価;場合 (m_pSelectedNode = = NULL)AfxThrowNotSupportedException();してください。{m_pSelectedNode - > CopyToClipboard(TRUE);}CATCH_ALL(e){AfxMessageBox (「クリップボードにコピーできませんでした");}END_CATCH_ALL}

OCLIENT の同じバージョンに比べて HIERSVR の MFC 2.0 バージョンのコンパイルから生じるエラーがあったが、ある実際に少数の変更。

この時点で HIERSVR コンパイルしリンクされ、OLE サーバーとしてがインプレース編集機能には、次に実装する機能。

「ビジュアル編集」を追加

「ビジュアル編集」だ (またはインプレース アクティブ化) このサーバー アプリケーションに追加するには、あなたの世話をする必要がありますのみ、いくつかのこと:

メニュー リソースを作成するは簡単です。Visual C を実行、メニュー リソース IDR_HIERSVRTYPE IDR_HIERSVRTYPE_SRVR_IP と呼ばれるメニュー リソースにコピーします。編集およびヘルプ メニューのポップアップだけが残っているように、メニューを変更します。メニュー、編集およびヘルプ メニューの間に 2 つの区切り記号を追加 (それのようになります: 編集 | |ヘルプ)。これらの区切り文字は何を意味し、サーバー メニューとコンテナー メニューのマージ方法の詳細については、「メニューとリソース: メニューの結合」 OLE 2 クラスを参照してください。

[サブセット] ツールバーのビットマップは、チェックを「サーバー」オプションでは、新鮮な生成 AppWizard アプリケーションをコピーして簡単に作成できます。このビットマップは、Visual C にインポートできます。ビットマップの場合は、ID IDR_HIERSVRTYPE_SRVR_IP をしてください。

生成した COleIPFrameWndの派生クラスは、サーバーのサポートで生成 AppWizard アプリケーションからコピーできます。両方のファイルは、IPFRAME をコピーします。CPP と IPFRAME。H とそれらをプロジェクトに追加します。LoadBitmap呼び出し IDR_HIERSVRTYPE_SRVR_IP、前の手順で作成したビットマップを参照しているかどうかを確認します。

すべての新しいリソースとクラスが作成されますが、フレームワークこれらについて知っている (このアプリケーションで埋め込み先編集をサポートしていることを知っているように) 必要なコードを追加します。これは、いくつか複数のパラメーターをSetServerInfoに、 InitInstance関数の呼び出しを追加することによって行われます:

pDocTemplate-gt;SetServerInfo (IDR_HIERSVRTYPE_SRVR_EMB、IDR_HIERSVRTYPE_SRVR_IP、RUNTIME_CLASS(CInPlaceFrame))(&G)

それは場所で実行になりましたまたインプレース アクティブ化をサポートする任意のコンテナーで。しかし、まだ、コード内に潜んでいる 1 つのマイナーなバグです。HIERSVR はマウスの右ボタンを押したときに表示されるコンテキスト メニューをサポートしています。HIERSVR 全開、埋め込みの場所を編集するときは動作しませんが、このメニューを動作します。理由この 1 行のコードで CServerView::OnRButtonDown を固定することができます

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

参照を通知afxgetapp を呼び出して ()-gt; m_pMainWnd。サーバーがインプレース アクティブ化の場合は、それをメイン ウィンドウと m_pMainWnd が設定されているは通常表示されません。さらに、このウィンドウは、アプリケーションは、サーバーが完全に開いているときに表示されますまたはスタンドアロン実行 MDI フレーム ウィンドウのメインウィンドウを指します。アクティブなフレーム ウィンドウを参照してくださいしない-はインプレース アクティブ化がから生成した COleIPFrameWndの派生フレーム ウィンドウ。新しい関数、 AfxGetMainWndも、インプレース編集この MFC のバージョンを追加すると、正しいのアクティブなウィンドウを取得するには。通常、この関数の代わりに使用する必要がありますAfxGetApp() - > m_pMainWnd。このコードは次のとおり変更する必要があります。:

 pMenu-gt;TrackPopupMenu(TPM_CENTERALIGN |TPM_RIGHTBUTTON、point.x、point.y、AfxGetMainWnd(&))

今、最小機能のインプレース アクティブ化を有効に、OLE サーバーがあります。まだ多くの機能が動作で利用されていない MFC および OLE 2 で利用可能です。HIERSVR サンプルより多くのアイデアを実装するとして可能性があります機能を参照してください。HIERSVR を実装する機能のいくつか次のとおりです。:

MFC 3.0 の HIERSVR サンプルもはサーバー アイテムの異なるデザインを使用します。これはメモリを節約し、あなたのリンクをより柔軟になります。バージョン 2.0 の HIERSVR では、ツリー内の各ノードは、COleServerItemCOleServerItemは厳密にこれらのノードごとに必要なよりも多少のオーバーヘッドいますが、機能のアクティブなリンクが必要です。しかし、ほとんどの部分については、いつでも非常にほとんどのアクティブなリンクがありません。これをより効率的にするには、このバージョンの MFC で HIERSVR ノードCOleServerItemから分離します。それは、CServerNode とCServerItemクラスの両方があります。( COleServerItemの派生) CServerItemのみ、必要に応じて作成されます。その特定のリンクにはその特定のノードを使用して、コンテナー (コンテナー) を停止すると、CServerNode と関連付けられている、CServerItem オブジェクトが削除されます。このデザインより効率的かつ柔軟です。その柔軟性と複数選択リンクを扱うときになります。HIERSVR の 2 つのバージョンのどちらも複数の選択をサポートしますが、より簡単に追加するには (とそのような選択へのリンクをサポートする) ことが MFC 3.0 バージョンCOleServerItemはネイティブのデータから分離されて以来の HIERSVR の 。

番号順テクニカル ノート|nbsp;カテゴリ別テクニカル ノート(&N)

Index