Sehr Umfangreiche Webseite zum Programmieren in C Perl CGI, Skripting, Linux, Systemprogrammierung C C++ C/C++ ANSI C Linux Linuxsystemprogrammierung Semigrafik curses.h ncurses curses Linuxsystemprogrammieren Semigrafik curses.h ncurses curses 10. Semigrafik (curses.h)

10.7. Mausprogrammierung mit ncurses           zurück zum Inhaltsverzeichnis

Mit Curses ist es auch möglich, die Maus mit hinzu beziehen. Gemeint sind nicht die Funktionen der Headerdatei <gpm.h>. Diese möchte ich in einem späteren Kapitel besprechen. Der Vorteil der Mausroutinen von Curses ist, dass diese sowohl im Textmodus als auch im XTerm laufen. Folgende Struktur wurde dafür definiert ...

typedef struct {
                 short ID;      //Indentität,falls mehrere Mäuse angeschlossen sind
                 int x,y,z;     //Koordinaten,z nicht benötigt
                 mmask_t bstate;//Bitmaske für Mausknöpfe
               }MEVENT;

Der Datentyp mmask_t wurde folgendermaßen definiert ...

typedef unsigned long mmask_t;

Damit Curses überhaupt eine Mauseingabe zur Kenntnis nimmt, muss die Funktion ...

mmask_t mousemask(mmask_t neuemaske, mmask_t *altemaske);

...aufgerufen werden. In der Variablen neuemaske definieren Sie, welche Mausereignisse bearbeitet werden. Folgende Mausereignisse sind in Curses definiert ...

#define BUTTON1_RELEASED        000000000001L
#define BUTTON1_PRESSED         000000000002L
#define BUTTON1_CLICKED         000000000004L
#define BUTTON1_DOUBLE_CLICKED  000000000010L
#define BUTTON1_TRIPLE_CLICKED  000000000020L
#define BUTTON1_RESERVED_EVENT  000000000040L
#define BUTTON2_RELEASED        000000000100L
#define BUTTON2_PRESSED         000000000200L
#define BUTTON2_CLICKED         000000000400L
#define BUTTON2_DOUBLE_CLICKED  000000001000L
#define BUTTON2_TRIPLE_CLICKED  000000002000L
#define BUTTON2_RESERVED_EVENT  000000004000L
#define BUTTON3_RELEASED        000000010000L
#define BUTTON3_PRESSED         000000020000L
#define BUTTON3_CLICKED         000000040000L
#define BUTTON3_DOUBLE_CLICKED  000000100000L
#define BUTTON3_TRIPLE_CLICKED  000000200000L
#define BUTTON3_RESERVED_EVENT  000000400000L
#define BUTTON4_RELEASED        000001000000L
#define BUTTON4_PRESSED         000002000000L
#define BUTTON4_CLICKED         000004000000L
#define BUTTON4_DOUBLE_CLICKED  000010000000L
#define BUTTON4_TRIPLE_CLICKED  000020000000L
#define BUTTON4_RESERVED_EVENT  000040000000L
#define BUTTON_CTRL             000100000000L
#define BUTTON_SHIFT            000200000000L
#define BUTTON_ALT              000400000000L
#define ALL_MOUSE_EVENTS
#define REPORT_MOUSE_POSITION

Ich nehme mal an, diese Funktionen sind selbsterklärend. Mit ...

int maske=mousemask(BUTTON1_PRESSED,NULL);

...können Sie die Routine BUTTON1_PRESSED, also die linke Maustaste gedrückt, bearbeiten. Nun wollen wir mit wgetch() die Mauseigenschaft abrufen ...

chtype button;
button = wgetch(stdscr);

Wurde eine Mausaktivität registriert, so gibt wgetch KEY_MOUSE zurück ...

if(button==KEY_MOUSE)
{
   {/*Mausaktivitäten*/
   ..................

Jetzt wollen wir die Mausaktivität auslesen. Dies geschieht mit der Funktion ...

int getmouse(MEVENT *event);

...in der Praxis...

if(getmouse(&event) == OK)
{
   /*Konnte Mausereignis lesen*/
   ......................

Der Rückgabewert der Funktion getmouse() lautet OK bei erfolgreichem lesen. Ansonsten ERR. Auf einzelne Ereignisse greifen Sie folgendermaßen zu ...

y-Koordinate = event.y;
x-Koordinate = event.x;
bitmaske = event.bstate;
ID = event.id;

z.B. Sie wollen auf Doppelklick testen ...

If(event.bstate == BUTTON1_DOUBLE_CLICK)
{
   /*die linke Taste wurde Doppeltgeklickt*/
   ..............................

Um zu überprüfen, wo und ob im zulässigen Fenster die Mauskoordinate (y,x) liegt, benötigen Sie die Funktion ...

bool wenclose(WINDOW *win, int y, int x);

Der Rückgabewert dieser Funktion lautet, falls das Ereignis im Fenster passierte, TRUE, ansonsten bei Fehler FALSE. Ein kleines Programmbeispiel soll dies Demonstrieren. Wir klicken in einem Bereich des Fensters stdscr und geben die Werte zurück, an welcher Position genau, wir im Fenster den linken Mausbutton betätigt haben ...

#include <curses.h>
#include <stdlib.h>

int main()
{
  MEVENT pos;
  int l_maus;
  chtype button;

  initscr();
  noecho();
  keypad(stdscr,TRUE);
  l_maus=mousemask(BUTTON1_PRESSED,NULL);

  while(1)
    {
      button=wgetch(stdscr);
      if(button==KEY_MOUSE)
        {
          if(getmouse(&pos)==OK)
            {
              wenclose(stdscr,pos.y,pos.x);
              mvwprintw(stdscr,1,0,"y = %2d x = %2d",pos.y,pos.x);
            }
         }
       wrefresh(stdscr);
     }
  endwin();
  return 0;
}

Dieses Beispiel wollen wir jetzt Verändern und Überprüfen an welcher Stelle im Fenster stdscr die Maustaste gedrückt wurde (y,x) und an welcher Stelle die Maustaste im Fenster wieder losgelassen wurde ...

#include <curses.h>
#include <stdlib.h>

int main()
{
  MEVENT pos;
  int l_maus;
  chtype button;

  initscr();
  noecho();
  keypad(stdscr,TRUE);
  l_maus=mousemask(BUTTON1_RELEASED|BUTTON1_PRESSED|BUTTON1_CLICKED,NULL);

  while(1)
    {
      button=wgetch(stdscr);
      clear();
      if(button==KEY_MOUSE)
        {
          if(getmouse(&pos)==OK)
            {/*linke Maustaste gedrückt bei..*/
              if(pos.bstate==BUTTON1_PRESSED)
                {
                  wenclose(stdscr,pos.y,pos.x);
                  mvwprintw(stdscr,1,0,
                      "linke Maustaste gedrückt bei y = %2d x = %2d",pos.y,pos.x);
                }/*linke Maustaste losgelassen bei....*/
             if(pos.bstate==BUTTON1_RELEASED)
               {/*Reaktionszeit beim loslassen auf 1 Tausendstel  Sekunde*/
                  mouseinterval(1);
                  wenclose(stdscr,pos.y,pos.x);
                 mvwprintw(stdscr,2,0,
                    "linke Maustaste losgelassen y = %2d x = %2d",pos.y,pos.x);
               }
            }
        }
      wrefresh(stdscr);
    }
  endwin();
  return 0;
}

Wenn die Maustaste zu schnell oder zu langsam reagiert, können Sie (wie im Beispiel eben geschehen) die Funktion ...

int mouseinterval(int Tausendstelsekunde);

...benutzen. Jetzt wollen wir die Mausroutinen etwas praktischer Einsetzten. Wir erzeugen ein Fenster (WINDOW *fenster) und geben dies auf dem Bildschirm aus. Sie können jetzt auf jedem beliebigen Bereich im stdscr mit der linken Maus drücken und das Fenster wird an diesem Punkt falls möglich versetzt. Als Ausgangspunkt nehmen wir die linke obere Ecke. Weiterhin habe ich an der linken oberen Ecke den Buchstaben 'S' und an der rechten oberen Ecke den Buchstaben 'M' an die Fensterecken gesetzt. Mit 'S' für Schließen, schließen wir das Fenster. Mit 'M' Maximieren wir das Fenster *fenster. Erneutes Klicken auf 'M' bewirkt wieder das Minimieren zur normalen Größe des Fensters ...

#include <curses.h>
#include <stdlib.h>
#define MAXSIZE 1
#define MINSIZE 0

int y_click,x_click;
int y_click2,x_click2;
int size=MINSIZE;

void where_clicked(WINDOW *win,WINDOW *win2,MEVENT pos)
{
  getbegyx(win2,y_click2,x_click2); /*linke obere Ecke von win2*/
  mouseinterval(1);
  wenclose(win,pos.y,pos.x); /*wo in win wurde geklickt*/
  y_click = pos.y;
  x_click = pos.x;
/*wurde auf die linke obere Ecke von win2*/
  if(y_click==y_click2 && x_click==x_click2)
    {
      endwin();
      exit(0);
    }
  else if(y_click==y_click2 && x_click==x_click2+39 || x_click==x_click2+78)
    { //oder wurde auf der rechten oberen Ecke geklickt
      touchwin(stdscr);
      refresh();
      if(size==MINSIZE)
        {
          delwin(win2);
          size=MAXSIZE;
        }
      else if(size==MAXSIZE)
        {
          delwin(win2);
          size=MINSIZE;
        }
  }
}


/*Verschieben des Fensters an Position der globalen Variablen*/
/* x_click und y_click die zuvor mit where_clicked() ermittelt wurden*/
void move_win_to(WINDOW *win)
{
  touchwin(stdscr);
  wrefresh(stdscr);
  mvwin(win,y_click+1,x_click+1);
  touchwin(win);
  wrefresh(win);
}


WINDOW *create_new_window(WINDOW *neues_fenster, int zeilen,
  int spalten, int hinterg, int vordergr, int begin_y, int begin_x)
{
  neues_fenster=newwin(zeilen,spalten,begin_y,begin_x);
  init_pair(1,hinterg,vorderg);
  wattrset(neues_fenster,COLOR_PAIR(1));
  box(neues_fenster,ACS_VLINE,ACS_HLINE);
  return neues_fenster;
}



int main()
{
  MEVENT pos;
  int l_maus;
  chtype button;
  WINDOW *fenster,mfenster;
  int y_alt,x_alt;

  initscr();
  if(has_colors()==TRUE)
      start_color();
  noecho();
  keypad(stdscr,TRUE);

  fenster=create_new_window(fenster,10,40,COLOR_RED,COLOR_BLUE,5,15);
  init_pair(2,COLOR_BLACK,COLOR_YELLOW);
  wattrset(fenster,COLOR_PAIR(2));
  mvwaddch(fenster,0,0,'S');
  mvwaddch(fenster,0,39,'M');
  wattrset(fenster,COLOR_PAIR(0));
  mvwprintw(fenster,2,10,"S=Fenster schliessen");
  mvwprintw(fenster,6,10,"M=Fenster maximieren");
  wrefresh(fenster);

  l_maus=mousemask(BUTTON1_RELEASED|BUTTON1_PRESSED,NULL);

  while(1)
    {
      button=wgetch(stdscr);
      if(button==KEY_MOUSE)
        {
          if(getmouse(&pos)==OK)
            {
              where_clicked(stdscr,fenster,pos);
              //move_win_to(fenster);
             if(size==MAXSIZE)
              {
                fenster=create_new_window(fenster,24,79,COLOR_RED,COLOR_BLUE,0,0);
                wattrset(fenster,COLOR_PAIR(2));
                mvwaddch(fenster,0,0,'S');
                mvwaddch(fenster,0,78,'M');
                wattrset(fenster,COLOR_PAIR(0));
                mvwprintw(fenster,10,30,"S=Fenster schliessen");
                mvwprintw(fenster,14,30,"M=Fenster minimieren");
                wrefresh(fenster);
              }
            else if(size==MINSIZE)
              {
               fenster=create_new_window(fenster,10,40,COLOR_RED,COLOR_BLUE,5,15);
                 init_pair(2,COLOR_BLACK,COLOR_YELLOW);
                 wattrset(fenster,COLOR_PAIR(2));
                 mvwaddch(fenster,0,0,'S');
                 mvwaddch(fenster,0,39,'M');
                 wattrset(fenster,COLOR_PAIR(0));
                 mvwprintw(fenster,2,10,"S=Fenster schliessen");
                 mvwprintw(fenster,6,10,"M=Fenster maximieren");
                 wrefresh(fenster);
                 move_win_to(fenster);
               }
           }
      }
   }
  endwin();
return 0;
}

So siehts aus:

Auf diesem Grundwissen können Sie eine Benutzeroberfläche bauen. Zwei weitere Funktionen die es noch gibt, hier aber nicht durchgenommen wurden, währen ...

int ungetmouse(MEVENT *event);
bool wmouse_trafo(WINDOW *win, int *Py, int *Px);

Für Informationen dazu lesen Sie bitte die man-Page (man mouse).

Weiter mit 10.8. Videoverwaltungsprogramm mit ncurses