首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

Curses 庫光標操作完整指南

     編輯:關於C語言

光標模型:物理 vs 邏輯

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

常見坑點

  1. 座標順序是 (y, x):行優先,列次之,與直覺 (x, y) 相反。
  2. move()/wmove() 僅修改邏輯光標,**不會立即移動物理光標**,需 refresh()/wrefresh() 同步。
  3. mvcur() 繞過 curses 緩衝區直接操作終端機,**慎用**,可能導致 curses 內部狀態不同步。
  4. curs_set(2)(高亮)在許多終端機無效果,建議僅用 0/1。
  5. 啟用 keypad(stdscr, TRUE) 才能接收 KEY_LEFT 等特殊鍵碼。

參考來源:「暗日」博客 原文連結

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved