Allowing the TAB key in Edit Controls

WEBINAR: On-demand webcast

How to Boost Database Development Productivity on Linux, Docker, and Kubernetes with Microsoft SQL Server 2017 REGISTER >

Introduction

I was quite frustrated in with my application. I have a dialog with a simple multi-line edit (MLE) control. When I attempted to press the TAB key, the entire contents of my edit control would be highlighted! Evidently, this is the default action of an edit control when the Tab key is pressed. Anyway, I wanted the Tab key to work as I would expect it to in a control that is supposedly mimicing an editor so I set out to find a solution.

Solution

Basically, it came down to control's the tried and true, PreTranslateMessage member function. It works like this. PreTranslateMessage is a virtual member function that is called in order to give your control a chance to do something before (or instead of) the default behavior of the control. Therefore, in this function, I check to see if the message being sent is a WM_KEYDOWN message (indicating that the user has pressed some key). I then determine if the key being pressed is the Tab key (whose id is VK_TAB). If these two cases are true, I simply deselect any selected text and insert a tab character into the control (\t).

Implementing this Solution

Here are the steps necessary to implement my work-around.
  1. To your override of CDialog class, add the following method:
  2. virtual BOOL PreTranslateMessage(MSG *);
    
  3. Implement this function, for example:
  4. BOOL CEditExDlg::PreTranslateMessage(MSG* pMsg) 
    {
     if ((pMsg->message == WM_KEYDOWN) && (pMsg->wParam == VK_TAB)) 
     {
      // get the char index of the caret position
      int nPos = LOWORD(m_MyEditCtl.CharFromPos(m_MyEditCtl.GetCaretPos()));
      
      // select zero chars
      m_MyEditCtl.SetSel(nPos, nPos);
      
      // then replace that selection with a TAB
      m_MyEditCtl.ReplaceSel("\t", TRUE);
    
      // no need to do a msg translation, so quit. 
      // that way no further processing gets done
      return TRUE;
     }
    
     //just let other massages to work normally
     return CDialog::PreTranslateMessage(pMsg);
    }
    

Downloads

Download demo project - 10 Kb


Comments

  • Can you control the width of the Tab space?

    Posted by mtb2440 on 10/28/2005 05:14pm

    I would like to set it to 4 spaces. Thanks - great technique. MB

    Reply
  • ON_WM_GETDLGCODE

    Posted by Legacy on 10/28/2003 12:00am

    Originally posted by: Andy Walker

    Hi,
    
    

    There is an MFC defined way of doing this which means you don't have to check for the correct controls in a muti-control dialog etc.

    All you need to do to get the Tab to work in an edit control of a dialog is override the WM_GETDLGCODE message which is sent to all controls in a dialog box. The solution isn't available via ClassWizard.

    Create your control in the Resource Editor.

    Derive a class from CEdit, and add the handler to the header...

    class CTabEdit : public CEdit
    {
    // Construction
    .
    .blaa
    .
    protected:
    //{{AFX_MSG(CTabEdit)
    //}}AFX_MSG

    afx_msg UINT OnGetDlgCode();

    DECLARE_MESSAGE_MAP()
    };

    ...and the function body to the .cpp...

    BEGIN_MESSAGE_MAP(CTabEdit, CEdit)
    //{{AFX_MSG_MAP(CTabEdit)
    // NOTE - the ClassWizard will add and remove mapping macros here.
    //}}AFX_MSG_MAP
    ON_WM_GETDLGCODE()
    END_MESSAGE_MAP()

    /////////////////
    // CTabEdit message handlers
    UINT CTabEdit::OnGetDlgCode()
    {
    return DLGC_WANTTAB;
    }

    ...In the function return DLGC_WANTTAB as above.

    In your dialog with the control in it, include the Header for the above class in the .h file.

    #include "TabEdit.h"

    class CBuildManagerDlg : public CDialog
    {
    ...

    Now add a variable for the control in the dialog using the Class wizard.

    Then alter the Classwizard code to use your new CTabEdit...

    // Dialog Data
    //{{AFX_DATA(CBuildManagerDlg)
    enum { IDD = IDD_BUILDMANAGER_DIALOG };
    CTabEdit m_cTabEdit;
    CButton m_cOKBtn;
    CListbox m_cStopStartList;
    //}}AFX_DATA

    Done.

    No need to use Pre-Translate.

    Andy.

    Reply
  • Thanks for the post

    Posted by Legacy on 04/22/2003 12:00am

    Originally posted by: Newbie

    Thanks for the post. I don't due alot of windows programming but ran into this same problem and because of your post I made this change in under 5 minutes. So thanks for taking the time to post.

    Reply
  • How do I catch any key without using MFC?

    Posted by Legacy on 03/08/2003 12:00am

    Originally posted by: Witek

    If keybord focus is in some edit control and I want to catch arrow keys without using MFC. Can anybody helps?

    Reply
  • Greate Thank you..

    Posted by Legacy on 02/19/2003 12:00am

    Originally posted by: Kim Su-Jung

    i am in agony this problem. 
    
    

    thank you

    Reply
  • Can we display new line chracter as well

    Posted by Legacy on 08/06/2002 12:00am

    Originally posted by: Ramesh

    I have an Edit Control in VC++, and I basically use it for logging. So I assign the member variable to the log info I want and then I use the UpdateData(FALSE).
    Now the problem I have is I want the new line character to function as new line, but instead it displays some special character there. How do I send a new line character to my Edit Control.

    Reply
  • We can also use CEdit::PreTranslateMessage

    Posted by Legacy on 01/02/2002 12:00am

    Originally posted by: Franz Wong

    If we use CEdit::PreTranslateMessage, then the program will only do the job when the focus is on the edit box.
    

    Reply
  • a simple question???

    Posted by Legacy on 12/07/2001 12:00am

    Originally posted by: John Miller

    Hi,
    This question may look stupid or simple for you folks here,
    but I am still puzzled with this:

    is a control (such as a Edit box or Static control) area
    still the client area of the main dialog window?

    When the mouse move occurs within any control box area,
    it looks that the neither the WM_MOUSEMOVE nor the WM_NCMOUSEMOVE message does not get sent!

    When you put a control on top of the dialog client area,
    how do you capture the mouse move event WITHIN the control
    area????

    Hope some one would kindly point it out, thanks!


    Reply
  • if this isn't the only control in the window ...

    Posted by Legacy on 08/15/2001 12:00am

    Originally posted by: Rick Phillips

    I found this solution to be quite helpful, as in my application I needed a simple way to enter script-language syntax.  However I ran into a slight problem. Because this solution captures all of the <TAB> key events, if there are other controls on the window then it is no longer possible to <TAB> from one to the other.
    
    

    The solution to this is quite simple. In pre-translate message, just check to see if your edit control has the input focus:


    CEdit* pMyEditControl = (CEdit*)GetDlgItem(IDC_MY_EDIT);

    // see if the multiline edit control has the input focus
    if ((CEdit*)this->GetFocus() == pMyEditControl)
    {
    // implement Hilmi Jauffer's solution here

    ...

    }

    voila!

    Reply
  • enabling ctrl+c and ctrl+v for copy and paste for an edit control

    Posted by Legacy on 08/01/2001 12:00am

    Originally posted by: kiran

    hello all

    how to enable ctrl+c and ctrl+v for an edit control...

    In my application I have over ridden the cut,copy,paste context sensitive menu for all edit controls...

    and also one more thing I am creating these edit controls dynamically.

    can anybody help me in this regard..

    thanks in advance...

    kiran

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Many enterprises are working with an IT architecture that's evolved over time. As business needs evolve, IT must decide whether to modernize incrementally, or all at once. Each approach has its benefits and drawbacks. Identity Management is key to modernizing IT; it plays a crucial role in migrating to cloud apps like Office 365 or HR information systems, building web and mobile apps, and opening developer access to business systems. Read how Okta's modern approach to identity management helps business lower …

  • This case study will highlight the opportunity for mobile and cloud technologies in the Public Sector—specifically for state, local and federal government agencies -where secure mobile application access can offer key productivity gains

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date