2010-02-05 89 views
2

我有一個RichEdit控制在我簡單的應用程序,我希望模擬一個控制檯般的顯示。我想能夠有一個x行數(例如300)的緩衝區,並且每當添加一行時,如果新行超過閾值x,我還想刪除最早的行(頂行)。我也希望它自動滾動到底部以顯示添加的最新行。如何像使用Win32 API一樣使用RichEdit控件?

我一直在使用SetWindowText取得了一些成功,但是我發現有一種更有效的方法可以將文本附加到最後並從頭開始刪除文本,而無需每次都替換所有文本。這是真的嗎?如果是這樣,我該怎麼辦?

另外,如何在添加新文本時自動滾動到窗口的底部?

這是使用C的Win32 API,我沒有使用MFC版本的RichEdit(只使用XP和Vista上的vanilla Win32 API)。

回答

3

要添加文本,請將所選內容設置爲文本的末尾(EM_SETSEL),然後將所選內容替換爲新文本(EM_​​REPLACESEL)。

要滾動到底部,可以使用SB_BOTTOM向其發送一個WM_VSCROLL。

+1

我使用了-1作爲'EM_SETSEL'的開始和結束位置來獲得結束,它似乎已經工作。它是否正確?另外,我如何有效地找到第一個換行符來刪除RichEdit控件中的第一行? – Sydius 2010-02-06 00:19:39

+0

是的,我通常使用-1作爲起點和終點。我相信你應該能夠用EM_FINDTEXT找到一個換行符(你可能需要查找「\ r \ n」),儘管我想我必須檢查確定。 – 2010-02-06 00:23:52

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); 
} 

內置自己的類,並檢查該!