打印时调整CreatePatternBrush的位图大小

时间:2018-03-13 17:44:04

标签: winapi printing device-context hdc

我正在尝试打印我在屏幕上看到的画笔图案,但根据打印机DC,我会得到不同的结果。我使用Microsoft PDF或打印机。两者都使用600 DPI进行打印。当我通过调整CreatePatternBrush使用的位图大小来打印时,我试图获得相同的模式。这似乎适用于Microsoft PDF,但不适用于打印机。使用打印机的图案太大了。有什么线索的原因?

OnBnClickedButtonprint是我尝试打印在模式位图上完成ScaleBitmap的地方。这是代码:

#include "stdafx.h"
#include "Printing.h"
#include "PrintingDlg.h"
#include "afxdialogex.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

RECT rcSmall    = { 25, 25, 75, 75 };
RECT rcBig      = { 55, 55, 255, 255 };
RECT rcWholeArea = { 0, 0, 300, 300 };

COLORREF crRed      = RGB(255, 0, 0);
COLORREF crGreen    = RGB(0, 255, 0);
COLORREF crBlue     = RGB(0, 0, 255);
COLORREF crWhite    = RGB(255, 255, 255);
COLORREF crBlack    = RGB(0, 0, 0);

CPrintingDlg::CPrintingDlg(CWnd* pParent /*=NULL*/)
    : CDialogEx(IDD_PRINTING_DIALOG, pParent)
{
    WORD HatchBits[8] = { 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe };
    m_hBitmap = ::CreateBitmap(8, 8, 1, 1, HatchBits);
}

void CPrintingDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CPrintingDlg, CDialogEx)
    ON_WM_PAINT()
    ON_WM_QUERYDRAGICON()
    ON_BN_CLICKED(IDC_BUTTONPRINT, &CPrintingDlg::OnBnClickedButtonprint)
END_MESSAGE_MAP()


// CPrintingDlg message handlers

BOOL CPrintingDlg::OnInitDialog()
{
    CDialogEx::OnInitDialog();

    return TRUE;  // return TRUE  unless you set the focus to a control
}

HBITMAP CPrintingDlg::ScaleBitmap(HDC hdc, HBITMAP hBitmapSrc)
{
    double gDPIScaleX = GetDeviceCaps(hdc, LOGPIXELSX) / 96.0f;
    double gDPIScaleY = GetDeviceCaps(hdc, LOGPIXELSY) / 96.0f;

    if (gDPIScaleX == 1.0 && gDPIScaleY == 1.0)
        return hBitmapSrc;

    // Get logical coordinates
    BITMAP bm;
    ::GetObject(hBitmapSrc, sizeof(bm), &bm);

    int iWidth = (int)(bm.bmWidth * gDPIScaleX);
    int iHeight = (int)(bm.bmHeight * gDPIScaleY);

    // Select the source DC
    HDC hdcSrc = ::CreateCompatibleDC(hdc);
    HBITMAP hBitmapOldSrc = (HBITMAP)::SelectObject(hdcSrc, hBitmapSrc);

    // Create the bitmap and select the destination DC
    HDC hdcDst = ::CreateCompatibleDC(hdc);
    HBITMAP hBitmapDst = ::CreateCompatibleBitmap(hdcDst, iWidth, iHeight);
    HBITMAP hBitmapOldDst = (HBITMAP)::SelectObject(hdcDst, hBitmapDst);

    // Resize
    ::StretchBlt(hdcDst, 0, 0, iWidth, iHeight, hdcSrc, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);

    // Reselect the old bitmaps
    ::SelectObject(hdcSrc, hBitmapOldSrc);
    ::SelectObject(hdcDst, hBitmapOldDst);

    // Delete the resources
    DeleteDC(hdcSrc);
    DeleteDC(hdcDst);

    return hBitmapDst;
}

RECT CPrintingDlg::ScaleRect(HDC hdc, RECT rcOriginal)
{
    double gDPIScaleX = GetDeviceCaps(hdc, LOGPIXELSX) / 96.0f;
    double gDPIScaleY = GetDeviceCaps(hdc, LOGPIXELSY) / 96.0f;

    if (gDPIScaleX == 1.0 && gDPIScaleY == 1.0)
        return rcOriginal;

    RECT rcScaled;

    rcScaled.left = (long)(rcOriginal.left * gDPIScaleX);
    rcScaled.right = (long)(rcOriginal.right * gDPIScaleX);
    rcScaled.top = (long)(rcOriginal.top * gDPIScaleY);
    rcScaled.bottom = (long)(rcOriginal.bottom * gDPIScaleY);

    return rcScaled;
}

void CPrintingDlg::DrawRectangle(HDC hdc, RECT rect, COLORREF cr)
{
    HPEN hPen = ::CreatePen(PS_SOLID, 1, cr);
    ::SelectObject(hdc, hPen);

    HBRUSH hBrush = ::CreateSolidBrush(cr);
    ::SelectObject(hdc, hBrush);

    ::Rectangle(hdc, rect.left, rect.top, rect.right, rect.bottom);
}

void CPrintingDlg::DrawPatternRectangle(HDC hdc, HBITMAP hBitmap, RECT rect, COLORREF cr)
{
    int oldROP2 = 0;

    HPEN hPen = ::CreatePen(PS_SOLID, 1, crBlack);
    ::SelectObject(hdc, hPen);

    HBRUSH hPatternBrush = ::CreatePatternBrush(hBitmap);
    ::SelectObject(hdc, hPatternBrush);

    ::SetTextColor(hdc, crBlack);
    if (::GetROP2(hdc) == R2_COPYPEN)
    {
        ::SetBkColor(hdc, crWhite);
        oldROP2 = ::SetROP2(hdc, R2_MASKNOTPEN);
        ::Rectangle(hdc, rect.left, rect.top, rect.right, rect.bottom);

        ::SetBkColor(hdc, cr);
        ::SetROP2(hdc, R2_MERGEPEN);
        ::Rectangle(hdc, rect.left, rect.top, rect.right, rect.bottom);

        ::SetROP2(hdc, oldROP2);
    }
    else
    {
        ::SetBkColor(hdc, cr);
        ::Rectangle(hdc, rect.left, rect.top, rect.right, rect.bottom);
    }
}

void CPrintingDlg::OnPaint()
{
    CPaintDC hdc(this);

    DrawRectangle(hdc, rcWholeArea, crWhite);
    DrawRectangle(hdc, rcSmall, crGreen);
    DrawPatternRectangle(hdc, m_hBitmap, rcBig, crRed);
}

void CPrintingDlg::OnBnClickedButtonprint()
{
    CPrintDialog dlgPrint(FALSE, PD_NOSELECTION);
    dlgPrint.GetDefaults();
    dlgPrint.m_pd.Flags &= ~PD_RETURNDEFAULT;

    DEVMODE* dm = (DEVMODE*)GlobalLock(dlgPrint.m_pd.hDevMode);
    dm->dmFields |= DM_ORIENTATION;
    dm->dmOrientation = DMORIENT_LANDSCAPE;
    GlobalUnlock(dlgPrint.m_pd.hDevMode);

    dlgPrint.DoModal();
    HDC hdc = dlgPrint.GetPrinterDC();

    DOCINFO docInfo;
    ZeroMemory(&docInfo, sizeof(docInfo));
    docInfo.cbSize = sizeof(docInfo);
    docInfo.lpszDocName = _T("PrintTest");

    StartDoc(hdc, &docInfo);
    StartPage(hdc);

    DrawRectangle(hdc, ScaleRect(hdc, rcWholeArea), crWhite);
    DrawRectangle(hdc, ScaleRect(hdc, rcSmall), crGreen);
    DrawPatternRectangle(hdc, ScaleBitmap(hdc, m_hBitmap), ScaleRect(hdc, rcBig), crRed);

    EndPage(hdc);
    EndDoc(hdc);

    DeleteDC(hdc);
}

以下是我试图打印的内容:

enter image description here

0 个答案:

没有答案