Eating returns in a single line edit

I was quite frustrated in my app - I have a dialog with a few single-line edit controls; after updating the edits, when I pressed Enter the dialog was closed (IDOK was the default button). "Want return" option is unfortunately valid only for multiline edits.

Here is my fix:

I override PreTranslateMessage. If there is WM_KEYDOWN with VK_ENTER going to the edit, I set the focus to the default button and discard the message. If the dialog has no defualt button, I let VK_ENTER through - no problem this time.

I check if the window is an editbox by calling GetClassName and comparing the return value to "Edit". There are much more possibilities - comparing the FromHandle(hwnd) to array of CWnd*, to array of IDs (comparing to GetDlgItem() return values) etc.

For the code to be completely correct, it should check for the edit's windows style and it should not act if it is multi-line, want-return edit. [I haven't done that as I don't use multiline edits.]

1. To your override of CDialog, add the following method:


	virtual BOOL PreTranslateMessage(MSG *);

2. Implement this function, for example:


BOOL CMyDialog::PreTranslateMessage(MSG *pMsg)
{
	if (pMsg->message==WM_KEYDOWN && pMsg->wParam==VK_RETURN)
	{
		DWORD def_id=GetDefID();
		if (def_id!=0)
		{
			CWnd *wnd=FromHandle(pMsg->hwnd);
			// you may implement other ways of testing, e.g.
			//  comparing to array of CWnd*, comparing to array of IDs etc.
			char class_name[16];
			if (GetClassName(wnd->GetSafeHwnd(),class_name,sizeof(class_name))!=0)
			{
				if (strnicmp(class_name,"edit",5)==0)
				{
					GetDlgItem(LOWORD(def_id))->SetFocus();
					return TRUE;
					// discard the message!
				}
			}
		}
	}
	// be a good citizen - call the base class
	return CDialog::PreTranslateMessage(pMsg);
}


Comments

  • Lazy way to do this

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

    Originally posted by: Kehlar

    I found a lazy way to capture the return key in an editbox inside a dialog so that the OK button doesn't get pressed. This will work for non-MFC projects as well. In your OnOK function do the following:
    
    

    HWND hWnd = GetFocus();
    if (hWnd == myeditbox.m_hWnd)
    {
    //... do my thing.
    return 0;
    }

    Obvious this means the OK button only gets processed if another control on the dialog is in focus or if the OK button is clicked with the mouse.

    Reply
  • convert RETURN to TAB

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

    Originally posted by: cmoc

    You can do this way:
    set edit control to muti-line and want-return
    void CMyEdit::OnKeyDown(UINT nChar,UINT nRepCnt,UINT nFlags)
    {
    if (nChar==VK_RETURN)
    {
    PostMessage(WM_KEYDOWN,VK_TAB);
    return;
    }
    CEdit::OnKeyDown(nChar,nRepCnt,nFlags);
    }

    Reply
  • Just change to tab...

    Posted by Legacy on 05/30/2001 12:00am

    Originally posted by: Jon Erdman

    I was using this in a CPropertySheet, so was unable to use
    
    the nice GotoDlgItem() function to make the selection and
    such act as if the user had hit tab. also,

    anyway, it occured to me to just let the framework take
    care of it by simply changing the keycode if the edit
    control tests are passed.

    basically, change the return to a tab, then let MFC do the
    rest:

    BOOL CMySheet::PreTranslateMessage(MSG* pMsg)
    {
    if (pMsg->message == WM_KEYDOWN)
    {
    if ((int)pMsg->wParam == VK_RETURN)
    {
    CString classname;
    CWnd *pwnd = FromHandle(pMsg->hwnd);

    if (GetClassName(pwnd->GetSafeHwnd(),classname.GetBuffer(20),20) != 0)
    if (classname == "Edit")
    pMsg->wParam = VK_TAB;
    }
    }

    return CPropertySheet::PreTranslateMessage(pMsg);
    }

    Reply
  • Thanks

    Posted by Legacy on 11/07/2000 12:00am

    Originally posted by: Zeeshan Razzaque

    This really made my day..

    Reply
  • Slightly different version than Mark Johnson's which handles focus like an actual tab stroke

    Posted by Legacy on 01/07/1999 12:00am

    Originally posted by: Shannon O'Brien


    // This is just a different twist on Mark Johnson's approach
    // it handles focus like an actual tab stroke would by placing focus
    // rect around controls like command buttons

    void CMyDlg::OnOK ( void )
    {
    CWnd *pCurWnd = GetFocus ( );

    UpdateData(TRUE);

    // I check the type of control first using CObject's IsKindOf
    // member function
    if ( pCurWnd->IsKindOf ( RUNTIME_CLASS ( CEdit ) ) ||
    pCurWnd->IsKindOf ( RUNTIME_CLASS ( CComboBox ) ) ||
    ( pCurWnd->IsKindOf ( RUNTIME_CLASS ( CButton ) ) &&
    pCurWnd->GetDlgCtrlID ( ) == IDC_ISACTIVE ) )
    {
    // if we aren't on the OK button fake a tab
    CWnd *pNextWnd = GetNextDlgTabItem( pCurWnd );

    // This next line of code will make sure that the
    // focus rectangle surrounds the next control...
    // good in the case of fake tabbing from say a
    // CEdit control to a CButton control...
    // Just calling SetFocus does not do this
    GotoDlgCtrl ( GetDlgItem ( pNextWnd->GetDlgCtrlID ( ) ) );

    return;
    }
    else
    {
    // Call some other handler function here
    // for your specific needs
    }

    return;
    }

    Reply
  • Even Simpler...?

    Posted by Legacy on 12/22/1998 12:00am

    Originally posted by: Mark Johnson

    Typically, i want the enter key to act like the tab key because it's so natural, or sometimes I want the
    enter key to invoke a special process which isn't actviated by a tab involving OnKillfocusXXXX().  
    
    

    #define WM_VALIDATEFORM WM_APP + 101
    #define IsKeyDown(key) (::GetKeyState(key) & 0x1000)
    #define IsKeyUp(key) !IsKeyDown(key)

    void CMyDlg::OnOK()
    {
    UpdateData(TRUE);

    if( GetFocus() != GetDlgItem(IDOK) )
    {
    // if we aren't on the OK button fake a tab
    GetNextDlgTabItem(GetFocus(), IsKeyDown(VK_SHIFT))->SetFocus();
    return;
    }

    CDialog::OnOK();
    }

    void CMyDlg::OnKillfocusUserSelection()
    {
    if( IsKeyDown(VK_RETURN) )
    PostMessage(WM_VALIDATEFORM, ED_USERSELECT, 0L);
    }


    Reply
  • Simpler Option (?)

    Posted by Legacy on 11/27/1998 12:00am

    Originally posted by: Shankar

    Iam just a beginner at MFC & had the same problem in my application. 
    
    This is how I got around it.Maybe some beginners might find it useful.
    First I added a handler to the BNCLICKED message of the OK button,
    which, if u use the classWizard, would be OnOK(). This function did
    nothing.
    CMyDialog::OnOK()
    {
    //Note: I dont have the call to the base class function.
    }

    Then I went ahead and changed the ID of the OK button.
    ( say IDCLICKEDOK ). Add a handler to that using the classWizard, which
    gives you CMyDialog::OnClickedOK(). Then I called the base class OnOK()
    from this.
    CMyDialog::OnClickedOK()
    {
    CDialog::OnOK();
    }
    Then, finally, in the properties box for the OK button, uncheck the
    'default button' check box. That takes care of eveything.

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

Top White Papers and Webcasts

  • Java developers know that testing code changes can be a huge pain, and waiting for an application to redeploy after a code fix can take an eternity. Wouldn't it be great if you could see your code changes immediately, fine-tune, debug, explore and deploy code without waiting for ages? In this white paper, find out how that's possible with a Java plugin that drastically changes the way you develop, test and run Java applications. Discover the advantages of this plugin, and the changes you can expect to see …

  • Packaged application development teams frequently operate with limited testing environments due to time and labor constraints. By virtualizing the entire application stack, packaged application development teams can deliver business results faster, at higher quality, and with lower risk.

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds