Editbox showing through to dialog

I’m having a problem with the ui::EditBox. My main screen has several edit boxes, and I’m using “userData” to tab between fields.

Problem is, when I create a dialog (just a panel with a z rating), one of the fields from the screen shows through my dialog. Any suggestion? This happens on multiple screens.

Oh, this is on Windows. I can’t get the “next” or “tab” to work on the Mac, so the mac isn’t having this problem.

Show me please.

Actually, I now have it working! So, my current version of UIEditBoxImpl-win32.cpp now lets me tab between fields and no longer has this problem. I’m working with 3.17, so I don’t think I want to do a pull request, but if anyone would like a copy of my edit, I can do that.

But actually, I simply modified the function thus. I simply added pThis->endAction = RETURN, because in my code where I support the TAB key, I look for TAB_TO_NEXT.

I need to clean this up, debugging/stepping wasn’t going too well, so I added a lot of CCLOG statements and found it.

LRESULT EditBoxImplWin::hookGLFWWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
    case WM_COMMAND:
        if (HIWORD(wParam) == EN_CHANGE) {
            EditBoxImplWin* pThis = (EditBoxImplWin*)GetWindowLongPtrW((HWND)lParam, GWLP_USERDATA);
            if (pThis && !pThis->_changedTextManually)
            {
                pThis->editBoxEditingChanged(pThis->getText());
                pThis->_changedTextManually = false;
            }

        }
        break;
    case WM_LBUTTONDOWN:
      // CCLOG("\nUIEditBox, WM_LBUTTONDOWN");
      
      if (s_previousFocusWnd != s_hwndCocos) {

        // CCLOG("WM_LBUTTONDOWN, entered block (s_previousFocusWnd != s_hwndCocos), before showWindow (hide)");
        // added this so that I can manually override the _endAction on the current edit field
        EditBoxImplWin* pThis = (EditBoxImplWin*)GetWindowLongPtrW(s_previousFocusWnd, GWLP_USERDATA);
        if (pThis != nullptr)
          pThis->_endAction = EditBoxDelegate::EditBoxEndAction::RETURN;

        ::ShowWindow(s_previousFocusWnd, SW_HIDE);
        // CCLOG("WM_LBUTTONDOWN, *after* showWindow (hide)");
          
        // EditBoxImplWin* pThis = (EditBoxImplWin*)GetWindowLongPtrW(s_previousFocusWnd, GWLP_USERDATA);
        if (pThis!=nullptr && !pThis->_hasFocus)
        {
          // CCLOG("WM_LBUTTONDOWN, next block (pThis != nullptr)");

          // next experiment with commenting out IsWindowVisible
          // if (pThis->_editingMode && !IsWindowVisible(s_previousFocusWnd))
          if (pThis->_editingMode) //  && !IsWindowVisible(s_previousFocusWnd))
          {
            // CCLOG("WM_LBUTTONDOWN, inner block (pThis->_editingMode)");
            pThis->editBoxEditingDidEnd(pThis->getText(), EditBoxDelegate::EditBoxEndAction::RETURN);
          }
        }
        else
        {
          // CCLOG("WM_LBUTTONDOWN, else block (NOT pThis != nullptr)");
          ::PostMessageW(s_hwndCocos, WM_SETFOCUS, (WPARAM)s_previousFocusWnd, 0);
        }
        s_previousFocusWnd = s_hwndCocos;
      }

      break;
    default:
        break;
    }

    return ::CallWindowProcW(s_prevCocosWndProc, hwnd, uMsg, wParam, lParam);
}

I support tabbing here (the VK_TAB part)

void EditBoxImplWin::_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
  // CCLOG("uMsg = %d, wParam = %d, lParam = %d", uMsg, wParam, lParam);
    switch (uMsg)
    {
    case WM_CHAR:
        if (wParam == VK_ESCAPE)
        {
          _hasFocus = false;
          //when app enter background, this message also be called.
          if (this->_editingMode && !::IsWindowVisible(hwnd))
          {
            _endAction = EditBoxDelegate::EditBoxEndAction::RETURN;
            this->editBoxEditingDidEnd(this->getText(), _endAction);
          }
        }
        else if (wParam == VK_RETURN || wParam == VK_TAB)
        {
          // KERRY BATTS - added "VK_TAB"
            if (_editBoxInputMode != cocos2d::ui::EditBox::InputMode::ANY) {
                if (s_previousFocusWnd != s_hwndCocos) {
                    switch (_keyboardReturnType)
                    {
                    case EditBox::KeyboardReturnType::DEFAULT:
                        _endAction = EditBoxDelegate::EditBoxEndAction::UNKNOWN;
                        break;
                    case EditBox::KeyboardReturnType::DONE:
                        _endAction = EditBoxDelegate::EditBoxEndAction::RETURN;
                        break;
                    case EditBox::KeyboardReturnType::SEND:
                        _endAction = EditBoxDelegate::EditBoxEndAction::RETURN;
                        break;
                    case EditBox::KeyboardReturnType::SEARCH:
                        _endAction = EditBoxDelegate::EditBoxEndAction::RETURN;
                        break;
                    case EditBox::KeyboardReturnType::GO:
                        _endAction = EditBoxDelegate::EditBoxEndAction::RETURN;
                        break;
                    case EditBox::KeyboardReturnType::NEXT:
                        _endAction = EditBoxDelegate::EditBoxEndAction::TAB_TO_NEXT;
                        break;
                    default:
                        _endAction = EditBoxDelegate::EditBoxEndAction::UNKNOWN;
                        break;
                    }
                    ::ShowWindow(s_previousFocusWnd, SW_HIDE);
                    ::SendMessageW(s_hwndCocos, WM_SETFOCUS, (WPARAM)s_previousFocusWnd, 0);
                    s_previousFocusWnd = s_hwndCocos;
                }
            }
        }
        break;
    case WM_SETFOCUS:
        if (hwnd != s_previousFocusWnd)
        {
          //CCLOG("\nWM_SETFOCUS, entered block");
          
            ::PostMessageW(hwnd, WM_ACTIVATE, (WPARAM)s_previousFocusWnd, 0);
            ::PostMessageW(hwnd, WM_SETCURSOR, (WPARAM)s_previousFocusWnd, 0);
            s_previousFocusWnd = _hwndEdit;
            _hasFocus = true;
            this->_changedTextManually = false;
        }
        else
        {
          // CCLOG("\nWM_SETFOCUS, did NOT enter block");
        }
        break;
    case WM_KILLFOCUS:
        _hasFocus = false;
        //when app enter background, this message also be called.
        if (this->_editingMode && !::IsWindowVisible(hwnd))
        {
          // CCLOG("\nWM_KILLFOCUS, entered block");
            this->editBoxEditingDidEnd(this->getText(), _endAction);
        }
        else
        {
          // CCLOG("\nWM_KILLFOCUS, did NOT enter block");
        }
        break;
    default:
        break;
    }
}

and finally, I have my own EditBoxDelegate subclass that does this:

void PsfEditBoxDelegate::editBoxEditingDidEndWithAction(cocos2d::ui::EditBox *editBox, cocos2d::ui::EditBoxDelegate::EditBoxEndAction action)
{
updateDataFromEditBox(editBox);
// updateDataFromEditBoxes();
// CCLOG(“fired DidEndWithAction”);

if (action == cocos2d::ui::EditBoxDelegate::EditBoxEndAction::TAB_TO_NEXT)
{
EditBox *next = (EditBox *)editBox->getUserData();
if (next != nullptr)
{
editBox->closeKeyboard();
setFocus(next);
}
}
}

void PsfEditBoxDelegate::setFocus(cocos2d::ui::EditBox *editBox)
{
editBox->openKeyboard();
}

1 Like