Printing problems--->ARG!

Hi All,

I've got a vc++.net project that when needed prints from a listview form. Here's an example I found on MSDN:

http://msdn.microsoft.com/library/d...p agetopic.asp

This is a an example of how to print one line per row starting at the left most of the page for the xaxis. Like I said before, I have a listview with multiple rows AND columns. Anyways, I got the columns printing where they should under each column. Great.

Then I had to implement code that would print out the columns and rows etc... properly even if the user had completely covered the values in the listview. I had to create my own ratio of screen font to print font to figure out how to do that. I set up column minimum limits and have a function that removes charaters until they fit under the appropriate columns WITHOUT overlapping. Here's an example of what I mean:

Normal print:
Vendor------PartD---Description
Johnny_Boy-123456-wrench

User overlaps the listview fields completely and prints:
Vendor-Part-Description
Johnny_1234wrench

Anyways my ratio seemed ok but now I have to right align some fields (ARRG!). Here's my code so far:

private: System::Void printPickList_PrintPage(System::Object * sender, System:rawing:rinting:rintPageEventArgs * e)
{
float linesPerPage = 0;
float xPos=0;
float yPos = 0;
int count = 2;
float leftMargin = (float)e->MarginBounds.Left;
float topMargin = (float)e->MarginBounds.Top;
ListViewItem* line;
bool moreLines=false;
String* description = new String("Description");
String* vendor = new String("Vendor");
String* substitute = new String("");
String* part = new String("Part");
String* qty = new String("Qty.");
String* bin = new String("Bin");
String* onhand = new String("On Hand");
String* onorder = new String("On Order");
String* price = new String("Price");
String* cost = new String("Cost");

//Ratio created to support the sizing difference between
//the print width and the text width.
double ratio = 7.15152;

//Dealing with the xaxis of text
double value = 0.0;

// Calculate the number of lines per page.
linesPerPage = e->MarginBounds.Height / printFont->GetHeight(e->Graphics);

if (pfwSettings->HeaderPrintOut->Length>0) {
e->Graphics->DrawString(pfwSettings->HeaderPrintOut, printUnderlineFont, Brushes::Black, leftMargin, topMargin , new StringFormat());
String *delim = "
";
String *split[] = pfwSettings->HeaderPrintOut->Split(delim->ToCharArray());
count+=split->Length;
} else {
e->Graphics->DrawString(pfwSettings->WindowTitle, printUnderlineFont, Brushes::Black, leftMargin, topMargin , new StringFormat());
}

yPos = topMargin + (count * printFont->GetHeight(e->Graphics));
xPos = 0;
if (!pfwSettings->Print_HideVendor) {
e->Graphics->DrawString(vendor, printUnderlineFont, Brushes::Black, xPos, yPos, new StringFormat());
xPos += convertViewWidthToPrintWidth(clmn_Vendor->Width, vendor->Length, ratio,0);
}

if (!pfwSettings->Print_HideSubstitute) {
e->Graphics->DrawString(substitute, printUnderlineFont, Brushes::Black, xPos, yPos, new StringFormat());
xPos += convertViewWidthToPrintWidth(clmn_Subs->Width,substitute->Length, ratio,0);
}

e->Graphics->DrawString(part, printUnderlineFont, Brushes::Black, xPos, yPos, new StringFormat());
xPos += convertViewWidthToPrintWidth(clmn_Part->Width, part->Length, ratio,1);

if (!pfwSettings->Print_HideDescription) {
e->Graphics->DrawString(description, printUnderlineFont, Brushes::Black, xPos, yPos, new StringFormat());
xPos += convertViewWidthToPrintWidth(clmn_Description->Width, description->Length, ratio,0);
}

e->Graphics->DrawString(qty, printUnderlineFont, Brushes::Black, xPos, yPos, new StringFormat());
xPos += convertViewWidthToPrintWidth(clmn_Qty->Width, qty->Length, ratio,2);

if (!pfwSettings->Print_HideBinLocation) {
e->Graphics->DrawString(bin, printUnderlineFont, Brushes::Black, xPos, yPos, new StringFormat());
xPos += convertViewWidthToPrintWidth(clmn_BinLoc->Width, bin->Length, ratio,3);
}

if (!pfwSettings->Print_HideOnHand) {
e->Graphics->DrawString(onhand, printUnderlineFont, Brushes::Black, xPos, yPos, new StringFormat());
xPos += convertViewWidthToPrintWidth(clmn_OnHand->Width, onhand->Length, ratio,0);
}

if (!pfwSettings->Print_HideOnOrder) {
e->Graphics->DrawString(onorder, printUnderlineFont, Brushes::Black, xPos, yPos, new StringFormat());
xPos += convertViewWidthToPrintWidth(clmn_OnOrder->Width,onorder->Length, ratio,0);
}

if (!pfwSettings->Print_HidePrice) {
e->Graphics->DrawString(price, printUnderlineFont, Brushes::Black, xPos, yPos, new StringFormat());
xPos += convertViewWidthToPrintWidth(clmn_UnitPrice->Width,price->Length, ratio,0);
}

if (!pfwSettings->Print_HideCost) {
e->Graphics->DrawString(cost, printUnderlineFont, Brushes::Black, xPos, yPos, new StringFormat());
}
count+=2;

// Print each line of the file.
while(count < linesPerPage && (moreLines=itemsToPrint->MoveNext()) )
{

line = dynamic_cast(itemsToPrint->Current);
yPos = topMargin + (count * printFont->GetHeight(e->Graphics));

xPos = 0;
if (!pfwSettings->Print_HideVendor) {
value = convertViewWidthToPrintWidth(clmn_Vendor->Width, vendor->Length, ratio,0);
e->Graphics->DrawString(convertTextForPrintWidth(line->SubItems->Item[1]->Text,value,ratio,0), printFont, Brushes::Black, xPos, yPos, new StringFormat());
xPos += (float)value;
}

if (!pfwSettings->Print_HideSubstitute) {
value = convertViewWidthToPrintWidth(clmn_Subs->Width, substitute->Length, ratio,0);
e->Graphics->DrawString(convertTextForPrintWidth(line->SubItems->Item[2]->Text,value,ratio,0), printFont, Brushes::Black, xPos, yPos, new StringFormat());
xPos += (float)value;
}

value = convertViewWidthToPrintWidth(clmn_Part->Width, part->Length, ratio,1);
e->Graphics->DrawString(convertTextForPrintWidth(line->SubItems->Item[3]->Text,value,ratio,1), printFont, Brushes::Black, xPos, yPos, new StringFormat());
xPos += (float)value;

if (!pfwSettings->Print_HideDescription) {
value = convertViewWidthToPrintWidth(clmn_Description->Width, description->Length, ratio,0);
e->Graphics->DrawString(convertTextForPrintWidth(line->SubItems->Item[4]->Text,value,ratio,0), printFont, Brushes::Black, xPos, yPos, new StringFormat());
xPos += (float)value;
}

value = convertViewWidthToPrintWidth(clmn_Qty->Width, qty->Length, ratio,2);
e->Graphics->DrawString(convertTextForPrintWidth(line->SubItems->Item[5]->Text,value,ratio,2), printFont, Brushes::Black, xPos, yPos, new StringFormat());
xPos += (float)value;

if (!pfwSettings->Print_HideBinLocation) {
value = convertViewWidthToPrintWidth(clmn_BinLoc->Width, bin->Length, ratio,3);
e->Graphics->DrawString(convertTextForPrintWidth(line->SubItems->Item[6]->Text,value,ratio,3), printFont, Brushes::Black, xPos, yPos, new StringFormat());
xPos += (float)value;
}

if (!pfwSettings->Print_HideOnHand) {
value = convertViewWidthToPrintWidth(clmn_OnHand->Width, onhand->Length, ratio,0);
e->Graphics->DrawString(convertTextForPrintWidth(line->SubItems->Item[7]->Text,value,ratio,0), printFont, Brushes::Black, xPos, yPos, new StringFormat());
xPos += (float)value;
}

if (!pfwSettings->Print_HideOnOrder) {
value = convertViewWidthToPrintWidth(clmn_OnOrder->Width, onorder->Length, ratio,0);
e->Graphics->DrawString(convertTextForPrintWidth(line->SubItems->Item[8]->Text,value,ratio,0), printFont, Brushes::Black, xPos, yPos, new StringFormat());
xPos += (float)value;
}

if (!pfwSettings->Print_HidePrice) {
value = convertViewWidthToPrintWidth(clmn_UnitPrice->Width, price->Length, ratio,0);
e->Graphics->DrawString(convertTextForPrintWidth(line->SubItems->Item[9]->Text,value,ratio,0), printFont, Brushes::Black, xPos, yPos, new StringFormat());
xPos += (float)value;
}

if (!pfwSettings->Print_HideCost) {
value = convertViewWidthToPrintWidth(clmn_Cost->Width, cost->Length, ratio,0);
e->Graphics->DrawString(convertTextForPrintWidth(line->SubItems->Item[10]->Text,value,ratio,0), printFont, Brushes::Black, xPos, yPos, new StringFormat());
}

count++;
}

// If more lines exist, print another page.
if (moreLines) {
e->HasMorePages = true;
} else {
e->HasMorePages = false;
}
}
//This function takes care of the spacing between the fields
private:float convertViewWidthToPrintWidth(int len, int textLen, double ratio, int vipField)
{
//Minimum value a field is allowed to be moved
float min=0;
System:rawing::Font* viewFont = lv_Parts->Font;

//vipField's are Part, Qty and Bin
//The title of the field (and the text underneath)
//must be of a specified width.
switch(vipField)
{
//Part
case 1 :
if(textLen<=15)
{
textLen += 15 - textLen;
}
break;

//Qty
case 2 :
if(textLen<=4)
{
textLen += 4 - textLen;
}
break;

//Bin
case 3 :
if(textLen<=10)
{
textLen += 10 - textLen;
}
break;

default:
break;
}

//If no vip fields were encountered then use the textLen passed in
min = ((textLen * (float)ratio)/viewFont->Size)*printFont->Size;

//The actual width of the field selected by user on the main menu.
float value = (len/viewFont->Size)*printFont->Size;

//If the value is less than the minimum size setup above
//set the value to the minimum.
if(value < min)
{
value = min;
}

return value;
}

//This function will format the text passed in so that it will fit according
//to the field width size established in convertViewWidthToPrintWidth(...).
private:String* convertTextForPrintWidth(String* text, double value, double ratio, int vipField)
{
//Used below to determine if two fields are close together.
double limit = 40.0;

//Using the ratio we can find out how much space
//the text will need.
double textRatio = text->Length * ratio;
Boolean forLoopBreak = false;

//If this is true the text is overlapping onto the next field
if(textRatio > value)
{
//Loop through and while the text is overlapping
//remove a char from the string until it no longer overlaps.
for(int y = (text->Length - 1);y>0;y--)
{
textRatio = text->Length * ratio;

//Vip fields are preset and should not have
//chars removed unless larger than the allowable format.
// Part(15), Qty(4), Bin(10)
switch(vipField)
{
case 1 :
if(text->Substring(0,y)->Length<=15)
{
forLoopBreak = true;
}
else
{
text = text->Substring(0,y);
}
break;

case 2 :
if(text->Substring(0,y)->Length<=4)
{
forLoopBreak = true;
}
else
{
text = text->Substring(0,y);
}
break;

case 3 :
if(text->Substring(0,y)->Length<=10)
{
forLoopBreak = true;
}
else
{
text = text->Substring(0,y);
}
break;
default:
text = text->Substring(0,y);
break;
}

//Vip field is the right size
//therefore break out of the loop.
if(forLoopBreak == true)
{
break;
}

//Is it finally not overlapping?
if(textRatio < value)
{
//If its close continue on and take another
//char off, otherwise break out.
if((value - textRatio) < (ratio * 1.5))
{
continue;
}
else
{
break;
}
}
}
}
else if((value>limit) && (text->Length * ratio) > (value - 40))
{
//If the app runs through here then two fields are near
//each other and have the danger of overlapping. A field
//being completely or semi covered by another field has already been
//taken care of.
//Therefore this block of code is when one field edge is very
//close to another and yet the textRatio is NOT greater than value.
//ie: Not overlapping but close.

//This will represent just how close they are
double difference = 0.0;
difference = (text->Length * ratio) - (value - 40);

//Never change preset vip fields in this case
if(!(vipField>0))
{
//Close but not overlapping
if(difference<10.0)
{
text = text->Substring(0, (text->Length));
}
else if(difference<15.0)//Too close, knock off a char
{
text = text->Substring(0, (text->Length - 1));
}
else if(difference<20.0)
{
text = text->Substring(0, (text->Length - 2));
}
else
{
text = text->Substring(0, (text->Length - 3));
}
}
}

return text;
}

Has anyone dealt with complex printing like this before? Is there a more accurate way to determine spacing on the xaxis when printing?

I mean in the MSDN example above they have this:

linesPerPage = e->MarginBounds.Height / printFont->GetHeight(e->Graphics);

Which deals with figuring out exactly the amount of lines per page. I've since found you can't do this to find out the exact amount of chars you can go width wise. Like this:

charWidthPerPage = e->MarginBounds.Width / printFont->GetWidth(e->Graphics);

Unfortunately, printFont does not have a getWidth member. Thus my need for my ratio. I'd like to remove that ratio all together so I can exactly determine my xaxis spacing properly. The code is getting pretty complicated and it isn't even dead exact. Anyone have any suggestions? Tips, Tricks or helpful links?

Any help would be outstanding,
Todd

Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Categories