2

RichEdit単純なアプリケーションに、コンソールのようなディスプレイをシミュレートしたいコントロールがあります。行数 (たとえば 300)のバッファーを保持できるようにしたいのですがx、行が追加されるたびに、新しい行がしきい値を超えた場合は最も古い (一番上の) 行も削除したいと考えていxます。また、追加されたときに最新の行を表示するために自動的に一番下までスクロールしたいと思います。

私はSetWindowTextいくつかの成功を収めて使用してきましたが、テキストを最後に追加し、毎回すべてを置き換えることなく最初からテキストを削除するより効率的な方法がある可能性が高いと思います。これは本当ですか? もしそうなら、どうすればいいですか?

また、新しいテキストが追加されたときにウィンドウの一番下まで自動的にスクロールするにはどうすればよいですか?

これは C の Win32 API を使用しており、MFC バージョンは使用していませんRichEdit(XP と Vista でバニラの Win32 API を使用しているだけです)。

4

2 に答える 2

3

テキストを追加するには、選択範囲をテキストの末尾に設定し (EM_SETSEL)、選択範囲を新しいテキストに置き換えます (EM_REPLACESEL)。

一番下までスクロールするには、SB_BOTTOM で WM_VSCROLL を送信できます。

于 2010-02-05T23:55:06.467 に答える
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 );
}

独自のクラスを構築し、これを確認してください!

于 2012-11-26T16:03:13.480 に答える