Windows 7 上の CScrollView を使用した MFC アプリケーションで OLE アイコンの表示が上下反転します

現象
Windows 7 上で動作する MFC アプリケーションについて、以下のシナリオを考えます。
  • アプリケーションにて CScrollView の継承クラスを OLE コンテナとして使用します
  • コンテナで CScrollView::SetScaleToFitSize() を呼び出してビューサイズ の自動調整を行います
  • コンテナから COleInsertDialog クラスを使用して OLE の [オブジェクトの挿入] ダイアログを表示し、ファイルを参照指定して OLE オブジェクトを挿入します

上記シナリオでは、ファイル種別に依存して、コンテナ上で以下の現象が発生する場合があります。
  • アイコンの画像表示が上下反転します
  • アイコンのタイトル (ファイル名) が表示されません



原因
アイコンの描画処理は OS 付属のコンポーネントによって行われ、描画処理ではマップモードや描画対象のアイコンによって、内部で行われる処理はそれぞれ異なります。
これらの描画処理において、以下の双方の条件が満たされる場合は OS のコンポーネントによって Y 軸を反転させる処理が行われます。

  • テキスト ファイル (*.txt) のアイコン等、アイコン固有の処理が実装されていない場合
  • コンテナのマップモードが MM_ANISOTROPIC に設定されている場合

      (CScrollView::SetScaleToFitSize() を呼び出した場合、CScrollView の描画領域のデバイス コンテキスト (DC) に対しては、MM_ANISOTROPIC が指定されます)
上記反転処理は Windows Vista 以降の OS にて導入された OS の実装変更に起因しており、弊社製品の不具合となります。
MFC を使用しない場合でも、OLE コンテナの DC のマップ モードとして MM_ANISOTROPIC を指定した場合には、同様の現象が発生する可能性があります。

なお、Windows Vista 以降でのアイコン表示に関わる変更点として、[オブジェクトの挿入] ダイアログから「アイコンで表示」チェックボックスを有効にした場合、「アイコンの変更」で設定をした内容が反映されないという問題がございますが、こちらは本不具合とは無関係に発生する OS の制限動作となります。


回避策
コンテナクラスでは、CScrollView::SetScaleToFitSize() を呼び出さずに、CScrollView::OnPrepareDC() をオーバーライドして別途サイズの自動調整処理を実装します。
以下に基本的な例を示します。

1. 通常、CScrollView::OnInitialUpdate() にて呼び出されている SetScaleToFitSize() 呼び出しを行わないように実装を削除します。
2. CScrollView::OnPrepareDC() をオーバーライドするため、ヘッダファイルに定義を行います

 MyScrollView.h
class CMyScrollView : public CScrollView { ..... virtual void OnPrepareDC(CDC * pDC, CPrintInfo* pInfo);
3. CScrollView::OnPrepareDC() をオーバーライドして、MM_ISOTROPIC モードを指定しサイズ調整を行います。

  CMyScrollView.cpp
// MM_ISOTROPIC モードを設定する場合、デバイスコンテキストのウィンドウ範囲を SetWindowExt() 関数で指定し、次に SetViewportExt() 関数にてビューポートのウィンドウ範囲を指定します// 以下では SetWindowExt() 関数では、起動直後のウィンドウサイズを利用して設定を行っています。 bool g_bFirstCall = true;CRect g_baseRect; void CMyScrollView::OnPrepareDC(CDC * pDC, CPrintInfo* pInfo) { CRect rect; GetClientRect (&rect); pDC->SetMapMode(MM_ISOTROPIC); if(g_bFirstCall) { g_baseRect = rect; g_bFirstCall = false; } CSize ptOldWinExt = pDC->SetWindowExt(g_baseRect.Width(), g_baseRect.Height()); CSize ptOldViewportExt = pDC->SetViewportExt(rect.Width(), rect.Height()); }
状況
JA_Confbug3
注意 : これは、マイクロソフトのサポート組織内で直接作成された "緊急公開" の資料です。 この資料には、確認中の問題に関する現状ベースの情報が記載されています。 情報提供のスピードを優先するため、資料には誤植が含まれる可能性があり、予告なしに随時改定される場合があります。 その他の考慮事項については、使用条件を参照してください。
プロパティ

文書番号:2918843 - 最終更新日: 09/29/2016 15:34:00 - リビジョン: 3.0

Microsoft Visual Studio 2010 Premium with MSDN, Microsoft Visual Studio 2010 Professional, Microsoft Visual Studio 2010 Ultimate, Microsoft Visual Studio 2013 Preview

  • KB2918843
フィードバック