C Menüstruktur erstellen (speziell für LCD´s)

Janiiix3

Aktives Mitglied
28. Sep. 2013
1.333
10
38
Hannover
Sprachen
  1. ANSI C
  2. C#
Hallo liebe Mitglieder,

im Moment bin Ich ja wirklich schwer dabei mich tiefer in "C" zu bohren.
Dabei habe ich mir mein "Hardware Enwicklungsboard" wieder aus meiner Bastelkiste raus gekramt.

Nun habe ich damals ja schön ein "paar" Menüs auf einem LCD erstellt mit ein paar Untermenüs.
Das war für den Anfang schon ziemlich "Tricky"... Auf der Suche im Web, bin ich auf folgenden Lösungsvorschlag gekstoßen..



CodeBox C
static const char menu_string0[] PROGMEM = "Highpass";
static const char menu_string1[] PROGMEM = "Bandpass";
static const char menu_string2[] PROGMEM = "Lowpass";

typedef struct MENU {
  const unsigned char *text;
  int8_t previous;
  int8_t next;
  void ( *fp )( void );
} MENU_ENTRY;

const MENU_ENTRY menue[] PROGMEM= {
  { menu_string0, 2, 1, highpass },
  { menu_string1, 0, 2, bandpass },
  { menu_string2, 1, 0, lowpass }
  };


Auf meinem (G)LCD würde Ich nun ein vill. übersichtlicheres / strukturiertes Menü erstellen wollen.
Da kommen die "structs" ja schon ziemlich gut oder?

Desweiten möchte Ich gerne den aktuellen "Menüpunkt" mit einem Pfeil hervorheben "->"..

->Einstellungen
Ausschalten
Neustarten
Exit
---

Das man quasi mit dem Pfeil erkennen kann wo man gerade überhaupt ist.

Habt Ihr da noch Ideen, Anregungen?
 
Das mit dem Pfeil wird einfacher, wenn er vor dem Text erscheint (also der selektierte Text nicht rüberrutschen muß). Gehen tut natürlich beides.
Zu structs usw kann ich nichts sagen.
Zur allgemeinen Handhabung von Menus gabs (im BASCOM-Bereich) mal'n recht interessantes Konzept.
Die Idee war, jede Menu-Seite(?) zu sowas wie 'nem Objekt (in Form von Speicheradressen im Flash) zu machen, mit Eigenschaften (was soll wo angezeigt werden) und Methoden (was soll geschehen wenn Taster X betätigt wird).
Der Zustandsautomat hinter dem Menü greift dann immer auf die Adressen der gerade aktiven Menu-Seite zu.
Sowas läßt sich (logischerweise) grundsätzlich auch in anderen Sprachen realisieren, und in beliebiger Komplexität...
 
An sowas habe ich auch schon gedacht.
Das Beispiel oben ist ja schon gar nicht so schnlecht.



CodeBox C
typedef struct MENU
{
  const unsigned char *text;
  int8_t previous;
  int8_t next;
  void ( *fp )( void );
} MENU_ENTRY;




CodeBox C
const MENU_ENTRY menue[] =
{
  {"Einstellungen"   , 0   , 1   , openSettings    },
  {"Beenden"       , 1   , 2   , NULL           },
  {"Exit"           , 2   , 0   , NULL            }
};



Und dann halt in einer Funktion den aktuellen betätigten Taster auswerte (Taster = Index)



CodeBox C
openMenue(uint8_t index)
{
     for(uint8_t i = 0 ; i < SIZE_OF_ENTRYS : i++)
     {
          if(index == i)
          {
               strcpy(buffer,"->");
               strcat(buffer,menue[index].text);
          }
          else
          {
               strcpy(buffer,menue[index].text);
          }
          glcdGotoXY(index,0);
          glcdPuts(buffer);
     }
}


Ich hatte diese Funktion schon geschrieben, damit werden mir meine ganzen Menüeintrage auf das Display geworfen und wenn "index == i" also ein Taster gedrückt wurde oder eben mit nem Drehencoder die Position gewählt wurde, würde da halt der "Cursor" in Form eines "->" vor stehen.
 
Habe vielleicht was für dich. Es besteht aus einem Atmega, einem Drehgeber an einem Port und einem Display über den I2C Bus. Der Drehgeber kann links und rechts unterscheiden und mit dem Druckkopf im Drehgeber gibt es noch einen Einknopfbedieneng mit kurz oder landdrücken dazu. Anzeige erfolgt auf dem Display mit einem Pfeil und können mehrere Untermenues gebaut werden. Vielleicht kannst du es gebrauchen.
achim
 
Hallo @achim S.
Anschauen kann Ich es mir ja mal.
 
Sieh es dir mal an:


CodeBox C
/* ATB_Enc_Menue_Prg_1.c
 * Created: 14.12.2016 12:21:55 Author : AS */

//#define F_CPU 16000000           // CPU clock in Hz
#include <stdbool.h>
#include <avr/pgmspace.h>
#include "main.h"
#include <util/delay.h>
#include "i2clcd.h"
#include "i2cmaster.h"
#include "avr/io.h"
#include <avr/interrupt.h>
#include <stdlib.h>
#include <stdint.h>
//#include "encoder.h" !!!!!!!!
//#include "encoder.c"



volatile uint8_t wait;
volatile uint8_t key_state;
volatile uint8_t key_press;
volatile uint8_t key_rpt;

volatile int16_t led1=0;
volatile int8_t Anz=0;
volatile int8_t zeile=2;
volatile int8_t lauf=0;
int8_t Menue;


#define KEY_DDR    DDRA                        // Datenrichtung A
#define KEY_PORT   PORTA                        // Angabe Port A
#define KEY_PIN    PINA                         // Angabe PIN A
#define KEY_1       7                           // PA 3
#define KEY_2       6                           // PA 5
#define KEY_3       5                           // PA 7
#define KEY_4       3                           // PA 6
#define ALL_KEYS (1<<KEY_1|1<<KEY_2|1<<KEY_3|1<<KEY_4)
#define REPEAT_MASK (1<<KEY_1|1<<KEY_2|1<<KEY_3)
#define REPEAT_START 80                          // after 500ms  50
#define REPEAT_NEXT 40                           // every 200ms  50

#define PHASE_A     (PINA & 1<<PA0)       // Eingang Encoder A  P98
#define PHASE_B     (PINA & 1<<PA1)       // Eingang Encoder B  P98

//#define PHASE_A     (PINA & 1<<PA2)       // Eingang Encoder A  P32
//#define PHASE_B     (PINA & 1<<PA1)       // Eingang Encoder B  P32

#define LEDS_DDR    DDRB               // Ausgang LED
#define LEDS        PORTB               //

volatile int8_t enc_delta;               // -128 ... 127
static int8_t last;

char Buffer[20];
int8_t dreh1 = 4;
//int8_t dreh1u = 2;

// ATmega 1284p auf Board 1, 16 MHz, Drehgeber auf P98 auf Port A, NT2, 8x LED auf P20 am Port B

//***********************************************************************                                                                   
//                      Reading rotary encoder                                                                                         
//              Author: Peter Dannegger                                                                                                     
//************************************************************************

void encode_init( void )
  {
   int8_t new;
   new = 0;
   if( PHASE_A ) new = 3;   //3
   if( PHASE_B ) new ^= 1;               // convert gray to binary
   last = new;                           // power on state
   enc_delta = 0;
  }  
/////////////////////////////////////////////
ISR (TIMER0_COMPA_vect)                   // ISR mit 1 ms
  {
    int8_t new, diff;                   // ab hier Encoder
   new = 0;
   if( PHASE_A ) new = 3;
   if( PHASE_B ) new ^= 1;               // convert gray to binary
   diff = last - new;                   // difference last - new
   if( diff & 1 )
     {                                   // bit 0 = value (1)
       last = new;                       // store new as next last
       enc_delta += (diff & 2) - 1;   // bit 1 = direction (+/-)
     }
   static uint8_t ct0=0xFF, ct1=0xFF, rpt;       // ab hier Tasten
   uint8_t i;
   if(wait<=9)                                // bei 9 sind es 10ms
   {
        wait++;
     }                      // erhöht
   else                    // wenn dann ...
     {
       wait=0;                  // setzt wait auf 0
       i=key_state ^ KEY_PIN;       // nach +5V
       //i=key_state ^~KEY_PIN;   // nach GND
       ct0=~(ct0&i);
       ct1=ct0^(ct1&i);
       i&=ct0&ct1;
       key_state^=i;
       key_press|=key_state&i;
       if((key_state & REPEAT_MASK)==0)
       rpt=REPEAT_START;
       if(--rpt==0)
         {
           rpt=REPEAT_NEXT;
           key_rpt|=key_state & REPEAT_MASK;
         }
     }
   }   
 //////////////////////////////////////////////////////////
int8_t encode_read1( void )               // lesen einzel Schritt Encoder = schnell
  {
   int8_t val;
   cli();
   val = enc_delta;
   enc_delta = 0;
   sei();
   return val;                   // counts since last call
  }
int8_t encode_read2( void )               // lesen zwei Schritt Encoder = mittel
  {
   int8_t val;
   cli();
   val = enc_delta;
   enc_delta = val & 1;
   sei();
   return val >> 1;
  }
int8_t encode_read4( void )               // lesen vier Schritt Encoder = langsam
  {
   int8_t val;
   cli();
   val = enc_delta;
   enc_delta = val & 3;
   sei();
   return val >> 2;
  }
////////////////////////////////////////////////////////////////////  
void timer_init()
  {
   //TCCR0A = (1<<WGM01);
   TCCR0A = 0;
   TCCR0B = (1<<WGM01)|(1<<CS01)|(1<<CS00);
   TCNT0=1;
   OCR0A = 249;
   TIMSK0 |=(1<<OCIE0A);
  }
//////////////////////////////////////////////////////
uint8_t get_key_press(uint8_t key_mask)
  {
   cli();
   key_mask &=key_press;
   key_press^=key_mask;
   sei();
   return key_mask;
  }
/////////////////////////////////////////
uint8_t get_key_rpt(uint8_t key_mask)
  {
   cli();
   key_mask &=key_rpt;
   key_rpt^=key_mask;
   sei();
   return key_mask;
  }
///////////////////////////////////////////////////////
uint8_t get_key_short(uint8_t key_mask)
  {
   return get_key_press(~key_state & key_mask);
  }
///////////////////////////////////////////////////////
uint8_t get_key_long(uint8_t key_mask)
  {
   return get_key_press(get_key_rpt(key_mask));
  }   
///////////////////////////////////////////////////////////////////
void led_blinken1()
  {
   led1++;
   if(led1==500)
     {
       PORTA &= ~(1<<PA5);        // Schaltet Pin
     }
   else
     {
       if(led1==1000)
         {
           PORTA |= (1<<PA5);      // Schaltet Pin
           led1=0;
         }
     }
  }
/////////////////////////////////////////////////////////////////  
void Startanzeige()
  {   
    lcd_printlc(1,3,"Enc-Menue 1");                // Text Zeile 1
    lcd_printlc(2,2,"**************");           // Text Zeile 2
    lcd_printlc(3,1,"Encoder Menue 1");       // Text Zeile 3
    lcd_printlc(4,2,"(by achim S.)");           // Text Zeile 4
  }
///////////////////////////////////////////////////////////  
void Bedienung()
  {
   lcd_printlc(1,1,"Bedienung-Menue");                // Text Zeile 1
   lcd_printlc(2,3,"< + > Auswahl");           // Text Zeile 2
   lcd_printlc(3,3,"kurz - Start");       // Text Zeile 3
   lcd_printlc(4,3,"lang - Reset");           // Text Zeile 4
  }  
///////////////////////////////////////////////////
void Anzeige(int8_t valk)
  {
    Anz++;
    if (Anz==50)
      {
       lcd_printlc(1,3,"Enc-Menue 1");                // Text Zeile 1
       lcd_printlc(2,2,"**************");           // Text Zeile 2
       lcd_printlc(3,2,"Werte Encoder:");       // Text Zeile 3
       itoa(valk,Buffer,10);
        lcd_printlc(4,4,Buffer);
        Anz=0;
      }
  }
//////////////////////////////////////////////////////////////////
void Menue1(int8_t zeile)            //
  {
   lauf++;
   if(lauf==100)
     {
       //lcd_command(LCD_CLEAR);                       // Leere Display
       //_delay_ms(2);
         
       lcd_printlc(1,2,"Menue 1 - I2C");
       lcd_printlc(2,4,"Menue 1-1");
       lcd_printlc(3,4,"Menue 1-2 ");
       lcd_printlc(4,4,"Menue 1-3");
       lcd_printlc(2,1,"  ");
       lcd_printlc(3,1,"  ");
       lcd_printlc(4,1,"  ");
       lcd_printlc(zeile,1,">>");
       lauf=0;
     }
  }  
///////////////////////////////////////////////////////////////////////  
void Menue11()
  {
   lcd_command(LCD_CLEAR);                       // Leere Display
   _delay_ms(2);
   lcd_printlc(1,1,"Bedienung-Menue");                // Text Zeile 1
   //lcd_printlc(2,3,"< + > Auswahl");           // Text Zeile 2
   lcd_printlc(3,3,"Menue 1-1");       // Text Zeile 3
   lcd_printlc(4,3,"lang - Reset");           // Text Zeile 4
  }  
///////////////////////////////////////////////////////////////////////
void Menue12()
{
   lcd_command(LCD_CLEAR);                       // Leere Display
   _delay_ms(2);
   lcd_printlc(1,1,"Bedienung-Menue");                // Text Zeile 1
   //lcd_printlc(2,3,"< + > Auswahl");           // Text Zeile 2
   lcd_printlc(3,3,"Menue 1-2");       // Text Zeile 3
   lcd_printlc(4,3,"lang - Reset");           // Text Zeile 4
}
///////////////////////////////////////////////////////////////////////
void Menue13()
{
   lcd_command(LCD_CLEAR);                       // Leere Display
   _delay_ms(2);
   lcd_printlc(1,1,"Bedienung-Menue");                // Text Zeile 1
   //lcd_printlc(2,3,"< + > Auswahl");           // Text Zeile 2
   lcd_printlc(3,3,"Menue 1-3");       // Text Zeile 3
   lcd_printlc(4,3,"lang - Reset");           // Text Zeile 4
}  
/////////////////////////////////////////////////////////////////////  
/////////   Hauptprogramm  
/////////////////////////////////////////////////////////////////////
 
int main( void )                               // Hauptschleife
  {
   timer_init();  
   i2c_init();                                   // Starte I2C Bus
   lcd_init();                                   // Starte I2CLCD
   lcd_light(0);                               // 0=Licht an, 1=Licht aus
   // Display Befehle
   lcd_command(LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKINGOFF);
   // Display ON/OFF / Cursor ON/OFF / Blinken ON/OFF
   lcd_command(LCD_CLEAR);                       // Leere Display
   _delay_ms(2);
                                   // warte 2ms
   Startanzeige();
   _delay_ms(3000);   
   
   lcd_command(LCD_CLEAR);                       // Leere Display
   _delay_ms(2);                               // warte 2ms
   
   Bedienung();
   _delay_ms(3000);
   
   lcd_command(LCD_CLEAR);                       // Leere Display
   _delay_ms(2);
   
   KEY_DDR&=~ALL_KEYS;
   KEY_PORT|=ALL_KEYS;
   
   DDRA |= 0b01111100 ;   // LED1+2 auf PA4 und PA5, alle auf Ausgang
   //PORTA = 0b00000000;       // alle LED auf aus bei 1
   PORTA |= (1<<PA5);   // LED Blau auf P98 Pin 5
   PORTA |= (1<<PA6);   // LED Blau auf P98 Pin 5
   int8_t val = 0;
   LEDS_DDR = 0xff;       
   encode_init();
   val=2;
   sei();
   while(1)
     {
       led_blinken1();                           // Aufruf Unterprogramm LED blinken
       
       val += encode_read4();                   // Aufruf Encoder 4 mit Rückgabe
       
       if (Menue==0)
        {
       
       
       Menue1(val);
     }
       // Auswertung Grundmenue 1 ////////////////////////////////////
       if (val>dreh1)                           // Begrenzung oben
         {
           val=2;
         }
       if (val<2)                               // Begrenzung unten
         {
           val=dreh1;
         }
       //////////////////////////////////////////////////////////////  
         
       //LEDS = val;
       //Anzeige(val);
       
       if (val==2)       // LED blau
         {
           PORTA &= ~(1<<PA4);   // LED auf P98  L3 ??
         }
       else
         {
           PORTA |= (1<<PA4);   // LED Blau auf P98 Pin 5 ??
         }
       if (val==4)       // LED grün
         {
           PORTA &= ~(1<<PA3);   // LED auf P98  L3   ???
         }
       else
         {
           PORTA |= (1<<PA3);   // LED Blau auf P98 Pin 5 ????
         }
       if (val==6)       // LED rot
         {
           PORTA &= ~(1<<PA2);   // LED auf P98  L3 ???
         }
       else
         {
           PORTA |= (1<<PA2);   // LED Blau auf P98 Pin 5 ???
         }
       if (val==8)
         {
           PORTA &= ~(1<<PA2);   // LED auf P98  L3
           PORTA &= ~(1<<PA3);   // LED auf P98  L3
           PORTA &= ~(1<<PA4);   // LED auf P98  L3   
         }
         
         /*
       else
         {
           PORTA |= (1<<PA2);   // LED Blau auf P98 Pin 5
           PORTA |= (1<<PA3);   // LED Blau auf P98 Pin 5
           PORTA |= (1<<PA4);   // LED Blau auf P98 Pin 5   
         }
       */
       
       if(get_key_short(1<<KEY_1))       // schaltet kurz
         {
           PORTA &= ~(1<<PA6);   // LED auf P98  L3   
           if (val==2)       // LED rot
             {
               Menue=1;  
               Menue11();
             }
           if (val==3)       // LED rot
             {
               Menue=1;  
               Menue12();
             }
           if (val==4)       // LED rot
             {
               Menue=1;  
               Menue13();
             }   
         }
         
       if(get_key_long(1<<KEY_1))       // schaltet lang
         {
           Menue=0;
           PORTA |= (1<<PA6);   // LED Blau auf P98 Pin 5
           lcd_command(LCD_CLEAR);                       // Leere Display
           _delay_ms(2);   
         }
       //PORTA |= (1<<PA3);   // LED Grün auf P98 Pin 4
       //PORTA |= (1<<PA2);   // LED Rot auf P98 Pin 3  
     }
    }
 


CodeBox C
typedef struct
{
   char *Name;
   void (*fp)           (void);
   void (*setCursor)   (int8_t *cursor, int8_t pos);
}menue_t;


Kann Ich es irgendwie anstellen, dass ich auch andere Funktionsparameter übergeben kann bzw. keine?!
Aktuell besteht die Struktur ja aus..

char *Name = Menüname
void (*fp) (void)
void (*setCursor)(int8_t *, int8_t)

Leider ist man ja nun an die Parameter gebunden und kann nicht "einfach" andere Funktionen "verlinken / zuweisen".
Hoffentlich versteht mich einer:D

Gibt es da eine Lösung?



CodeBox C
menue_t mainMenue[]=
{
   {"  ++HeschDevBoard++ "   ,menueSetMainMenue       ,menueSetCursor       },
   {"Uhrzeit stellen"       ,menueSetTime           ,menueSetCursor       },
   {"Datum stellen"       ,menueSetDate           ,menueSetCursor       },
   {"Helligkeit"           ,menueBrightness       ,menueSetCursor       },
   {"Kontrast"               ,menueContrast           ,menueSetCursor       },
   {"Seriennummer"           ,menueDispSerNr           ,menueSetCursor       },
   {"Admin Login"           ,menuePassword           ,menueSetCursor       },
   {"Bluetooth"           ,menueSetBluetoothMenue   ,menueSetCursorHome   },
   {"Relais"               ,menueSetRelais           ,menueSetCursor       },
   {"Hardware Info"       ,menueHardwareInfo       ,menueSetCursor       },
   {"Neustart"               ,menueRestart           ,menueSetCursor       },
   {"Verlassen"           ,menueError               ,menueSetCursor       },
};
 
In Deinem Beispiel/Deiner Vorlage aus #1 werden generell Funktionen ohne Parameter (Argumente?) verwendet, oder? Du müßtest also auf Parameter verzichten, oder die anders übergeben. Insbesondere kannst Du dann auch eine leere Funktion implementieren/zuweisen.
 
In Deinem Beispiel/Deiner Vorlage aus #1 werden generell Funktionen ohne Parameter (Argumente?) verwendet, oder? Du müßtest also auf Parameter verzichten, oder die anders übergeben. Insbesondere kannst Du dann auch eine leere Funktion implementieren/zuweisen.

Muss ich nicht. Das ist jetzt halt auch eine Frage. Mache Ich die ganzen Variablen global so das ich von jeder Funktion drauf zugreifen kann oder gibt es doch eine Möglichkeit verschiedene Funktionsparameter dort mit einzuarbeiten.

Aktuell wie man in #7 sieht, habe ich zwei Funktionszeiger aufgenommen.
1/ Ist ein "void" Funktionszeiger der keinen Übergabeparameter erwartet.
2/ ist ein "void" Funktionszeiger der einen "int8_t *" Zeiger erwaret und der zweite erwartet einen "int8_t" Werr.

Den zweiten Funktionspointer nutze Ich aktuell dafür, dass ich einen Cursor flexibel in einer Funktion immer auf eine bestimmte Position setzen kann.
 
???
Wenn Du mehrere Funktionspointer (mit unterschiedlich vielen Parametern) in der Struktur festlegst mußt Du doch auch in jeder erzeugten Instantz (?) für jeden Funktionspointer 'ne Zuweisung vornehmen, oder nicht?
Das hattest Du ja in #7 schon. Wie ist da die Frage zu verstehen?
 
In dieser Struktur habe ich zwei Funktionspointer. Wenn ich jetzt eine "Instanz" erstelle, gibt es für diese folgendes..


CodeBox C
Name, Funktionszeiger(keine Rückgabe, keine Übergabe), Funktionszeiger(int8_t *,int8_t value)

Aktuell hat eine "Instanz" oder wie Ich es gerade bei Mir nenne "Menüpunkt" diese Inhalte.

Natürlich kann ich z.B


CodeBox C
void rufDieseFunktionJetztAuf(void)
{
     hierDieEigentlicheFunktionDieAufgerufenWerdenSollte(char *buff)
     {
          ...
     }
}

Für eine Funktion, die andere Parameter erwartet wieder eine Funktion erstellen. Nur das bläht den Kode zu sehr auf. Dafür muss es doch noch eine bessere Lösung geben.
 
Für eine Funktion, die andere Parameter erwartet wieder eine Funktion erstellen...
Natürlich!
Dafür muss es doch noch eine bessere Lösung geben.
Wie stellst Du Dir das vor?
Wenn die Funktion aufgerufen wird, wird ihre Adresse im Flash angesprungen (mit einem Call, ob nun direkt oder indirekt bleibt sich gleich). Insbesondere wird dabei die Rücksprungadresse auf den Stack gepackt (genaugenommen druntergeheftet).
Die Parameter müssen aber auch irgendwie übergeben werden, und zwar indem sie vorher irgendwo abgelegt werden. Je nach Anzahl und/oder Typ (und ob es sich um tatsächliche Werte (values) oder Adressen (Referenzen) handelt) sind das unterschiedlich viele Speicherzellen (Bytes), die benötigt werden, und die Konstellation beim Aufruf muß eben zur Funktion an der tatsächlich angesprungenen Adresse passen.
Du brauchst also für jede mögliche Konstellation ein "Muster" der Funktion (weil beim tatsächlichen Aufruf genau dort das ablegen der Parameter abgearbeitet wird).
Mit Deiner Struktur hast Du Dir jetzt einen zusammengesetzten Datentypen erschaffen, der eben auch Funktionsaufrufe enthält, und aufgrund der unterschiedlichen Parameter eben mehrere (alle möglichen verwendeten "Muster").
Für jede Instanz dieses zusammengesetzten Datentypen müssen natürlich auch alle darin enthaltenen Sub-Datentypen miterzeugt werden.

In einer Hochsprache kümmert sich ebendiese um das korrekte übergeben der Parameter - sie nimmt es Dir ab, Du mußt Dich an entsprechende Regeln bei der Syntax und Verwendung halten. Wenn Du stattdessen völlige Kontrolle haben willst, mußt Du eine weniger hohe Sprache verwenden...

P.S.: auf Rückgabewerte bin ich nicht weiter eingegangen - quasi dasselbe wie ein Parameter, nur eben beim Rücksprung...
 
Ist ja schon n Rattenschwanz geworden hier...

Nur zur Info, weißt du eigentlich auch selber - in der PC Entwicklung gibt es Events wie OnClick, OnKeyDown, ...
Diese haben als Parameter immer sender (Object) und e (EventArgs). Also eine einheitliche Struktur für sämtliche Funktionen die aufgerufen werden, sollte dieses Ereignis eintreten. EventArgs ist die Basisklasse, die aber erweitert werden kann (KeyDownEventArgs als Beispiel). sender brauchen wir hier strenggenommen nicht, e ist eine Structure oder Klasse die sämtliche Daten beinhaltet, ggf. ein- wie auch ausgehend. Da du den Kram selber entwickelst* weißt du ja auch welche Funktion welche Parameter hin und her gibt. kA ob es in C auch Klassen und Vererbung gibt, im Endeffekt sind es eh nur Pointer. Ganz früher, teilweise auch noch heute, waren die Aufrufe zum Betriebssystem was die Parameter angeht auch nichts Anderes als TLV. Siehe dazu deinem anderen Thread,

* musste mir ein hüsteln verkneifen. Hat grad noch so geklappt.
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)