我正在将基于控制台的程序调整为GUI。
控制台程序读取一个文本文件并对其进行“编译”。
我的GUI应用程序读取文本文件并显示在RichTextBox中。
我正在寻找将RichTextBox视为C++ std::istream
的方法。这将允许我使用控制台程序中的代码而无需对其进行修改。
我搜索了Web和StackOverflow,但是没有找到任何将RichTextBox视为std::istream
的解决方案。
有谁知道允许将RichTextBox视为std::istream
的Winforms库函数吗?
我的想法:
编译器部分,并具有两个getline函数(一个作为
std::getline,另一个用于从RichTextBox中获取一行)。
编译器。
我在Win 7上使用Visual Studio 2010,使用“.NET” 4.0,在上使用C++ (不建议使用任何C#技术,因为我不太熟练翻译)。
最佳答案
在真实的C++中,您可以通过RTF控件创建流缓冲区,如下所示:
class RTF_buf : public std::streambuf {
std::vector<char> buffer;
public:
RTF_buf(HWND ctrl) {
DWORD len = SendMessage(ctrl, WM_GETTEXTLENGTH, 0, 0);
buffer.resize(len+1);
SendMessageA(ctrl, WM_GETTEXT, len+1, (LPARAM)&buffer[0]);
setg(&buffer[0], &buffer[0], &buffer[len]);
}
};
请注意,这实际上并不限于RTF控件。仅举另一个例子,使用普通的EDIT控件也可以正常工作。
C++ / CLI为此增加了一些皱纹。首先,您正在处理RichTextBox中的“宽”字符。其次,您(通常)不会以HWND开始-您必须通过其
System.Windows.Forms.RichTextBox
属性从Handle
检索它。不幸的是,这会返回HWND
作为IntPtr
而不是HWND
,因此您必须添加强制类型转换以将其转换为正确的类型。这使代码有些丑陋,但没有什么太糟糕了:#include <windows.h>
#include <streambuf>
#include <iostream>
#include <vector>
#include <algorithm>
#pragma comment(lib, "user32.lib")
using namespace System;
using namespace System::Windows::Forms;
class RTF_buf : public std::wstreambuf {
std::vector<wchar_t> buffer;
public:
RTF_buf(RichTextBox^ control) {
HWND ctrl = *reinterpret_cast<HWND *>(&control->Handle);
int len = SendMessage(ctrl, WM_GETTEXTLENGTH, 0, 0);
buffer.resize(len+1);
SendMessage(ctrl, WM_GETTEXT, len+1, (LPARAM)&buffer[0]);
setg(&buffer[0], &buffer[0], &buffer[len]);
}
};
我们可以创建一个缓冲区并istream这样的东西:
RTF_buf b(this->richTextBox1);
std::wistream in(&b);
最后,我们可以从流中读取数据并像对待其他任何(宽)流一样进行处理。例如:
wchar_t ch;
while (in >> ch)
// do something with ch
因此,C++ / CLI确实给任务增加了一点复杂性,但最终却只增加了一点-主要是获得控件句柄并将其转换为正确类型的一行。除此之外,缓冲区类的代码几乎不需要更改,实例化和使用它仅在我们使用宽字符而不是窄字符的程度上进行了更改。