How Do I Print a Black Rectangle?

EDN Admin

Well-known member
Joined
Aug 7, 2010
Messages
12,794
Location
In the Machine
Hi Folks:
Developing 32 bit app on Win 7 Ultra 64, VS 2010 Pro, C++, Win32, no MFC.
I have a large app that uses the same function to display the contents of a report on the screens HDC and the printers HDC, using GDI.
The report consists of a lot of text. Several rectangles, drawn with FrameRect(), indicate that different text is grouped together.
The report also uses several circles, drawn with Arc().
The report displays fine on the screen.
The printed report has the text displayed fine, but the rectangles and circles are pail, almost invisible.
For this application, printing to an XPS file, and displaying that file, shows everything properly printed, and printing that XPS file prints text, rectangles and circles properly.
My client reports the same problem with his printed report.
The app is over 100K lines in length, so Ive duplicated the problem with a small program. Ive included that code, its .rc file and resoruce.h.
This sample program uses a function to display a simple collection of a rectangle, an ellipse and two lines. It has a print and a quit button.
This function displays on the screen fine, but doesnt display properly for the printer.
The XPS file has pail lines for 3 sides of the rectangle, and no visible line for the bottom of the rectangle. The lines and ellipse are fine.
The printed page has all elements displayed as pail lines and curves.
What am I doing wrong?
The project uses multi char rather than unicode.
I hope someone can take a look at this.
Here is the source:

<
<

<pre>#include <windows.h>
#include <string>
#include <commctrl.h>
#include "resource.h"

INT_PTR CALLBACK brush_printer_problem_dialog_box(HWND hdlg,
UINT message,
WPARAM wParam,
LPARAM lParam);

bool process_print_button(HWND hwnd, std::string *message_string_ptr);
bool select_printer(HWND hwnd, PRINTDLGEX *print_dialog_struct_ptr);
bool print_cover_sheet(HDC printer_hdc, std::string *message_string_ptr);
bool print_image(HDC printer_hdc, std::string *message_string_ptr);
void draw_image(HDC hdc, int width, int height);

int WINAPI WinMain (HINSTANCE hinstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
INT_PTR dialogbox_return = 0;
DWORD error_code = 0;
char error_message_buffer[256];

SetLastError(0);

dialogbox_return =
DialogBox(hinstance,
"IDD_PRINTER_BRUSH_PROBLEM",
NULL,
(DLGPROC)brush_printer_problem_dialog_box);

}

INT_PTR CALLBACK brush_printer_problem_dialog_box(HWND hdlg,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
HDC hdc = NULL;
std::string local_message_string;
HBRUSH background_brush_handle = NULL;
PAINTSTRUCT ps;
RECT dialog_rect;

switch (message)
{
case WM_CTLCOLORDLG:

background_brush_handle = (HBRUSH)GetStockObject(WHITE_BRUSH);
return INT_PTR(background_brush_handle);

case WM_INITDIALOG:

return FALSE;

case WM_PAINT:

hdc = BeginPaint(hdlg, &ps);
GetClientRect(hdlg, &dialog_rect);

draw_image(hdc, dialog_rect.right - dialog_rect.left,
dialog_rect.bottom - dialog_rect.top);

EndPaint(hdlg, &ps);

return 0;

case WM_COMMAND:

switch(LOWORD (wParam))
{
case IDOK:

if(HIWORD(wParam) == BN_CLICKED)
{
process_print_button(hdlg, &local_message_string);
}

break;

case IDCANCEL:

switch(HIWORD(wParam))
{
case BN_CLICKED:

SetLastError(0);
EndDialog(hdlg, true);

break;
}

return 0;
}
}

return 0;
}

bool process_print_button(HWND hwnd, std::string *message_string_ptr)
{
bool error_found = false;
HDC printer_hdc = NULL;
HINSTANCE hinstance = NULL;
static PRINTDLGEX print_dialog_struct;
std::string local_message_string;

hinstance = HINSTANCE(GetWindowLongPtr(hwnd, GWLP_HINSTANCE));

if(!select_printer(hwnd, &print_dialog_struct))
{
error_found = true;
}
else
{
printer_hdc = print_dialog_struct.hDC;

if(printer_hdc != NULL)
{
print_image(printer_hdc, message_string_ptr);
DeleteDC(printer_hdc);
}
}

return !error_found;
}

bool select_printer(HWND hwnd, PRINTDLGEX *print_dialog_struct_ptr)
{
bool error_found = false;

if(print_dialog_struct_ptr != NULL)
{
memset(print_dialog_struct_ptr, 0x00, sizeof (PRINTDLGEX));

print_dialog_struct_ptr->lStructSize = sizeof (PRINTDLGEX);
print_dialog_struct_ptr->hwndOwner = hwnd;
print_dialog_struct_ptr->Flags = PD_ALLPAGES |
PD_COLLATE |
PD_RETURNDC |
PD_NOSELECTION |
PD_HIDEPRINTTOFILE |
PD_NOPAGENUMS; // Allows page ranges to be ignored.
print_dialog_struct_ptr->nCopies = 1;
print_dialog_struct_ptr->nStartPage = START_PAGE_GENERAL;

if(PrintDlgEx(print_dialog_struct_ptr) != S_OK)
{
error_found = true;
}
}

return !error_found;
}

bool print_image(HDC printer_hdc, std::string *message_string_ptr)
{
bool error_found = false;
static DOCINFO di = {sizeof (DOCINFO), TEXT ("Print Test")};
int x_pixels = 0;
int y_pixels = 0;

if (StartDoc(printer_hdc, &di) > 0)
{
x_pixels = GetDeviceCaps(printer_hdc, HORZRES);
y_pixels = GetDeviceCaps(printer_hdc, VERTRES);

if(StartPage(printer_hdc) > 0)
{
draw_image(printer_hdc, x_pixels, y_pixels);
EndPage(printer_hdc);
}

EndDoc(printer_hdc);
}

return !error_found;
}

void draw_image(HDC hdc, int width, int height)
{
RECT test_rect;
HBRUSH stock_black_brush_handle = (HBRUSH)GetStockObject(BLACK_BRUSH);
HPEN stock_black_pen_handle = (HPEN)GetStockObject(BLACK_PEN);
HBRUSH original_brush = (HBRUSH)SelectObject(hdc, stock_black_brush_handle);
HPEN original_pen = (HPEN)SelectObject(hdc, stock_black_pen_handle);

test_rect.left = width >> 2;
test_rect.right = width - test_rect.left;
test_rect.top = height >> 2;
test_rect.bottom = height - test_rect.top;


FrameRect(hdc, &test_rect, stock_black_brush_handle);

Arc(hdc, test_rect.left,
test_rect.top,
test_rect.right,
test_rect.bottom,
test_rect.right,
test_rect.bottom,
test_rect.right,
test_rect.bottom);

MoveToEx(hdc, test_rect.left, test_rect.top, NULL);
LineTo(hdc, test_rect.right, test_rect.bottom);
MoveToEx(hdc, test_rect.left, test_rect.bottom, NULL);

LineTo(hdc, test_rect.right, test_rect.top);
SelectObject(hdc, original_brush);
SelectObject(hdc, original_pen);
}
[/code]
<br/>
<br/>

<
<
<br/>
Here is the .rc file:<br/>
<
<
<br/>
<pre>// Microsoft Visual C++ generated resource script.
//
#include "resource.h"

#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"

/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS

/////////////////////////////////////////////////////////////////////////////
// English (United States) resources

#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US

#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//

1 TEXTINCLUDE
BEGIN
"resource.h"
END

2 TEXTINCLUDE
BEGIN
"#include ""afxres.h""rn"
""
END

3 TEXTINCLUDE
BEGIN
"rn"
""
END

#endif // APSTUDIO_INVOKED


/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//

IDD_PRINTER_BRUSH_PROBLEM DIALOGEX 0, 0, 316, 183
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "Dialog"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
DEFPUSHBUTTON "Print",IDOK,106,162,50,14
PUSHBUTTON "Cancel",IDCANCEL,160,162,50,14
END


/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//

#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
"IDD_PRINTER_BRUSH_PROBLEM", DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 309
TOPMARGIN, 7
BOTTOMMARGIN, 176
END
END
#endif // APSTUDIO_INVOKED

#endif // English (United States) resources
/////////////////////////////////////////////////////////////////////////////



#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//


/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

[/code]
<br/>
<br/>
<
<
<br/>
Here is the resource.h file:<br/>
<
<
<br/>
<pre>//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by printer_brush_problem.rc
//
#define IDD_DIALOG1 101

// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 102
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
[/code]
<br/>
<br/>
<
<

View the full article
 
Back
Top