> For the complete documentation index, see [llms.txt](https://docs.apryse.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.apryse.com/core/get-started/samples/pdfdctest.md).

# PDF Device Context - PDFDC

Sample C#, C++, VB code for using Apryse SDK to create and use PDFDC (i.e. a PDF Device Context). Windows developers can use standard GDI or GDI+ API-s to write on PDFDC and to generate PDF documents

Sample C#, C++, and VB code for using Apryse SDK to create and use PDFDC (i.e. a PDF Device Context). Windows developers can use standard GDI or GDI+ API-s to write on PDFDC and to generate PDF documents based on their existing drawing functions. PDFDC can also be used to implement file conversion from any printable file format to PDF.

Learn more about our [Server SDK for Windows](/core/get-started/platforms/windows.md) and [Windows PDF Library](/core/conversion/conversion.md).

{% tabs %}
{% tab title="C#" %}
{% code lineNumbers="true" %}

```csharp
//
// Copyright (c) 2001-2024 by Apryse Software Inc. All Rights Reserved.
//

using System;
using System.Drawing;
using System.Drawing.Drawing2D;

using pdftron;
using pdftron.Common;
using pdftron.Filters;
using pdftron.SDF;
using pdftron.PDF;

namespace PDFDCTestCS
{
	/// <summary>
	/// This sample shows how to create and use PDFDC (i.e. a PDF Device Context).
	/// Windows developers can use standard GDI or GDIPlus API-s to write on PDFDC 
	/// and to generate PDF documents based on their existing drawing functions.
	/// 
	/// The second portion of this sample shows how to create and use PDFDCEX.
	/// Windows developers can use standard GDI or GDIPlus API-s to write multi-page
	/// PDF documents using existing drawing code.
	///
	/// PDFDCEX can also be used to implement file conversion from any printable 
	/// file format to PDF (i.e. a virtual PDF printer driver).
	/// </summary>
	class Class1
	{
		private static pdftron.PDFNetLoader pdfNetLoader = pdftron.PDFNetLoader.Instance();
		static Class1() {}
		
		// Relative path to the folder containing test files.
		const string input_path = "../../../../TestFiles/";
		const string output_path = "../../../../TestFiles/Output/";

		/// <summary>
		/// The main entry point for the application.
		/// </summary>
		[STAThread]
		static void Main(string[] args)
		{
			PDFNet.Initialize(PDFTronLicense.Key);

			try
			{
				//////////////////////////////////////////////////////////////////////////
				// First the PDFDC
				// Start with a PDFDoc to put the picture into, and a PDFDC to translate GDI to PDF
				using (PDFDoc pdfdoc = new PDFDoc())
				{
					PDFDC pdf_dc = new PDFDC();

					// Set the scale between GDI logical units and the PDF page at 50/inch.
					pdf_dc.SetDPI(50);

					// Create a page to put the GDI content onto
					Page page = pdfdoc.PageCreate();

					// Begin the translation from GDI to PDF.
					// Provide the page to place the picture onto, and the bounding box for the content.
					// We're going to scale the GDI content to fill the page while preserving the aspect
					// ratio.
					// Get back a GDIPlus Graphics Object
					using (Graphics gr = pdf_dc.Begin(page, page.GetCropBox()))
					{
						// Create a path that consists of a single polygon.
						System.Drawing.Point[] polyPoints = 
						{
							new System.Drawing.Point(10, 10),
							new System.Drawing.Point(150, 10), 
							new System.Drawing.Point(100, 75),
							new System.Drawing.Point(100, 150)
						};

						GraphicsPath path = new GraphicsPath();
						path.AddPolygon(polyPoints);

						// Construct a region based on the path.
						Region region = new Region(path);

						// Draw the outline of the region.
						Pen pen = Pens.Black;
						gr.DrawPath(pen, path);

						// Set the clipping region of the Graphics object.
						gr.SetClip(region, CombineMode.Replace);

						// Draw some clipped strings.
						FontFamily fontFamily = new FontFamily("Arial");
						System.Drawing.Font font = new System.Drawing.Font(
							fontFamily,
							36, FontStyle.Bold,
							GraphicsUnit.Pixel);
						SolidBrush solidBrush = new SolidBrush(Color.FromArgb(255, 255, 0, 0));

						gr.DrawString(
							"A Clipping Region",
							font, solidBrush,
							new PointF(15, 25));

						gr.DrawString(
							"A Clipping Region",
							font,
							solidBrush,
							new PointF(15, 68));


						pdf_dc.End(); // Close PDF Device Context
					}

					// Add the page to the document
					pdfdoc.PagePushBack(page);

					//////////////////////////////////////////////////////////////////////////
					// Page two
					page = pdfdoc.PageCreate();
					using (Graphics gr = pdf_dc.Begin(page, page.GetCropBox(), true))
					{
						Rectangle myRectangle = new Rectangle(0, 0, 100, 50);
						LinearGradientBrush myLinearGradientBrush = new LinearGradientBrush(
							myRectangle,
							Color.Blue,
							Color.Green,
							LinearGradientMode.Horizontal);
						gr.FillEllipse(myLinearGradientBrush, myRectangle);

						// Complete the translation
						pdf_dc.End();
					}

					// Add the page to the document
					pdfdoc.PagePushBack(page);

					pdfdoc.Save(output_path + "PDFDCTest.pdf", SDFDoc.SaveOptions.e_remove_unused);
				}
				Console.WriteLine("Saved PDFDCTest.pdf");


				//////////////////////////////////////////////////////////////////////////
				// 
				// Now for PDFDCEX
				// Start with a PDFDoc to put the picture into, and a PDFDCEX to translate GDI to PDF
				using (PDFDoc pdfdoc2 = new PDFDoc())
				{
					PDFDCEX pdf_dcex = new PDFDCEX();

					// Begin the translation from GDI to PDF.
					// The page dimensions and the converter DPI determine the coordinate system.
					// Unlike PDFDC, the drawings will not be scaled to fit the bounding box.
					pdf_dcex.Begin(pdfdoc2);

					// Start the first page -- Get back a Graphics Object
					System.Drawing.Graphics gr2 = pdf_dcex.StartPage();

					// Create a path that consists of a single polygon.
					System.Drawing.Point[] polyPoints2 = 
					{
						new System.Drawing.Point(10, 10),
						new System.Drawing.Point(150, 10), 
						new System.Drawing.Point(100, 75),
						new System.Drawing.Point(100, 150)
					};

					GraphicsPath path2 = new GraphicsPath();
					path2.AddPolygon(polyPoints2);

					// Construct a region based on the path.
					Region region2 = new Region(path2);

					// Draw the outline of the region.
					Pen pen2 = Pens.Black;
					gr2.DrawPath(pen2, path2);

					// Set the clipping region of the Graphics object.
					gr2.SetClip(region2, CombineMode.Replace);

					// Draw some clipped strings.
					FontFamily fontFamily2 = new FontFamily("Arial");
					System.Drawing.Font font2 = new System.Drawing.Font(
						fontFamily2,
						36, FontStyle.Bold,
						GraphicsUnit.Pixel);
					SolidBrush solidBrush2 = new SolidBrush(Color.FromArgb(255, 255, 0, 0));

					gr2.DrawString(
						"A Clipping Region",
						font2, solidBrush2,
						new PointF(15, 25));

					gr2.DrawString(
						"A Clipping Region",
						font2,
						solidBrush2,
						new PointF(15, 68));

					pdf_dcex.EndPage();
					// at this point the Graphics Context gr2 has been disposed

					//////////////////////////////////////////////////////////////////////////
					// Page two -- get a new Graphics Object

					gr2 = pdf_dcex.StartPage();

					Rectangle myRectangle2 = new Rectangle(0, 0, 100, 50);
					LinearGradientBrush myLinearGradientBrush2 = new LinearGradientBrush(
						myRectangle2,
						Color.Blue,
						Color.Green,
						LinearGradientMode.Horizontal);
					gr2.FillEllipse(myLinearGradientBrush2, myRectangle2);
					gr2.DrawString(
						"An Ellipse Filled with a Linear Gradient",
						font2, solidBrush2,
						new PointF(15, 200));
					pdf_dcex.EndPage();

					// Complete the translation
					pdf_dcex.End();

					pdfdoc2.Save(output_path + "PDFDCEXTest.pdf", SDFDoc.SaveOptions.e_remove_unused);
				}
				Console.WriteLine("Saved PDFDCEXTest.pdf");
				Console.WriteLine("Done.");
			}
			catch (PDFNetException e)
			{
				Console.WriteLine(e.Message);
			}
			PDFNet.Terminate();
		}
	}
}
```

{% endcode %}
{% endtab %}

{% tab title="C++" %}
{% code lineNumbers="true" %}

```cpp
//---------------------------------------------------------------------------------------
// Copyright (c) 2001-2021 by PDFTron Systems Inc. All Rights Reserved.
// Consult legal.txt regarding legal and license information.
//---------------------------------------------------------------------------------------

#include <iostream>
#include <sstream>
#include <PDF/PDFNet.h>
#include <PDF/PDFDC.h>
#include <PDF/PDFDCEX.h>
#include "../../LicenseKey/CPP/LicenseKey.h"

//-----------------------------------------------------------------------------------
// This sample shows how to create and use the PDFDCEX which allows 
// printer-like multipage translations with GDI resources used across pages.
// PDFDCEX allows you to create page after page of GDI to PDF conversion using existing 
// printing functions.
//-----------------------------------------------------------------------------------

using namespace pdftron;
using namespace PDF;

// Relative path to the folder containing test files.
std::string inputPath =  "../../TestFiles/";
std::string outputPath = "../../TestFiles/Output/";

// Define a font
static const LOGFONTW ArialFont =
{ 
	12,							// height (points)
	0,							// width (use default)
	0,							// rotation of baseline for text strings
	0,							// rotation of each character
	FW_NORMAL,					// weight
	FALSE,						// italic
	FALSE,						// underline
	FALSE,						// strike out
	ANSI_CHARSET,				// character set
	OUT_DEFAULT_PRECIS,			// output precision
	CLIP_DEFAULT_PRECIS,		// clip precision
	DEFAULT_QUALITY,			// quality
	VARIABLE_PITCH | FF_SWISS,	// pitch and family
	L"Arial"					// font name
};


int main()
{
	int ret = 0;
#if defined(_WIN32) && !defined(WINCE)

	PDFNet::Initialize(LicenseKey);

	try  
	{	
		////////////////////////////////////////////////////////////////////////////////
		// Add two pages to a new PDFDoc.
		// Fonts and resources are shared across pages.  No need to work with each PDFPage.
		// We work in page coordinates which are page dimensions (inches) times
		// DPI. Origin is at upper left corner of the page, positive down and to right.

		// Start with a PDFDoc to put the translation into, and a PDFDCEX to translate GDI to PDF
		PDFDoc pdfdoc2;
		PDFDCEX pdfDcEx;
		HDC hDC2;
		HFONT hArialFont2;
		HGDIOBJ hOldFont2;
		HGDIOBJ hPen2, hOldPen2;

		// Begin the translation from GDI to PDF -- provide the PDFDoc to append to.
		// Get back a GDI Device Context, we've added "::" the start of all of the
		// GDI calls to emphasize that we only use the PDFDCEX at the beginning and end.
		PDF::Point paperDimensions(8.5, 11);
		hDC2 = pdfDcEx.Begin( pdfdoc2, paperDimensions );

		UInt32 dpi = pdfDcEx.GetDPI(); 
		PDF::Point paperSize( paperDimensions.x * dpi, paperDimensions.y * dpi);

		::StartPage(hDC2);

		// We like to think of font height in "points" -- convert this to page pixels
		LOGFONTW tmpFont = ArialFont;
		tmpFont.lfHeight *= dpi / 72;
		hArialFont2 = ::CreateFontIndirectW( &tmpFont );
		hOldFont2 = ::SelectObject(hDC2, hArialFont2 );

		hPen2 = ::CreatePen(PS_SOLID, 1, RGB(0,0,0));
		hOldPen2 = ::SelectObject(hDC2, hPen2);
		::SetBkMode(hDC2, TRANSPARENT);
		::Ellipse(hDC2, (int)(paperSize.x/2 - dpi), (int)(paperSize.y/2 - dpi), (int)(paperSize.x/2 + dpi), (int)(paperSize.y/2 + dpi));
		::SetTextAlign(hDC2, TA_CENTER | TA_BOTTOM);
		::TextOutW(hDC2, (int)(paperSize.x/2), (int)(paperSize.y/2 + tmpFont.lfHeight / 2), L"Hello World", 11);
		::SelectObject(hDC2, hOldPen2);
		::DeleteObject(hPen2);
		::EndPage(hDC2);

		////////////////////////////////////////////////////////////////////////////
		// Page two
		// Reuse existing font and DC.
		::StartPage(hDC2);
		::Ellipse(hDC2, -20, -20, 20, 20);
		::SetTextAlign(hDC2, TA_CENTER | TA_BOTTOM);
		::TextOutW(hDC2, (int)(paperSize.x/2), (int)(paperSize.y/2 + ArialFont.lfHeight / 2), L"Page 2", 6);
		::SelectObject(hDC2, hOldFont2);
		::DeleteObject(hArialFont2);
		::EndPage(hDC2);

		// Complete the translation
		pdfDcEx.End();

		// Save the PDF document
		pdfdoc2.Save(outputPath + "PDFDCEXTest.pdf", SDF::SDFDoc::e_remove_unused, NULL);
		std::cout << "Saved PDFDCEXTest.pdf\nDone.\n";
	}
	catch(Common::Exception& e)
	{
		std::cout << e << std::endl;
		ret = 1;
	}
	catch(...)
	{
		std::cout << "Unknown Exception" << std::endl;
		ret = 1;
	}

	PDFNet::Terminate();
#endif // defined(_WIN32) && !defined(WINCE)
	return ret;
}
```

{% endcode %}
{% endtab %}

{% tab title="VB" %}
{% code lineNumbers="true" %}

```vb
'
' Copyright (c) 2001-2024 by Apryse Software Inc. All Rights Reserved.
'

Imports System
Imports System.Drawing
Imports System.Drawing.Drawing2D

Imports pdftron
Imports pdftron.Common
Imports pdftron.Filters
Imports pdftron.SDF
Imports pdftron.PDF

' This sample shows how to create and use PDFDC (i.e. a PDF Device Context).
' Windows developers can use standard GDI or GDIPlus API-s to write on PDFDC 
' and to generate PDF documents based on their existing drawing functions.
' 
' The second portion of this sample shows how to create and use PDFDCEX.
' Windows developers can use standard GDI or GDIPlus API-s to write multi-page
' PDF documents using existing drawing code.
'
' PDFDCEX can also be used to implement file conversion from any printable 
' file format to PDF (i.e. a virtual PDF printer driver).

Module PDFDCTestVB
	Dim pdfNetLoader As PDFNetLoader
	Sub New()
		pdfNetLoader = pdftron.PDFNetLoader.Instance()
	End Sub

	' Relative path to the folder containing test files.
	Dim input_path As String = "../../../../TestFiles/"
	Dim output_path As String = "../../../../TestFiles/Output/"

	Sub Main()

		PDFNet.Initialize(PDFTronLicense.Key)

		Try

			Console.WriteLine("-------------------------------------------------")

			' Start with a PDFDoc to put the picture into, and a PDFDC to translate GDI to PDF
			Using pdf_doc As PDFDoc = New PDFDoc
				Dim pdf_dc As PDFDC = New PDFDC
				' Set the scale between GDI logical units and the PDF page at 50/inch.
				pdf_dc.SetDPI(50)

				' Create a page to put the GDI content onto
				Dim pg As Page = pdf_doc.PageCreate()

				' Begin the translation from GDI to PDF.
				' Provide the page to place the picture onto, and the bounding box for the content.
				' We're going to scale the GDI content to fill the page while preserving the aspect
				''/ ratio.
				' Get back a GDI Device Context
				Using gr As Graphics = pdf_dc.Begin(pg, pg.GetCropBox())
					Dim myImage As System.Drawing.Image = System.Drawing.Image.FromFile(input_path + "butterfly.png")
					Dim myTextureBrush As TextureBrush = New TextureBrush(myImage)
					gr.FillEllipse(myTextureBrush, 0, 0, 100, 50)

					pdf_dc.End() ' Close PDF Device Context
				End Using

				' Add the page to the document
				pdf_doc.PagePushBack(pg)

				pdf_doc.Save(output_path + "PDFDCTest.pdf", SDF.SDFDoc.SaveOptions.e_linearized)
			End Using
			Console.WriteLine("Wrote " + output_path + "PDFDCTest12.pdf")

			''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
			' 
			' Now the PDFDCEX example
			' Start with a PDFDoc to put the picture into, and a PDFDCEX to translate GDI to PDF
			Using pdf_doc2 As PDFDoc = New PDFDoc
				Dim pdf_dcex As PDFDCEX = New PDFDCEX

				' Begin the translation from GDI to PDF.
				' Get back a GDI Device Context -- this will be managed by the PDFDCEX class
				pdf_dcex.Begin(pdf_doc2)
				Dim gr2 As Graphics = pdf_dcex.StartPage()

				Dim myImage2 As System.Drawing.Image = System.Drawing.Image.FromFile(input_path + "butterfly.png")
				Dim myTextureBrush2 As TextureBrush = New TextureBrush(myImage2)
				gr2.FillEllipse(myTextureBrush2, 0, 0, 100, 50)

				pdf_dcex.EndPage() ' This also disposes of the Graphics Object gr2
				pdf_dcex.End() ' Close PDF Device Context

				pdf_doc2.Save(output_path + "PDFDCEXTest.pdf", SDF.SDFDoc.SaveOptions.e_linearized)
			End Using
			Console.WriteLine("Wrote " + output_path + "PDFDCEXTest.pdf")
			Console.WriteLine("Done.")

		Catch ex As PDFNetException

			Console.WriteLine(ex.Message)

		Catch ex As Exception

			MsgBox(ex.Message)

		End Try
		PDFNet.Terminate()
	End Sub

End Module
```

{% endcode %}
{% endtab %}
{% endtabs %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.apryse.com/core/get-started/samples/pdfdctest.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
