📄 gtk_tut_it-20.html
字号:
inputd = gtk_input_dialog_new(); gtk_signal_connect (GTK_OBJECT(inputd), "destroy", (GtkSignalFunc)input_dialog_destroy, &inputd); gtk_signal_connect_object (GTK_OBJECT(GTK_INPUT_DIALOG(inputd)->close_button), "clicked", (GtkSignalFunc)gtk_widget_hide, GTK_OBJECT(inputd)); gtk_widget_hide ( GTK_INPUT_DIALOG(inputd)->save_button); gtk_widget_show (inputd); } else { if (!GTK_WIDGET_MAPPED(inputd)) gtk_widget_show(inputd); else gdk_window_raise(inputd->window); }}</PRE></CODE></BLOCKQUOTE><P>(Notate come gestiamo questo dialogo. Con la connessione del segnale``destroy'' ci assicuriamo di non tenerci in giro il puntatore al dialogodopo che lo abbiamo distrutto, cosa che potrebbe portare ad un errore disegmentazione.)<P><P>L'InputDialog ha due pulsanti, ``Close'' e ``Save'', i quali non hanno alcunaazione predefinita assegnata ad essi. Nella funzione precedente, abbiamofatto in modo che ``Close'' nasconda la finestra di dialogo, e abbiamo nascostoil pulsante ``Save'' dal momento che in questo programma non implementiamo ilsalvataggio delle opzioni di XInput.<P><H3>Usare le informazioni estese</H3><P>Una volta abilitato il dipositivo, possiamo usare le informazioni esteseche si trovano nei corrispondenti campi delle strutture che descrivono glieventi. A dire il vero, l'utilizzo di questi campi è sempre sicuro, perchésono tutti posti per difetto a valori ragionevoli ancje quando la gestionedegli eventi estesi non è abilitata.<P><P>Un cambiamento che dobbiamo fare è di chiamare <CODE>gdk_input_window_get_pointer()</CODE>invece di <CODE>gdk_window_get_pointer</CODE>. Ciò si rende necessario perché<CODE>gdk_window_get_pointer</CODE> non restituisce le informazioni esetese.<P><BLOCKQUOTE><CODE><PRE>void gdk_input_window_get_pointer (GdkWindow *window, guint32 deviceid, gdouble *x, gdouble *y, gdouble *pressure, gdouble *xtilt, gdouble *ytilt, GdkModifierType *mask);</PRE></CODE></BLOCKQUOTE><P>Quando chiamiamo questa funzione, dobbiamo specificare l'identificativodel dispositivo e la finestra. Normalmente questo identificativo lo siottiene dal campo <CODE>deviceid</CODE> della struttura dell'evento.Questa funzione restituirà valori ragionevoli nel caso che la gestionedegli eventi estesi non sia attivata (in questo caso, <CODE>event->deviceid</CODE>avrà il valore <CODE>GDK_CORE_POINTER</CODE>).<P>Quindi, la struttura di base dei gestori degli eventi relativi allapressione di bottoni e ai movomenti non cambia molto - abbiamo solobisogno di aggiungere il codice necessario per tenere conto delleinformazioni estese.<P><BLOCKQUOTE><CODE><PRE>static gintbutton_press_event (GtkWidget *widget, GdkEventButton *event){ print_button_press (event->deviceid); if (event->button == 1 && pixmap != NULL) draw_brush (widget, event->source, event->x, event->y, event->pressure); return TRUE;}static gintmotion_notify_event (GtkWidget *widget, GdkEventMotion *event){ gdouble x, y; gdouble pressure; GdkModifierType state; if (event->is_hint) gdk_input_window_get_pointer (event->window, event->deviceid, &x, &y, &pressure, NULL, NULL, &state); else { x = event->x; y = event->y; pressure = event->pressure; state = event->state; } if (state & GDK_BUTTON1_MASK && pixmap != NULL) draw_brush (widget, event->source, x, y, pressure); return TRUE;}</PRE></CODE></BLOCKQUOTE><P>Avremo anche bisogno di fare qualcosa con queste nuove informazioni. Lanostra nuova funzione <CODE>draw_brush</CODE> disegna con un colore diverso perogni <CODE>event->source</CODE> e cambia la dimensione della linea in funzionedella pressione.<P><BLOCKQUOTE><CODE><PRE>/* Disegna un rettangolo sullo schermo, con la dimensione dipendente dalla pressione e il colore dipendente dal tipo di dispositivo */static voiddraw_brush (GtkWidget *widget, GdkInputSource source, gdouble x, gdouble y, gdouble pressure){ GdkGC *gc; GdkRectangle update_rect; switch (source) { case GDK_SOURCE_MOUSE: gc = widget->style->dark_gc[GTK_WIDGET_STATE (widget)]; break; case GDK_SOURCE_PEN: gc = widget->style->black_gc; break; case GDK_SOURCE_ERASER: gc = widget->style->white_gc; break; default: gc = widget->style->light_gc[GTK_WIDGET_STATE (widget)]; } update_rect.x = x - 10 * pressure; update_rect.y = y - 10 * pressure; update_rect.width = 20 * pressure; update_rect.height = 20 * pressure; gdk_draw_rectangle (pixmap, gc, TRUE, update_rect.x, update_rect.y, update_rect.width, update_rect.height); gtk_widget_draw (widget, &update_rect);}</PRE></CODE></BLOCKQUOTE><P><H3>Trovare ulteriori informazioni su di un dispositivo</H3><P>Come esempio del modo di trovare altre informazioni su di un dispositivo,il nostro programma stamperà il nome di ogni dispositivo che genera unevento di pressione di un pulsante. Per avere il nome di un dispositivo,chiamiamo la funzione<P><BLOCKQUOTE><CODE><PRE>GList *gdk_input_list_devices (void);</PRE></CODE></BLOCKQUOTE><P>che restituisce una GList (un tipo di lista collegata che si trova nellalibreria glib) di strutture di tipo GdkDeviceInfo. La definizione diGdkDeviceInfo è la seguente:<P><BLOCKQUOTE><CODE><PRE>struct _GdkDeviceInfo{ guint32 deviceid; gchar *name; GdkInputSource source; GdkInputMode mode; gint has_cursor; gint num_axes; GdkAxisUse *axes; gint num_keys; GdkDeviceKey *keys;};</PRE></CODE></BLOCKQUOTE><P>La maggior parte di questi campi rappresentano informazioni di configurazioneche potete ignorare a meno che non implementiate il salvataggio dellaconfigurazione di un XInput. Quelle che ci interessano sono <CODE>name</CODE>, cheè semplicemente il nome che X assegna al dispositivo, e <CODE>has_cursor</CODE>. Anche<CODE>has_cursor</CODE> non è informazione di configurazione, e indica, nel casoabbia valore ``falso'', che dobbiamo disegnare da soli il nostro cursore. Madal momento che abbiamo specificato <CODE>GDK_EXTENSION_EVENTS_CURSOR</CODE>,possiamo anche non preoccuparcene.<P><P><P>La nostra funzione <CODE>print_button_press()</CODE> scorre semplicemente la listache è stata restituita finché non trova il valore corretto, e poi stampail nome del dispositivo.<P><BLOCKQUOTE><CODE><PRE>static voidprint_button_press (guint32 deviceid){ GList *tmp_list; /* gdk_input_list_devices restituisce una lista interna, così poi non dobbiamo liberarla */ tmp_list = gdk_input_list_devices(); while (tmp_list) { GdkDeviceInfo *info = (GdkDeviceInfo *)tmp_list->data; if (info->deviceid == deviceid) { printf("Button press on device '%s'\n", info->name); return; } tmp_list = tmp_list->next; }}</PRE></CODE></BLOCKQUOTE>Questo completa i cambiamenti necessari per usare gli XInput nel nostroprogramma. Come per la prima versione, i sorgenti completi sono prelevabilida dove avete prelevato questo tutorial, oppure da:<P><A HREF="http://www.msc.cornell.edu/~otaylor/gtk-gimp/tutorial">http://www.msc.cornell.edu/~otaylor/gtk-gimp/tutorial</A><P><H3><A NAME="sec_Further_Sophistications"></A> Ulteriori sofisticazioni </H3><P>Anche se ora il nostro programma supporta XInput pittosto bene, gli mancanoalcune caratteristiche che probabilmente vorremmo mettere in una applicazionecompleta. In primo luogo, probabilmente all'utente non farà piacere doverconfigurare i propri dispositivi ogni volta che lanciano il programma, percui dovremmo dare la possibilità di salvare la configurazione dei dispositivi.Ciò può essere fatto scorrendo la lista restituita da <CODE>gdk_input_list_devices()</CODE>e scrivendo la configurazione su di un file.<P><P>Per tornare allo stato salvato la prossima volta che il programma vieneeseguito, GDK mette a disposizione delle funzioni per cambiare la configurazionedei dispositivi:<P><BLOCKQUOTE><CODE><PRE>gdk_input_set_extension_events()gdk_input_set_source()gdk_input_set_mode()gdk_input_set_axes()gdk_input_set_key()</PRE></CODE></BLOCKQUOTE><P>(La lista restituita da <CODE>gdk_input_list_devices()</CODE> non dovrebbeessere modificata direttamente.) Un esempio di come fare può esseretrovato nel programma di disegno gsumi (disponibile da <A HREF="http://www.msc.cornell.edu/~otaylor/gsumi/">http://www.msc.cornell.edu/~otaylor/gsumi/</A>). Sarebbe belloavere alla fine un modo standard di recuperare le informazioni per tuttele applicazioni. Questo probabilmente appartiene ad un livello un po'più elevato ripetto a GTK, forse alla libreria GNOME.<P><P>Un'altra notevole omissione a cui abbiamo accennato precedentemente è ilfatto di non disegnare il cursore direttamente. Piattaforme diverse daXFree86 non permettono in questo momento di usare contemporaneamente undispositivo sia come puntatore principale sia direttamente da unaapplicazione. Vedere <A HREF="http://www.msc.cornell.edu/~otaylor/xinput/XInput-HOWTO.html">XInput-HOWTO</A> per ulteriori informazioni. Ciò significa che leapplicazioni che vogliono rivolgersi al pubblico più ampio dovranno prevederedi disegnare esse stesse il proprio cursore.<P><P>Un'applicazione che voglia disegnare il proprio cursore dovrà fare due cose:determinare se il dispositivo corrente necessita che venga disegnato uncursore, e determinare se il dispositivo corrente è in prossimità. (Se ildispositivo è una tavoletta grafica, un tocco di finezza è fare sparireil puntatore quando lo stilo viene sollevato dalla tavoletta. Quando c'ècontatto fra lo stilo e la tavoletta, si dice che il dispositivo è ``inprossimità".) La prima cosa viene fatta scorrendo la lista dei dispositivi,come abbiamo fatto per trovare il nome del dispositivo. La seconda cosaviene ottenuta selezionando gli eventi ``proximity_out''. Un esempio didisegno del proprio cursore si trova nel programma 'testinput' incluso nelladistribuzione di GTK.<P><HR NOSHADE><A HREF="gtk_tut_it-21.html">Avanti</A><A HREF="gtk_tut_it-19.html">Indietro</A><A HREF="gtk_tut_it.html#toc20">Indice</A></BODY></HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -