CRichEditCtrl::GetSelText() is not working right

こ雲淡風輕ζ 提交于 2019-12-20 04:14:13

问题


MFC File: winctrl4.cpp

(C:\Program Files\Microsoft Visual Studio 8\VC\atlmfc\src\mfc)

CString CRichEditCtrl::GetSelText() const
{
    ASSERT(::IsWindow(m_hWnd));
    CHARRANGE cr;
    cr.cpMin = cr.cpMax = 0;
    ::SendMessage(m_hWnd, EM_EXGETSEL, 0, (LPARAM)&cr);
    CStringA strText;
    LPSTR lpsz=strText.GetBufferSetLength((cr.cpMax - cr.cpMin + 1)*2); 
    lpsz[0] = NULL;
    ::SendMessage(m_hWnd, EM_GETSELTEXT, 0, (LPARAM)lpsz);
    strText.ReleaseBuffer();
    return CString(strText);
}

I am having a weird problem, when I call this it only returns the first character of the selected string. cr is correctly being set but after ::SendMessage(m_hWnd, EM_GETSELTEXT,... the whole string is not present.

I saw similar behavior in my custom code due to WCHAR issues (two-byte character containing a zero in one byte) when CHAR was expected. But this is part of MFC/Win32! Is it possible my .rc file sets something wrong? Is there a Create style relating to this? Or since we create a CFont for the control in question, could that screw it up?


回答1:


This is not the correct MFC source code, have you edited it? Using CStringA and LPSTR is quite inappropriate, the real code uses CString and LPTSTR so that Unicode is correctly handled. Yes, as posted the code would only return one character.


Seeing the version helped. The bug is described in this feedback article. If you can't reasonably upgrade to VS2008 SP1, you could derive your own class from CRichEditCtrl and replace the function. For example:

CString CRichEditCtrlFix::GetSelText() const
{
    ASSERT(::IsWindow(m_hWnd));
    CHARRANGE cr;
    cr.cpMin = cr.cpMax = 0;
    ::SendMessage(m_hWnd, EM_EXGETSEL, 0, (LPARAM)&cr);
    CString strText;
    LPTSTR lpsz=strText.GetBufferSetLength((cr.cpMax - cr.cpMin + 1) * 2);
    lpsz[0] = NULL;
    ::SendMessage(m_hWnd, EM_GETSELTEXT, 0, (LPARAM)lpsz);
    strText.ReleaseBuffer();
    return CString(strText);
}



回答2:


To get a wide char string you have to use the EM_GETTEXTEX message. CRichEditCtrl source does not contain a method which utilizes such message. Here is a correct implementation of GetSelText() which actually does return Unicode characters:

CString CRichEditCtrlFix::GetSelText() const
{
    ASSERT(::IsWindow(m_hWnd));
    CHARRANGE cr;
    cr.cpMin = cr.cpMax = 0;
    ::SendMessage(m_hWnd, EM_EXGETSEL, 0, (LPARAM)&cr);
    CString strText;
    int sz = (cr.cpMax - cr.cpMin + 1) * sizeof(tchar);
    LPTSTR lpsz = strText.GetBufferSetLength(sz);
    lpsz[0] = NULL;
    GETTEXTEX gte;
    memset( &gte, 0, sizeof(GETTEXTEX) );
    gte.cb = sz;
    gte.flags = GT_SELECTION;
    if( sizeof(tchar) == 2 ) gte.codepage = 1200;
    ::SendMessage(m_hWnd, EM_GETTEXTEX, (WPARAM)&gte, (LPARAM)lpsz);
    strText.ReleaseBuffer();
    return CString(strText);
}

1200 here means UTF-16LE



来源:https://stackoverflow.com/questions/2333684/cricheditctrlgetseltext-is-not-working-right

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!