65.9K
CodeProject 正在变化。 阅读更多。
Home

从iostreams框架派生自己的流

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.80/5 (7投票s)

2002年7月25日

3分钟阅读

viewsIcon

92289

downloadIcon

987

通过自定义流探索扩展 iostreams 框架。

引言

这是我的 iostreams 三部曲文章中的第三篇。 已经介绍了如何创建插入器、提取器和修改器,接下来我应该解释如何编写一个流。 我将提供两个类,其中一个类覆盖 basic_streambuf,并提供流实现,另一个类派生自 ostream,以便为我们提供一个流来将信息传递给我们的底层代码。

想法

本文的基本想法源于有人在 C++ 论坛中提出的一个问题,即关于将 printf 重定向到编辑框。 因此,手头的任务是创建一个流,该流将流输入附加到编辑框的文本。

MFC?

文章代码采用 MFC 对话框项目的形式,但实际的流不使用 MFC。 你可以将头文件复制到任何 Win32 项目中,它应该也能很好地工作。 我怀疑它也应该适用于 WTL,但我根本没有测试过,好吗?

入口点

因为我们是从一个 iostream 类派生的,我们需要覆盖特定的函数,以便我们的代码可以集成到库中。 我们有三个选择。 流操作可能看起来像这样

cout << "this is some text " << 42 << InstanceOfSomeOtherType;

在这个例子中,cout 处理输入的可能位置如下

函数调用位置
overflow对于传递到流中的每个字符调用一次
flush当发生刷新时调用,通常通过 endl 或析构函数
xsputn每个移位运算符调用一次

所以我们看到了三种选择。

  1. 当调用 overflow 时,将每个字符传递到编辑框中
  2. 当调用 overflow 时,存储每个字符,并在 flush 中一次性传递
  3. xsputn 中一次传递每个字符串或其他对象

选项 1 应该只被那些执行功能开销低的流使用。 选项 2 最适合昂贵的操作。 选项 3 与选项 1 一样简单,而且更有效。 我们将采用选项 3。

基本上,我们在函数中的方法是调用 GetWindowTextLength 来获取窗口中文本的长度,并调用 GetWindowText 来获取字符串,然后我们将其与我们已经拥有的字符串连接起来,并使用(惊喜)SetWindowText 将其放回去。

为了做到这一切,我们需要编辑框的 HWND,所以我们在两个流对象中提供了一个函数,该函数接受一个 HWND 并返回之前存储的那个。 如果它没有被设置,我们的流什么也不做。

代码如下:

        std::streamsize xsputn(const charT * pChar, std::streamsize n)
        {
            if (NULL != m_hWnd)
            {
                const int nLength = ::GetWindowTextLength(m_hWnd) + 1;
                char * pText = new char [nLength];
                ::memset(pText, 0, nLength);
                ::GetWindowText(m_hWnd, pText, nLength);

                std::string s(pText);
                delete [] pText;

                s += std::string(pChar);

                ::SetWindowText(m_hWnd, s.c_str());

                return static_cast<std::streamsize>(s.length());
            }
            else
                return 0;
        }

现在我们只需要用编辑框的 HWND 初始化我们的流,并使用我们想要传递的文本调用我们的流。 演示程序提供了一个禁用的编辑框,显示已经收到的文本,以及一个启用的编辑框,当你按下提供的按钮时,其内容会被流式传输。

如果你是我写这篇文章的人,我希望它对你有所帮助。 无论如何,我希望它能为你提供更多关于如何使用 iostreams 使你的输入和输出生活更轻松的想法。 在我看来,这是一个很棒的库,但似乎很多人都没有充分利用它。 我希望你发现它对你有用。

© . All rights reserved.