Skip to content

Send To Printer

A C program that shows the standard print dialog and sends a line of text to the chosen printer using GDI.

Published Mar 22, 2000

The complete classic printing sequence in one small program. PrintDlg with PD_RETURNDC pops up the standard printer chooser and hands back a device context for the selected printer; then the four-call document lifecycle - StartDoc, StartPage, draw (here just TextOut), EndPage, EndDoc - sends the job. Every stage is checked and reported, which makes this a clean template for adding basic print support to any GDI application.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>

int main()
{
	PRINTDLG	pd;
	DOCINFO 	di;
	char*		szMessage;

	memset (&pd, 0, sizeof(PRINTDLG));
	memset (&di, 0, sizeof(DOCINFO));

	di.cbSize = sizeof(DOCINFO);
	di.lpszDocName = "Test";

	pd.lStructSize = sizeof(PRINTDLG);
	pd.Flags = PD_PAGENUMS | PD_RETURNDC;
	pd.nFromPage = 1;
	pd.nToPage = 1;
	pd.nMinPage = 1;
	pd.nMaxPage = 1;

	szMessage = 0;

	if (PrintDlg (&pd))
	{
		if (pd.hDC)
		{
			if (StartDoc (pd.hDC, &di) != SP_ERROR)
			{
				StartPage (pd.hDC);

				TextOut (pd.hDC, 0, 0, "Hello, printer!", 15);

				EndPage (pd.hDC);

				EndDoc (pd.hDC);

				szMessage = "Printed.";
			}
			else
			{
				szMessage = "Could not start document.";
			}
		}
		else
		{
			szMessage = "Could not create device context.";
		}
	}
	else
	{
		szMessage = "Canceled or printer could not be setup.";
	}

	if (szMessage)
	{
		MessageBox (NULL, szMessage, "Print Test", MB_OK);
	}

	return 0;
}

Notes: coordinates are in printer units (twips by default - 1/1440 inch), so (0,0) is the top-left corner of the page within the printable area; for multi-page output wrap the StartPage/draw/EndPage calls in a loop and set the page range flags accordingly. On modern systems XPSDocumentPrinter or the spooler's document API are alternatives, but this GDI path still works everywhere.

An unhandled error has occurred. Reload 🗙