You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ncurses(C语言)终端缩小时窗口不显示问题求助

问题分析

你的代码在终端缩小时窗口消失,核心原因有两点:

  • 无效窗口尺寸:当终端宽度缩小到一定程度时,xMax/2 - 2*padding会计算出小于等于0的宽度值,此时newwin无法创建有效窗口,返回NULL。后续对NULL窗口执行wborder、wrefresh等操作会导致异常,窗口无法正常渲染。
  • 未重绘全局元素:终端resize后,顶部的标题和底部的提示信息没有重新绘制,会被窗口操作覆盖或位置偏移。
修复后的代码
#include <ncurses.h>
#include <stdlib.h>

WINDOW *CreateNewWin(int mainWinHeight, int mainWinWidth, int startY, int startX) {
    // 确保窗口尺寸至少为1,避免创建无效窗口
    if (mainWinHeight < 1) mainWinHeight = 1;
    if (mainWinWidth < 1) mainWinWidth = 1;

    WINDOW *localWin = newwin(mainWinHeight, mainWinWidth, startY, startX);
    if (localWin != NULL) {
        box(localWin, 0, 0); 
        wrefresh(localWin); 
    }
    return localWin;
}

void DestroyWin(WINDOW *localWin) {
    // 先判断窗口是否有效,避免操作NULL指针
    if (localWin == NULL) return;
    
    wborder(localWin, ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ');
    wrefresh(localWin);
    delwin(localWin);
}

void DrawGlobalUI(int yMax) {
    // 清除原有内容并重新绘制全局UI
    mvprintw(0, 0, "                "); // 清除原标题位置
    attron(A_BOLD);
    mvprintw(0, 0, "Test app");
    attroff(A_BOLD);

    mvprintw(yMax - 1, 1, "                        "); // 清除原提示位置
    mvprintw(yMax - 1, 1, "Press F1 to quit");
    refresh();
}

int main(int argc, char *argv[]) {
    WINDOW *mainWin = NULL;
    WINDOW *detailsWin = NULL;

    int mainWinHeight, mainWinWidth;
    int detailsWinHeight, detailsWinWidth;
    int padding = 1;

    initscr();            
    cbreak();             
    keypad(stdscr, TRUE); 
    noecho(); // 可选,避免输入字符显示在终端

    int yMax, xMax;
    getmaxyx(stdscr, yMax, xMax);

    // 初始化窗口尺寸
    mainWinHeight = yMax - (2 * padding);
    mainWinWidth = xMax / 2 - (2 * padding);
    detailsWinHeight = yMax - (2 * padding);
    detailsWinWidth = xMax / 2 - (2 * padding);

    DrawGlobalUI(yMax);

    mainWin = CreateNewWin(mainWinHeight, mainWinWidth, padding, padding);
    detailsWin = CreateNewWin(detailsWinHeight, detailsWinWidth, padding, xMax / 2 + padding);

    int ch;
    while ((ch = getch()) != KEY_F(1)) {
        switch (ch) {
            case KEY_RESIZE:
                getmaxyx(stdscr, yMax, xMax);

                // 重新计算窗口尺寸
                mainWinHeight = yMax - 2 * padding;
                mainWinWidth = xMax / 2 - 2 * padding;
                detailsWinHeight = yMax - (2 * padding);
                detailsWinWidth = xMax / 2 - (2 * padding);

                // 销毁旧窗口
                DestroyWin(mainWin);
                mainWin = NULL;
                DestroyWin(detailsWin);
                detailsWin = NULL;

                // 重新绘制全局UI
                DrawGlobalUI(yMax);

                // 创建新窗口
                mainWin = CreateNewWin(mainWinHeight, mainWinWidth, padding, padding);
                detailsWin = CreateNewWin(detailsWinHeight, detailsWinWidth, padding, xMax / 2 + padding);

                break;
            default:
                break;
        }
    }

    // 确保销毁所有窗口
    DestroyWin(mainWin);
    DestroyWin(detailsWin);
    endwin(); 
    return 0;
}
关键修改说明
  • 尺寸边界检查:在CreateNewWin中强制窗口宽高至少为1,避免newwin返回NULL。
  • 安全销毁窗口:DestroyWin先判断窗口指针是否非空,防止操作无效指针导致崩溃。
  • 全局UI重绘:新增DrawGlobalUI函数,在初始化和resize时重新绘制标题和提示,确保元素位置正确。
  • 空指针初始化:将窗口指针初始化为NULL,销毁后重置为NULL,避免重复销毁无效窗口。

内容的提问来源于stack exchange,提问作者JamieBuckerton

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 07:26:34