Click here to Skip to main content
15,867,453 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
I am learning to use print property sheet so I can start learning printing by drawing a rectangle on the paper.

My problem is that I do not have a printer, and am testing the results by printing to XPS file and MS Office OneNote 2007. I am drawing the rectangle with this code snippet :
C++
// hWnd is the window that owns the property sheet.
HRESULT DisplayPrintPropertySheet(HWND hWnd)
{
    HRESULT hResult;
    PRINTDLGEX pdx = {0};
    LPPRINTPAGERANGE pPageRanges = NULL;

    // Allocate an array of PRINTPAGERANGE structures.
    pPageRanges = (LPPRINTPAGERANGE) GlobalAlloc( GPTR, 
        10 * sizeof(PRINTPAGERANGE) );

    if (!pPageRanges)
        return E_OUTOFMEMORY;

    //  Initialize the PRINTDLGEX structure.
    pdx.lStructSize = sizeof(PRINTDLGEX);
    pdx.hwndOwner = hWnd;
    pdx.hDevMode = NULL;
    pdx.hDevNames = NULL;
    pdx.hDC = NULL;
    pdx.Flags = PD_RETURNDC;
    pdx.Flags2 = 0;
    pdx.ExclusionFlags = 0;
    pdx.nPageRanges = 0;
    pdx.nMaxPageRanges = 10;
    pdx.lpPageRanges = pPageRanges;
    pdx.nMinPage = 1;
    pdx.nMaxPage = 1000;
    pdx.nCopies = 1;
    pdx.hInstance = 0;
    pdx.lpPrintTemplateName = NULL;
    pdx.lpCallback = NULL;
    pdx.nPropertyPages = 0;
    pdx.lphPropertyPages = NULL;
    pdx.nStartPage = START_PAGE_GENERAL;
    pdx.dwResultAction = 0;

    //  Invoke the Print property sheet.

    hResult = PrintDlgEx(&pdx);

    if ( ( hResult == S_OK )    
        && ( pdx.dwResultAction == PD_RESULT_PRINT ) )
    {

        // User clicked the Print button, 
        // so use the DC and other information returned in the 
        // PRINTDLGEX structure to print the document.

        DOCINFO diDocInfo = {0};
        diDocInfo.cbSize = sizeof( DOCINFO ); 
        diDocInfo.lpszDocName = L"Testing printing...";

        if( StartDoc( pdx.hDC, &diDocInfo ) > 0 )
        {
            if( StartPage( pdx.hDC ) > 0 )
            {
                // get paper dimensions
                int pageWidth, pageHeight;

                pageWidth = GetDeviceCaps( pdx.hDC, HORZRES );
                pageHeight = GetDeviceCaps( pdx.hDC, VERTRES );

                // graphics object for rendering text, grid lines, bitmaps ...
                Graphics g( pdx.hDC );

                /************ draw a testing rectangle***************/

                g.DrawRectangle( &Pen( Color::Red, 4 ), 0, 0, 
                    pageWidth, pageHeight );

                /************************************************/

                if( EndPage( pdx.hDC ) < 0 )
                    // for now pop a message box saying something went wrong
                    MessageBox( hWnd, L"EndDoc failed!", L"Error", MB_OK );
            }

            EndDoc( pdx.hDC );

        }
    }

    if (pdx.hDevMode != NULL) 
        GlobalFree(pdx.hDevMode); 
    if (pdx.hDevNames != NULL) 
        GlobalFree(pdx.hDevNames); 
    if (pdx.lpPageRanges != NULL)
        GlobalFree(pPageRanges);
    if (pdx.hDC != NULL) 
        DeleteDC(pdx.hDC);

    return hResult;
}


The problem I get[^] is that right and bottom coordinates are not properly calculated. The expected result should be like this[^].

Apparently, I do not obtain the proper rectangle coordinates for the bottom right.

Therefore I ask for a solution that can calculate proper rectangle coordinates for paper, so I can draw the red rectangle like in the second picture above.
Posted
Updated 14-Jun-14 11:07am
v3

Take a look at GDI Drawing and Printing[^].
 
Share this answer
 
Comments
AlwaysLearningNewStuff 16-Jun-14 11:05am    
I did find that article before, but I can not compile the project because I have VS 2008, and Debug doesn't run either...

I have managed to solve the problem, but will update my post after I test it on the real printer ( so far everything works fine on XPS and OneNote2007 ).

Thank you anyway, I have voted 5.
I have discovered that the issue is to do with the default unit settings in the Graphics class, as described in http://msdn.microsoft.com/en-us/library/ms535812(v=vs.85).aspx[^]
You need to use the following line of code to set it to pixels.
C++
g.SetPageUnit(UnitPixel);

That now works in XPS and on the real printer.


[edit]
Using old-style GDI rather than GDI+, the following code works fine:
C++
HANDLE hPen = CreatePen(PS_SOLID, 60, RGB(255, 0, 0)); // pen width 1/10th inch
SelectObject(pdx.hDC, hPen);
Rectangle(pdx.hDC, 0, 0, pageWidth, pageHeight);

[/edit]
 
Share this answer
 
v2
Comments
AlwaysLearningNewStuff 17-Jun-14 16:46pm    
Thank you so much!

I have found a way to get consistent results in both XPS and OneNote2007, by applying scaling factor. I haven't tested this on the real printer though...

After I change the graphics mode to pixels, the way you suggest, and apply scaling factor, I get both the GDI and GDI+ result to be the same, but they do not cover entire "page" of the XPS/OneNote documents. If I remove the setting you suggested, in both documents the picture is drawn over entire "page" properly with GDI+ only.

Therefore I must test this scaling on a real printer to see what is going on... As soon as I do that I will report my results and will probably accept your solution since I believe you are right.

Best regards until then!
AlwaysLearningNewStuff 25-Jun-14 18:56pm    
Thank you for your help. I have 5ed both solutions. Best regards 'till next time!
Richard MacCutchan 25-Jun-14 21:18pm    
You are welcome. It was an interesting problem.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900