簡體   English   中英

未在 ncurses 字段中顯示的更改

[英]changes not showing in field in ncurses

我有一個 ncurses 程序,它是一個登錄菜單,我使用字段作為用戶名和密碼。
問題是當我在字段中輸入內容時,字符會注冊但不會顯示在終端中。 換句話說,如果您執行代碼並輸入一些內容,您將無法在終端中看到它,但是如果您按 F2,您可以看到字符已注冊。
這是我的代碼:
測試.cpp

#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

預先感謝您的回復

您需要使用echonoecho打開/關閉回聲。 如果您願意,可以將該部分烘焙到輸入函數中:

#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的動態創建:

int main(){
  WelcomeMenu myConWin;
}

注 2:使用nullptr ,而不是NULL

fields[4] = nullptr; // was NULL

注 3:如@kebs 在評論中所述,您應該使用 C++ 版本的頭文件:

#include <cassert>   // was assert.h
#include <cstdio>    // was stdio.h
#include <cstdlib>   // was stdlib.h

該示例的基本問題是它沒有提供顯示字符的功能。 在 ncurses 中,這將使用form_driver函數完成:

form_driver

   Once a form has been posted (displayed), you should funnel input events
   to it through form_driver.  This routine has three major input cases:

   o   The input is a form navigation request.  Navigation  request  codes
       are constants defined in <form.h>, which are distinct from the key-
       and character codes returned by wgetch(3x).

   o   The input is a printable character.   Printable  characters  (which
       must  be positive, less than 256) are checked according to the pro-
       gram's locale settings.

   o   The input is the KEY_MOUSE special key  associated  with  an  mouse
       event.

讓你的程序使用form_driver需要對程序進行一些重組,將 switch 語句移動到一個可以從表單驅動程序調用的函數中。

ncurses 示例包括一些使用form_driver 您可能想通讀測試代碼,了解基本循環如何

while (!finished) {
     switch (form_driver(form, c = form_virtualize(form, w))) {
     case E_OK:
          MvAddStr(5, 57, field_buffer(secure, 1));
          clrtoeol();
          refresh();
          break;
     case E_UNKNOWN_COMMAND:
          finished = my_form_driver(form, c);
          break;
     default:
          beep();
          break;
     }

使用它的form_virtualize函數來讀取字符(或表單請求)。 您(未)看到的可打印字符由form_driver處理,它更新表單上的當前字段。 您可以像在form_virtualize那樣操作字段緩沖區並執行其他特殊操作,但是更新表單中的字段是您使用form_driver

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM