usncahill
usncahill

Reputation: 466

WinAPI StartDoc fails for default Adobe PDF when providing DEVMODE

Objective: Print text to AdobePDF from multiple sources in Access using WinAPI GDI Print functions. Specifically,

Problem: StartDoc always returns -1 for hDCs (for Adobe PDF) created using a DEVMODE and returns > 0 for all other printers chosen. Is the DEVMODE different size or format for Adobe PDF?

Info: Here's what I've tried and the results thus far:

Code:

Public Function printRawData(objRTB As Object, Optional strFilename As String = "cBasePrint") As Boolean
  Dim hDCPrinter As Long, sDeviceName As String, lJob As Long
  Dim udtDevMode As DEVMODE, udtDocInfo As DOCINFO

  If printPrintDialog(udtDevMode, hDCPrinter) Then
    Debug.Print hDCPrinter, IsValidDevMode(udtDevMode, LenB(udtDevMode)), udtDevMode.dmOrientation, udtDevMode.dmDeviceName

    If hDCPrinter <> 0 Then
        udtDocInfo.pDocName = strFilename
        udtDocInfo.pOutputFile = vbNullString
        udtDocInfo.pDatatype = "RAW"
        udtDocInfo.fType = 0
        udtDocInfo.sSize = LenB(udtDocInfo)

        lJob = StartDoc(hDCPrinter, udtDocInfo)
        Debug.Print lJob, Err.LastDllError

        If lJob > 0 Then
            objRTB.SelPrint hDCPrinter, 0
            EndDoc (hDCPrinter)
        End If

        DeleteDC (hDCPrinter)
    End If
  End If
End Function

Related Questions:
Raw Printing Set DevMode options (Orientation, copies, margins, default source, etc.)
How to show printer properties/preferences dialog and save changes?

References:
Lessan Vaezi: Printer Settings Nearly identical code to mine.
MS KB: Saving DEVMODE Properties Don't want to do this. My PrintDlgEx call works and returns a valid DEVMODE for other printers.
CodeGuru: Printing-using-Win32-Printer Identical issue from what I can tell. No answer.
Adobe PDF Community Most of the way down the thread, people are having the same issues.

Upvotes: 2

Views: 831

Answers (1)

Daniel
Daniel

Reputation: 11

Hope it's not too late. But I found a solution by studying some sample MFC projects created by MS

        // Determine name of Adobe PDF Printer if installed.
        CString AdobePrinterName = L"";
        DWORD cbNeeded, cReturned;
        EnumPrinters(PRINTER_ENUM_LOCAL, NULL, 2, NULL, 0, &cbNeeded, &cReturned);
        PRINTER_INFO_2* pPrinterInfo = (PRINTER_INFO_2*)malloc(cbNeeded);
        EnumPrinters(PRINTER_ENUM_LOCAL, NULL, 2, (LPBYTE)pPrinterInfo, cbNeeded, &cbNeeded, &cReturned);
        for (int i = 0; i < cReturned; i++) {
            if (wcscmp(pPrinterInfo[i].pDriverName, L"Adobe PDF Converter") == 0) {
                // Adobe PDF printer is found
                AdobePrinterName = pPrinterInfo[i].pPrinterName;
                break;
            }
        }

        int started = 0;
        // start the print document
        if (po->printerName.CompareNoCase(AdobePrinterName) == 0) {

            // This is a work around for printing to Adobe PDF printer.
            DOCINFO docInfo;
            memset(&docInfo, 0, sizeof(DOCINFO));
            docInfo.cbSize = sizeof(DOCINFO);
            docInfo.lpszDocName = L"_untitle"; // <-- Adobe PDF printer needed this to work properly
            started = dc.StartDoc(&docInfo);
        }
        else {
            started = StartDoc(&dc, po);
        }

        if (!started)
        {
            DWORD error = GetLastError();
            goto fail;
        }

Upvotes: 0

Related Questions