0

我正在尝试使用下面的代码来尝试学习如何使用和控制滚动板。当按下 Z 键时,键盘会向上滚动,这很好。问题是它这样做时会“涂抹”。当它向上滚动时,底线“9-9-9-9-9-”将自身复制到它在移动时接触到的每个部分。我该如何阻止它这样做?

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <errno.h>
#include <ncurses.h>

int main() {

    int key=0, a=0, b=0, c=0, d=0, e=0, f=0;
    WINDOW *mypad;

    initscr();          /* Start curses mode        */
    cbreak();           /* Line buffering disabled, Pass on everything to me */
    timeout(0);         /* wait for user input */   
    noecho();
    keypad(stdscr, TRUE);       /* I need those nifty Function keys     */
    start_color();

    mypad = newpad(10, 10);

    waddstr(mypad, "0-0-0-0-0-");
    waddstr(mypad, "1-1-1-1-1-");
    waddstr(mypad, "2-2-2-2-2-");
    waddstr(mypad, "3-3-3-3-3-");
    waddstr(mypad, "4-4-4-4-4-");
    waddstr(mypad, "5-5-5-5-5-");
    waddstr(mypad, "6-6-6-6-6-");
    waddstr(mypad, "7-7-7-7-7-");
    waddstr(mypad, "8-8-8-8-8-");
    waddstr(mypad, "9-9-9-9-9-");


    prefresh(mypad, 0, 0, 0, 3, 9, 12);
    scrollok(mypad, TRUE);

    a=0;
    b=0;
    c=0;
    d=3;
    e=9;
    f=12;

    key=-1;
    while(key!='q')
    {
        key = wgetch(mypad);
        if(key=='a') { a--; }
        if(key=='z') { a++; }
        if(key=='s') { b--; }
        if(key=='x') { b++; }
        if(key=='d') { c--; }
        if(key=='c') { c++; }
        if(key=='f') { d--; }
        if(key=='v') { d++; }
        if(key=='g') { e--; }
        if(key=='b') { e++; }
        if(key=='h') { f--; }
        if(key=='n') { f++; }

        prefresh(mypad, a, b, c, d, e, f);
    }

    delwin(mypad);
    endwin();

    return 0;
}
4

2 回答 2

0

当您的示例get 时,对minrowz的调用会prefresh更改,这会告诉 ncurses 开始显示 pad 中的相应行。但是垫子只有 10 行长,当 ncurses 到达垫子的末尾时,它会停止从该源显示。这恰好没有达到之前未触及的位置。

您可以提供一个比视口长的 pad,或者使用clrtoeol()clrtobot() 之类的清除操作之一进行整理。

这不是特定于 ncurses 的;pads 的行为可以追溯到 1980 年代中期的 SVr3(请参阅手册中的便携性说明)。

于 2019-12-21T13:25:55.097 回答
0

这并不能回答为什么垫子会模糊,但它确实回答了问题的初衷,即如何让一些文本能够在不丢失任何内容的情况下四处移动和滚动到屏幕外。

好的,所以经过更多的阅读、测试和谷歌搜索......显然答案有两个部分:

A. 垫不滚动,只有窗口滚动。

B. Windows 会滚动,但不是您想的那样。当窗口滚动时,任何从窗口边缘掉下来的文本都会永远丢失(不是我想要的)。

看起来答案是您必须自己缓冲字符,因为 Ncurses 没有。

所以......我想出了这个确实有效

A、S、D、F 键使窗口滚动。Q退出。

更改 main 中的 window_width 和 window_height 变量以使窗口成为您想要的任何大小。

当然,您也可以打印任何您想要的文本。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <errno.h>
#include <ncurses.h>

chtype **initialize_screen_buffer(chtype **input_buffer, int window_width, int window_height)
{
    int size=0, i=0, j=0;

    //Allocate mem for the base pointer
    size=sizeof(chtype*)*window_width;
    input_buffer=calloc(size,1);
    if( input_buffer==NULL ) { fprintf(stderr, "\ninitialize_screen_buffer:> Failed to allocate %d bytes of memory for input_buffer\n", size); exit(1); }

    //Allocate mem for all of the columb pointers
    for(i=0; i<window_width; i++)
    {
        size=sizeof(chtype*)*window_height;
        input_buffer[i]=calloc(size,1);
        if( input_buffer[i]==NULL ) { fprintf(stderr, "\ninitialize_screen_buffer:> Failed to allocate %d bytes of memory for input_buffer[%d]\n", size, i); exit(1); }
    }

    return input_buffer;
}

void free_screen_buffer(chtype **input_buffer, int window_width, int window_height)
{
    int size=0, i=0, j=0;

    //Allocate mem for all of the columb pointers
    for(i=0; i < window_width; i++)
    {
        free(input_buffer[i]);
    }

    //Allocate mem for the base pointer
    free(input_buffer);
}


void copy_window_to_buffer(WINDOW *mywin, chtype **input_buffer, int window_width, int window_height)
{
    int x=0, y=0;

    //start from the beginning
    wmove(mywin, 0, 0 );

    //Copy all chars and from the given window into the buffer
    for(x=0; x < window_width; x++)
    {
        for(y=0; y < window_height; y++)
        {
            input_buffer[x][y]=(chtype)mvwinch(mywin, y, x);
        }
    }
}

void copy_buffer_to_window(WINDOW *mywin, chtype **input_buffer, int window_width, int window_height, int x_offset, int y_offset)
{
    int x=0, y=0;

    //start from the beginning

    //Copy all chars and from the given window into the buffer
    for(x=0; x < window_width; x++)
    {
        for(y=0; y < window_height; y++)
        {
            mvwaddch(mywin, y + y_offset, x + x_offset, input_buffer[x][y]);
        }
    }
}


int main() {

    WINDOW *mywin;
    int key=0, window_width=15, window_height=15, size=0, i=0, j=0, x_offset=0, y_offset=0;
    chtype **screen_buffer;


    screen_buffer=initialize_screen_buffer(screen_buffer, window_width, window_height);

    initscr();          /* Start curses mode        */
    cbreak();           /* Line buffering disabled, Pass on everything to me */
    timeout(0);         /* wait for user input */   
    noecho();
    keypad(stdscr, TRUE);       /* I need those nifty Function keys     */
    start_color();

    mywin = newwin(window_width, window_height, 0, 0);

    waddstr(mywin, "0-0-0-0-0-\n");
    waddstr(mywin, "1-1-1-1-1-\n");
    waddstr(mywin, "2-2-2-2-2-\n");
    waddstr(mywin, "3-3-3-3-3-\n");
    waddstr(mywin, "4-4-4-4-4-\n");
    waddstr(mywin, "5-5-5-5-5-\n");
    waddstr(mywin, "6-6-6-6-6-\n");
    waddstr(mywin, "7-7-7-7-7-\n");
    waddstr(mywin, "8-8-8-8-8-\n");
    waddstr(mywin, "9-9-9-9-9-\n");

    wrefresh(mywin);

    copy_window_to_buffer(mywin, screen_buffer, window_width, window_height);

    key=-1;
    while(key!='q')
    {
        key = wgetch(mywin);
        if(key=='w') { y_offset--; }
        if(key=='s') { y_offset++; }
        if(key=='a') {  x_offset--;  }
        if(key=='d') {  x_offset++; }

        wclear(mywin);
        copy_buffer_to_window(mywin, screen_buffer, window_width, window_height, x_offset, y_offset);
        wrefresh(mywin);
    }

    delwin(mywin);
    endwin();
    free_screen_buffer(screen_buffer, window_width, window_height);

    return 0;
}

这确实解决了使窗口向各个方向滚动而没有文本丢失的问题,但是它有一个问题。它是静态的。这是您当时在您面前的窗户的快照。它不允许在不覆盖旧行的情况下添加更多文本行。

下一步是添加一些重新分配,以便在添加文本时,屏幕缓冲区将增长,以便它可以容纳额外的文本

于 2019-12-19T13:16:35.467 回答