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 - 最終更新日: 2016/09/29 - リビジョン: 1

フィードバック