📄 piano.c
字号:
Piano *piano; GdkWindowAttr attributes; gint attributes_mask; gint i, x, mod; GdkPixmap *pixmap; GdkColormap *cmap; g_return_if_fail (widget != NULL); g_return_if_fail (IS_PIANO (widget)); GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED); piano = PIANO (widget); attributes.x = widget->allocation.x; attributes.y = widget->allocation.y; attributes.width = widget->allocation.width; attributes.height = widget->allocation.height; attributes.wclass = GDK_INPUT_OUTPUT; attributes.window_type = GDK_WINDOW_CHILD; attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK; attributes.visual = gtk_widget_get_visual (widget); attributes.colormap = gtk_widget_get_colormap (widget); attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; widget->window = gdk_window_new (widget->parent->window, &attributes, attributes_mask); widget->style = gtk_style_attach (widget->style, widget->window); gdk_window_set_user_data (widget->window, widget); gtk_style_set_background (widget->style, widget->window, GTK_STATE_ACTIVE); pixmap = gdk_pixmap_new (piano->widget.window, 676, 48, -1); gdk_draw_rectangle (pixmap, piano->widget.style->white_gc, TRUE, 1, 1 + POFSY, 674, 46); gdk_draw_line (pixmap, piano->widget.style->black_gc, 0, 0 + POFSY, 675, 0 + POFSY); gdk_draw_line (pixmap, piano->widget.style->black_gc, 0, 47 + POFSY, 675, 47 + POFSY); gdk_draw_line (pixmap, piano->widget.style->black_gc, 1, 44 + POFSY, 674, 44 + POFSY); piano->shadowgc = gdk_gc_new (piano->widget.window); cmap = gtk_widget_get_colormap (widget); piano->shadclr.red = piano->shadclr.green = piano->shadclr.blue = 49152; gdk_colormap_alloc_color (cmap, &piano->shadclr, FALSE, TRUE); gdk_gc_set_foreground (piano->shadowgc, &piano->shadclr); gdk_draw_line (pixmap, piano->shadowgc, 1, 45 + POFSY, 674, 45 + POFSY); gdk_draw_line (pixmap, piano->shadowgc, 1, 46 + POFSY, 674, 46 + POFSY); for (i = 0, x = 0; i < 76; i++, x += 9) { gdk_draw_line (pixmap, piano->widget.style->black_gc, x, 1 + POFSY, x, 46 + POFSY); mod = i % 7; if ((mod != 0) && (mod != 3) && (i != 75)) gdk_draw_rectangle (pixmap, piano->widget.style->black_gc, TRUE, x - 2, 1 + POFSY, 5, 27); } piano->keyb_pm = pixmap; /* capture small pixmap of white key unselected state */ piano->unsw_pm = gdk_pixmap_new (piano->widget.window, 8, 8, -1); gdk_draw_pixmap (piano->unsw_pm, piano->widget.style->fg_gc[GTK_WIDGET_STATE (&piano->widget)], pixmap, 1, 39 + POFSY, 0, 0, 8, 8); /* copy and modify unselected white key state to get selected white key */ piano->selw_pm = gdk_pixmap_new (piano->widget.window, 8, 8, -1); gdk_draw_pixmap (piano->selw_pm, piano->widget.style->fg_gc[GTK_WIDGET_STATE (&piano->widget)], piano->unsw_pm, 0, 0, 0, 0, 8, 8); gdk_draw_rectangle (piano->selw_pm, piano->widget.style->black_gc, TRUE, 2, 0, 4, 3); gdk_draw_rectangle (piano->selw_pm, piano->widget.style->white_gc, TRUE, 0, 5, 8, 3); /* capture small pixmap of black key unselected state */ piano->unsb_pm = gdk_pixmap_new (piano->widget.window, 5, 8, -1); gdk_draw_pixmap (piano->unsb_pm, piano->widget.style->fg_gc[GTK_WIDGET_STATE (&piano->widget)], pixmap, 7, 20 + POFSY, 0, 0, 5, 8); /* copy and modify unselected black key state to get selected black key */ piano->selb_pm = gdk_pixmap_new (piano->widget.window, 5, 8, -1); gdk_draw_pixmap (piano->selb_pm, piano->widget.style->fg_gc[GTK_WIDGET_STATE (&piano->widget)], piano->unsb_pm, 0, 0, 0, 0, 5, 8); gdk_draw_rectangle (piano->selb_pm, piano->widget.style->white_gc, TRUE, 1, 0, 3, 3); gdk_draw_line (piano->selb_pm, piano->widget.style->white_gc, 0, 7, 1, 7); gdk_draw_line (piano->selb_pm, piano->widget.style->white_gc, 3, 7, 4, 7);}static voidpiano_size_request (GtkWidget * widget, GtkRequisition * requisition){ requisition->width = PIANO_DEFAULT_SIZEX; requisition->height = PIANO_DEFAULT_SIZEY;}static voidpiano_size_allocate (GtkWidget * widget, GtkAllocation * allocation){ Piano *piano; g_return_if_fail (widget != NULL); g_return_if_fail (IS_PIANO (widget)); g_return_if_fail (allocation != NULL); widget->allocation = *allocation; piano = PIANO (widget); if (GTK_WIDGET_REALIZED (widget)) { gdk_window_move_resize (widget->window, allocation->x, allocation->y, allocation->width, allocation->height); }}static gintpiano_expose (GtkWidget * widget, GdkEventExpose * event){ Piano *piano; g_return_val_if_fail (widget != NULL, FALSE); g_return_val_if_fail (IS_PIANO (widget), FALSE); g_return_val_if_fail (event != NULL, FALSE); piano = PIANO (widget); gdk_draw_pixmap (widget->window, widget->style->fg_gc[GTK_WIDGET_STATE (widget)], piano->keyb_pm, event->area.x, event->area.y, event->area.x, event->area.y, event->area.width, event->area.height); return FALSE;}static gintpiano_button_press (GtkWidget * widget, GdkEventButton * event){ Piano *piano; gint i, x, y, xval; guint8 keynum; g_return_val_if_fail (widget != NULL, FALSE); g_return_val_if_fail (IS_PIANO (widget), FALSE); g_return_val_if_fail (event != NULL, FALSE); piano = PIANO (widget); if (piano->key_mouse < 128) return (FALSE); /* A key is active (with mouse)? */ if ((event->button != 1) || (event->x < 0) || (event->x > 672) || (event->y < 0 + POFSY) || (event->y > 47 + POFSY)) return (FALSE); x = event->x; y = event->y; xval = x % 63; /* pixel offset into keyboard octave */ if (y <= 26 + POFSY) { /* possible black key? */ for (i = 0; i < 12; i++) /* loop through key selection offsets */ if (xval <= keyinfo[i].selx) break; /* is offset within key select */ } else { /* button press is below black key line */ xval /= 9; /* white key number offset within octave */ for (i = 0; i < 12; i++) if (keyinfo[i].white && xval-- <= 0) break; } keynum = x / 63 * 12 + i; /* calc key number */ piano->key_mouse = keynum; /* assign mouse selected key */ /* run user piano key press handler */ gtk_signal_emit (GTK_OBJECT (piano), piano_signals[NOTE_ON], keynum); piano_note_on (piano, keynum); /* update key selection list */ gtk_grab_add (widget); /* grab all mouse events */ return (FALSE);}static gintpiano_button_release (GtkWidget * widget, GdkEventButton * event){ Piano *piano; g_return_val_if_fail (widget != NULL, FALSE); g_return_val_if_fail (IS_PIANO (widget), FALSE); g_return_val_if_fail (event != NULL, FALSE); piano = PIANO (widget); if (piano->key_mouse > 127) return (FALSE); /* no key is active?(with mouse) */ if (event->button == 1) { gtk_grab_remove (widget); /* no more mouse event grabbing */ /* signal user piano release key handlers */ gtk_signal_emit (GTK_OBJECT (piano), piano_signals[NOTE_OFF], piano->key_mouse); piano_note_off (piano, piano->key_mouse); /* unselect active key */ piano->key_mouse = 255; /* no key selected with mouse */ } return FALSE;}static gintpiano_motion_notify (GtkWidget * widget, GdkEventMotion * event){ Piano *piano; GdkModifierType mods; gint x, y; g_return_val_if_fail (widget != NULL, FALSE); g_return_val_if_fail (IS_PIANO (widget), FALSE); g_return_val_if_fail (event != NULL, FALSE); piano = PIANO (widget); if (piano->key_mouse > 127) return (FALSE); x = event->x; y = event->y; if (event->is_hint || (event->window != widget->window)) gdk_window_get_pointer (widget->window, &x, &y, &mods); if (mods & GDK_BUTTON1_MASK) piano_update_mouse (piano, x, y); return (FALSE);}static voidpiano_update_mouse (Piano * piano, gint x, gint y){ gint i; gint xval; guint8 keynum; g_return_if_fail (piano != NULL); g_return_if_fail (IS_PIANO (piano)); if (piano->key_mouse > 127) return; if (x < 0) x = 0; else if (x > 672) x = 672; xval = x % 63; /* pixel offset into keyboard octave */ if (y <= 26 + POFSY || y > 47) { /* possible black key? */ for (i = 0; i < 12; i++) { /* loop through key selection offsets */ if (xval <= keyinfo[i].selx) /* is offset within key select */ break; } } else { /* button press is below black key line */ xval /= 9; /* white key number offset within octave */ for (i = 0; i < 12; i++) { if (keyinfo[i].white) if (xval-- == 0) break; } } keynum = x / 63 * 12 + i; /* calc key number */ if (keynum != piano->key_mouse) { /* still same key selected? */ /* signal user piano key release handlers */ gtk_signal_emit (GTK_OBJECT (piano), piano_signals[NOTE_OFF], piano->key_mouse); /* unselect previously active mouse piano key */ piano_note_off (piano, piano->key_mouse); piano->key_mouse = keynum; /* assign new mouse selected key */ /* signal user piano key press handlers */ gtk_signal_emit (GTK_OBJECT (piano), piano_signals[NOTE_ON], keynum); piano_note_on (piano, keynum); /* update key selection list */ }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -