0

文字列内のリッチエディット コントロールからのニュースラインの保存に問題があります。私がやっていることは次のとおりです。

  1. RichEdit コントロールからテキストを取得する
  2. スペースで区切られたすべてを分割する
  3. RTF フォーマットを追加する
  4. 「融合」言葉を元に戻す
  5. コントロールにテキストを送る

どの部分がこれを引き起こしているのかわからないので、最も関連性の高いビットは次のとおりです。

int RichEdit::GetTextLength() const
{
    GETTEXTLENGTHEX len;
    len.codepage = 1200;
    len.flags = GTL_NUMBYTES;
    return (int)SendMessage(this->handle, EM_GETTEXTLENGTHEX, (WPARAM)&len, 0) + 1;
}

tstring RichEdit::GetText() const
{
    auto len = this->GetTextLength();
    GETTEXTEX str;

    TCHAR* tmp = new TCHAR[len];
    str.cb = len;
    str.flags = GT_USECRLF;
    str.codepage = 1200;


    str.lpDefaultChar = NULL;
        str.lpUsedDefChar = NULL;

        (void)SendMessage(this->handle, EM_GETTEXTEX, (WPARAM)&str, (LPARAM)tmp);

        tstring ret(tmp);

        delete[] tmp;
        return ret;
    }

void RichEdit::SetRtfText(const tstring& text, int flags)
    {
        DWORD WideLength = text.length();
        DWORD Length     = WideLength * 4;
        PSTR Utf8        = (PSTR)malloc(Length);

        int ReturnedLength = WideCharToMultiByte(CP_UTF8,
            0,
            text.c_str(),
            WideLength-1,
            Utf8,
            Length-1,
            NULL,
            NULL);

        if (ReturnedLength)
            Utf8[ReturnedLength] = 0;

        SETTEXTEX st = {0};
        st.flags = flags;
        st.codepage = CP_UTF8;
        (void)SendMessage(this->handle, EM_SETTEXTEX, (WPARAM)&st, (LPARAM)Utf8 );

        free(Utf8);
    }

void split ( tstring input , tstring split_id, std::vector<std::pair<tstring,bool>>& res ) {
    std::vector<std::pair<tstring,bool>> result;
    int i = 0;
    bool add;
    tstring temp;
    std::wstringstream ss;
    size_t found;
    tstring real;
    int r = 0;
    while ( i != input.length() ) 
    {
        add = false;
        ss << input.at(i);
        temp = ss.str();

        found = temp.find(split_id);
        if ( found != tstring::npos ) 
        {
            add = true;
            real.append ( temp , 0 , found );
        } else if ( r > 0 &&  ( i+1 ) == input.length() ) 
        {
            add = true;
            real.append ( temp , 0 , found );
        }
        if ( add ) 
        {
            result.emplace_back(std::make_pair(real,false));
            ss.str(tstring());
            ss.clear();
            temp.clear();
            real.clear();
            r = 0;
        }
        i++;
        r++;
    }
    res = result;
}

ps: tstring は std::wstring/std::string の単なる typedef です

改行を保持するにはどうすればよいですか?

4

1 に答える 1

1

コードにはかなりの問題があります。

コードはTCHARベースになっていますが、実際にはTCHAR正しく使用してRTFデータを取得/設定していません。

テキストを取得するときは、改行をCRLFに正規化しますが、テキストの長さを取得するときは同じ正規化を行わないため、互いに同期しなくなります。

UTF-8を使用してRichEditにデータを書き込んでいますが、RTFは、Unicodeデータにエスケープシーケンスを使用するASCIIベースの形式です。データをUnicodeとして取得する場合は、Unicodeを使用してデータを記述し、最初からすべてを正しく実行していることを確認することもできます。RichEditコントロールにUnicodeを処理させます。

あなたの使用WideCharToMultiByte()は間違っています。文字列の長さから-1を引いてはいけません。ヌルターミネータを考慮しようとしている可能性がありますが、長さの値には、そもそもヌルターミネータが含まれていません。UTF-8を使い続ける場合はWideCharToMultiByte()、ハードコーディングするのではなく、を使用して正しいUTF-8の長さを計算する必要があります。

int Length = WideCharToMultiByte(CP_UTF8, 0, text.c_str(), text.length(), NULL, 0, NULL, NULL);
char Utf8 = new char[Length+1];
WideCharToMultiByte(CP_UTF8, 0, text.c_str(), text.length(), Utf8, Length, NULL, NULL);
Utf8[Length] = 0;
...
delete[] Utf8;

そうは言っても、あなたが固執するつもりなら、これをTCHAR試してみてください:

#ifdef UNICODE
#define RTFCodePage 1200
#else
#define RTFCodePage CP_ACP
#endif

int RichEdit::GetTextLength() const
{
    GETTEXTLENGTHEX len = {0};
    len.codepage = RTFCodePage;
    len.flags = GTL_NUMCHARS | GTL_USECRLF;
    return SendMessage(this->handle, EM_GETTEXTLENGTHEX, (WPARAM)&len, 0);
}

tstring RichEdit::GetText() const
{
    int len = this->GetTextLength() + 1;

    GETTEXTEX str = {0};
    str.cb = len * sizeof(TCHAR);
    str.flags = GT_USECRLF;
    str.codepage = RTFCodePage;

    vector<TCHAR> tmp(len);
    len = SendMessage(this->handle, EM_GETTEXTEX, (WPARAM)&str, (LPARAM)&tmp[0]);

    return tstring(&tmp[0], len-1);
}

void RichEdit::SetRtfText(const tstring& text, int flags)
{
    SETTEXTEX st = {0};
    st.flags = flags;
    st.codepage = RTFCodePage;

    #ifdef UNICODE
    st.flags |= ST_UNICODE;
    #endif

    SendMessage(this->handle, EM_SETTEXTEX, (WPARAM)&st, (LPARAM)text.c_str());
}

ドロップTCHARして、すべてにUnicodeを使用することをお勧めします。

int RichEdit::GetTextLength() const
{
    GETTEXTLENGTHEX len = {0};
    len.codepage = 1200;
    len.flags = GTL_NUMCHARS | GTL_USECRLF;
    return SendMessage(this->handle, EM_GETTEXTLENGTHEX, (WPARAM)&len, 0);
}

wstring RichEdit::GetText() const
{
    int len = this->GetTextLength() + 1;

    GETTEXTEX str = {0};
    str.cb = len * sizeof(WCHAR);
    str.flags = GT_USECRLF;
    str.codepage = 1200;

    vector<WCHAR> tmp(len);
    len = SendMessage(this->handle, EM_GETTEXTEX, (WPARAM)&str, (LPARAM)&tmp[0]);

    return wstring(tmp, len-1);
}

void RichEdit::SetRtfText(const wstring& text, int flags)
{
    SETTEXTEX st = {0};
    st.flags = flags | ST_UNICODE;
    st.codepage = 1200;

    SendMessage(this->handle, EM_SETTEXTEX, (WPARAM)&st, (LPARAM)text.c_str());
}

更新:EM_SETTEXTEXメッセージをUTF-8に戻す必要がある場合は、次のことを試してください。

void RichEdit::SetRtfText(const tstring& text, int flags)
{
    string Utf8;
    int Length;

    #ifdef UNICODE

    Length = WideCharToMultiByte(CP_UTF8, 0, text.c_str(), text.length(), NULL, 0, NULL, NULL);
    if (Length > 0)
    {
        Utf8.resize(Length);
        WideCharToMultiByte(CP_UTF8, 0, text.c_str(), text.length(), &Utf8[0], Length, NULL, NULL);
    }

    #else

    Length = MultiByteToWideChar(CP_ACP, 0, text.c_str(), text.length(), NULL, 0);
    if (Length > 0)
    {
        vector<WCHAR> tmp(Length);
        MultiByteToWideChar(CP_ACP, 0, text.c_str(), text.length(), &tmp[0], Length);

        Length = WideCharToMultiByte(CP_UTF8, 0, tmp.c_str(), tmp.length(), NULL, 0, NULL, NULL);
        if (Length > 0)
        {
            Utf8.resize(Length);
            WideCharToMultiByte(CP_UTF8, 0, tmp.c_str(), tmp.length(), &Utf8[0], Length, NULL, NULL);
        }
    }

    #endif

    SETTEXTEX st = {0};
    st.flags = flags & ~ST_UNICODE;
    st.codepage = CP_UTF8;
    SendMessage(this->handle, EM_SETTEXTEX, (WPARAM)&st, (LPARAM)Utf8.c_str());
}
于 2013-03-07T20:09:52.470 に答える