首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在ncurses中未在字段中显示的更改

在ncurses中未在字段中显示的更改
EN

Stack Overflow用户
提问于 2020-02-08 14:28:40
回答 1查看 443关注 0票数 0

我有一个ncurses程序,这是一个登录菜单,我使用字段的用户名和密码。

问题是,当我在字段中键入某些内容时,字符会注册,但不会显示在终端中。换句话说,如果您执行代码but并键入某些内容,您将无法在终端中看到它,但是如果您按F2,您可以看到字符已经注册。

这是我的代码:

test.cpp

代码语言:javascript
复制
#include <curses.h>
#include <form.h>
#include <menu.h>
#include <string>
#include <cstring>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>

class WelcomeMenu {
private:
  int _row; // number of rows of the terminal
  int _col; // number of columns of the terminal
public:
  WelcomeMenu();
  ~WelcomeMenu();
  void welcomeBox();
  void loginMenu();
  void registerMenu();
};

WelcomeMenu::WelcomeMenu(){
  initscr();
  noecho();
  cbreak();
  keypad(stdscr, true);
  int row, col;
  getmaxyx(stdscr,row,col);   /* get the number of rows and columns */
  this->_row = row; this->_col = col;
  loginMenu();
}

WelcomeMenu::~WelcomeMenu(){
  refresh();
  endwin();
}

/*
 * This is useful because ncurses fill fields blanks with spaces.
 */
char* trim_whitespaces(char *str)
{
  char *end;

  // trim leading space
  while(isspace(*str))
    str++;

  if(*str == 0) // all spaces?
    return str;

  // trim trailing space
  end = str + strnlen(str, 128) - 1;

  while(end > str && isspace(*end))
    end--;

  // write new null terminator
  *(end+1) = '\0';

  return str;
}

void WelcomeMenu::loginMenu(){
  // erase();
  FORM *form;
  FIELD *fields[5];
  WINDOW *win_body, *win_form;

  int ch;

  win_body = newwin(24, 80, 0, 0);
  assert(win_body != NULL);
  box(win_body, 0, 0);
  win_form = derwin(win_body, 20, 78, 3, 1);
  assert(win_form != NULL);
  box(win_form, 0, 0);
  mvwprintw(win_body, 1, 2, "Press F1 to quit and F2 to print fields content");

  fields[0] = new_field(1, 10, 0, 0, 0, 0);
  fields[1] = new_field(1, 40, 0, 15, 0, 0);
  fields[2] = new_field(1, 10, 2, 0, 0, 0);
  fields[3] = new_field(1, 40, 2, 15, 0, 0);
  fields[4] = NULL;
  assert(fields[0] != NULL && fields[1] != NULL && fields[2] != NULL && fields[3] != NULL);

  set_field_buffer(fields[0], 0, "Username: ");
  set_field_buffer(fields[1], 0, "username");
  set_field_buffer(fields[2], 0, "Password: ");
  set_field_buffer(fields[3], 0, "password");

  set_field_opts(fields[0], O_VISIBLE | O_PUBLIC | O_AUTOSKIP);
  set_field_opts(fields[1], O_VISIBLE | O_PUBLIC | O_EDIT | O_ACTIVE);
  set_field_opts(fields[2], O_VISIBLE | O_PUBLIC | O_AUTOSKIP);
  set_field_opts(fields[3], O_VISIBLE | O_PUBLIC | O_EDIT | O_ACTIVE);

  set_field_back(fields[1], A_UNDERLINE);
  set_field_back(fields[3], A_UNDERLINE);

  form = new_form(fields);
  assert(form != NULL);
  set_form_win(form, win_form);
  set_form_sub(form, derwin(win_form, 18, 76, 1, 1));
  post_form(form);

  refresh();
  wrefresh(win_body);
  wrefresh(win_form);

  while ((ch = getch()) != KEY_F(1)){

    switch (ch) {
      case KEY_F(2):
        // Or the current field buffer won't be sync with what is displayed
        form_driver(form, REQ_NEXT_FIELD);
        form_driver(form, REQ_PREV_FIELD);
        move(LINES-3, 2);

        for (int i = 0; fields[i]; i++) {
          printw("%s", trim_whitespaces(field_buffer(fields[i], 0)));

          if (field_opts(fields[i]) & O_ACTIVE)
            printw("\"\t");
          else
            printw(": \"");
        }

        refresh();
        pos_form_cursor(form);
        break;

      case KEY_DOWN:
        form_driver(form, REQ_NEXT_FIELD);
        form_driver(form, REQ_END_LINE);
        break;

      case KEY_UP:
        form_driver(form, REQ_PREV_FIELD);
        form_driver(form, REQ_END_LINE);
        break;

      case KEY_LEFT:
        form_driver(form, REQ_PREV_CHAR);
        break;

      case KEY_RIGHT:
        form_driver(form, REQ_NEXT_CHAR);
        break;

      // Delete the char before cursor
      case KEY_BACKSPACE:
      case 127:
        form_driver(form, REQ_DEL_PREV);
        break;

      // Delete the char under the cursor
      case KEY_DC:
        form_driver(form, REQ_DEL_CHAR);
        break;

      default:
        form_driver(form, ch);
        break;
    }
  }

  wrefresh(win_form);

  unpost_form(form);
  free_form(form);
  free_field(fields[0]);
  free_field(fields[1]);
  free_field(fields[2]);
  free_field(fields[3]);
  delwin(win_form);
  delwin(win_body);
}

int main(){
  WelcomeMenu * myConWin = new WelcomeMenu();
  delete myConWin;
  return 0;
}

您可以像:g++ -lncurses -lform test.cpp那样编译它

谢谢你的答复

EN

回答 1

Stack Overflow用户

发布于 2020-02-08 14:36:32

您需要使用echonoecho来打开/关闭回显。如果您愿意,可以将该部分烘焙成一个输入函数:

代码语言:javascript
复制
#include <memory>

struct input_context {
    input_context() {
        echo();       // echo typed characters
        curs_set(1);  // show the cursor
    }
    ~input_context() {
        curs_set(0);  // hide the cursor
        noecho();     // turn off echoing
    }
};

std::string get_string(WINDOW* win, size_t len) {
    std::unique_ptr<char[]> buf = std::make_unique<char[]>(len);
    input_context dummy;
    if(wgetnstr(win, buf.get(), len) != ERR) return std::string{buf.get()};
    return {};
}

注1:只有当所有其他选项耗尽时,才应该使用new/delete (和new[]/delete[])。在您的main中,您可以将动态创建的WelcomeMenu替换为一个自动变量:

代码语言:javascript
复制
int main(){
  WelcomeMenu myConWin;
}

注2:使用nullptr而不是NULL

代码语言:javascript
复制
fields[4] = nullptr; // was NULL

注3:正如@kebs在注释中所述,您应该使用头文件的C++版本:

代码语言:javascript
复制
#include <cassert>   // was assert.h
#include <cstdio>    // was stdio.h
#include <cstdlib>   // was stdlib.h
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60127743

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档