using System; using System.Runtime.InteropServices; namespace Vanara.PInvoke { public static partial class Gdi32 { /// Enable color optimization. public const uint EMF_PP_COLOR_OPTIMIZATION = 0x01; /// The GdiDeleteSpoolFileHandle function releases a spool file handle. /// Caller-supplied spool file handle, obtained by a previous call to GdiGetSpoolFileHandle. /// If the operation succeeds, the function returns TRUE. Otherwise the function returns FALSE. /// /// /// The GdiDeleteSpoolFileHandle function is exported by Gdi32.dll for use within a print processor's /// PrintDocumentOnPrintProcessor function. /// /// /// Print processors should call GdiDeleteSpoolFileHandle after calling GdiEndDocEMF, when processing a print job's EMF data /// stream has been completed. The function calls ClosePrinter (described in the Microsoft Window SDK documentation) to close the /// printer connection. /// /// For additional information, see Using GDI Functions in Print Processors. /// // https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/winppi/nf-winppi-gdideletespoolfilehandle BOOL // GdiDeleteSpoolFileHandle( HANDLE SpoolFileHandle ); [DllImport(Lib.Gdi32, SetLastError = false, ExactSpelling = true)] [PInvokeData("winppi.h", MSDNShortId = "ff22498e-404f-42f6-82fd-f0178f6c7789")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool GdiDeleteSpoolFileHandle(HSPOOLFILE SpoolFileHandle); /// The GdiEndDocEMF function ends EMF playback operations for an EMF-formatted print job. /// Caller-supplied spool file handle, obtained by a previous call to GdiGetSpoolFileHandle. /// /// If the operation succeeds, the function returns TRUE. Otherwise the function returns FALSE, and an error code can /// be obtained by calling GetLastError. /// /// /// /// The GdiEndDocEMF function is exported by Gdi32.dll for use within a print processor's PrintDocumentOnPrintProcessor function. /// /// /// The function performs operations that must be performed after a print job's EMF records have been played. The function calls the /// spooler's EndDoc function (described in the Microsoft Window SDK documentation), which in turn calls the printer driver's /// DrvEndDoc function. /// /// For additional information, see Using GDI Functions in Print Processors. /// // https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/winppi/nf-winppi-gdienddocemf BOOL GdiEndDocEMF( HANDLE // SpoolFileHandle ); [DllImport(Lib.Gdi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("winppi.h", MSDNShortId = "e58403d4-aacc-4d22-98e5-86db1a69c54a")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool GdiEndDocEMF(HSPOOLFILE SpoolFileHandle); /// The GdiEndPageEMF function ends EMF playback operations for a physical page of an EMF-formatted print job. /// Caller-supplied spool file handle, obtained by a previous call to GdiGetSpoolFileHandle. /// /// Caller-supplied flags. The following flag is defined: /// EMF_PP_COLOR_OPTIMIZATION /// Enable color optimization. For more information, see Remarks. /// /// /// If the operation succeeds, the function returns TRUE. Otherwise the function returns FALSE, and an error code can /// be obtained by calling GetLastError. /// /// /// /// The GdiEndPageEMF function is exported by Gdi32.dll for use within a print processor's PrintDocumentOnPrintProcessor function. /// /// /// The GdiEndPageEMF function ends the processing of a physical page and causes it to be ejected from the printer. A print /// processor should call GdiEndPageEMF at the following times: /// /// /// /// /// After the appropriate number of document pages have been placed on the physical page by making calls to GdiPlayPageEMF. Note /// that GdiPlayPageEMF does not actually print on the device context, but instead prepares a data structure that describes /// the text and graphics that are to be printed on the physical page(s). The text and graphics are printed to the device context /// when GdiEndPageEMF is called. /// /// /// /// /// Whenever a call to GdiGetDevmodeForPage indicates a document page's DEVMODEW structure is different from the previous page's /// DEVMODE structure. /// /// /// /// /// If this function is called with the dwOptimization parameter set to EMF_PP_COLOR_OPTIMIZATION, color optimization is enabled. If /// dwOptimization is set to 0, no optimization is performed. When color optimization is enabled, the presence of color in the spool /// file causes the spool file to be played in color; the lack of color in the spool file causes the spool file to be played in monochrome. /// /// /// If you are creating a Unidrv rendering plug-in to generate color watermarks, be advised that color optimization causes color /// watermarks to be printed in black and white when they are printed on black-and-white documents. To ensure that color watermarks /// print correctly with color and black-and-white documents, disable color optimization. /// /// /// The color optimization controlled by the dwOptimization parameter can also be controlled by setting the /// dwColorOptimization member of the ATTRIBUTE_INFO_2 or ATTRIBUTE_INFO_3 structures. This optimization also can be /// controlled by the Unidrv * ChangeColorModeOnDoc? color attribute (see Color Attributes). /// /// For additional information, see Using GDI Functions in Print Processors. /// // https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/winppi/nf-winppi-gdiendpageemf BOOL GdiEndPageEMF( HANDLE // SpoolFileHandle, DWORD dwOptimization ); [DllImport(Lib.Gdi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("winppi.h", MSDNShortId = "e15344a5-32ed-43a8-93c2-d5201617d595")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool GdiEndPageEMF(HSPOOLFILE SpoolFileHandle, uint dwOptimization); /// The GdiGetDC function returns a handle to a printer's device context. /// Caller-supplied spool file handle, obtained by a previous call to GdiGetSpoolFileHandle. /// If the operation succeeds, the function returns a device context handle. Otherwise the function returns NULL. /// /// /// The GdiGetDC function is exported by Gdi32.dll for use within a print processor's PrintDocumentOnPrintProcessor function. /// /// /// A print processor can call GdiGetDC to obtain a printer's device context handle anytime after calling /// GdiGetSpoolFileHandle. The print processor can use the context handle to call Win32 device context functions, in order to /// perform such operations as applying transformations on the print image. /// /// For additional information, see Using GDI Functions in Print Processors. /// // https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/winppi/nf-winppi-gdigetdc HDC GdiGetDC( HANDLE SpoolFileHandle ); [DllImport(Lib.Gdi32, SetLastError = false, ExactSpelling = true)] [PInvokeData("winppi.h", MSDNShortId = "f8aacb6d-4e8a-4fdb-902c-3d0efbc40f08")] public static extern HDC GdiGetDC(HSPOOLFILE SpoolFileHandle); /// /// The GdiGetDevmodeForPage function returns DEVMODEW structures for the specified and previous pages of a print job. /// /// Caller-supplied spool file handle, obtained by a previous call to GdiGetSpoolFileHandle. /// Caller-supplied number of the page for which DEVMODEW contents are to be returned. /// Caller-supplied location to receive a pointer to a DEVMODE structure for the page specified by dwPageNumber. /// /// Caller-supplied location to receive a pointer to a DEVMODE structure for the page previous to the one specified by dwPageNumber. /// /// If the operation succeeds, the function returns TRUE. Otherwise it returns FALSE. /// /// /// The GdiGetDevmodeForPage function is exported by Gdi32.dll for use within a print processor's /// PrintDocumentOnPrintProcessor function. /// /// /// Before calling GdiPlayPageEMF to execute a page's EMF instructions, a print processor must call GdiGetDevmodeForPage to /// determine if the DEVMODE structure associated with the page to be printed is the same as that of the last page printed. If the /// two returned DEVMODE structures are not identical, the print processor must perform the following steps, in order, before /// calling GdiPlayPageEMF for the page: /// /// /// /// Call GdiEndPageEMF. /// /// /// Call GdiResetDCEMF, specifying the DEVMODE pointed to by pCurrDM. /// /// /// Call GdiStartPageEMF. /// /// /// For additional information, see Using GDI Functions in Print Processors. /// // https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/winppi/nf-winppi-gdigetdevmodeforpage BOOL GdiGetDevmodeForPage( // HANDLE SpoolFileHandle, DWORD dwPageNumber, PDEVMODEW *pCurrDM, PDEVMODEW *pLastDM ); [DllImport(Lib.Gdi32, SetLastError = false, ExactSpelling = true, CharSet = CharSet.Unicode)] [PInvokeData("winppi.h", MSDNShortId = "3410e8b1-820f-4892-8d26-d803e3f943da")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool GdiGetDevmodeForPage(HSPOOLFILE SpoolFileHandle, uint dwPageNumber, out IntPtr pCurrDM, out IntPtr pLastDM); /// The GdiGetPageCount function returns the number of pages in a print job. /// Caller-supplied spool file handle, obtained by a previous call to GdiGetSpoolFileHandle. /// /// If the operation succeeds, the function returns the number of pages in the current print job. Otherwise the function returns zero. /// /// /// /// The GdiGetPageCount function is exported by Gdi32.dll for use within a print processor's PrintDocumentOnPrintProcessor function. /// /// /// Note The GdiGetPageCount function does not return until all pages have been spooled, even if the print server /// administrator has specified that print jobs should be printed during spooling. Therefore, this function should not be used /// unless it is necessary to obtain the total page count before document processing can begin, such as for printing pages in /// reverse order.Usually, a better method for determining the page count is to count the number of calls made to GdiGetPageHandle. /// /// For additional information about this set of functions, see Using GDI Functions in Print Processors. /// // https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/winppi/nf-winppi-gdigetpagecount DWORD GdiGetPageCount( HANDLE // SpoolFileHandle ); [DllImport(Lib.Gdi32, SetLastError = false, ExactSpelling = true)] [PInvokeData("winppi.h", MSDNShortId = "0a101b59-c610-4158-97a8-002222a94309")] public static extern uint GdiGetPageCount(HSPOOLFILE SpoolFileHandle); /// The GdiGetPageHandle function returns a handle to the specified page within a print job. /// Caller-supplied spool file handle, obtained by a previous call to GdiGetSpoolFileHandle. /// Caller-supplied page number. /// /// /// Caller-supplied pointer to a location that receives the page type. The possible page types are shown in the following table: /// /// /// /// Page Type /// Meaning /// /// /// EMF_PP_FORM /// The page is a form or has a watermark. (Not currently supported.) /// /// /// EMF_PP_NORMAL /// The page is a normal page. /// /// /// /// /// If the operation succeeds, the function returns TRUE. Otherwise the function returns FALSE, and an error code can /// be obtained by calling GetLastError. /// /// /// /// The GdiGetPageHandle function is exported by Gdi32.dll for use within a print processor's PrintDocumentOnPrintProcessor function. /// /// /// Print processors must obtain a page handle before calling GdiPlayPageEMF to draw a page. If a Page value is specified that is /// too large, the function returns ERROR_NO_MORE_ITEMS. /// /// For additional information, see Using GDI Functions in Print Processors. /// // https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/winppi/nf-winppi-gdigetpagehandle HANDLE GdiGetPageHandle( HANDLE // SpoolFileHandle, DWORD Page, LPDWORD pdwPageType ); [DllImport(Lib.Gdi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("winppi.h", MSDNShortId = "7eaed9d2-20fa-4cf1-b924-fbe1443535e9")] public static extern HANDLE GdiGetPageHandle(HSPOOLFILE SpoolFileHandle, uint Page, out uint pdwPageType); /// The GdiGetSpoolFileHandle function returns a handle to a print job's EMF file. /// /// Caller-supplied pointer to a string representing the name of the target printer. See the following Remarks section. /// /// Caller-supplied pointer to a DEVMODEW structure. See the following Remarks section. /// Caller-supplied pointer to the print job's document name. See the following Remarks section. /// If the operation succeeds, the function returns a spool file handle. Otherwise the function returns NULL. /// /// /// The GdiGetSpoolFileHandle function is exported by Gdi32.dll for use within a print processor's /// PrintDocumentOnPrintProcessor function. /// /// /// When a print processor calls GdiGetSpoolFileHandle, it should supply arguments as illustrated in the following table. /// /// /// /// Parameter /// Argument /// /// /// pwszPrinterName /// Pointer to the printer name received by the print processor's OpenPrintProcessor function. /// /// /// pDevmode /// /// Pointer to the DEVMODEW structure contained in the PRINTPROCESSOROPENDATA structure, received by the print processor's /// OpenPrintProcessor function. /// /// /// /// pwszDocName /// Document name pointer received by the print processor's PrintDocumentOnPrintProcessor function. /// /// /// /// A print processor must call the GdiGetSpoolFileHandle function before calling any other GDI printing functions, because /// the returned handle must be passed to the other functions. The function calls OpenPrinter to open a connection to the printer, /// and CreateDC to create a device context for drawing. The print processor can obtain the device context's handle by calling GdiGetDC. /// /// For additional information, see Using GDI Functions in Print Processors. /// // https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/winppi/nf-winppi-gdigetspoolfilehandle HANDLE // GdiGetSpoolFileHandle( LPWSTR pwszPrinterName, LPDEVMODEW pDevmode, LPWSTR pwszDocName ); [DllImport(Lib.Gdi32, SetLastError = false, ExactSpelling = true, CharSet = CharSet.Unicode)] [PInvokeData("winppi.h", MSDNShortId = "c820ee94-29c2-4478-884c-49dd68cd713a")] public static extern SafeHSPOOLFILE GdiGetSpoolFileHandle([MarshalAs(UnmanagedType.LPWStr)] string pwszPrinterName, in DEVMODE pDevmode, [MarshalAs(UnmanagedType.LPWStr)] string pwszDocName); /// /// The GdiPlayPageEMF function plays the EMF records within a specified rectangle for one document page of a spooled print job. /// /// Caller-supplied spool file handle, obtained by a previous call to GdiGetSpoolFileHandle. /// /// Caller-supplied page handle, obtained by calling GdiGetPageHandle, identifying the page for which records are to be played. /// /// /// Caller-supplied pointer to a RECT structure specifying the rectangle into which the page is to be drawn. /// /// /// Caller-supplied pointer to a RECT structure specifying the page's border rectangle (if any). Can be NULL. /// /// /// Caller-supplied pointer to a RECT structure specifying the coordinates of the page's clip region (if any). Can be NULL. /// /// /// If the operation succeeds, the function returns TRUE. Otherwise the function returns FALSE, and an error code can /// be obtained by calling GetLastError. /// /// /// /// The GdiPlayPageEMF function is exported by Gdi32.dll for use within a print processor's PrintDocumentOnPrintProcessor function. /// /// /// The GdiPlayPageEMF function is the means by which a print processor positions a document page or a specified rectangular /// region of a document page on a physical page. Note that GdiPlayPageEMF does not actually print on the device context, but /// instead prepares a data structure that describes the text and graphics that are to be printed on the physical page(s). The text /// and graphics are printed to the device context when GdiEndPageEMF is called. /// /// /// The print processor uses prectClip to describe the rectangular region to be printed, and prectDocument to describe a rectangle /// into which the document page (or clipped region) must fit. If prectClip is NULL, the entire document page will be /// printed. For non- NULL values of prectClip, only the portion of the document page within the clip region will be printed. /// The GdiPlayPageEMF function then performs the scaling and translation operations required to make the document page (or /// selected portion) fit into the rectangle. /// /// /// The prectBorder parameter, if it is non- NULL, describes a solid-line border rectangle to be drawn around the document /// page. If prectBorder is NULL, no such border will be drawn. /// /// For additional information, see Using GDI Functions in Print Processors. /// // https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/winppi/nf-winppi-gdiplaypageemf BOOL GdiPlayPageEMF( HANDLE // SpoolFileHandle, HANDLE hemf, RECT *prectDocument, RECT *prectBorder, RECT *prectClip ); [DllImport(Lib.Gdi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("winppi.h", MSDNShortId = "e0122858-0c9d-4aa8-a394-89d65fb98fda")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool GdiPlayPageEMF(HSPOOLFILE SpoolFileHandle, HANDLE hemf, in RECT prectDocument, in RECT prectBorder, in RECT prectClip); /// The GdiResetDCEMF function resets a printer's device context during playback of a spooled EMF print job. /// Caller-supplied spool file handle, obtained by a previous call to GdiGetSpoolFileHandle. /// Caller-supplied pointer to a DEVMODEW structure, obtained by a previous call to GdiGetDevmodeForPage. /// If the operation succeeds, the function returns TRUE. Otherwise the function returns FALSE. /// /// /// The GdiResetDCEMF function is exported by Gdi32.dll for use within a print processor's PrintDocumentOnPrintProcessor function. /// /// /// Print processors must call GdiResetDCEMF whenever it is necessary to reset the printer's device context. The function /// must be called whenever the GdiGetDevmodeForPage function indicates that the current document page's DEVMODEW structure is not /// identical to that of the previous document page. /// /// For additional information, see Using GDI Functions in Print Processors. /// // https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/winppi/nf-winppi-gdiresetdcemf BOOL GdiResetDCEMF( HANDLE // SpoolFileHandle, PDEVMODEW pCurrDM ); [DllImport(Lib.Gdi32, SetLastError = false, ExactSpelling = true, CharSet = CharSet.Unicode)] [PInvokeData("winppi.h", MSDNShortId = "ea97cc22-6057-427d-90c1-4f23ced932aa")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool GdiResetDCEMF(HSPOOLFILE SpoolFileHandle, IntPtr pCurrDM); /// The GdiStartDocEMF function performs initialization operations for an EMF-formatted print job. /// Caller-supplied spool file handle, obtained by a previous call to GdiGetSpoolFileHandle. /// Caller-supplied pointer to a DOCINFOW structure (described in the Microsoft Window SDK documentation). /// /// If the operation succeeds, the function returns TRUE. Otherwise the function returns FALSE, and an error code can /// be obtained by calling GetLastError. /// /// /// /// The GdiStartDocEMF function is exported by Gdi32.dll for use within a print processor's PrintDocumentOnPrintProcessor function. /// /// /// The function performs initializations that must take place before a print job's EMF records can be played. The function calls /// the spooler's StartDoc function (described in the Window SDK documentation), which in turn calls the printer driver's /// DrvStartDoc function. /// /// /// The print processor must set the lpszOutput member of the DOCINFOW structure to the output file name contained in the /// PRINTPROCESSOROPENDATA structure, previously received by the OpenPrintProcessor function. /// /// /// The print processor must set the lpszDocName member of the DOCINFOW structure to the document name pointer, previously /// received by the PrintDocumentOnPrintProcessor function. /// /// For additional information, see Using GDI Functions in Print Processors. /// // https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/winppi/nf-winppi-gdistartdocemf BOOL GdiStartDocEMF( HANDLE // SpoolFileHandle, DOCINFOW *pDocInfo ); [DllImport(Lib.Gdi32, SetLastError = true, ExactSpelling = true, CharSet = CharSet.Unicode)] [PInvokeData("winppi.h", MSDNShortId = "aca4534a-871e-4d86-b329-cb4f84611a29")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool GdiStartDocEMF(HSPOOLFILE SpoolFileHandle, in DOCINFO pDocInfo); /// /// The GdiStartPageEMF function performs initialization operations for a physical page of an EMF-formatted print job. /// /// Caller-supplied spool file handle, obtained by a previous call to GdiGetSpoolFileHandle. /// /// If the operation succeeds, the function returns TRUE. Otherwise the function returns FALSE, and an error code can /// be obtained by calling GetLastError. /// /// /// /// The GdiStartPageEMF function is exported by Gdi32.dll for use within a print processor's PrintDocumentOnPrintProcessor function. /// /// /// A print processor must call the GdiStartPageEMF function each time a new physical page is to be created. It can then call /// GdiPlayPageEMF for each document page that is to be placed on the physical page. /// /// For additional information, see Using GDI Functions in Print Processors. /// // https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/winppi/nf-winppi-gdistartpageemf BOOL GdiStartPageEMF( HANDLE // SpoolFileHandle ); [DllImport(Lib.Gdi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("winppi.h", MSDNShortId = "963c809f-da89-4f27-ba8b-3de8cdcec179")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool GdiStartPageEMF(HSPOOLFILE SpoolFileHandle); /// Provides a handle to a spool file. [StructLayout(LayoutKind.Sequential)] public struct HSPOOLFILE : IHandle { private IntPtr handle; /// Initializes a new instance of the struct. /// An object that represents the pre-existing handle to use. public HSPOOLFILE(IntPtr preexistingHandle) => handle = preexistingHandle; /// Returns an invalid handle by instantiating a object with . public static HSPOOLFILE NULL => new HSPOOLFILE(IntPtr.Zero); /// Gets a value indicating whether this instance is a null handle. public bool IsNull => handle == IntPtr.Zero; /// Performs an explicit conversion from to . /// The handle. /// The result of the conversion. public static explicit operator IntPtr(HSPOOLFILE h) => h.handle; /// Performs an implicit conversion from to . /// The pointer to a handle. /// The result of the conversion. public static implicit operator HSPOOLFILE(IntPtr h) => new HSPOOLFILE(h); /// Implements the operator !=. /// The first handle. /// The second handle. /// The result of the operator. public static bool operator !=(HSPOOLFILE h1, HSPOOLFILE h2) => !(h1 == h2); /// Implements the operator ==. /// The first handle. /// The second handle. /// The result of the operator. public static bool operator ==(HSPOOLFILE h1, HSPOOLFILE h2) => h1.Equals(h2); /// public override bool Equals(object obj) => obj is HSPOOLFILE h ? handle == h.handle : false; /// public override int GetHashCode() => handle.GetHashCode(); /// public IntPtr DangerousGetHandle() => handle; } /// Provides a for that is disposed using . public class SafeHSPOOLFILE : SafeHANDLE { /// Initializes a new instance of the class and assigns an existing handle. /// An object that represents the pre-existing handle to use. /// /// to reliably release the handle during the finalization phase; otherwise, (not recommended). /// public SafeHSPOOLFILE(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { } /// Initializes a new instance of the class. private SafeHSPOOLFILE() : base() { } /// Performs an implicit conversion from to . /// The safe handle instance. /// The result of the conversion. public static implicit operator HSPOOLFILE(SafeHSPOOLFILE h) => h.handle; /// protected override bool InternalReleaseHandle() => GdiDeleteSpoolFileHandle(handle); } } }