【问题标题】:How can I make a EDIT control in wxwidgets accepting ENTER and TAB key如何在 wxwidgets 中制作一个接受 ENTER 和 TAB 键的 EDIT 控件
【发布时间】:2016-08-15 19:51:14
【问题描述】:

下面是在wxWidgets中测试Native Win32 Edit控件的简单代码,无论我是否添加样式WS_EX_CONTROLPARENT或者无论我是否添加TranslateMessage函数,EDIT控件都不接受ENTER键和TAB键。我还捕获了 wxEVT_NAVIGATION_KEY 并将其发送到子窗口,但它不起作用。这似乎是一个基本功能。我错过了什么吗? (接受意味着在 EDIT 框中显示 ENTER 和 TAB 字符,如果您可以看到 GIF,则捕获消息,但在 EDIT 框中没有 ENTER 或 TAB 字符)

#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>

【问题讨论】:

  • 到底是什么问题? “接受”是什么意思?另外,代码太多了,为什么你需要带有按钮的 XRC 和所有其他东西,这肯定与问题无关,不管它是什么。
  • @VZ.Hi VZ,美好的一天,这些按钮与我忘记删除它们的问题无关。如果你能看到 GIF,你可以在调试窗口中看到,代码 65/97, 13,9 代表“a”,ENTER 和 TAB 被捕获,但在 EDIT 框中只显示“a”,TAB 和 ENTER 没有显示。
  • 您希望如何显示 ENTER 和 TAB?抱歉,这个问题对我来说没有意义。
  • @VZ 再次嗨,我只是深入查看源代码并发现事实,它们被非常特殊地对待... C:\usr\lib\wxWidgets-3.1.0\src\ msw\textctrl.cpp:void wxTextCtrl::OnChar(wxKeyEvent& 事件)。 Te be shown 表示编辑框中的新行或“\t”(显示为 4 个空格)

标签: winapi visual-c++ wxwidgets


【解决方案1】:

受这篇文章的启发 Win32 - Appending text to an Edit Control和一些wxWidget源码src\msw\textctrl.cpp

问题通过以下方式解决

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);
    }

【讨论】:

    猜你喜欢
    • 2012-09-08
    • 2013-03-08
    • 2021-07-15
    • 1970-01-01
    • 2012-09-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-03
    相关资源
    最近更新 更多