2013-12-16 36 views
1

我正在調整基於控制檯的程序到GUI。Winforms RichTextBox astream

控制檯程序讀取文本文件並「編譯」它。

我的GUI應用程序讀取文本文件並顯示在RichTextBox中。

我正在尋找一種將RichTextBox作爲C++ std::istream對待的方法。這將允許我使用控制檯程序中的代碼而不修改它。

我搜索了網絡和StackOverflow,並沒有發現任何將RichTextBox視爲std::istream的解決方案。

有誰知道任何Winforms庫函數,可以將RichTextBox當作std::istream嗎?

我的想法:

  1. 創建一個適配器來治療的RichTextBox作爲流。
  2. 更改控制檯程序以將「getline」函數傳遞給 編譯器部分,並且有兩個getline函數(一個作爲 std :: getline,另一個作爲從RichTextBox獲取一行)。
  3. 將RichTextBox內容寫入文件並將文件送入 編譯器。用C++(正如我在翻譯我不流利不建議任何C#技術)

我使用Visual Studio 2010在Win 7中使用 「.NET」 4.0,

回答

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開始 - 你必須通過Handle屬性從System.Windows.Forms.RichTextBox中檢索它。不幸的是,這將返回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不加複雜的任務,但最終只有一點點 - 主要是一線獲得控件的句柄,並將其轉換爲正確的類型。除此之外,緩衝區類的代碼幾乎不需要改變,並且實例化和使用它只會改變我們使用寬字符而不是縮小的程度。

+0

這就是令牌錯誤,下面是另一個錯誤:'錯誤LNK2019:無法解析的外部符號'extern「C」long __stdcall SendMessageW(struct HWND__ *,unsigned int,unsigned int,long)「(?SendMessageW @@ $ $ __ @@ IIJ @ Z)在函數「extern」C中引用long __clrcall SendMessage(struct HWND__ *,unsigned int,unsigned int,long)「(?SendMessage @@ $$ J0YMJPAUHWND __ @@ IIJ @ Z)' –

+0

I將「user32.lib」添加到鏈接器輸入中,解決了鏈接器錯誤 –

+0

This works。Thanks for the enlightenment。 –

1

的正確方法創建流堵到Iostreams庫是實現一個流緩衝區,即從std::streambufstd::wstreambuf得到(我不是一個Windows程序員,但我的理解是,大多數代碼在傳播方面wchar_t而不是char),並覆蓋合適的成員函數virtual。假設你可以獲得一堆字符(可能全部是bukl),所有你真的超載的是underflow(),如果輸入緩衝區已用盡,則會調用該字符。如果你可以在施工期間獲得所有的角色,你也可以設置一個緩衝區。

一旦你有一個流緩衝區,你可以使用指向流緩衝區的指針來初始化一個std::istream。這裏是使用存儲器在構造作爲其輸入arean通過一個簡單的例子:

#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"; 
    } 
} 
+0

+1爲寫入內存緩衝區的示例。不幸的是,在託管和非託管C++之間存在一個障礙,這使得實現這個例子並不簡單。 :-( –

相關問題