gdi +

2016-05-25 7 views
0

を使用してEMFの図面を正しくスケールする方法Windows C++プログラムは、クリップボード、単語、およびExcelにエクスポートするEMF(拡張メタファイル形式)を作成します。gdi +

以下のコード例は、キャンバスが25×25(:私のラップトップis3600x1800の画面解像度注)である間のみ12×12であるEMF矩形(幅=高さ= 25)を生成します。 他の画面解像度では、同様のスケーリングの異常が発生します(大きすぎる/小さすぎます)。 解像度の関数としてグラフィックス図面のスケーリングを設定する必要があります。 私の知るところには明らかにギャップがあります。助けていただければ幸いです。あなたの実際の問題とは関係のないものの

HDC ref_dc = GetDC(NULL); 
Rect r(0, 0, 25, 25); 
Metafile* emf = new Metafile(ref_dc, r, MetafileFrameUnitPixel, EmfTypeEmfPlusDual, L"Drawing");//to HDC 
Graphics* g = new Graphics(emf); 

//draw a simple box 
Gdiplus::Pen* pen = new Pen(Color(0, 255, 0), 1.0f); 
pen->SetDashStyle(DashStyleSolid); 
pen->SetLineCap(LineCapRound, LineCapRound, DashCapFlat); 
g->DrawRectangle(pen, r); // DrawMyObject(g); 

// code here to put on clipboard 
+0

EMFは、Eclipse Modeling Frameworkに割り当てられているため、間違ったタグであるようです。 –

答えて

0

、私は、ヒープ上のすべてのオブジェクトを作成するあなたのプログラミングスタイルは非常に奇妙であることを指摘するのは非常に強要さを感じます。このようにnewを使用する理由はありません。スタック上に一時オブジェクトを作成するだけです。これは、あなたが篩のようなメモリや他のリソースを漏らさないようにします。例として、必要なのは次のとおりです。

// Create Graphics object 
Graphics g(emf); 

// Draw a simple box 
Gdiplus::Pen pen(Color(0, 255, 0), 1.0f); 
pen.SetDashStyle(DashStyleSolid); 
pen.SetLineCap(LineCapRound, LineCapRound, DashCapFlat); 
g.DrawRectangle(pen, r); 

// g and pen automatically go out of scope here, implicitly calling the destructor 
// and freeing their resources. No need to call delete. 

実際の質問については、メタファイルは固定サイズではありません。基本的には、GDIの描画命令のシリーズをカプセル化して、自由に組み直すことができます。

拡張メタファイルをクリップボードに挿入する通常の方法は、CF_ENHMETAFILE形式を使用してSetClipboardData関数を呼び出すことです。ハンドルタイプは明らかにHENHMETAFILEになります。おそらく、Metafile::GetHENHMETAFILE methodを使用して、メタファイルオブジェクトの読み込み/作成を完了した後で、GDI +を入手する必要があります。

スケーリング/サイジングは、クリップボードからメタファイルを受け取り、表示しようとするクライアントコードの責任です。メタファイルヘッダーには、水平および垂直の解像度を指定するエントリが含まれています。それはディスプレイDPIの観点からスケーリングすることができます。

Graphics g(...); 

Metafile mf(L"MyFile.emf"); 
MetafileHeader mfh; 
mf->GetMetafileHeader(&mfh); 

REAL xScale = mfh->GetDpiX()/g.GetDpiX(); 
REAL yScale = mfh->GetDpiY()/g.GetDpiY(); 

g.ScaleTransform(xScale, yScale); 
0

自己回答:GDI +のようなものでは

  1. ザ・グラフィックスは、 '新しい' それがEMF前 を破壊しなければならないので、 '書かれた' されて作成されます。そうでなければ、emfはGraphicsオブジェクトによって実行されるステップを「記録」しません。おそらく、追加の中括弧を置くべきですが、それは同じように扱いにくいでしょう。ドキュメンテーションによると: "グラフィックスオブジェクトが削除されたり、範囲外になったときに記録が終了します。"したがって、明示的な新しい(s)と削除(s)。 EMFはグラフィックスの破棄後クリップボードにプッシュされ、EMFが破棄される前にプッシュされます。

  2. * Rect構造体を引数とするEMFのコンストラクタを使用すると、間違いや問題が発生しているように見えます。 Rectディメンションは、描画に使用されるグラフのオブジェクト座標と識別可能な関係がないように見えます。したがって、予測される方法でEMFをトリミングします。 HDCまたはHDCとファイル名だけのコンストラクタを使用すると、少なくとも私の手でこの問題が解決されます。

  3. 最後に、コード行

    を追加

    REAL xScaleは= mfh-> GetDpiX()/ g.GetDpiX(); REAL yScale = mfh-> GetDpiY()/ g.GetDpiY(); g。 g。ScaleTransform(xScale、yScale);

は、emfsが画面の解像度にかかわらずほぼ同じサイズになるようにベーススケーリングを提供します。これは、ユーザー側の輸出に一貫性のある妥当なデフォルトサイズを与えるのに非常に便利です。