[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now

x
?
Solved

How to Limit no. of characters per line in Multi Line Edit box

Posted on 2006-05-04
18
Medium Priority
?
1,425 Views
Last Modified: 2013-12-03
I have a requirement that to limit no. of character per line to 64 in each line of Multi Line edit box using MFC.  I started using Call back procedure EDITWORDBREAKPROC to override the editbox word break behaviour.  Horizontal scrollbar is required. Can any body send me the sample code for the requirement?
0
Comment
Question by:rk2611
  • 8
  • 7
  • 3
18 Comments
 
LVL 22

Expert Comment

by:mahesh1402
ID: 16606157
If you get this two long lines in the edit control - do you see a horizontal scroll bar ?
If it is so, remove the ES_AUTOHSCROLL style from your window creation style list. You may use ModifyStyle() for this.

Also, see the following text from MSDN:

Handling Word Wrap
-----------------------------
An application can use word wrap functions with multiline edit controls to locate the word or word fragment that should be wrapped to the next line.
Using the default word wrap function provided by the system, lines always end at the spaces between words.
An application can specify its own word wrap function by supplying a EditWordBreakProc word wrap function and sending an edit control an EM_SETWORDBREAKPROC message.

An application can retrieve the address of the current word wrap function by sending the control an EM_GETWORDBREAKPROC message.

An application may direct a multiline edit control to add or remove a soft line break character (two carriage returns and a linefeed) automatically at the end of wrapped text lines. An application can turn this feature on or off by sending the edit control an EM_FMTLINES message. This message applies only to multiline edit controls and does not affect a line that ends with a hard line break (one carriage return and a linefeed entered by the user).

-MAHESH
0
 
LVL 22

Expert Comment

by:mahesh1402
ID: 16606179
My suggestion is Just do *not* use ES_AUTOHSCROLL style.

-MAHESH
0
 

Author Comment

by:rk2611
ID: 16607176
Thanks for your comment.  If I turned off  'AUTO HScroll' property of the edit box from dialog properties, I may not limit exact no. of characters per line.  It's depend on the size of the edit box & max. no. of characters allowed may not be same in all lines (because it's depend on the character width).  Pls. give me comment on my openion.
0
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

 
LVL 22

Expert Comment

by:mahesh1402
ID: 16612293
what about using EM_SETLIMITTEXT ? CEdit::SetLimitText()...

You'd need to implement something like that yourself - handle the EN_UPDATE message (OnUpdate handler), use GetWindowText to get the current (yet to be displayed text), do your checking and if it violates your limits, change the text to the last known good text in the control.

-MAHESH
0
 
LVL 22

Expert Comment

by:mahesh1402
ID: 16612302
EM_LIMITTEXT ( CEdit::LimitText)

-MAHESH
0
 

Author Comment

by:rk2611
ID: 16614327
I have added the following code in OnUpdate command handler of Edit box.  When user enters 65th character, new line break character inserted beween 64th and 65the character & carrot position is moved to next line automatically.  I am using SetSel & ReplaceSel() to insert line break character. This is working fine  at the time of inputting characters.  The problem is that when user deletes the end characters in the line, the carrot position is moved to unknown position.  This is causing a problem to me.


  int lintLineCount = 0;
  int lintStartPos = 0;
  int lintEndPos = 0;
  int lintLineLength = 0;
  int lintMaxChars = 10;
  int lintTotChars = 0;
 
  CString lstrLine;
  CString lstrText;
  CString lstrTemp;
  lintLineCount = mCAnnotationEdit.GetLineCount();
  CString lstrFull = _T("");
  if (lintLineCount > 0 ) {
    for (int k = 0; k <lintLineCount; k++) {
      lintLineLength =
      mCAnnotationEdit.LineLength(mCAnnotationEdit.LineIndex(k));
      lintStartPos = mCAnnotationEdit.LineIndex(k);
      lintEndPos =  lintStartPos + mCAnnotationEdit.LineLength(lintStartPos);

        if (lintLineLength > lintMaxChars ) {
          mCAnnotationEdit.GetLine
            (k,lstrLine.GetBuffer(lintLineLength),lintLineLength);
          lstrLine.ReleaseBuffer(lintLineLength);
          lstrText.Format("%s",lstrLine);
          lintTotChars = lstrText.GetLength();
          lstrTemp = lstrText.Right(lintTotChars - lintMaxChars);
          lstrText = lstrText.Left(lintMaxChars);
          LPTSTR  lpStrline = new TCHAR[lstrText.GetLength() + 1];
          _tcscpy(lpStrline, lstrText);
          lstrText = lpStrline;
          if (lstrTemp.GetLength() > 0 ) {
            lstrText += "\r\n" + lstrTemp;
          }
          else {
            lstrText += "\r\n";
          }
         
          mCAnnotationEdit.SetSel(lintStartPos, lintEndPos);
          mCAnnotationEdit.ReplaceSel(lstrText);
          delete lpStrline;
        }
    }
  }

Appreciate if you can give a immediate solution to this problem.
0
 
LVL 22

Expert Comment

by:mahesh1402
ID: 16614360
So cant you control that using GetCarotPos() / SetCarotPos() functions ???

-MAHESH
0
 
LVL 22

Expert Comment

by:mahesh1402
ID: 16614429
ALSO if you found SetCaretPos is not appropriate then to move the caret, use the SetSel function and specify the same position for both the start and end parameters. This moves the text insertion point, and repositions the caret.

-MAHESH
0
 

Author Comment

by:rk2611
ID: 16614525
It is not worked out.  At the the time of insertion of characters, the carot position should be at end of last input character.  But, the at the time of deleting characters, the carror position should remain at the same position.  This I am not able to differentiate.  You can check the above sample code & suggest me for any solution.
0
 
LVL 22

Expert Comment

by:mahesh1402
ID: 16614855
but cant you set caret position forcefully using SetCaretPos when you delete characters by retrieving caret position and if its not at end then setting it forcefully..

-MAHESH
0
 

Author Comment

by:rk2611
ID: 16614955
I can not differenitate whether we are deleting a character or inputting a character.  At the time of deleting a last character of line, characters in the next line is shifted to first line. New line character is inserted again in this case.  But, at the time of inputting a character, carrot position is on the next line.  At the time of deleting a character,the carrot position should remain on the position.  We cannot differentiate.  You may try in the sampel application with above code in OnChange event.
0
 
LVL 22

Expert Comment

by:mahesh1402
ID: 16615160
>>I can not differenitate whether we are deleting a character or inputting a character

I think its good to derive your own Edit control from CEdit and respond to events accordingly..

-MAHESH
0
 

Author Comment

by:rk2611
ID: 16616574
Is thery any simple method that we can limit 64 characters per line?  Can we override any call back function EM_SETWORDBREAKPROC to get this functionality?  I don't know how to use call back function. Pls. help me.
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 16619337
I looked at adding a WordBreakProc, but it only gets called when the edit control thinks it needs to break a line.  And it only thinks that when the displayed characters won't fit
and that's a problem becasue of proportional fonts (66 of each below):
   iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii
   MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
Thus, it won't get called in the line of i's but will on the line of Ms.

NOTE: If you con't mind using a fixed-width font (such as Courier) then this might be a valid approach.  Let me know.

Here is my first pass at how to handle it via an OnUpdate handler.  I'm out of time right now, but test this out and let me know where it needs improvment:

void CD20Dlg::OnUpdateEdit1()
{
      int nStartPos, nEndPos;
      m_ctlEdit.GetSel( nStartPos, nEndPos );

      int nLineNum= m_ctlEdit.LineFromChar(-1); // current line
      int nLineLen= m_ctlEdit.LineLength(-1);   // current line
      int nLineIdx= m_ctlEdit.LineIndex(-1);    // pos of start of current line
      
      if ( nLineLen > 65 ) {
            char szBuf[100];
            int nBrkAt;
            
             int nLen= m_ctlEdit.GetLine( nLineNum, szBuf, sizeof(szBuf) );
            szBuf[nLen]='\0';

            for (int j=nLen-1; j>0; j-- ) {  // find a space so we can break the line
                  if ( szBuf[j]== ' ') {
                        nBrkAt= nLineIdx + j;
                        break;
                  }
            }
            if ( nBrkAt == -1) {
                  nBrkAt= nLineIdx + 64;  // start of cur line + 64
            }
            m_ctlEdit.SetSel( nBrkAt, nBrkAt );
            m_ctlEdit.ReplaceSel("\r\n", TRUE );
            m_ctlEdit.SetSel( nStartPos, nEndPos );
      }
}

-- Dan
0
 

Author Comment

by:rk2611
ID: 16623778
I have tested the above code.  I found some issues in the above code.

a) when user entered 65th character in the line, the 65th character is moving to next line. But, carrot position is still at the end of the previous line.  Usually, cursor should also move to next line and at the end of the character,

b) But, when user delete end character from the line, the carrot position should remain at the same position.

In above my code, (b) is not working.  In your code, (a) is not working.  Pls. suggest me.
0
 
LVL 49

Accepted Solution

by:
DanRollins earned 2000 total points
ID: 16624593
This version seems to do the trick.  

Note that the settings for my edit control include:
   Multiline
   Auto HScroll
   Vertical Scroll
   Auto VScroll
   Want Return
It may not work the same with other settings.

void CD28Dlg::OnUpdateEdit1()
{
      static BOOL fBusy= FALSE;
      if ( fBusy ) {
            return;
      }
      fBusy= TRUE;
      
      int nStartPos, nEndPos;
      m_ctlEdit.GetSel( nStartPos, nEndPos );

      int nLineNum= m_ctlEdit.LineFromChar(-1); // current line
      int nLineLen= m_ctlEdit.LineLength(-1);   // current line
      int nLineIdx= m_ctlEdit.LineIndex(-1);    // pos of start of current line
      int nPosOnLine= nStartPos-nLineIdx;

      if ( nLineLen > 65 ) {
            char szBuf[100];
            int nBrkAt= -1;

            int nLen= m_ctlEdit.GetLine( nLineNum, szBuf, sizeof(szBuf) );
            szBuf[nLen]='\0';

            for (int j=nLen-1; j>0; j-- ) {  // find a space so we can break the line
                  if ( szBuf[j]== ' ') {
                        nBrkAt= nLineIdx + j;
                        if (j < 64) {
                              break;
                        }
                  }
            }
            if ( nBrkAt == -1) {
                  nBrkAt= nLineIdx + 64;  // start of cur line + 64
            }
            m_ctlEdit.SetSel( nBrkAt, nBrkAt );
            m_ctlEdit.ReplaceSel("\r\n", FALSE );

            if ( nPosOnLine>65) {  // if cursor was at the end...
                  nStartPos= nEndPos += 2;
            }
            m_ctlEdit.SetSel( nStartPos, nEndPos );
      }
      fBusy= FALSE;
}
0
 

Author Comment

by:rk2611
ID: 16685532
Thanks for your suggestion.  It is working fine...
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 16686192
Glad to help.  Thgaks for the points and the grade :-)

BTW, When I was working on this, I found that a self-limiting line-length worked best when using a fixed-width font in the Edito Control.    It is more intuitive for the user... as he gets near the end of the window, he will tend to press Enter to start a new line -- and thus not be interrupted by an "unexpected" forced line wrapping.  With variable-width fonts, it is hard to know that you are nearing the max as you type.
0

Featured Post

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!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

In this article, I'll describe -- and show pictures of -- some of the significant additions that have been made available to programmers in the MFC Feature Pack for Visual C++ 2008.  These same feature are in the MFC libraries that come with Visual …
Have you tried to learn about Unicode, UTF-8, and multibyte text encoding and all the articles are just too "academic" or too technical? This article aims to make the whole topic easy for just about anyone to understand.
Excel styles will make formatting consistent and let you apply and change formatting faster. In this tutorial, you'll learn how to use Excel's built-in styles, how to modify styles, and how to create your own. You'll also learn how to use your custo…
If you’ve ever visited a web page and noticed a cool font that you really liked the look of, but couldn’t figure out which font it was so that you could use it for your own work, then this video is for you! In this Micro Tutorial, you'll learn yo…
Suggested Courses

873 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question