我正在调整基于控制台的程序到GUI。
控制台程序读取文本文件并“编译”它。
我的GUI应用程序读取文本文件并显示在RichTextBox中。
我正在寻找一种方法将RichTextBox视为C ++ std::istream
。这将允许我使用控制台程序中的代码而无需修改它。
我搜索了网络和StackOverflow,并没有找到任何将RichTextBox视为std::istream
的解决方案。
是否有人知道任何允许将RichTextBox视为std::istream
的Winforms库函数?
我的想法:
我在Win 7上使用Visual Studio 2010使用“.NET”4.0,使用C ++ (不建议任何C#技术,因为我不能流利地翻译)< / em>的。
答案 0 :(得分:1)
创建插入IOStreams库的流的正确方法是实现流缓冲区,即从std::streambuf
或std::wstreambuf
派生(我不是Windows程序员,但我的理解是大多数代码都以wchar_t
而不是char
的形式传播,并覆盖合适的virtual
成员函数。假设你可以获得一串中的字符(可能全部都是bukl),那么你真正重载的是underflow()
,如果输入缓冲区已用尽,则调用它。如果你可以在构造过程中获得所有字符,你也可以设置一个缓冲区。
获得流缓冲区后,可以使用指向流缓冲区的指针初始化std::istream
。这是一个简单的例子,它使用在构造函数中传递的内存作为其输入:
#include <iostream>
#include <streambuf>
class membuf
: std::streambuf {
public:
membuf(char* buffer, std::size_t size) {
this->setg(buffer, buffer, buffer + size);
}
};
int main() {
char input[] = "hello, world!\n";
membuf sbuf(input, sizeof(input - 1));
std::istream in(&sbuf);
char buffer[100];
if (in.getline(buffer, sizeof(buffer)) {
std::cout << "read '" << buffer << "'\n";
}
else {
std::cout << "ERROR: failed to read a line but Dietmar said...!?!\n";
}
}
答案 1 :(得分:1)
在真正的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]);
}
};
我们可以创建一个缓冲区,然后像这样:
RTF_buf b(this->richTextBox1);
std::wistream in(&b);
最后,我们可以从流中读取数据并像处理任何其他(宽)流一样处理它们。例如:
wchar_t ch;
while (in >> ch)
// do something with ch
因此,C ++ / CLI确实为任务添加了小复杂性,但最终只有一点 - 主要是获得控件句柄的一行,并将其转换为正确的类型。除此之外,缓冲类的代码几乎不需要改变,并且实例化和使用它只会改变我们使用宽字符而不是缩小的范围。