[kaze's test] プログラミングメモ →目次

データをプリンタに印刷する(VC++)

ダイアログバースなどアプリケーションで、自分でプリンタに印刷する処理を実装しなければなりません。このメモは、APIを呼び出して、①デフォルトプリンタに印刷すると、②プリンタ選択画面を出してから印刷する手順を記述します。③MFCのCPrintDialogで印刷する方法もを記述します。



1.テストする為に、簡単な印刷ジョブを実装します。用紙の上に長方形と文字列のPrinter Testing.を描画します。

void CPrinterTestDlg::DoPrinting(CDC* pDC)
{
    DOCINFO docinfo;
    memset(&docinfo, 0, sizeof(DOCINFO));
    docinfo.cbSize = sizeof(DOCINFO);
    docinfo.lpszDocName = _T("Printer Testing.");

    pDC->StartDoc(&docinfo);
    pDC->StartPage();

    DWORD dwScrWidth  = pDC->GetDeviceCaps(HORZRES);
    DWORD dwScrHeight = pDC->GetDeviceCaps(VERTRES);
    CRect r(0, 0, dwScrWidth-1, dwScrHeight-1);
    r.DeflateRect(1, 1);
    pDC->Rectangle(&r);
    CString strText(_T("Printer Testing."));
    pDC->DrawText(strText, &r, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
    pDC->EndPage();
    pDC->EndDoc();
}

2.APIで、用紙は横向き、B5サイズとして、デフォルトプリンタに印刷します。

#include "winspool.h"

void CPrinterTestDlg::PrintFromDefaultPrinter()
{
	TCHAR PrinterName[400];
	DWORD dwBufferSize = 400;
	BOOL bRet = GetDefaultPrinter(PrinterName, &dwBufferSize);
	if (!bRet)
		return;
	LPDEVMODE pDevMode = GetDevMode_LandscapeB5(PrinterName);
	CDC dcPrint;
	bRet = dcPrint.CreateDC(NULL, PrinterName, NULL, pDevMode);
	if (!bRet)
		return;
	DoPrinting(&dcPrint);
	dcPrint.DeleteDC();
}
LPDEVMODE CPrinterTestDlg::GetDevMode_LandscapeB5(LPTSTR pPrinterName)
{
	HANDLE      hPrinter;
	LPDEVMODE   pDevMode = NULL;
	DWORD       dwNeeded;
	DWORD dwRet;

	if (!OpenPrinter(pPrinterName, &hPrinter, NULL))
		return NULL;

	dwNeeded = DocumentProperties(m_hWnd,
				hPrinter,       /* handle to our printer */ 
				pPrinterName,   /* Name of the printer */ 
				NULL,           /* Asking for size so */ 
				NULL,           /* these are not used. */ 
				0);             /* Zero returns buffer size. */ 
	pDevMode = (LPDEVMODE)malloc(dwNeeded);

	dwRet = DocumentProperties(m_hWnd,
				hPrinter,
				pPrinterName,
				pDevMode,       /* The address of the buffer to fill. */ 
				NULL,           /* Not using the input buffer. */ 
				DM_OUT_BUFFER); /* Have the output buffer filled. */ 

	if (dwRet != IDOK)
	{
		free(pDevMode);
		ClosePrinter(hPrinter);
		return NULL;
	}

	if (pDevMode->dmFields & DM_ORIENTATION)
	{
		/* 用紙は横向き */ 
		pDevMode->dmOrientation = DMORIENT_LANDSCAPE;
	}

	if (pDevMode->dmFields & DM_PAPERSIZE)
	{
		/* 用紙サイズ = B5*/ 
		pDevMode->dmPaperSize = DMPAPER_B5;
	}

	dwRet = DocumentProperties(m_hWnd,
				hPrinter,
				pPrinterName,
				pDevMode,       /* Reuse our buffer for output. */ 
				pDevMode,       /* Pass the driver our changes. */ 
				DM_IN_BUFFER |  /* Commands to Merge our changes and */ 
				DM_OUT_BUFFER); /* write the result. */ 

	ClosePrinter(hPrinter);

	if (dwRet != IDOK)
	{
		free(pDevMode);
		return NULL;
	}
	return pDevMode;
}

3.APIでプリンタ選択画面を出してから印刷します。

BOOL CPrinterTestDlg::PrintFromDialogBox()
{
	PRINTDLG pd;
	// Initialize PRINTDLG
	ZeroMemory(&pd, sizeof(pd));
	pd.lStructSize = sizeof(pd);
	pd.hwndOwner   = m_hWnd;
	pd.hDevMode    = NULL;     // Don't forget to free or store hDevMode
	pd.hDevNames   = NULL;     // Don't forget to free or store hDevNames
	pd.Flags       = PD_USEDEVMODECOPIESANDCOLLATE | PD_RETURNDC; 
	pd.nCopies     = 1;
	pd.nFromPage   = 0xFFFF; 
	pd.nToPage     = 0xFFFF; 
	pd.nMinPage    = 1; 
	pd.nMaxPage    = 0xFFFF; 

	if (PrintDlg(&pd)==TRUE) 
	{
		CDC dcPrint;
		dcPrint.Attach(pd.hDC);
		DoPrinting(&dcPrint);
		dcPrint.Detach();
		DeleteDC(pd.hDC);
		GlobalFree(pd.hDevMode);
		GlobalFree(pd.hDevNames);
		return TRUE;
	}
	return FALSE;
}

4.MFCのCPrintDialogで印刷します。

void Test(BOOL bDispDialog)
{
	CPrintDialog dlg(FALSE);
	if (!bDispDialog)          //デフォルトプリンタに印刷します。
	{
		dlg.GetDefaults();
		CDC dc;
		dc.Attach(dlg.CreatePrinterDC());
		DoPrinting(&dcPrint);
		dc.Detach();
	}
	else
	if (dlg.DoModal() == IDOK) //プリンタ選択画面を出してから印刷します。
	{
		CDC dc;
		dc.Attach(dlg.CreatePrinterDC());
		DoPrinting(&dcPrint);
		dc.Detach();
	}
}