• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 820
  • Last Modified:

Tab spaces in RichEdit

I have information which is read from arrays and displayed onto a RichEdit component.

Each record contains 3 lines of information then I loop and display the next three lines of information for record 2.  The information would look like this:

Record 1:                      Name
Info1             Info2                    Info3
Type1                    Type2             Type3          Type4

I know how to select all of a RichEdit and apply tabstops but this is assuming that each line has the same tabstops.  My question is how to I apply different tabstops to each line in a richEdit component.

I had tried to put the code below one line of the Richedit

RichEdit1->SelStart = 0;
RichEdit1->SelLength =  (I am unsure of the length of the first line as the length is not always the same)
The above line of code didnt work as im unsure of the length


Any help would be greatly appreciated
0
lisa_mc
Asked:
lisa_mc
  • 13
  • 8
1 Solution
 
pivarCommented:
Hi,

I believe you can use the EM_LINELENGTH message to retrieve it.

REdit.Perform(EM_LINELENGTH, REdit.SelStart,0) ;

/peter
0
 
lisa_mcAuthor Commented:
Hey Peter

So would I use the code

TParaFormat* pParaFormat1 = new TParaFormat;
pParaFormat1->cbSize = sizeof(TParaFormat);
pParaFormat1->cTabCount = 2;
pParaFormat1->rgxTabs[0] = 2000;
pParaFormat1->rgxTabs[0] = 4000;
pParaFormat1->dwMask = PFM_TABSTOPS;

in my main program then the line below:

REdit.Perform(EM_LINELENGTH, REdit.SelStart,0) ;

under the first line of my RichEdit?

Sorry I just don't understand how that line links to my tab spacing where do I set the tabspaces?
0
 
pivarCommented:
I may have misunderstood you, but I thought you wanted to get the length to fill SelLength. I don't have knowledge on changing tabs, which I thought you already know.

I did gave you some Delphi code, more as a pointer. In C++ Builder I think it should read:

RichEdit1->SelLength = RichEdit1->Perform(EM_LINELENGTH, RichEdit1->SelStart,0)

0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
lisa_mcAuthor Commented:
Sorry I understand the code now but  I forgot to mention that I have a header of 3 lines at the top so the line I want to select would be the fifth line in the RIchEdit component so I cant use SelStart = 0 is there a way around this?
0
 
lisa_mcAuthor Commented:
I will try and explain a bit better below is a layout of my RIchEdit Component

Header1
Header2


Record1                         Name
Info1              info2              info3
type1        type2              type3            type4

Record2                        Name
Info1             info2                info3
type1        type2              type3            type4

Record3                        Name
info1             info2                 info3
type1        type2              type3             type4

and so on.  All my records are read from arrays and there are 9 records to each page then I have a page break.  On a new page is the header as shown above then another 9 records.  Each loop writes exactly one record to the richEdit component, then I increment a counter which writes the second record and so on.

I would like some way of selecting the record line from start of that line to end of that line (length can be different for each record).  I then want to select the second and third line seperatly for each record again length can be different.  

I know how to apply tabstops Im just not sure how to select each line

PLease can you help as this would make my presentation alot better
0
 
pivarCommented:
Add the length of each line up to the fifth line.

int start = 0;
for (int i = 0; i < 5; i++) start += RichEdit1->Perform(EM_LINELENGTH, start ,0) ;


0
 
lisa_mcAuthor Commented:
the above solution wont work because for the first record it will start on line 5 the next record will start on line 9.  (record 1 starts on line 5 record 2 will start on line 9)

Each loop only writes one record to the Richedit at a time
0
 
pivarCommented:
The above shows how to find the position of the fifth line. Then you can build on that.

int start = 0;
for (int i = 0; i < 4; i++) start += RichEdit1->Perform(EM_LINELENGTH, start, 0) ;       // I changed to 4 here
// start is position of 5th line

int start1 = start;
for (int i = 0; i < 3; i++) start1 += RichEdit1->Perform(EM_LINELENGTH, start1, 0) ;
// start1 is position of 8th line, start1 - start = length of first record
start1 += RichEdit1->Perform(EM_LINELENGTH, start1, 0) ;
// start1 is position of 9th line

int start2 = start1;
for (int i = 0; i < 3; i++) start2 += RichEdit1->Perform(EM_LINELENGTH, start2 ,0) ;
// start2 is position of 12th line, start2 - start1= length of 2nd record

And so on
0
 
lisa_mcAuthor Commented:
Sorry again im not sure if you understand what I mean, ill show you code

linecount2b is the number of records stored in my text file so if 10 records in file then I will be printing 30 lines of information to the screen as each record has 3 lines.

Once each line has printed the loop starts over again and prints the exact same 3 lines again (only some information could be different depending on the machine).

This is why I think your solution will not work because on the first increment of the loop the first record will start at line 5 the next record will start at line 9 and so on.

Plus I can't count each record as 3 lines because I need to space each line within a record differently

ie line 1 could have 2 tabstops
line 2 will have 3 tabstops and line 4 will have 4 tabstops

this is why I need to be able to read from the start to end of each individual line is there a way of doing this?

Hope this clears it up
for(int i=0; i<linecount2b; i++)
{
        if(i == 0)
        {
RichEdit1->Lines->Append("Machine Printout for "+AnsiString(arcade)+" arcade    Date Printed: "+AnsiString(Date())+"    Page: "+AnsiString(pages));
                        RichEdit1->Lines->Append("Batch: "+AnsiString(b_meter[i])+"    Percentage range: "+AnsiString(b_minpercentvaluew[i])+"% - "+AnsiString(b_maxpercentvaluew[i])+"%    Limit Range: £"+AnsiString(b_minlimitvaluew[i])+" - £"+AnsiString(b_maxlimitvaluew[i]));
                        RichEdit1->Lines->Append("\n");
                        pages++;
      }
 
// line 1 of record
 
RichEdit1->Lines->Append("B: "+AnsiString(b_meter[i])+" C: "+AnsiString(c_meter[i])+AnsiString("\t")+AnsiString(array2c[i].machine_namec2.c_str())+AnsiString("\t")+AnsiString(array2c[i].date_setupc2.c_str()));
 
// line 2 of record
 
RichEdit1->Lines->Append(AnsiString(percentage2b1[i].c_str())+AnsiString("%")+AnsiString("\t")+"THERE ARE NO TOTALS FOR THIS MACHINE");
 
// line 3 of record
                
RichEdit1->Lines->Append("c = "+AnsiString(moneycount2b1[i].c_str())+AnsiString("\t")+AnsiString("    ")+"e = "+AnsiString(exp_count2b1[i].c_str())+AnsiString("\t")+AnsiString("    ")+"r = "+AnsiString(refill_count2b1[i].c_str())+AnsiString("\t")+AnsiString("    ")+"f = "+AnsiString(flt_count2b1[i].c_str())+AnsiString("\t")+AnsiString("    ")+"b = "+AnsiString(total_count2b1[i].c_str())+AnsiString("\t")+AnsiString("    ")+"s/o = "+AnsiString(stockprice1[add2].c_str())+AnsiString("\t")+"d = "+AnsiString(actual_balance2b1[i].c_str()));
 
}
                        

Open in new window

0
 
lisa_mcAuthor Commented:
I have shown all code but as ive mentioned before each page holds 9 records and the header as shown above (check i==0) I have to include page breaks as I later write this information to an rtf document and wanted a new page everytime a b number changed
0
 
pivarCommented:
I don't think I understand what you need. I have shown you how to get the length of a line in the rtf control and find the startposition for each line. What are you missing? What do you want to do?

It's even easier to retrieve length of line if you do it in the loop.


int start = 0;
for(int i=0; i<linecount2b; i++)
{

        if(i == 0)
        {
RichEdit1->Lines->Append("Machine Printout for "+AnsiString(arcade)+" arcade    Date Printed: "+AnsiString(Date())+"    Page: "+AnsiString(pages));
                        RichEdit1->Lines->Append("Batch: "+AnsiString(b_meter[i])+"    Percentage range: "+AnsiString(b_minpercentvaluew[i])+"% - "+AnsiString(b_maxpercentvaluew[i])+"%    Limit Range: £"+AnsiString(b_minlimitvaluew[i])+" - £"+AnsiString(b_maxlimitvaluew[i]));
                        RichEdit1->Lines->Append("\n");
                        pages++;
      }
 
// line 1 of record


RichEdit1->SelStart = RichEdit1->Text.Length() - 1;   // Start selection

RichEdit1->Lines->Append("B: "+AnsiString(b_meter[i])+" C: "+AnsiString(c_meter[i])+AnsiString("\t")+AnsiString(array2c[i].machine_namec2.c_str())+AnsiString("\t")+AnsiString(array2c[i].date_setupc2.c_str()));

RichEdit1->SelLength =  RichEdit1->Text.Length() - 1;    // End of selection

RichEdit1->Perform(EM_SETPARAFORMAT,0,Integer(pParaFormat1));     // APPLY YOUR TABS WITH CURRENT SELECTION
 
// line 2 of record
 
RichEdit1->Lines->Append(AnsiString(percentage2b1[i].c_str())+AnsiString("%")+AnsiString("\t")+"THERE ARE NO TOTALS FOR THIS MACHINE");
 
// line 3 of record
               
RichEdit1->Lines->Append("c = "+AnsiString(moneycount2b1[i].c_str())+AnsiString("\t")+AnsiString("    ")+"e = "+AnsiString(exp_count2b1[i].c_str())+AnsiString("\t")+AnsiString("    ")+"r = "+AnsiString(refill_count2b1[i].c_str())+AnsiString("\t")+AnsiString("    ")+"f = "+AnsiString(flt_count2b1[i].c_str())+AnsiString("\t")+AnsiString("    ")+"b = "+AnsiString(total_count2b1[i].c_str())+AnsiString("\t")+AnsiString("    ")+"s/o = "+AnsiString(stockprice1[add2].c_str())+AnsiString("\t")+"d = "+AnsiString(actual_balance2b1[i].c_str()));
 
}
0
 
lisa_mcAuthor Commented:
got the first line working - i wont be in the office tomorrow can you please come back and check on thursday morning

Many thanks
0
 
lisa_mcAuthor Commented:
got the first line working except for the very first record.

My problem now is how do i select the second and third line in my loop could you help?
0
 
lisa_mcAuthor Commented:
Sorry ive just checked all my records and the first line is not working

Attached is the code for first line

Can you see what im doing wrong
         TParaFormat* pParaFormat2 = new TParaFormat;
        pParaFormat2->cbSize = sizeof(TParaFormat);
        pParaFormat2->cTabCount = 2;
        pParaFormat2->rgxTabs[0] = 2000;
        pParaFormat2->rgxTabs[1] = 7000;
        pParaFormat2->dwMask = PFM_TABSTOPS;
 
RichEdit1->SelStart = RichEdit1->Text.Length() - 1;   // Start selection
 
                RichEdit1->Lines->Append("B: "+AnsiString(b_meter[i])+" C: "+AnsiString(c_meter[i])+AnsiString("\t")+AnsiString(array2c[i].machine_namec2.c_str())+AnsiString("\t")+AnsiString(array2c[i].date_setupc2.c_str()));
 
                RichEdit1->SelLength =  RichEdit1->Text.Length() - 1;    // End of selection
 
 
                RichEdit1->Perform(EM_SETPARAFORMAT,0,Integer(pParaFormat2));     // APPLY YOUR TABS WITH CURRENT SELECTION

Open in new window

0
 
pivarCommented:
Can you explain what's not working?
0
 
lisa_mcAuthor Commented:
when i apply the above code to the first line of my record the tabstops are not working, have I selected the first line correctly
0
 
lisa_mcAuthor Commented:
I have got a feeling you really don't understand what im trying to do?

Referring to your code about getting the start position for each line

int start = 0;
for (int i = 0; i < 4; i++) start += RichEdit1->Perform(EM_LINELENGTH, start, 0) ;       // I changed to 4 here
// start is position of 5th line

int start1 = start;
for (int i = 0; i < 3; i++) start1 += RichEdit1->Perform(EM_LINELENGTH, start1, 0) ;
// start1 is position of 8th line, start1 - start = length of first record
start1 += RichEdit1->Perform(EM_LINELENGTH, start1, 0) ;
// start1 is position of 9th line

int start2 = start1;
for (int i = 0; i < 3; i++) start2 += RichEdit1->Perform(EM_LINELENGTH, start2 ,0) ;
// start2 is position of 12th line, start2 - start1= length of 2nd record

And so on

You are starting at line 5 which I understand as this includes the header then you are finding the length to line 8 which is the length of the record but I dont need the length of the record I need the length of each line within the record

Line 1
Line 2
Line3

I need the length of each individual line not the combination of all three lines.  Then  you start at line 9 and finish at line 12 again giving me the total length of each record - if I have got this wrong could you tell me your understanding of what you think im trying to do
0
 
pivarCommented:
As I understand you, you want to apply different tabstops on each line of the record? I showed you how to apply tabstops to the first line, do the same for each line. I also changed selectedlength computation.
// line 1 of record
 
 
RichEdit1->SelStart = RichEdit1->Text.Length() - 1;   // Start selection 
 
RichEdit1->Lines->Append("B: "+AnsiString(b_meter[i])+" C: "+AnsiString(c_meter[i])+AnsiString("\t")+AnsiString(array2c[i].machine_namec2.c_str())+AnsiString("\t")+AnsiString(array2c[i].date_setupc2.c_str()));
 
RichEdit1->SelLength =  RichEdit1->Text.Length() - RichEdit1->SelStart;    // End of selection
 
RichEdit1->Perform(EM_SETPARAFORMAT,0,Integer(pParaFormat1));     // APPLY YOUR TABS FOR LINE 1 WITH CURRENT SELECTION
 
// line 2 of record
 
RichEdit1->SelStart = RichEdit1->Text.Length() - 1;   // Start selection 
 
RichEdit1->Lines->Append(AnsiString(percentage2b1[i].c_str())+AnsiString("%")+AnsiString("\t")+"THERE ARE NO TOTALS FOR THIS MACHINE");
 
 
RichEdit1->SelLength =  RichEdit1->Text.Length() - RichEdit1->SelStart;    // End of selection
 
RichEdit1->Perform(EM_SETPARAFORMAT,0,Integer(pParaFormat1));     // APPLY YOUR TABS FOR LINE 2 WITH CURRENT SELECTION
 
// line 3 of record
 
RichEdit1->SelStart = RichEdit1->Text.Length() - 1;   // Start selection 
                
RichEdit1->Lines->Append("c = "+AnsiString(moneycount2b1[i].c_str())+AnsiString("\t")+AnsiString("    ")+"e = "+AnsiString(exp_count2b1[i].c_str())+AnsiString("\t")+AnsiString("    ")+"r = "+AnsiString(refill_count2b1[i].c_str())+AnsiString("\t")+AnsiString("    ")+"f = "+AnsiString(flt_count2b1[i].c_str())+AnsiString("\t")+AnsiString("    ")+"b = "+AnsiString(total_count2b1[i].c_str())+AnsiString("\t")+AnsiString("    ")+"s/o = "+AnsiString(stockprice1[add2].c_str())+AnsiString("\t")+"d = "+AnsiString(actual_balance2b1[i].c_str()));
 
 
RichEdit1->SelLength =  RichEdit1->Text.Length() - RichEdit1->SelStart;    // End of selection
 
RichEdit1->Perform(EM_SETPARAFORMAT,0,Integer(pParaFormat1));     // APPLY YOUR TABS FOR LINE 3 WITH CURRENT SELECTION
 

Open in new window

0
 
lisa_mcAuthor Commented:
I have tried the code below:

When I comment out line 2 and 3, line 1 is aligned perfectly with the tabstops except for the first record.

When I include line 2 using the specified tabstops for that line neither line 1 or line 2 is aligned properly

Do you have any idea what could be causing this
         TParaFormat* pParaFormat2 = new TParaFormat;
        pParaFormat2->cbSize = sizeof(TParaFormat);
        pParaFormat2->cTabCount = 2;
        pParaFormat2->rgxTabs[0] = 2000;
        pParaFormat2->rgxTabs[1] = 7000;
        pParaFormat2->dwMask = PFM_TABSTOPS;
 
         TParaFormat* pParaFormat3 = new TParaFormat;
        pParaFormat3->cbSize = sizeof(TParaFormat);
        pParaFormat3->cTabCount = 4;
        pParaFormat3->rgxTabs[0] = 1000;
        pParaFormat3->rgxTabs[1] = 2500;
        pParaFormat3->rgxTabs[2] = 5000;
        pParaFormat3->rgxTabs[3] = 7000;
        pParaFormat3->dwMask = PFM_TABSTOPS;
 
// pParaFormat2 applies to line 1
RichEdit1->SelStart = RichEdit1->Text.Length() - 1;   // Start selection
 
                RichEdit1->Lines->Append("B: "+AnsiString(b_meter[i])+" C: "+AnsiString(c_meter[i])+AnsiString("\t")+AnsiString(array2c[i].machine_namec2.c_str())+AnsiString("\t")+AnsiString(array2c[i].date_setupc2.c_str()));
 
 
                RichEdit1->SelLength =  RichEdit1->Text.Length() - RichEdit1->SelStart;    // End of selection
 
 
                RichEdit1->Perform(EM_SETPARAFORMAT,0,Integer(pParaFormat2));     // APPLY YOUR TABS WITH CURRENT SELECTION
    
//pParaFormat3 applies to line 2
 
 
                               RichEdit1->SelStart = RichEdit1->Text.Length() - 1;  // start selection
 
                               RichEdit1->Lines->Append(AnsiString(percentage2b1[i].c_str())+AnsiString("%")+AnsiString("\t")+AnsiString(meter_refill2b1[i].c_str())+"R"+AnsiString("\t")+AnsiString(meterin_difference2b1[i].c_str())+AnsiString("\t")+AnsiString(meterout_difference2b1[i].c_str())+AnsiString("\t")+AnsiString(meter_balance2b1[i].c_str()));
 
                               RichEdit1->SelLength =  RichEdit1->Text.Length() - RichEdit1->SelStart;    // End of selection
 
 
 
                                RichEdit1->Perform(EM_SETPARAFORMAT,0,Integer(pParaFormat3));     // APPLY YOUR TABS WITH CURRENT SELECTION
                                    

Open in new window

0
 
pivarCommented:
I know that it is sensitive where the rtf commands is placed. Experiment with adding space/linebreak before SelStart assignment. Also test and change the length by -1 or less.

For instance:


RichEdit1->Lines->Append(" \n");
 
// pParaFormat2 applies to line 1
RichEdit1->SelStart = RichEdit1->Text.Length() - 2;   // Start selection
 
                RichEdit1->Lines->Append("B: "+AnsiString(b_meter[i])+" C: "+AnsiString(c_meter[i])+AnsiString("\t")+AnsiString(array2c[i].machine_namec2.c_str())+AnsiString("\t")+AnsiString(array2c[i].date_setupc2.c_str()));
 
 
                RichEdit1->SelLength =  RichEdit1->Text.Length() - RichEdit1->SelStart - 1;    // End of selection
RichEdit1->Lines->Append(" \n");
 
 
                RichEdit1->Perform(EM_SETPARAFORMAT,0,Integer(pParaFormat2));     // APPLY YOUR TABS WITH CURRENT SELECTION
 
//pParaFormat3 applies to line 2
 
 
RichEdit1->Lines->Append(" \n");
                               RichEdit1->SelStart = RichEdit1->Text.Length() - 2;  // start selection
 
                               RichEdit1->Lines->Append(AnsiString(percentage2b1[i].c_str())+AnsiString("%")+AnsiString("\t")+AnsiString(meter_refill2b1[i].c_str())+"R"+AnsiString("\t")+AnsiString(meterin_difference2b1[i].c_str())+AnsiString("\t")+AnsiString(meterout_difference2b1[i].c_str())+AnsiString("\t")+AnsiString(meter_balance2b1[i].c_str()));
 
                               RichEdit1->SelLength =  RichEdit1->Text.Length() - RichEdit1->SelStart - 2;    // End of selection
 
RichEdit1->Lines->Append(" \n");
 
 
                                RichEdit1->Perform(EM_SETPARAFORMAT,0,Integer(pParaFormat3)); 

Open in new window

0
 
lisa_mcAuthor Commented:
Got it working had to change to -2 and didnt need the extra line

Thank you so much you have saved me alot of time thanks :-)
0

Featured Post

New feature and membership benefit!

New feature! Upgrade and increase expert visibility of your issues with Priority Questions.

  • 13
  • 8
Tackle projects and never again get stuck behind a technical roadblock.
Join Now