title: Expected and actual printing results do not match
body: <h2>INTRODUCTION AND RELEVANT INFORMATION:</h2>
  
  <p>I am trying to bypass another problem in my application by trying to do printing/print preview on my own.</p>
  
  <p>I am trying to create a table that would look like in the picture below:</p>
  
  <p><img src="https://i.stack.imgur.com/xcbS4.png" alt="enter image description here"></p>
  
  <p>I am using <code>C++</code> and <code>WinAPI</code>, on WindowsXP SP3. I work in MS Visual Studio 2008.</p>
  
  <p><strong>I do not have a printer, so I am testing the results by printing to</strong> <code>MS OneNote</code> <strong>and</strong> <code>XPS file</code><strong>.</strong></p>
  
  <h2>PROBLEM:</h2>
  
  <p><strike>Text is obtained from database and is of variable length. Since it might not fit into the original cell, I will need to expand the cell and fit the text appropriately, like in the above image.</strike></p>
  
  <p><strike><em>SIDE EFFECT:</em></strike></p>
  
  <p>The result of my testing code gives inconsistent results regarding font size. </p>
  
  <p>In <em>OneNote</em> the print result seems fine :</p>
  
  <p><img src="https://i.stack.imgur.com/jeKAj.png" alt="enter image description here"></p>
  
  <p>However, in <em>XPS</em> it looks different :</p>
  
  <p><img src="https://i.stack.imgur.com/0x2Z0.png" alt="enter image description here"></p>
  
  <h2>MY EFFORTS TO SOLVE THIS TASK:</h2>
  
  <p>I have checked <em>MSDN documentation</em> to get started. So far I am able to successfully draw text and lines on a printing surface.</p>
  
  <p>I have used <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/dd162499%28v=vs.85%29.aspx" rel="nofollow noreferrer"><code>DrawTextEx</code></a> to perform word breaking ( by using flag <code>DT_WORDBREAK</code> ).</p>
  
  <p>To obtain the size of the printing area I have used <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/dd144877%28v=vs.85%29.aspx" rel="nofollow noreferrer"><code>GetDeviceCaps</code></a>, and to obtain printer device context I have used <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms646829%28v=vs.85%29.aspx#print_property" rel="nofollow noreferrer">print property sheet</a>.</p>
  
  <h2>QUESTIONS:</h2>
  
  <p><em>IMPORTANT REMARKS:</em></p>
  
  <p><em>If the following questions are considered too broad please leave a comment and I will edit my post. I still believe that my mistakes are minor and can be explained in a single post.</em></p>
  
  <p><strike>1. Can you explain me how to adjust cells so the entire string can fit ?</strike></p>
  
  <ol start="2">
  <li>Why is my font inconsistently drawn ?</li>
  </ol>
  
  <p>As always, here are the instructions for creating <a href="http://www.sscce.org/" rel="nofollow noreferrer"><em>SSCCE</em></a> :</p>
  
  <p>1) In Visual Studio, create default Win32 project.</p>
  
  <p>2) in <code>stdafx.h</code> file <strong>comment out</strong> <code>#define WIN32_LEAN_AND_MEAN</code> so print property sheet can work properly.</p>
  
  <p>3) In <code>stdafx.h</code> add the following, below <code>#include &lt;windows.h&gt;</code> line :</p>
  
  <pre><code>#include &lt;windowsx.h&gt;
  #include &lt;commctrl.h&gt;
  
  #pragma comment( linker, "/manifestdependency:\"type='win32' \
      name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \
      processorArchitecture='*' publicKeyToken='6595b64144ccf1df' \
      language='*'\"")
  </code></pre>
  
  <p>4) Add the following function above window procedure :</p>
  
  <pre><code>// 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(&amp;pdx);
  
      if ( ( hResult == S_OK )    
          &amp;&amp; ( 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.
  
          /***************** IMPORTANT INFO : ********************/
          /****** I have added additional test code here *********/
          /**** please refer to the edited part of this post *****/
          /***************** at the very bottom !! ***************/
  
          DOCINFO diDocInfo = {0};
          diDocInfo.cbSize = sizeof( DOCINFO ); 
          diDocInfo.lpszDocName = L"Testing printing...";
  
          //******************** initialize testing font *****************//
  
          HFONT font, oldFont; 
  
          long lfHeight = -MulDiv( 14, GetDeviceCaps( pdx.hDC, LOGPIXELSY), 72 );
  
          font = CreateFont( lfHeight, 
              0, 0, 0, FW_BOLD, TRUE, FALSE, FALSE, 0, 0, 0, 
              0, 0, L"Microsoft Sans Serif" );
  
          oldFont = SelectFont( pdx.hDC, font );
  
          SetBkMode( pdx.hDC, TRANSPARENT );
  
          SetTextColor( pdx.hDC, RGB( 255, 0, 0 ) );
  
          //******************** end of initialization ******************//
  
          if( StartDoc( pdx.hDC, &amp;diDocInfo ) &gt; 0 )
          {
              if( StartPage( pdx.hDC ) &gt; 0 )
              {
                  // get paper dimensions
                  int pageWidth, pageHeight;
  
                  pageWidth = GetDeviceCaps( pdx.hDC, HORZRES );
                  pageHeight = GetDeviceCaps( pdx.hDC, VERTRES );
  
                  /************ draw a testing grid ***************/
  
                  // draw vertical lines of the grid
                  for( int i = 0; i &lt; pageWidth; i += pageWidth / 4 )
                  {
                       MoveToEx( pdx.hDC, i, 0, NULL );
                       LineTo( pdx.hDC, i, pageHeight );
                  }
  
                  // draw horizontal lines of the grid
                  for( int j = 0; j &lt; pageHeight; j += pageWidth / 10 )
                  {
                       MoveToEx( pdx.hDC, 0, j, NULL );
                       LineTo( pdx.hDC, pageWidth, j );
                  }
  
                  /************************************************/
  
                  // test rectangle for drawing the text
                  RECT r;
                  r.left = 0;
                  r.top = 0;
                  r.right = 550;
                  r.bottom = 100;
  
                  // fill rectangle with light gray brush
                  // so we can see if text is properly drawn
  
                  FillRect( pdx.hDC, &amp;r, 
                      (HBRUSH)GetStockObject(LTGRAY_BRUSH) );
  
                  // draw text in test rectangle 
                  if( 0 == DrawTextEx( pdx.hDC, 
                       L"This is test string!", 
                       wcslen( L"This is test string!" ), 
                       &amp;r, 
                       DT_CENTER | DT_WORDBREAK | DT_NOCLIP, NULL ) )
                       // for now pop a message box saying something went wrong
                       MessageBox( hWnd, L"DrawText failed!", L"Error", MB_OK );
  
                  if( EndPage( pdx.hDC ) &lt; 0 )
                       // for now pop a message box saying something went wrong
                       MessageBox( hWnd, L"EndDoc failed!", L"Error", MB_OK );
              }
  
              EndDoc( pdx.hDC );
  
              SelectFont( pdx.hDC, oldFont );
              DeleteFont( font );
          }
      }
  
      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;
  }
  </code></pre>
  
  <p>5) In <code>WM_COMMAND</code> handler, modify <code>case IDM_ABOUT</code> like this :</p>
  
  <pre><code>case IDM_ABOUT:   // test our printing here
      {
          if( FAILED( DisplayPrintPropertySheet( hWnd ) ) )
              MessageBox( hWnd, 
                  L"Can't display print property sheet!", 
                  L"Error", MB_OK );
      }
      //DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
      break;
  </code></pre>
  
  <h2>EDITED on June, 8th 2014 :</h2>
  
  <p>After the block <code>if ( ( hResult == S_OK ) &amp;&amp; ( pdx.dwResultAction == PD_RESULT_PRINT ) )</code> in the submitted <em>SSCCE</em> I have added the following for testing purposes :</p>
  
  <pre><code>int xDpi = GetDeviceCaps( pdx.hDC, LOGPIXELSX ),
      yDpi = GetDeviceCaps( pdx.hDC, LOGPIXELSY );
  
  int mapMode = GetMapMode( pdx.hDC );
  
  wchar_t displayDPI[50];
  swprintf_s( displayDPI, 50, L" xDPI = %s , yDPI = %s", xDpi, yDpi );
  MessageBox( hWnd, displayDPI, L"", MB_OK );
  
  switch( mapMode )
  {
  case MM_ANISOTROPIC:
      MessageBox( hWnd, L"MM_ANISOTROPIC", L"", MB_OK );
      break;
  case MM_HIENGLISH:
      MessageBox( hWnd, L"MM_HIENGLISH", L"", MB_OK );
      break;
  case MM_HIMETRIC:
      MessageBox( hWnd, L"MM_HIMETRIC", L"", MB_OK );
      break;
  case MM_ISOTROPIC:
      MessageBox( hWnd, L"MM_ISOTROPIC", L"", MB_OK );
      break;
  case MM_LOENGLISH:
      MessageBox( hWnd, L"MM_LOENGLISH", L"", MB_OK );
      break;
  case MM_LOMETRIC:
      MessageBox( hWnd, L"MM_LOMETRIC", L"", MB_OK );
      break;
  case MM_TEXT:
      MessageBox( hWnd, L"MM_TEXT", L"", MB_OK );
      break;
  case MM_TWIPS:
      MessageBox( hWnd, L"MM_TWIPS", L"", MB_OK );
      break;
  default:
      MessageBeep(0);
      break;
  }
  </code></pre>
  
  <p>In both cases mapping mode was the same ( <code>MM_TEXT</code> ) but for <em>XPS</em> I got <code>xDPI = 600 , yDPI = 600</code> in the <code>MessageBox</code> while <em>OneNote</em> had <code>xDPI = 300 , yDPI = 300</code>.</p>
  
  <p>This leads to the conclusion that comments made by member * Carey Gregory* were correct -> with the same characteristics virtual printers will reproduce the same result. This also explains why <em>OneNote</em> printed properly into <em>XPS</em> when I tested it, and why my application failed. To solve this problem I need to find DPI aware solution...</p>
  
  <h2>EDITED on June, 9th 2014 :</h2>
  
  <p>Using <code>GDI+</code> to create font and draw text I was able to get consistent results ( DPI is no longer a problem ). Still, if anyone knows how to achieve the same result using only <code>GDI</code> I would be still interested.</p>
  
  <p>The only thing left for me is to draw a proper grid so the text can fit into cells properly.</p>
  
  <h2>EDITED on June, 10th 2014 :</h2>
  
  <p>After carefully reading through <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ff684173%28v=vs.85%29.aspx" rel="nofollow noreferrer">this MSDN link</a> I was able to alter the font creating code to achieve ( in my opinion ) stable results ( the actual height of the font ends up way smaller, but I could use bigger number I guess ) :</p>
  
  <pre><code> font = CreateFont( 
      // DPI aware, thanks to the below equation ( or so it seems... )
      lfHeight / ( GetDeviceCaps( pdx.hDC, LOGPIXELSY ) / 96 ), 
      0, 0, 0, FW_BOLD, TRUE, FALSE, FALSE, 0, 0, 0,      // remained the same
      0, 0, L"Microsoft Sans Serif" );                    // remained the same
  </code></pre>
  
  <p>Just to be safe, I will try to stick with <code>GDI+</code> but will update this post with the testing results when <code>GDI</code> and the mentioned equation is used in case someone else stumbles upon the same problem. I just hope it will save that persons time...</p>