CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 5 of 5
  1. #1
    Join Date
    May 2010
    Posts
    6

    EM_FORMATRANGE keeps returning smaller ranges

    I'm using EM_FORMATRANGE to print from a RichEdit control to a printer. However, at a certain point, there are fewer and fewer lines on each page and the number of lines gets progressively smaller. This doesn't happen when I use EM_STREAMOUT on the RichEdit so I know it's the printing code I'm using.

    Below is the code I'm currently using. Please note the call to OutputDebugString
    Code:
      int left = GetDeviceCaps(dc, PHYSICALOFFSETX);
      int top = GetDeviceCaps(dc, PHYSICALOFFSETY);
      int width = GetDeviceCaps(dc, PHYSICALWIDTH);
      int height = GetDeviceCaps(dc, PHYSICALHEIGHT);
      int right = width - (left + GetDeviceCaps(dc, HORZRES));
      int bottom = height - (top + GetDeviceCaps(dc, VERTRES));
    
      FORMATRANGE format;
    
      format.hdc = dc;
      format.hdcTarget = dc;
      format.chrg.cpMin = 0;
      format.chrg.cpMax = -1;
    
      width = (int)(8.5 * 1440); // Letter width in TWIPS
      height = (int)(11 * 1440); // Letter height in TWIPS
    
      format.rcPage.left = 0;
      format.rcPage.top = 0;
      format.rcPage.right = width;
      format.rcPage.bottom = height;
    
      bool useMinimal = true;
    
      if (SendDlgItemMessage(mDialog, IDR_CUSTOMMARGIN, BM_GETCHECK, NULL, NULL) == BST_CHECKED){
        useMinimal = false;
    
        if (mCustLeft < left || mCustRight < right || mCustTop < top || mCustBottom < bottom){
          if (MessageBox(mDialog, "The custom margins are outside the selected printer's bounds. Would you like to use the anyway? Press No to use the printer's minimum margins.", "Story Folder", MB_YESNO|MB_APPLMODAL) == IDNO){
            useMinimal = true;
          } 
        }
      } 
      
      if (useMinimal){
        //  Minimal margins
        format.rc.left = left;
        format.rc.right = width - right;
        format.rc.top = top;
        format.rc.bottom = height - bottom;
      } else {
        format.rc.left = mCustLeft;
        format.rc.right = width - mCustRight;
        format.rc.top = mCustTop;
        format.rc.bottom = height - mCustBottom;
      }
    
      SendMessage(hwnd, EM_EXSETSEL, 0, (LPARAM)&format.chrg); // Select everything
      SendMessage(hwnd, EM_EXGETSEL, 0, (LPARAM)&format.chrg); // Fill in the charrange for the whole selection 
    
      SendMessage(hwnd, EM_SETTARGETDEVICE, (WPARAM)dc, width);
      
      bool success = true;
      int min;
      int page = 0;
      char buffer[100];
    
      while (format.chrg.cpMin < format.chrg.cpMax && success){
        success = StartPage(dc) > 0;
    
        if (!success) break;
    
        ++page;
    
        min = SendMessage(hwnd, EM_FORMATRANGE, TRUE, (LPARAM)&format);
        
        if (min <= format.chrg.cpMin){
          success = false;
          
          break;
        }
        
        sprintf(buffer, "\r\n(%d): %d", page, min - format.chrg.cpMin);
        OutputDebugString(buffer);
    
        format.chrg.cpMin = min;
        
        success = EndPage(dc) > 0;
    
        if (!success) break;
      }
    
      SendMessage(hwnd, EM_FORMATRANGE, FALSE, NULL);
    
      return success;
    Here is the debug output from the loop:

    Code:
    (1): 1249
    (2): 1148
    (3): 1365
    (4): 1193
    (5): 1125
    (6): 980
    (7): 1053
    (8): 1134
    (9): 1083
    (10): 1313
    (11): 1199
    (12): 1092
    (13): 932
    (14): 914
    (15): 796
    (16): 638
    (17): 822
    (18): 751
    (19): 858
    (20): 981
    (21): 663
    (22): 866
    (23): 788
    (24): 691
    (25): 715
    (26): 827
    (27): 595
    (28): 718
    (29): 703
    (30): 469
    (31): 486
    (32): 470
    (33): 478
    (34): 693
    (35): 474
    (36): 471
    (37): 467
    (38): 560
    (39): 696
    (40): 331
    (41): 40
    Any help with why my code is doing this would be very much appreciated.

  2. #2
    Join Date
    Apr 2009
    Posts
    598

    Re: EM_FORMATRANGE keeps returning smaller ranges

    Below
    Code:
    format.chrg.cpMin = min;
    Try
    Code:
    format.chrg.cpMax = -1;
    See http://support.microsoft.com/?scid=k...9860&x=10&y=12

  3. #3
    Join Date
    May 2010
    Posts
    6

    Re: EM_FORMATRANGE keeps returning smaller ranges

    Quote Originally Posted by olivthill2 View Post
    Below
    Code:
    format.chrg.cpMin = min;
    Try
    Code:
    format.chrg.cpMax = -1;
    See http://support.microsoft.com/?scid=k...9860&x=10&y=12
    Thank you for your suggestion. In the code I provided please note the lines
    Code:
      format.chrg.cpMin = 0;
      format.chrg.cpMax = -1;
    and

    Code:
      SendMessage(hwnd, EM_EXSETSEL, 0, (LPARAM)&format.chrg); // Select everything
      SendMessage(hwnd, EM_EXGETSEL, 0, (LPARAM)&format.chrg); // Fill in the charrange for the whole selection
    The final call to SendMessage fills in the CHARRANGE with the true character indexes for the RichEdit. Using 0 and -1 is a simply a way of avoiding having to find the absolute ranges. However, I made the change you suggested but it gave the same results.

  4. #4
    Join Date
    May 2010
    Posts
    6

    Re: EM_FORMATRANGE keeps returning smaller ranges

    Well, I discovered the source of the problem but not why it's happening. For fun, I watched the values of the FORMATRANGE struct that I pass to EM_FORMATRANGE after each call to SendMessage. As it turns out, the value of rc.bottom keeps shrinking and not by a consistent amount.

    I updated the loop to the following code and this has corrected the problem but I can't imagine why this would happen in the first place. Any ideas?

    Code:
      RECT saveRect;
    
      memcpy(&saveRect, &format.rc, sizeof(RECT));
    
      while (format.chrg.cpMin < format.chrg.cpMax && success){
        if (!(StartPage(dc) > 0)){
          OutputDebugString("\r\nPrintLoop failure on StartPage");
    
          success = false;
          
          break;
        }
    
        min = SendMessage(hwnd, EM_FORMATRANGE, TRUE, (LPARAM)&format);
    
        memcpy(&format.rc, &saveRect, sizeof(RECT));
        
        if (min <= format.chrg.cpMin){
          success = false;
          
          break;
        }
        
        ++page;
    
        sprintf(buffer, "\r\n(%d): %d", page, min - format.chrg.cpMin);
        OutputDebugString(buffer);
    
        format.chrg.cpMin = min;
        
        if (!(EndPage(dc) > 0)){
          OutputDebugString("\r\nPrintLoop failure on StartPage");
    
          success = false;
          
          break;
        }
      }

  5. #5
    Join Date
    May 2010
    Posts
    6

    Re: EM_FORMATRANGE keeps returning smaller ranges

    For anyone coming to this thread now, my "band-aid" solution was actually the correct solution. This behaviour is part of EM_FORMATRANGE.

    Here's the answer I received from the MSDN forums:

    EM_FORMATRANGE will set rc.bottom within the FORMATRANGE struct to be the
    bottom of the area actually printed to, so this must be reset between calls
    to make sure that the page boundaries are consistent between the pages

    http://osdir.com/ml/wine-cvs/2010-01/msg00497.html

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured