重定向std::wcout到自定义流,输出到窗口客户区

放这里,方便以后用!

// =============== 弄一个 自定义流类 ================================

class WindowStreamBuf : public std::wstreambuf {
public:
// 构造函数体的语法格式
// ClassName::ClassName(参数列表) : 成员变量1(初始化值1), 成员变量2(初始化值2), ... {
//
WindowStreamBuf(HWND hwnd, const std::wstring& filename)
: hwnd(hwnd), filename(filename), bufferSize(1024) {

}

~WindowStreamBuf() override {
sync(); // 确保缓冲区内容被刷新
file.close();
}

const std::wstring& getOutputText() const {
return outputText;
}

protected:
int_type overflow(int_type c) override {
// std::lock_guard<std::mutex> lock(mtx); // 加锁
if (c != traits_type::eof()) {
buffer.put(static_cast<wchar_t>(c));
if (c == L'\n' || buffer.str().length() >= bufferSize) {
sync();
}
}
return c;
}

int sync() override {
std::lock_guard<std::mutex> lock(mtx); // 加锁
std::wstring text = buffer.str();
if (!text.empty()) {
// 以追加模式打开文件
std::wofstream file(filename, std::ios::app);
if (file.is_open()) {
file.imbue(std::locale("")); // 设置文件流的区域设置,编码一致性,避免写入失败
file << text;
file.flush();
}

outputText += text;
buffer.str(L"");
InvalidateRect(hwnd, nullptr, TRUE); // 刷新窗口以显示新文本
}
return 0;
}

private:
std::wostringstream buffer;
std::wstring outputText;
HWND hwnd;
std::wstring filename;
std::wofstream file;
size_t bufferSize;
std::mutex mtx; // 互斥锁
};

class WindowStream : public std::wostream {
public:
WindowStream(HWND hwnd, const std::wstring& filename)
: std::wostream(new WindowStreamBuf(hwnd, filename)), originalBuf(std::wcout.rdbuf()) {}

// 恢复原始缓冲区
// 方式1:
WindowStream& operator=(WindowStream&& other) {
if (this != &other) {
std::wcout.rdbuf(originalBuf);
delete rdbuf();
originalBuf = other.originalBuf;
rdbuf(other.rdbuf());
}
return *this;
}
// 方式2:
void reduction() {
std::wcout.rdbuf(originalBuf);
return ;
}

// 析构函数
~WindowStream() {
std::wcout.rdbuf(originalBuf);
delete rdbuf();
}

const std::wstring& getOutputText() const {
return static_cast<WindowStreamBuf*>(rdbuf())->getOutputText();
}
private:
std::wstreambuf* originalBuf; // 保存原始缓冲区指针
};

// ============ 定一个全局变量 =============================================
WindowStream* winStream = nullptr;//  ============ 写在 窗口创建后 ============================================
//  可以放在 WM_CREATE 消息里 
// 重定向 std::wcout
winStream = new WindowStream(hwnd, filename.c_str());
std::wcout.rdbuf(winStream->rdbuf());
// 调用单独的函数获取数据并输出
std::wstring data = L"++++++++++++++"
std::wcout << data << std::endl;
// =============== 写在 WM_PAINT ====================================
// 假设每行高度为 20 像素
int lineHeight = 20;
int startY = -scrollPos * lineHeight;
int currentX = rect.left;
int currentY = startY;

std::wistringstream iss(text);
std::wstring line;
while (std::getline(iss, line)) {
// 检查当前行是否在可见区域内
if (currentY + lineHeight > rect.top && currentY < rect.bottom) {
TextOut(hMemDC, currentX, currentY, line.c_str(), static_cast<int>(line.length()));
}
currentY += lineHeight;
}
// 将内存中的位图复制到屏幕上
BitBlt(hdc, 0, 0, rect.right - rect.left, rect.bottom - rect.top, hMemDC, 0, 0, SRCCOPY);

 

posted @ 2025-02-15 15:50  O-Y  阅读(30)  评论(0)    收藏  举报