Curses 區分兩種光標:
WINDOW* 內部維護的游標位置,用於該窗口的輸出定位。每個窗口擁有獨立邏輯光標。輸入函數(如 getch())結束後,物理光標位置會改變。透過 _leave 標誌(由 leaveok() 控制)決定邏輯光標與物理光標的同步策略:
leaveok(win, TRUE):輸入結束後,物理光標停留在最後輸出位置,邏輯光標不自動歸位。leaveok(win, FALSE)(預設):輸入結束後,物理光標移回該窗口邏輯光標位置。| 函數 | 用途 | 參數說明 |
|---|---|---|
int move(int y, int x) | 移動 標準畫面 (stdscr) 邏輯光標 | y 行, x 列 (0 基址) |
int wmove(WINDOW *win, int y, int x) | 移動指定窗口邏輯光標 | 同上 |
void mvcur(int old_y, int old_x, int new_y, int new_x) | 直接移動物理光標,不經緩衝區刷新 | 舊/新座標;立即生效 |
int curs_set(int visibility) | 設定物理光標可見度 | 0=隱藏, 1=正常, 2=高亮(視終端機支援) |
int leaveok(WINDOW *win, bool bf) | 控制輸入後物理光標行為 | TRUE=保留位置, FALSE=歸位邏輯光標 |
int getyx(WINDOW *win, int y, int x) | 取得窗口邏輯光標位置(宏,非函數) | 將 y, x 填入傳入變數 |
#include <curses.h>
#define MAX_LEN 80
int main() {
initscr();
cbreak(); noecho(); keypad(stdscr, TRUE);
curs_set(1); // 顯示正常光標
leaveok(stdscr, FALSE); // 輸入後光標歸位
char buf[MAX_LEN+1] = {0};
int pos = 0, ch;
int start_y = 5, start_x = 10;
mvprintw(start_y, start_x, "輸入: ");
move(start_y, start_x + 6); // 定位到輸入區起始
while ((ch = getch()) != '\n') {
if (ch == KEY_BACKSPACE || ch == 127) { // 退格
if (pos > 0) {
pos--;
move(start_y, start_x + 6 + pos);
delch(); // 刪除字符並左移後續內容
}
} else if (ch == KEY_DC) { // Delete 鍵
if (pos < (int)strlen(buf)) {
move(start_y, start_x + 6 + pos);
delch();
}
} else if (ch == KEY_LEFT) {
if (pos > 0) pos--, move(start_y, start_x + 6 + pos);
} else if (ch == KEY_RIGHT) {
if (pos < (int)strlen(buf)) pos++, move(start_y, start_x + 6 + pos);
} else if (ch >= 32 && ch < 127 && pos < MAX_LEN) { // 可列印字符
buf[pos++] = ch;
insch(ch); // 插入字符並右移後續內容
}
refresh();
}
buf[pos] = '\0';
endwin();
printf("輸入內容: %s\n", buf);
return 0;
}
move()/wmove() 僅修改邏輯光標,**不會立即移動物理光標**,需 refresh()/wrefresh() 同步。mvcur() 繞過 curses 緩衝區直接操作終端機,**慎用**,可能導致 curses 內部狀態不同步。curs_set(2)(高亮)在許多終端機無效果,建議僅用 0/1。keypad(stdscr, TRUE) 才能接收 KEY_LEFT 等特殊鍵碼。參考來源:「暗日」博客 原文連結