【问题标题】:How to use a RichEdit control like a console with the Win32 API?如何使用带有 Win32 API 的控制台之类的 RichEdit 控件?
【发布时间】:2011-01-13 18:05:36
【问题描述】:

我的简单应用程序中有一个RichEdit 控件,我希望用它来模拟类似控制台的显示。我希望能够拥有x 行数(例如300)的缓冲区,并且每当添加一行时,如果新行超过阈值x,我还想删除最旧的(顶部)行.我还希望它在添加时自动滚动到底部以显示最新的行。

我一直在使用SetWindowText 并取得了一些成功,但我发现可能有一种更有效的方法可以将文本附加到末尾并从开头删除文本,而不必每次都替换所有文本。这是真的吗?如果是的话,我该怎么办?

另外,当添加新文本时,如何让它自动滚动到窗口底部?

这是使用 C 中的 Win32 API,我没有使用 RichEdit 的 MFC 版本(只是在 XP 和 Vista 上使用 vanilla Win32 API)。

【问题讨论】:

    标签: c winapi richedit


    【解决方案1】:

    我发给你一些示例类的方法cConsole

    class cConsole {
    private:
        //-------------------
        int lines;
        int max_lines;             // Init it with your choise ( 300 )
        //-------------------
        char* buf;
        int buf_size;
        //-------------------
        int CheckMemory( int size );
        void NewLine( int new_lines );
        void InternalPrint( char* msg, int size );
    
    public:
        HWND hWin;
        void Print( char* msg );    // Add text data through this methods
        void Print( char* msg, int size );
        cConsole( );
        ~cConsole( );
    };
    
    int cConsole::CheckMemory( int size ) {
    int rv = 1;
    if( size + 16 >= buf_size ) {
        int new_buf_size = size + 1024;
        char* new_buf = ( char* )realloc( buf, new_buf_size );
        if( new_buf != NULL ) {
            buf = new_buf;
            buf_size = new_buf_size;
        } else {
            rv = 0;
        }
    }
    return rv;
    }
    
    void cConsole::NewLine( int new_lines ) {
    int rem_lines = ( new_lines + lines + 1 ) - max_lines;
    if( rem_lines <= 0 ) {
        lines += new_lines;
    } else {
        int sel = SendMessage( hWin, EM_LINEINDEX, rem_lines, 0 );
    
        SendMessage( hWin, EM_SETSEL, 0, (LPARAM)sel );
        SendMessage( hWin, EM_REPLACESEL, FALSE, (LPARAM)"" );
        SendMessage( hWin, WM_VSCROLL, SB_BOTTOM, NULL );
    
        lines = max_lines - 1;
    }
    }
    
    void cConsole::Print( char* msg ) { InternalPrint( msg, -1 ); }
    void cConsole::Print( char* msg, int size ) { if( size < 0 ) size = 0; InternalPrint( msg, size ); }
    
    void cConsole::InternalPrint( char* msg, int size ) {
    int s, t = 0;
    int new_lines = 0;
    char* tb;
    
    // msg only mode
    if( size == -1 ) size = 0x7fffffff;
    
    if( msg != NULL && size && CheckMemory( t ) ) {
        for( s = 0; msg[ s ] && ( s < size ); s++ ) {
            if( msg[ s ] == '\r' ) continue;
            if( !CheckMemory( t ) ) break;
            if( msg[ s ] == '\n' ) {
                ++new_lines;
                buf[ t++ ] = '\r';
            }
            buf[ t++ ] = msg[ s ];
        }
        buf[ t ] = '\0';
    }
    if( t && msg != NULL ) {
        tb = buf;
    } else {
        ++new_lines;
        tb = "\r\n";
    }
    
    SendMessage( hWin, EM_SETSEL, (WPARAM)-2, (LPARAM)-1 );
    SendMessage( hWin, EM_REPLACESEL, FALSE, (LPARAM)tb );
    SendMessage( hWin, WM_VSCROLL, SB_BOTTOM, NULL );
    
    if( new_lines ) NewLine( new_lines );
    }
    

    构建你自己的类并检查这个!

    【讨论】:

      【解决方案2】:

      要添加文本,请将所选内容设置为文本末尾 (EM_SETSEL),然后将所选内容替换为新文本 (EM_REPLACESEL)。

      要滚动到底部,您可以发送一个带有 SB_BOTTOM 的 WM_VSCROLL。

      【讨论】:

      • 我使用 -1 作为 EM_SETSEL 的开始和结束位置来结束,它似乎有效。它是否正确?另外,我怎样才能有效地找到第一个换行符来删除 RichEdit 控件中的第一行?
      • 是的,我通常使用 -1 作为起点和终点。我相信您应该能够找到带有 EM_FINDTEXT 的换行符(您可能需要查找“\r\n”),但我想我必须检查一下才能确定。
      猜你喜欢
      • 2022-11-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-24
      • 2011-06-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多