ncurses高级应用

本文详细介绍了ncurses库中如何使用鼠标事件,包括设置鼠标事件、获取鼠标事件、处理鼠标位置等步骤。同时,还阐述了ncurses菜单的创建、显示、操作及各种设置方法,提供了示例代码帮助理解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值