ncurses高级应用
一,使用鼠标
在ncurses中使用鼠标需要几点注意,终端必须在非规范模式下接受鼠标事件,另外,应该有功能键,因为没有他,xterm不会正确的报告鼠标事件。
int raw(void);
int keypad(WINDOW *win, bool bf);
这两个函数用来完成上面要求的工作。
鼠标事件本身通过MEVENT结构来捕获,其定义如下:
typedef struct
{
short id;
int x, y, z;
mmask_t bstate;
}MEVENT;
id用来区分多个设备,xy用来给出鼠标事件发生的位置,z留给未来使用。bstate则指出事件发生时鼠标的状态。下表是鼠标事件的常量的定义
#define BUTTON1_RELEASED 000000000001L 按钮 1 松开
#define BUTTON1_PRESSED 000000000002L 按钮 1 按下
#define BUTTON1_CLICKED 000000000004L 按钮 1 单击
#define BUTTON1_DOUBLE_CLICKED 000000000010L 按钮 1 双击
#define BUTTON1_TRIPLE_CLICKED 000000000020L 按钮 1 三击
#define BUTTON1_RESERVED_EVENT 000000000040L 按钮 1 保留
#define BUTTON2_RELEASED 000000000100L 按钮 2 松开
#define BUTTON2_PRESSED 000000000200L 按钮 2 按下
#define BUTTON2_CLICKED 000000000400L 按钮 2 单击
#define BUTTON2_DOUBLE_CLICKED 000000001000L 按钮 2 双击
#define BUTTON2_TRIPLE_CLICKED 000000002000L 按钮 2 三击
#define BUTTON2_RESERVED_EVENT 000000004000L 按钮 2 保留
#define BUTTON3_RELEASED 000000010000L 按钮 3 松开
#define BUTTON3_PRESSED 000000020000L 按钮 3 按下
#define BUTTON3_CLICKED 000000040000L 按钮 3 单击
#define BUTTON3_DOUBLE_CLICKED 000000100000L 按钮 3 双击
#define BUTTON3_TRIPLE_CLICKED 000000200000L 按钮 3 三击
#define BUTTON3_RESERVED_EVENT 000000400000L 按钮 3 保留
#define BUTTON4_RELEASED 000001000000L 按钮 4 松开
#define BUTTON4_PRESSED 000002000000L 按钮 4 按下
#define BUTTON4_CLICKED 000004000000L 按钮 4 单击
#define BUTTON4_DOUBLE_CLICKED 000010000000L 按钮 4 双击
#define BUTTON4_TRIPLE_CLICKED 000020000000L 按钮 4 三击
#define BUTTON4_RESERVED_EVENT 000040000000L 按钮 4 保留
#define BUTTON_CTRL 000100000000L 同时 CTRL 键也被按下
#define BUTTON_SHIFT 000200000000L 同时 SHIFT 键也被按下
#define BUTTON_ALT 000400000000L 同时 ALT 键也被按下
#define ALL_MOUSE_EVENTS 000777777777L 接收所有的鼠标消息
#define REPORT_MOUSE_POSITION 001000000000L 报告鼠标位置
鼠标使用步骤:
mmask_t mousemask(mmask_t newmask, mmask_t *oldmask);
首先,调用mousemask来告诉ncurses你对那些鼠标事件感兴趣,他的值是上面列出的值的一个或者多个相或的结果,函数执行成功返回掩码的当前设置,出错则会返回0。
int getmouse(MEVENT *event);
int ungetmouse(MEVENT *event);
当有鼠标事件等待处理是,getch就会返回KEY_MOUSE,在再次调用getch之前,必须获得鼠标事件,否则他就会消失。getmouse用来获得下一个鼠标事件,如果出错将会返回ERR,否则返回OK,并填充传递给他的MEVENT结构,ungetmouse会将鼠标事件返回给鼠标事件队列,也会把KEY_MOUSE事件返回给getch函数正在工作的输入队列。
int mouseinterval(int erval);
另外,一次鼠标击键定义为在一定时间内一个按键被按下又被释放。默认的时间是1/5秒,但你可以使用上面的函数来更改这一时间的设置。erval的单位是千分之一秒,同样,函数成功返回OK,失败返回ERR。
bool wenclose(const WINDOW *win, int y, int x);
bool mouse_trafo(int* pY, int* pX, bool to_screen);
bool wmouse_trafo(const WINDOW* win, int* pY, int* pX, bool to_screen);
最后就是处理鼠标发生的位置。wenclose是用来确定给定的xy是不是在win中,getmouse返回的坐标值是相对于屏幕的,所以要用wenclose里来检测鼠标事件是否发生在你的窗口中。如果真的发生在这个窗口,便可以使用wmouse_trafo来产生相对于屏幕的坐标的值。其中最后一个参数应该为FALSE,如果是将相对子窗口的坐标转换成相对于屏幕的坐标值,则最后一个参数为TRUE。宏mouse_trafo是第一个参数为stdscr的wmouse_trafo函数。
/*show the position of mouse event*/
#include <curses.h>
#include <unistd.h>
int main(void)
{
int key;
int quit = 0;
MEVENT event;
initscr();
raw();
keypad(stdscr, TRUE);
mousemask(BUTTON1_CLICKED | BUTTON2_CLICKED, 0);
while (!quit)
{
key = getch();
switch (key)
{
case KEY_MOUSE :
getmouse(&event);
printw("Y:%d X:%d\n", event.y, event.x);
refresh();
break;
case 'q' :
quit = 1;
break;
default :
printw("Key = %d\n", key);
}
}
endwin();
return 0;
}
/*mouse.c*/
#include <curses.h>
#include <unistd.h>
void showstar(WINDOW * win, const int line);
int main(void)
{
int key;
int quit = 0;
MEVENT mouse;
WINDOW * win;
initscr();
raw();
win = newwin(10, 50, 5, 3);/*this must do before keypad*/
keypad(win, TRUE); /*then use win.*/
mousemask(BUTTON1_CLICKED | BUTTON2_CLICKED, 0); /*set actions*/
box(win, '|', '-');
mvwaddch(win, 1, 48, 'X');
mvwaddstr(win, 3, 3, "Test 1");
mvwaddstr(win, 4, 3, "Test 2");
mvwaddstr(win, 5, 3, "Test 3");
wrefresh(win);
while (!quit)
{
key = wgetch(win);
switch(key)
{
case KEY_MOUSE :
getmouse(&mouse); /*get mouse action*/
if (!wenclose(win, mouse.y, mouse.x))
break; /*do nothing if not in window*/
wmouse_trafo(win, &mouse.y, &mouse.x, FALSE);
if ((3 <= mouse.x && mouse.x <= 8)
&& (3 <= mouse.y && mouse.y <= 5))
showstar(win
ncurses高级应用
最新推荐文章于 2025-03-22 22:10:22 发布