Set focus to a second control in a CFormView using Tab key and PreTranslateMessage()

natedog977
natedog977 used Ask the Experts™
on
Hi all - This should be a fairly simple question for any veteran MFC coders out there...

I can't figure out how to set the focus to the next control using the tab key? I already have all the code necessary to perform this task working EXCEPT for setting the focus.

I am using MyCFormView::PreTranslateMessage() to capture a WM_KEYDOWN message, then checking for VK_TAB in the pMsg->wParam member.

See me code below...Why isn't the focus going to the appropriate control in the switch statements?

P.S. Additional points will be awarded if you can tell me a better way to catch the shift+tab keypress to set the focus to the previous (vs. next) control.

BOOL MyCFormView::PreTranslateMessage(MSG* pMsg)
{
  if (pMsg->message == WM_KEYDOWN){
    if( pMsg->wParam == VK_TAB ){
      if(m_lastCharVal == 16){ //Shift+Tab was entered - Tab backwards
      AfxMessageBox("BACKWARD");
        switch(m_activeCtrl){
          case 1:
            m_loginout.SetFocus();
            m_activeCtrl = 3;
            break;
          case 2:
            m_usr.SetFocus();
            m_activeCtrl = 1;
            break;
          case 3:
            m_pas.SetFocus();
            m_activeCtrl = 2;
            break;
        }
      }
      else{ //Tab Forward
        AfxMessageBox("FORWARD");
          switch(m_activeCtrl){
            case 1:
              m_pas.SetFocus();
              m_activeCtrl = 2;
              break;
            case 2:
              m_loginout.SetFocus();
              m_activeCtrl = 3;
              break;
            case 3:
              m_usr.SetFocus();
              m_activeCtrl = 1;
              break;
          }
        }
      }
      if(pMsg->wParam == VK_RETURN){
        AfxMessageBox("RETURN");
          Loginout();
      }
      m_lastCharVal = pMsg->wParam;
    }

    return CFormView::PreTranslateMessage(pMsg);
}
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®

Commented:
Try GoToDlgCtrl() instead of setfocus?

Also, doesn't tab and shift+tab work for your formview application by default?

Regards,
Priyesh

Author

Commented:
Hi Privesh,

See below my responses.

[Try GoToDlgCtrl() instead of setfocus?]
GotoDlgCtrl belongs to CDialog, not CFormView. It cannot be called from CMyFormView::PreTranslateMessage().

When I try...

     GotoDlgCtrl(CWnd::GetDlgItem(IDD_USRID));

...I get this error message...

     error C2065: 'GotoDlgCtrl' : undeclared identifier

[Also, doesn't tab and shift+tab work for your formview application by default?]
Tab and shift+tab work inside all of my CDialog derived classes, but not in my main CFormView class?

Perhaps a few more details would be helpful:
What I am trying to do with the application is allow the user to log in from the main start-up window by entering in values into two User ID and Password CEdit Boxes, then clicking a CStatic text (loaded with a "Logon" bitmap).
The CStatic text and the CEdit boxes are declared as member variables and created in OnInitialUpdate() (maybe this is why I can't tab). The controls were created in OnInitialUpdate() because I wanted the ability to reposition them when the main Window is resized.

Commented:
sorry for GotoDlgCtrl, it is a member of CDialog.

I remember having formviews with dialog controls on it without no problem with tab. i don't think they were created using Create calls. You can still use MoveWindow to move the controls in OnInitialUpdate(). I mean if you place the controls on your form dialog using the resource editor, and use GetDlgItem(IDC_CONTROL)->MoveWindow() in your oninitialupdate, it should still work and give you the tab keys too.

Learn Ruby Fundamentals

This course will introduce you to Ruby, as well as teach you about classes, methods, variables, data structures, loops, enumerable methods, and finishing touches.


 
  return CFormView::PreTranslateMessage(pMsg);

 Don't call this if you set the focus yourself, might be reseting the focus for you.
Sr Program Manager
Commented:
Hi,

I think, there is some problem. Even tho we can get tab going with ur code by maintaining which is active control, user may change the active control. Then the code fails. Remeber user may just activate a control but not click or ckeck it many times.

I tried the following. I have a form view and I have placed three controls Button-Edit-CheckBox in the specified order. Then, I wrote the PreTranslateMessage as follows

BOOL CMyFormView::PreTranslateMessage(MSG* pMsg)
{
     if((pMsg->message == WM_KEYDOWN) && (pMsg->wParam == VK_TAB))
     {
          // Is Shift pressed??
          if(GetKeyState(VK_SHIFT) & 0x8000)
          {
               // We should be moving backward
               if(m_ctrlBtn.GetSafeHwnd() == pMsg->hwnd)
               {
                    // Focus is on button, move back to check box
                    m_ctrlChk.SetFocus();
                    return TRUE;
               }
               else if(m_ctrlEdit.GetSafeHwnd() == pMsg->hwnd)
               {
                    // Focus is on button, move back to check box
                    m_ctrlBtn.SetFocus();
                    return TRUE;
               }
               if(m_ctrlChk.GetSafeHwnd() == pMsg->hwnd)
               {
                    // Focus is on button, move back to check box
                    m_ctrlEdit.SetFocus();
                    return TRUE;
               }
          }
          else
          {
               // We should be moving forward
               if(m_ctrlBtn.GetSafeHwnd() == pMsg->hwnd)
               {
                    // Focus is on button, move back to check box
                    m_ctrlEdit.SetFocus();
                    return TRUE;
               }
               else if(m_ctrlEdit.GetSafeHwnd() == pMsg->hwnd)
               {
                    // Focus is on button, move back to check box
                    m_ctrlChk.SetFocus();
                    return TRUE;
               }
               if(m_ctrlChk.GetSafeHwnd() == pMsg->hwnd)
               {
                    // Focus is on button, move back to check box
                    m_ctrlBtn.SetFocus();
                    return TRUE;
               }
          }
     }

     return CFormView::PreTranslateMessage(pMsg);
}

I am also checking for Shift key in different and I 'guess' in correct way.

Try it out.
VinExpert
Vinayak KumbarSr Program Manager

Commented:
Hi,

Sorry for few wrong comments in my code... simply ignored I think, here is correct version

BOOL CMyFormView::PreTranslateMessage(MSG* pMsg)
{
     if((pMsg->message == WM_KEYDOWN) && (pMsg->wParam == VK_TAB))
     {
          // Is Shift pressed??
          if(GetKeyState(VK_SHIFT) & 0x8000)
          {
               // We should be moving backward
               if(m_ctrlBtn.GetSafeHwnd() == pMsg->hwnd)
               {
                    // Focus is on button, move back to check box
                    m_ctrlChk.SetFocus();
                    return TRUE;
               }
               else if(m_ctrlEdit.GetSafeHwnd() == pMsg->hwnd)
               {
                    // Focus is on edit box, move back to button
                    m_ctrlBtn.SetFocus();
                    return TRUE;
               }
               if(m_ctrlChk.GetSafeHwnd() == pMsg->hwnd)
               {
                    // Focus is on check box, move back to edit box
                    m_ctrlEdit.SetFocus();
                    return TRUE;
               }
          }
          else
          {
               // We should be moving forward
               if(m_ctrlBtn.GetSafeHwnd() == pMsg->hwnd)
               {
                    // Focus is on button, move to edit box
                    m_ctrlEdit.SetFocus();
                    return TRUE;
               }
               else if(m_ctrlEdit.GetSafeHwnd() == pMsg->hwnd)
               {
                    // Focus is on edit, move to check box
                    m_ctrlChk.SetFocus();
                    return TRUE;
               }
               if(m_ctrlChk.GetSafeHwnd() == pMsg->hwnd)
               {
                    // Focus is on check box, move to button
                    m_ctrlBtn.SetFocus();
                    return TRUE;
               }
          }
     }

     return CFormView::PreTranslateMessage(pMsg);
}

Hope it helps u.
VinExpert

Commented:
You don't have to dynamically create controls to be able to move them when the window size changes. Create them in your form view's dialog template from the dialog editor. Then, when you want to move them when the window size changes, map the formview's WM_SIZE and do this. You have to be sure that the OnInitialUpdate was called before you try to access controls in your OnSize(), do this with a boolean variable like

bool m_bDone = false ;
void CFormtestView::OnInitialUpdate()
{
     CFormView::OnInitialUpdate();
     GetParentFrame()->RecalcLayout();
     ResizeParentToFit();

     m_bDone = true ;
}

void CFormtestView::MoveControls(int nCX, int nCY)
{
     GetDlgItem(IDC_EDIT1)->MoveWindow(10, 10, nCX/10, 20) ;
     GetDlgItem(IDC_EDIT2)->MoveWindow(10, 40, nCX/10, 20) ;
}

void CFormtestView::OnSize(UINT nType, int cx, int cy)
{
     CFormView::OnSize(nType, cx, cy);
     if(m_bDone)
          MoveControls(cx, cy) ;    
}

m_bDone will make sure that you move the controls only after  they are created.

Regards,
Priyesh

Author

Commented:
Thank you all so much for your efforts. I have decided to award VinExpert the points. Each of you had helpfull suggestions. Here is my reasoning...

[] williamcampbell []
You were right about the return value blocking the focus from being set, but after I made the change I was getting an alert beep each time I hit the Tab key?

[] Priyesh []
When I tried using the resource editor to create the controls, I experienced some strange behaviors: On start-up and during resizing the User ID and Password edit controls did not display untill after I hit a key? I realize this is probably because of my own code, but see VinExpert comment below for details on my decision.

[] VinExpert []
I awarded you the points because your comments were correct and your suggestions were the closest to the original code that I provided, meaning less work for me!

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial