Задача: программа для рисования; Особенности и свойства: Для упрощения понимания кода, программа разбита на множество отдельных функций. Также большинства различных переключателей между функциями, используются булевы переменные. Отдельно созданы две структуры: для объектов окна и объектов рисования. Вторая хранит в себе координаты курсора на поле, текущий тип рисования, текущую функцию рисования, графические переменные для левой и правой кнопки мыши, булева переменная для активации постоянного рисования, массив с характеристиками рисуемого объекта. Для одних объектов используются всего две ячейки для хранения ширины и высоты, а для вторых весь массив,к пример, для хранения координат точек для линии. На данный момент программа находится в стадии модернизации. //Подключение библиотеки gtk #pragma comment(lib,"gthread-2.0.lib") #pragma comment(lib,"gtk-win32-2.0.lib") #pragma comment(lib,"glib-2.0.lib") #pragma comment(lib,"gobject-2.0.lib") #pragma comment(lib,"gdk-win32-2.0.lib") #pragma comment(lib,"gdk_pixbuf-2.0.lib") #pragma comment(lib,"pango-1.0.lib") #pragma comment(lib,"pangowin32-1.0.lib") #pragma comment(lib,"intl.lib") #include <gdk/gdkkeysyms.h> //для считывания кнопок клавиатуры #include <gtk/gtk.h> //для работы с графикой #include <math.h> //для некоторых математических вычислений #include <stdlib.h> #include <stdio.h> #include <string.h> #define WIDTH 1125 //начальная ширина экрана #define HEIGHT 805 //начальная высота экрана #define lim_objects 150 //предельное количество обьектов окна //типы ф-ий рисования enum function{none,pixel,brush,line,way,vector_one_arrow,vector_two_arrow,arc,rectangle}; //типы рисования enum draw{one_in_one_false , alwase_draw_false , one_in_one_true , alwase_draw_true , re_draw}; //структура хранящая данные об обьектах окна typedef struct OBJECT OBJECT; struct OBJECTS { char name[lim_objects][10]; char paint[lim_objects][10]; int color[lim_objects][3]; int x0[lim_objects]; int y0[lim_objects]; int w[lim_objects]; int h[lim_objects]; }objects; //структура хранящаяя основные данные: ф-ия рисовани, тип рисования, координаты курсора, // графические переменные для левой и правой кнопки мыши, // массив значений рисуемого элемента, переменная отвечающая // за постоянную прорисовку обьекта. typedef struct MOUSE MOUSE; struct MOUSE { function f_type; draw d_type; int x_mouse,y_mouse; GdkColor l_clr,r_clr; int temp_element[4]; bool const_draw; }mouse; int lim_object;//кол-во обьектов в файле int button_click;//для сохранения номера нажатой кнопки міши OBJECTS * obj=(OBJECTS*)malloc(sizeof(objects)); MOUSE * m=(MOUSE*)malloc(sizeof(mouse)); GdkColor fclrs,bclr; GdkGC *gc; FILE *object=fopen("obstacle.dat","rt"); void choose_color(int i);//ф-ия для помещении значений цвета в переменную void choose_function();//выбор ф-ии рисования void choose_type_draw();//выбор типа рисования void init_window();//считывание параметров панелей gboolean mousemove(GtkWidget *w, GdkEvent *e,gpointer data);//отслеживание движения мыши gboolean destroy(GtkWidget *widget); gboolean on_click(GtkWidget *widget, GdkEventButton *event, gpointer data);//отслеживание клика gboolean first_draw(GtkWidget *Window);//построение окна и панелей gint delete_event(GtkWidget *widget); void draw_coord(GtkWidget *w);//отображение координат курсора на окне void const_draw(GtkWidget *w,int b);//ф-ия постоянного рисования void draw(GtkWidget *widget,gint b);//ф-ия стандартного рисования void skale(GtkWidget *widget);//ф-ия построения шкалы void draw_state(GtkWidget *widget);//Ф-ия отображения панели состояния gboolean keypress(GtkWidget *widget, GdkEventKey *e,gpointer data);//ф-ия отслеживания нажатия клавиш int main(int argc,char **argv) { //задание цвета фона bclr.pixel = 0; bclr.red = 240*257; bclr.green = 235*257; bclr.blue = 226*257; m->const_draw=false;//выключение постоянного рисование init_window(); //считывание параметров из файла gtk_init(&argc,&argv); GtkWidget *window=gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_widget_set_size_request(window,WIDTH,HEIGHT); gtk_window_set_position(GTK_WINDOW(window),GTK_WIN_POS_CENTER); gtk_widget_add_events(window,GDK_BUTTON_PRESS_MASK); gtk_widget_add_events(window,GDK_POINTER_MOTION_MASK); g_signal_connect(G_OBJECT(window),"motion-notify-event",G_CALLBACK(mousemove),NULL); g_signal_connect(G_OBJECT(window),"destroy",G_CALLBACK(destroy),NULL); g_signal_connect(G_OBJECT(window),"delete_event",G_CALLBACK(delete_event),NULL); g_signal_connect(G_OBJECT(window),"key-press-event",G_CALLBACK(keypress),NULL); g_signal_connect(G_OBJECT(window),"button-press-event",G_CALLBACK(on_click),NULL); g_signal_connect(G_OBJECT(window),"expose_event",G_CALLBACK(first_draw),NULL); gtk_widget_modify_bg(window,GTK_STATE_NORMAL,&bclr); gtk_widget_show(window); gtk_main(); return 0; } gboolean first_draw(GtkWidget *widget) { int i; gc = widget->style->fg_gc[GTK_WIDGET_STATE(widget)]; //построение обьектов согласно их типов for(i=1;i<lim_object+1;i++) { choose_color(i); gdk_gc_set_rgb_fg_color(gc,&fclrs); if(!strcmp(obj->name[i],"rectangle")) { if(!strcmp(obj->paint[i],"true")) gdk_draw_rectangle(widget->window,gc,TRUE,obj->x0[i],obj->y0[i],obj->w[i],obj->h[i]); else if(!strcmp(obj->paint[i],"false")) gdk_draw_rectangle(widget->window,gc,FALSE,obj->x0[i],obj->y0[i],obj->w[i],obj->h[i]); } else if(!strcmp(obj->name[i],"arc")) { if(!strcmp(obj->paint[i],"true")) gdk_draw_arc(widget->window,gc,TRUE,obj->x0[i],obj->y0[i],obj->w[i],obj->h[i],0,360*64); else if(!strcmp(obj->paint[i],"false")) gdk_draw_arc(widget->window,gc,FALSE,obj->x0[i],obj->y0[i],obj->w[i],obj->h[i],0,360*64); } else if(!strcmp(obj->name[i],"line")) { gdk_draw_line(widget->window,gc,obj->x0[i],obj->y0[i],obj->w[i],obj->h[i]); } } //отображение состояние параметра цвета на левую правую кнопку мыши gdk_gc_set_rgb_fg_color(gc,&m->l_clr); gdk_draw_rectangle(widget->window,gc,TRUE,obj->x0[1]+1,obj->y0[1]+1,obj->w[1]-1,obj->h[1]-1); gdk_gc_set_rgb_fg_color(gc,&m->r_clr); gdk_draw_rectangle(widget->window,gc,TRUE,obj->x0[2]+1,obj->y0[2]+1,obj->w[2]-1,obj->h[2]-1); skale(widget);//создание шкалы draw_state(widget);//создание панели состояния draw_coord(widget);//отображение координат мыши return TRUE; } gboolean destroy(GtkWidget *widget) { return FALSE; } gint delete_event(GtkWidget *widget) { gtk_main_quit(); return 1; } gboolean mousemove(GtkWidget *w, GdkEvent *e,gpointer data) { double a,b; guint button; gdk_event_get_coords(e,&a,&b); m->x_mouse=a; m->y_mouse=b;//извлечение координат мыши draw_state(w);//создание панели состояния draw_coord(w);//отображение координат мыши if(m->const_draw==true) const_draw(w,button_click); return FALSE; } void const_draw(GtkWidget *w,int b) { int x=m->x_mouse; int y=m->y_mouse; gboolean TF;//извлечение параметра для заливки if(m->d_type==one_in_one_false || m->d_type==alwase_draw_false) TF=false; else if(m->d_type==one_in_one_true || m->d_type== alwase_draw_true) TF=true; else TF=true; ////////// if(b==1) gdk_gc_set_rgb_fg_color(gc,&m->l_clr); else if(b==3) gdk_gc_set_rgb_fg_color(gc,&m->r_clr); //рисование обьекта согласно параметров if(m->f_type!=none) { if((x+m->temp_element[0]/2<905)&&(x-m->temp_element[0]/2>5)&&(y-m->temp_element[1]/2>5)&&(y+m->temp_element[1]/2<800)) { if(m->f_type==rectangle) { gdk_draw_rectangle(w->window,gc,TF,x-m->temp_element[0]/2,y-m->temp_element[1]/2,m->temp_element[0],m->temp_element[1]); } else if(m->f_type==arc) { gdk_draw_arc(w->window,gc,TF,x-m->temp_element[0]/2,y-m->temp_element[1]/2,m->temp_element[0],m->temp_element[1],0,64*360); } else if(m->f_type==brush) { gdk_draw_arc(w->window,gc,TF,x-m->temp_element[0]/2,y-m->temp_element[1]/2,m->temp_element[0],m->temp_element[1],0,64*360); } else if(m->f_type==pixel) { gdk_draw_arc(w->window,gc,TF,x-m->temp_element[0]/2,y-m->temp_element[1]/2,m->temp_element[0],m->temp_element[1],0,64*360); } } } /////////// } gboolean on_click(GtkWidget *widget, GdkEventButton *event, gpointer data) { gc = widget->style->fg_gc[GTK_WIDGET_STATE(widget)]; int i; int x= m->x_mouse,y= m->y_mouse,w,h,x0,y0; button_click=event->button;//извлечение номера нажатой кнопки if (event->button==1) { //Проверка на выбор цвета for(i=12;i<90;i++) { x0=obj->x0[i];y0=obj->y0[i];w=obj->w[i];h=obj->h[i]; if( (x>x0) && (x<x0+w) && (y>y0) && (y<y0+h)) { m->l_clr.pixel=0; m->l_clr.red=obj->color[i][0]*257; m->l_clr.green=obj->color[i][1]*257; m->l_clr.blue=obj->color[i][2]*257; choose_color(i); gdk_gc_set_rgb_fg_color(gc,&m->l_clr); gdk_draw_rectangle(widget->window,gc,TRUE,obj->x0[1]+1,obj->y0[1]+1,obj->w[1]-1,obj->h[1]-1); printf("SYSTEM:\tLEFT BUTTON choose (R,G,B)={%d;%d;%d}\n",obj->color[i][0],obj->color[i][1],obj->color[i][2]); } } if(m->const_draw==true) m->const_draw=false;//выключение постоянного рисование после клика else if( (m->d_type==alwase_draw_false || m->d_type== alwase_draw_true)&&((x>5) && (x<900) && (y>5) && (y<795))) { m->const_draw=true; }//включение постоянного рисования если выбран необходимый тип рисования и клип был произведён в поле для рисования choose_function();//проверка на выбор ф-ии и тип рисования choose_type_draw(); draw(widget,event->button);//рисование обьекта } if (event->button==3) {//Проверка на выбор цвета for(i=12;i<90;i++) { x0=obj->x0[i];y0=obj->y0[i];w=obj->w[i];h=obj->h[i]; if( (x>x0) && (x<x0+w) && (y>y0) && (y<y0+h)) { m->r_clr.pixel=0; m->r_clr.red=obj->color[i][0]*257; m->r_clr.green=obj->color[i][1]*257; m->r_clr.blue=obj->color[i][2]*257; choose_color(i); gdk_gc_set_rgb_fg_color(gc,&m->r_clr); gdk_draw_rectangle(widget->window,gc,TRUE,obj->x0[2]+1,obj->y0[2]+1,obj->w[2]-1,obj->h[2]-1); printf("SYSTEM:\tRIGHT BUTTON choose (R,G,B)={%d;%d;%d}\n",obj->color[i][0],obj->color[i][1],obj->color[i][2]); } } if(m->const_draw==true) m->const_draw=false;//выключение постоянного рисование после клика else if( (m->d_type==alwase_draw_false || m->d_type== alwase_draw_true)&&((x>5) && (x<900) && (y>5) && (y<795))) { m->const_draw=true; }//включение постоянного рисования если выбран необходимый тип рисования и клип был произведён в поле для рисования draw(widget,event->button);//рисование обьекта } return TRUE; } void draw(GtkWidget *w,int b) { gc = w->style->fg_gc[GTK_WIDGET_STATE(w)]; int x=m->x_mouse; int y=m->y_mouse; gboolean TF;//извлечение параметра для заливки if(m->d_type==one_in_one_false || m->d_type==alwase_draw_false) TF=false; else if(m->d_type==one_in_one_true || m->d_type== alwase_draw_true) TF=true; else TF=true; if( !(m->d_type==alwase_draw_false || m->d_type== alwase_draw_true)) { ////////// if(b==1) gdk_gc_set_rgb_fg_color(gc,&m->l_clr); else if(b==3) gdk_gc_set_rgb_fg_color(gc,&m->r_clr); //рисование обьекта согласно параметров if(m->f_type!=none) { if((x+m->temp_element[0]/2<905)&&(x-m->temp_element[0]/2>5)&&(y-m->temp_element[1]/2>5)&&(y+m->temp_element[1]/2<800)) { if(m->f_type==rectangle) { gdk_draw_rectangle(w->window,gc,TF,x-m->temp_element[0]/2,y-m->temp_element[1]/2,m->temp_element[0],m->temp_element[1]); } else if(m->f_type==arc) { gdk_draw_arc(w->window,gc,TF,x-m->temp_element[0]/2,y-m->temp_element[1]/2,m->temp_element[0],m->temp_element[1],0,64*360); } } } ///////// } } void choose_type_draw() { int i; int x= m->x_mouse,y= m->y_mouse; //выбор параметра рисования в случае если клик был произведён в необходимом поле if((y>625)&(y<655)) { if((x>915)&(x<965)) m->d_type=one_in_one_false; else if((x>965)&(x<1015)) m->d_type=alwase_draw_false; else if((x>1015)&(x<1065)) m->d_type=one_in_one_true; else if((x>1065)&(x<1115)) m->d_type=alwase_draw_true; } } void choose_function() { int i; int x= m->x_mouse,y= m->y_mouse,w,h,x0,y0; //Проверка на выбор ф-ии for(i=90;i<114;i++) { x0= obj->x0[i]; y0 = obj->y0[i]; w = obj->w[i]; h = obj->h[i]; if( (x>x0) && (x<x0+w) && (y>y0) && (y<y0+h)) { if(i==90) { m->f_type=pixel; m->d_type=alwase_draw_true; m->temp_element[0]=5; m->temp_element[1]=5; } else if(i==91) { m->f_type=brush; m->d_type=alwase_draw_true; m->temp_element[0]=20; m->temp_element[1]=20; } else if(i==92) m->f_type=line; else if(i==93) m->f_type=way; else if(i==94) m->f_type=vector_one_arrow; else if(i==95) m->f_type=vector_two_arrow; else if(i==96) { m->f_type=arc; m->temp_element[0]=50; m->temp_element[1]=50; } else if(i==97) { m->f_type=rectangle; m->temp_element[0]=50; m->temp_element[1]=50; } //свободные поля для добавления новых ф-ий else if(i==98); else if(i==99); else if(i==100); else if(i==101); else if(i==102); else if(i==103); else if(i==104); else if(i==105); else if(i==106); else if(i==107); else if(i==108); else if(i==109); else if(i==110); else if(i==111); else if(i==112); else if(i==113); } } } void choose_color(int i) { fclrs.pixel = 0; fclrs.red = obj->color[i][0]*257; fclrs.green = obj->color[i][1]*257;; fclrs.blue = obj->color[i][2]*257; } void init_window() { int i; char sim_kom; fscanf(object,"%d",&lim_object); // "#" - начало коментария в файле, "&" - конец коментария в файле for(i=1;i<lim_object+1;i++) { fscanf(object,"%c",&sim_kom);fscanf(object,"%c",&sim_kom); if(sim_kom=='#') { while(sim_kom!='&') fscanf(object,"%c",&sim_kom); } if(sim_kom!='#') { while(sim_kom!='&') fscanf(object,"%c",&sim_kom); //считывание данных fscanf(object,"%s %s %d %d %d %d %d %d %d",&obj->name[i],obj->paint[i],&obj->color[i][0],&obj->color[i][1],&obj->color[i][2],&obj->x0[i],&obj->y0[i],&obj->w[i],&obj->h[i]); } }fclose(object); for(i=0;i<4;i++) m->temp_element[i]=0;//обнуление данных о рисуемом обьекте } void draw_coord(GtkWidget *w) {//Ф-ия отображения координат курсора gc = w->style->fg_gc[GTK_WIDGET_STATE(w)]; GdkFont *font=gdk_fontset_load("Lucida Console"); int x=m->x_mouse-5, y=m->y_mouse-5; char c[2][4]; GdkColor clr; //ограничение на координат на поле рисования if(x<0) x=0; if(y<0) y=0; if(x>900) x=900; if(y>795) y=795; //Очищение поля,перенос значения в массив и вывод в поле gdk_gc_set_rgb_fg_color(gc,&bclr); gdk_draw_rectangle(w->window,gc,TRUE,985,480,100,20); clr.red = 0; clr.green = 0; clr.blue = 0; gdk_gc_set_rgb_fg_color(gc,&clr); sprintf(c[0],"%d",x); gdk_draw_string(w->window,font,gc,990,495,c[0]); gdk_draw_string(w->window,font,gc,1030,495,"X"); sprintf(c[1],"%d",y); gdk_draw_string(w->window,font,gc,1045,495,c[1]); } void draw_state(GtkWidget *w) {//Ф-ия отображения панели состояния gc = w->style->fg_gc[GTK_WIDGET_STATE(w)]; GdkColor clr; GdkFont *font=gdk_fontset_load("Lucida Console"); char slovo[10];//переменная для хранения текста //Вывод названий характеристик чёрным цветом clr.red = 0; clr.green = 0; clr.blue = 0; gdk_gc_set_rgb_fg_color(gc,&clr); gdk_draw_string(w->window,font,gc,925,530,"Width: "); gdk_draw_string(w->window,font,gc,915,550,"Height: "); gdk_draw_string(w->window,font,gc,915,570,"Type: "); gdk_draw_string(w->window,font,gc,915,590,"Size: +/-1"); gdk_draw_string(w->window,font,gc,925,610,"Gun: "); //Очищение поля и отображение ШИРИНЫ gdk_gc_set_rgb_fg_color(gc,&bclr); gdk_draw_rectangle(w->window,gc,TRUE,995,515,50,20); sprintf(slovo,"%d",m->temp_element[0]); gdk_gc_set_rgb_fg_color(gc,&clr); gdk_draw_string(w->window,font,gc,1000,530,slovo); //Очищение поля и отображение ВЫСОТЫ gdk_gc_set_rgb_fg_color(gc,&bclr); gdk_draw_rectangle(w->window,gc,TRUE,995,535,50,20); sprintf(slovo,"%d",m->temp_element[1]); gdk_gc_set_rgb_fg_color(gc,&clr); gdk_draw_string(w->window,font,gc,1000,550,slovo); //Очищение поля и отображение ПРЕДМЕТа РИСОВАНИЯ gdk_gc_set_rgb_fg_color(gc,&bclr); gdk_draw_rectangle(w->window,gc,TRUE,970,595,130,20); gdk_gc_set_rgb_fg_color(gc,&clr); if(m->f_type==none) gdk_draw_string(w->window,font,gc,970,610,"None"); if(m->f_type==pixel) gdk_draw_string(w->window,font,gc,970,610,"Pen"); if(m->f_type==brush) gdk_draw_string(w->window,font,gc,970,610,"Brush"); if(m->f_type==line) gdk_draw_string(w->window,font,gc,970,610,"Line"); if(m->f_type==way) gdk_draw_string(w->window,font,gc,970,610,"Way"); if(m->f_type==vector_one_arrow) gdk_draw_string(w->window,font,gc,970,610,"Vector (1a)"); if(m->f_type==vector_two_arrow) gdk_draw_string(w->window,font,gc,970,610,"Vector (2a)"); if(m->f_type==arc) gdk_draw_string(w->window,font,gc,970,610,"Arc"); if(m->f_type==rectangle) gdk_draw_string(w->window,font,gc,970,610,"Rectangle"); //Очищение поля и отображение ТИПа РИСОВАНИЯ gdk_gc_set_rgb_fg_color(gc,&bclr); gdk_draw_rectangle(w->window,gc,TRUE,965,555,150,20); gdk_gc_set_rgb_fg_color(gc,&clr); if(m->d_type==one_in_one_false) gdk_draw_string(w->window,font,gc,965,570,"1 in 1(false)"); if(m->d_type==alwase_draw_false) gdk_draw_string(w->window,font,gc,965,570,"alwase draw (f)"); if(m->d_type==one_in_one_true) gdk_draw_string(w->window,font,gc,965,570,"1 in 1(true)"); if(m->d_type==alwase_draw_true) gdk_draw_string(w->window,font,gc,965,570,"alwase draw (t)"); } gboolean keypress(GtkWidget *widget, GdkEventKey *e,gpointer data) { gc = widget->style->fg_gc[GTK_WIDGET_STATE(widget)]; if((m->f_type!=pixel)&&(m->f_type!=brush)) { switch(e->keyval) { case (GDK_KP_2): //уменьшение высоты обьекта { m->temp_element[1]=m->temp_element[1]-1; break; } case (GDK_KP_4): //уменьшение ширины обьекта { m->temp_element[0]=m->temp_element[0]-1; break; } case (GDK_KP_6): //увеличение ширины обьекта { m->temp_element[0]=m->temp_element[0]+1; break; } case (GDK_KP_8): //увеличение высоты обьекта { m->temp_element[1]=m->temp_element[1]+1; break; } } } if(m->f_type!=pixel) { switch(e->keyval) { case (GDK_KP_Add): //увеличение ширины и высоты обьекта { m->temp_element[0]=m->temp_element[0]+1; m->temp_element[1]=m->temp_element[1]+1; break; } case (GDK_KP_Subtract): //уменьшение ширины и высоты обьекта { m->temp_element[0]=m->temp_element[0]-1; m->temp_element[1]=m->temp_element[1]-1; break; } } } switch(e->keyval) { case (GDK_Delete): //очищение экрана { GdkColor c; c.pixel=0;c.red=0xFFFF;c.green=0xffff;c.blue=0xffff; gdk_gc_set_rgb_fg_color(gc,&c); gdk_draw_rectangle(widget->window,gc,TRUE,obj->x0[11],obj->y0[11],obj->w[11],obj->h[11]); break; } } //проверка на предельно маленькое значение характеристик if(m->temp_element[1]<0) m->temp_element[1]=0; if(m->temp_element[0]<0) m->temp_element[0]=0; //проверка на предельно большое значение характеристик if(m->temp_element[1]>795-5) m->temp_element[1]=795-5; if(m->temp_element[0]>900-5) m->temp_element[0]=900-5; draw_state(widget); return TRUE; } void skale(GtkWidget *w) {//Ф-ия рисования шкалы. Деления рисуются каждые 10 пикселей gc = w->style->fg_gc[GTK_WIDGET_STATE(w)]; int i=5; GdkColor c; c.pixel = 0; c.red = 0xFFFF; c.green = 0; c.blue = 0; gdk_gc_set_rgb_fg_color(gc,&c); for(;i<905;i+=10) { gdk_draw_line(w->window,gc,i,0,i,5); gdk_draw_line(w->window,gc,0,i,5,i); } }
Ключевые слова:
маляр, рисование, графика
|
|||||||