0

Below is simple code for testing Native Win32 Edit control in wxWidgets, no matter if or not I add style WS_EX_CONTROLPARENT or not OR no matter if I add TranslateMessage function, the EDIT control simple does not accept ENTER key and TAB key. I also captured wxEVT_NAVIGATION_KEY and send it to the child window, but it's not working. This seems a basic function. Did I miss someting? (accepting mean showing ENTER and TAB chars in the EDIT box, if you can see the GIF, the message is captured, but no ENTER or TAB chars in the EDIT box)

enter image description here

#include <wx/wx.h>
#include <wx/xrc/xmlres.h>
#include <wx/fs_mem.h>
#include <wx/textdlg.h>
#include <wx/sysopt.h>
#include <wx/socket.h>
#include <wx/aboutdlg.h>
#include <wx/utils.h>
#include <wx/nativewin.h>
#include <wx/process.h>
#include <wx/infobar.h>
#ifdef __WXMSW__
#include "wx/msw/private.h"
#endif

#include <wx/log.h>
//==============================================================================
class MyMSWEdit : public wxNativeWindow{
protected:
    HWND           m_cHWnd;
protected:
    virtual WXLRESULT MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam) wxOVERRIDE {
        switch (nMsg){
        case WM_KEYDOWN:
        case WM_KEYUP:
        case WM_CHAR:
            //MSG messages;
            //while (PeekMessage(&messages, (HWND)0, 0, 0, PM_REMOVE))
            //{
            //    /* Translate virtual-key messages into character messages */
            //    TranslateMessage(&messages);
            //    /* Send message to WindowProcedure */
            //    DispatchMessage(&messages);
            //}
            wxLogMessage("%d",wParam);
            return wxNativeWindow::MSWWindowProc(nMsg, wParam, lParam);
        }
        return wxNativeWindow::MSWWindowProc(nMsg, wParam, lParam);
    }
public:
    explicit MyMSWEdit(wxWindow * parent) : wxNativeWindow(){
        int winmode = WS_CHILD | WS_VISIBLE | ES_MULTILINE;
        int exwinmode =  0;
        m_cHWnd = CreateWindowExW(exwinmode, TEXT("EDIT"), TEXT("EDIT"), winmode, CW_USEDEFAULT, CW_USEDEFAULT, 100, 100, parent->GetHWND(), NULL, NULL, NULL);
        if (m_cHWnd)
            (void)Create(parent, wxID_ANY, m_cHWnd);
    }
    HWND Gethwnd(){
        return m_cHWnd;
    }
    virtual ~MyMSWEdit(){
        Disown();
    }
};
//==============================================================================
class MainFrame : public wxFrame {
protected:
    HWND           m_pHWnd;
    HWND           m_cHWnd;
    MyMSWEdit  *   m_myedit;

public:

    explicit MainFrame(const wxString& title) {
        wxXmlResource::Get()->LoadFrame(this, NULL, "Frame1");
        this->SetTitle(title);
#ifdef _DEBUG
        auto pLog = new wxLogWindow(this, "Debug");
        pLog->PassMessages(false);
        wxLog::SetActiveTarget(pLog);
#else
        wxLog::EnableLogging(false);
        wxLog::SetActiveTarget(NULL);
#endif
        auto P1 = XRCCTRL(*this, "m_panel1", wxPanel);
        P1->Bind(wxEVT_NAVIGATION_KEY, [=](wxNavigationKeyEvent& event){
            ::SendMessage(event.GetCurrentFocus()->GetHWND(),WM_CHAR, VK_TAB, 0);
            wxLogMessage("NAV");
            return 0;

        });
        auto P2 = XRCCTRL(*this, "m_panel2", wxPanel);
        m_myedit = new MyMSWEdit(P2);
        wxASSERT(m_myedit);
        P2->GetSizer()->Insert(0, m_myedit, 1, wxEXPAND | wxALL, 0);
        P2->GetSizer()->Layout();
        m_cHWnd = m_myedit->Gethwnd();
    }
    //--------------------------------------------------------------------------
    virtual ~MainFrame(){
    }
};// end class MainFrame
//=============================================================================
class CJApp : public wxApp {
protected:
    MainFrame* m_pFrame;
public:
    CJApp() {
        m_pFrame = NULL;
    }
    static bool LoadFromString(const wxString & data) {
        static int s_memFileIdx = 0;
        // Check for memory FS. If not present, load the handler:
        wxMemoryFSHandler::AddFile(wxT("XRC_resource/dummy_file"),
            wxT("dummy data"));
        wxFileSystem fsys;
        wxFSFile *f =
            fsys.OpenFile(wxT("memory:XRC_resource/dummy_file"));
        wxMemoryFSHandler::RemoveFile(wxT("XRC_resource/dummy_file"));
        if (f)
            delete f;
        else
            wxFileSystem::AddHandler(new wxMemoryFSHandler);

        // Now put the resource data into the memory FS
        wxString filename(wxT("XRC_resource/data_string_"));
        filename << s_memFileIdx;
        s_memFileIdx += 1;
        wxMemoryFSHandler::AddFile(filename, data);

        // Load the "file" into the resource object
        bool retval = wxXmlResource::Get()->Load(wxT("memory:") + filename);
        return retval;
    }
    virtual bool OnInit() {
        wxSystemOptions::SetOption("msw.remap", 2);
        wxInitAllImageHandlers();
        wxXmlResource::Get()->InitAllHandlers();
#ifdef USERES
        TCHAR * sResName = _T("#131");
        TCHAR * sRestype = _T("CUSTOMERSTRING");
        HRSRC hres = FindResource(NULL, sResName, sRestype);
        HGLOBAL    hbytes = LoadResource(NULL, hres);
        LPVOID pdata = LockResource(hbytes);
        LPBYTE sData = (LPBYTE)pdata;
        LPTSTR sXml = (LPTSTR)sData;
        char tmp[99999];
        sprintf(tmp, "%s", sXml);
        tmp[99998] = 0;
        std::string XRC(tmp);
        if (LoadFromString(XRC)){
            goto success;
        }
#else
        if (wxXmlResource::Get()->Load("Frame1.xrc")){
            goto success;
        }
#endif
        return false;
    success:
        m_pFrame = new MainFrame("");
        m_pFrame->Show(true);
        return true;
    }
};
//==============================================================================
DECLARE_APP(CJApp)
IMPLEMENT_APP(CJApp)

Frame1.xrc:

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<resource xmlns="http://www.wxwindows.org/wxxrc" version="2.3.0.1">
    <object class="wxFrame" name="Frame1">
        <style>wxDEFAULT_FRAME_STYLE|wxTAB_TRAVERSAL</style>
        <size>500,300</size>
        <title></title>
        <centered>1</centered>
        <aui_managed>0</aui_managed>
        <object class="wxPanel" name="m_panel1">
            <style>wxTAB_TRAVERSAL</style>
            <object class="wxBoxSizer">
                <orient>wxVERTICAL</orient>
                <object class="sizeritem">
                    <option>1</option>
                    <flag>wxEXPAND | wxALL</flag>
                    <border>5</border>
                    <object class="wxPanel" name="m_panel2">
                        <style>wxTAB_TRAVERSAL</style>
                        <object class="wxBoxSizer">
                            <orient>wxVERTICAL</orient>
                        </object>
                    </object>
                </object>
                <object class="sizeritem">
                    <option>0</option>
                    <flag>wxALL</flag>
                    <border>5</border>
                    <object class="wxButton" name="m_button1">
                        <label>MyButton</label>
                        <default>0</default>
                    </object>
                </object>
                <object class="sizeritem">
                    <option>0</option>
                    <flag>wxALL</flag>
                    <border>5</border>
                    <object class="wxButton" name="m_button2">
                        <label>MyButton</label>
                        <default>0</default>
                    </object>
                </object>
            </object>
        </object>
    </object>
</resource>
Boying
  • 1,404
  • 13
  • 20
  • What is the question exactly? What do you mean by "accept"? Also, this is way too much code, why do you need the XRC with buttons and all the rest, surely this has nothing to do with the problem, whatever it is. – VZ. Apr 22 '16 at 14:14
  • @VZ.Hi VZ, good day, The buttons are not related with the issue which I forgot to remove them. If you can see the GIF, you could see in the debug window, the code 65/97, 13,9 for "a", ENTER and TAB is captured but only "a" is shown in EDIT box, TAB and ENTER are not shown. – Boying Apr 22 '16 at 14:40
  • 1
    How do you expect ENTER and TAB to be shown?? Sorry but the question just doesn't make sense to me. – VZ. Apr 22 '16 at 15:10
  • @VZ Hi again, I just look deep into the source code and found out the fact, they are treated very special... C:\usr\lib\wxWidgets-3.1.0\src\msw\textctrl.cpp:void wxTextCtrl::OnChar(wxKeyEvent& event). Te be shown means a new line or a "\t"(appear like 4 spaces) in EDIT box – Boying Apr 22 '16 at 15:40

1 Answers1

0

Inspired by this post Win32 - Appending text to an Edit Control and some wxWidget source code src\msw\textctrl.cpp

The problem is resolved in following way

protected:
    void WriteText(TCHAR *newText) {
        // get the current selection
        //DWORD StartPos, EndPos;
        //SendMessage(m_cHWnd, EM_GETSEL, reinterpret_cast<WPARAM>(&StartPos), reinterpret_cast<WPARAM>(&EndPos));

        // move the caret to the end of the text
        //int outLength = GetWindowTextLength(m_cHWnd);
        //SaendMessage(m_cHWnd, EM_SETSEL, outLength, outLength);

        // insert the text at the new caret position
        SendMessage(m_cHWnd, EM_REPLACESEL, TRUE, reinterpret_cast<LPARAM>(newText));

        // restore the previous selection
        //SendMessage(m_cHWnd, EM_SETSEL, StartPos, EndPos);

    }
    virtual WXLRESULT MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam) wxOVERRIDE {
        switch (nMsg){
        case WM_CHAR:
            //MSG messages;
            //while (PeekMessage(&messages, (HWND)0, 0, 0, PM_REMOVE))
            //{
            //    /* Translate virtual-key messages into character messages */
            //    TranslateMessage(&messages);
            //    /* Send message to WindowProcedure */
            //    DispatchMessage(&messages);
            //}
            wxLogMessage("%d",wParam);
            switch (wParam){
            case VK_RETURN:
                WriteText(L"\r\n");
                break;
            case VK_TAB:
                WriteText(L"\t");
                break;
            }
        }
        return wxNativeWindow::MSWWindowProc(nMsg, wParam, lParam);
    }
Boying
  • 1,404
  • 13
  • 20