none
Enhanced Metafile (EMF) の描画について

    Question

  • WMFの描画では、次のコードは正常に描画されて、サイズもあります。

    	CMetaFileDC aEmfDC;
    
    	if ( !(aEmfDC.Create(_T("c:\\temp\\test.wmf") )))
    	    return;
    
    	CClientDC tmpdc(NULL);
    	aEmfDC.SetAttribDC(tmpdc.m_hAttribDC);
    
    	CRect rc2;
    	aEmfDC.GetClipBox(&rc2);
    
    	aEmfDC.SetMapMode( MM_ANISOTROPIC );
    	CSize size(2808, 1740);
    	aEmfDC.SetWindowExt( size );
    	CSize size2(2304, 1024);
    	aEmfDC.SetViewportExt(size2);
    	aEmfDC.SetViewportOrg( 0, 0 );
    
    	aEmfDC.MoveTo(0,0);
    	aEmfDC.LineTo(100,100);
    	
    	HMETAFILE hEmf = aEmfDC.Close();
    	::DeleteMetaFile(hEmf);

    次のEMF描画では、サイズが「0」となり、描画もされていません。

    何が原因になるのでしょうか。違いは、WMFのデバイスコンテキストかEMFデバイスコンテキストの違いだけだなのですが。。。

    MM_TEXTのままなら描画されます。

    	CMetaFileDC aEmfDC;
    
    	CClientDC tmpdc(NULL);
    	if ( !(aEmfDC.CreateEnhanced(&tmpdc, _T("c:\\temp\\test.emf"), NULL, NULL)) )
    	    return;
    
    
    	aEmfDC.SetAttribDC(tmpdc.m_hAttribDC);
    
    	aEmfDC.SetMapMode( MM_ANISOTROPIC );
    	CSize size(2808, 1740);
    	aEmfDC.SetWindowExt( size );
    	CSize size2(2304, 1024);
    	aEmfDC.SetViewportExt(size2);
    	aEmfDC.SetViewportOrg( 0, 0 );
    
    	aEmfDC.MoveTo(0,0);
    	aEmfDC.LineTo(100,100);
    
    	HENHMETAFILE hEmf =	aEmfDC.CloseEnhanced();
    	::DeleteEnhMetaFile(hEmf);

    vendredi 21 juillet 2017 03:42

Toutes les réponses

  • 1.CreateEnhanced();の第3引数に正しい矩形を設定してみてはどうでしょう。
    2.このマップモードと原点設定だと、ディスプレイ用DCでは何も表示されないかもしれません。
      それが原因である疑いもあります。

    vendredi 21 juillet 2017 03:51
  • 第3の引数は設定してみましたが、サイズはありましたが、描画がされていませんでした。

    	aEmfDC.MoveTo(0,0);
    	aEmfDC.LineTo(10000,10000);
    

    の描画結果は、1ミリくらいの線が描画されていました。

    vendredi 21 juillet 2017 04:03
  • 編集で前後してしまったかもしれませんので、確認です。
    まず、マップモードが任意スケーリングなので、
    最初はSetWindowExt()とSetViewportExt()の拡大比率を1:1にして、
    普通に表示できることを確認した方が良いかもしれません。
    その後、スケールをやりたい値に設定してみてはどうでしょう。

    vendredi 21 juillet 2017 04:12
  • >>最初はSetWindowExt()とSetViewportExt()の拡大比率を1:1にして、
    >>普通に表示できることを確認した方が良いかもしれません。

    これは、おこなっていまして、だたしく描画されていました。

    また、下記のように変更したとこ、正しく1/2に縮小描画され問題ありませんでした。

    	aEmfDC.SetWindowExt( 2,2);
    	aEmfDC.SetViewportExt(1, 1);

    WMFとEMFの結果が異なることが気になります。

    ※VC++2010で開発しております。


    • Modifié Brillia vendredi 21 juillet 2017 04:26
    vendredi 21 juillet 2017 04:24
  • 以前のスレッドでも発言しましたが、WMFではDCに対する初期化的動作の関数の一部が記録されません。
    従って、個人的にはWMFとEMFでは結果が異なるのは自然であると考えています。

    描画関数 MyDraw( CDC *dc)等で初期設定と描画を行い、
    引数のdcに、WMFのDC、EMFのDC、クライアントDCのそれぞれを与えて、
    違いを見てみるのが良いかもしれません。

    DCの初期設定の状態の保管呼び出しに関しては、
    SaveDC()、RestoreDC()が利用できるかもしれません。
    ただし、メタファイルDCで動作するのかは、未検証です。あしからず。

    vendredi 21 juillet 2017 04:42
  • 分かったことは、EMFの場合、下記の関数(SetViewportExt)の引数が、1であろうが、1000000であろうが、「1」で計算されているようです。

    aEmfDC.MoveTo(0,0);
    aEmfDC.LineTo(100,100);
    

    の直線を描画してみましたが、

    aEmfDC.SetWindowExt( 2,2);
    aEmfDC.SetViewportExt(1, 1);

    aEmfDC.SetWindowExt( 2,2);
    aEmfDC.SetViewportExt(100000, 100000);

    は、どちらも50,50の直線でした。


    • Modifié Brillia vendredi 21 juillet 2017 06:20
    vendredi 21 juillet 2017 05:50
  • 今回分かったこと。

    拡張メタファイルを作成するのに、aEmfDC.SetAttribDC(tmpdc.m_hAttribDC);が必要ないこと。aEmfDC.SetAttribDC(tmpdc.m_hAttribDC);をしない場合、クリッピング領域は「0」だが、描画は可能。

    しかし、これを設定しないと、実行時にGetClipBox関数などで、実行時エラー(ASSERT)が発生するのだが、
    これは、Debugモードでコンパイルした時に起こる現象で、Releaseモードでは、実行時エラーは発生しない。

    拡張メタファイルのMM_ANISOTROPICについてだが、aEmfDC.SetAttribDC(tmpdc.m_hAttribDC);をした後の、
    aEmfDC.SetViewportExt関数は意味が無いということ。

    aEmfDC.SetAttribDC(tmpdc.m_hAttribDC);をする前に、SetWindowExt、SetViewportExtで拡大率を設定する。

    クリッピング領域が必要な場合は、aEmfDC.SetAttribDC(tmpdc.m_hAttribDC);で設定する。

    が、今回分かった内容でした。

    mardi 25 juillet 2017 06:31