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
相关产品推荐
相关产品推荐

