2017-12-04 73 views
1

ドキュメントをユーザーに表示しているWindowsアプリケーションを作成しています。コンテンツはGDI関数を使用してペイントされ、すべてが画面に表示されます。Windows - GDI - ドロー機能を変更せずに、スクリーンDCをプリンタDCにスケーリングする

この文書を印刷します。私はプリンタのデバイスのコンテキストを取得し、私は画面上と同じように描いています。もちろん、印刷されたコンテンツは、印刷されたページの上部に小さいように見えます。この動作の理由は、私にとって明確で、かつ完全にここで説明されています

https://www.codeproject.com/Articles/764057/GDI-Drawing-and-Printing

だから、私は、プリンタDCにスケールされたビューポートを追加する必要があり、GDIでそれを達成するには、いくつかの機能があります。しかし、私はこれらの機能をどのように設定するかについて少し困惑しています。私はインターネット上で見つかったさまざまな例を試しましたが、どれも私のために働いていませんでした。

私の画面解像度は1920x1080ピクセルで、私はA4のポートレートページに印刷しようとしています。私は、さまざまな構成をテストし、私は私の印刷ページに収まるようにする最良の近似は次のようであることがわかった。もちろん、他のPC上の変更、私はどのように知っている必要があり、画面や印刷設定など

::SetMapMode(hDC, MM_ISOTROPIC); 
::SetWindowExtEx(hDC, 1, 1, NULL); 
::SetViewportExtEx(hDC, 5, 5, NULL); 
::SetViewportOrgEx(hDC, -10200, 0, NULL); 

上記の値が計算されることがありますが、私の場合には動作する数式を見つけることができません。特に私はSetViewportOrgEx()関数を使用してキャンバスの原点を拡大する必要があるのか​​どうかわかりません。

だから何がいることを考えると、私のプリントDCのビューポートを計算するための正しい方法です:まったく同じ絵の機能は、画面とプリンタの描画の両方に使用される、と私は別の関数を作成することはありません

  • 画面およびプリンタ
  • に印刷画面とプリンタデバイスが完全にユーザによって構成されてもよいが、印刷された結果は常に画面及びプリンタ

加算の両方に原稿に合わせなければなりませんこの問題を解決するには、メタファイルを使用する方が良いでしょうか?

+1

普遍的な方法は、例えば、入力パラメータからXFORMのcalculatetを送達する独自の機能を使用して、SetWorldTransformを使用することであろうxoffs、xoffs、scale、直感的な操作のための回転 – bummi

+0

可能です。ただし、MSDNのドキュメントでは、グラフィックモードをGM_ADVANCEDに設定してその設定を行う必要があります。このモードは一般にすべてのプリンタコンテキストと互換性がありますか? –

+1

すべてのプリンタでサポートされているわけではありませんが、私はそれがどれほど共通しているか分かりませんし、情報も見つけられませんでした。ターゲット環境が異なる可能性があるので、自分自身で問題があってはいけません。 – bummi

答えて

1

画面の座標を紙の座標にマップするには、用紙の幅と長さが必要です。この情報はGetDeviceCaps(hdc, PHYSICALWIDTH)GetDeviceCaps(hdc, PHYSICALHEIGHT)にあります。hdcはプリンタのデバイスコンテキストです。画面の座標はすでにどこかにあります。

プリンタは用紙の端に印刷できません。その情報はPHYSICALOFFSETXPHYSICALOFFSETYから得ることができます。

以下の例では、すべてのペイントを行う共通機能paintを使用しています。 printは絵を描かないので、代わりにpaintを呼び出します。

これは、画面座標でrc.leftrc.right(0,0)であることを前提としています。

void paint(HDC hdc, RECT rc) 
{ 
    HBRUSH brush = GetSysColorBrush(COLOR_WINDOWTEXT); 
    InflateRect(&rc, -10, -10); 
    FrameRect(hdc, &rc, brush); 
    DrawText(hdc, L"hello world", -1, &rc, 0); 
} 

void print(HWND hWnd, RECT rc) 
{ 
    PRINTDLG pd = { sizeof(pd) }; 
    pd.hwndOwner = hWnd; 
    pd.Flags = PD_RETURNDC; 
    if(!PrintDlg(&pd)) 
     return; 

    HDC hdc = pd.hDC; 
    DOCINFO doc = { sizeof(doc) }; 
    StartDoc(hdc, &doc); 
    StartPage(hdc); 
    SetMapMode(hdc, MM_ISOTROPIC); 
    SetWindowExtEx(hdc, rc.right, rc.bottom, NULL); 
    SetViewportExtEx(hdc, 
     GetDeviceCaps(hdc, PHYSICALWIDTH), GetDeviceCaps(hdc, PHYSICALHEIGHT), NULL); 
    SetViewportOrgEx(hdc, 
     -GetDeviceCaps(hdc, PHYSICALOFFSETX), -GetDeviceCaps(hdc, PHYSICALOFFSETY), NULL); 

    paint(hdc, rc); 

    EndPage(hdc); 
    EndDoc(hdc); 
    DeleteObject(hdc); 
} 

テスト:

case WM_PAINT: 
{ 
    PAINTSTRUCT ps; 
    HDC hdc = BeginPaint(hwnd, &ps); 
    RECT rc; 
    GetClientRect(hwnd, &rc); 
    paint(hdc, rc); 
    EndPaint(hwnd, &ps); 
    break; 
} 

case WM_LBUTTONDOWN: 
{ 
    RECT rc; 
    GetClientRect(hwnd, &rc); 
    print(hwnd, rc); 
    break; 
} 
+0

私は間違いを理解しました。最初に、図面の計算に間違ったサイズを使用しました.2番目は、私のドローでクリッピングも使用しました。明らかに、GDIクリッピング関数は、ビューポート関数やプリンタDCではうまく機能しません。しかし、少なくともそれらを除去し、上記の解決策を適用することで、私が期待した最終結果に非常に近い最終的な結果が得られました。答えてくれてありがとう。 –