今までの知識を基に、簡単なお絵書きツールを作ることができます。
x5.c |
#include <stdio.h> #include <X11/Xos.h> #include <X11/Xlib.h> #include <X11/Xutil.h> int main() { Display *dpy; int scr; Window win; GC gc; XGCValues gcv; XSetWindowAttributes xswa; char *xservname=NULL; if ((dpy = XOpenDisplay(xservname)) == NULL) { fprintf(stderr, "cant open display %s\n",XDisplayName(xservname)); exit(1); } scr = DefaultScreen(dpy); xswa.background_pixel = WhitePixel(dpy,scr); xswa.border_pixel = BlackPixel(dpy,scr); xswa.event_mask = ExposureMask | ButtonPressMask | ButtonReleaseMask; win=XCreateWindow(dpy,RootWindow(dpy,scr),0,0,320,240,1, CopyFromParent,CopyFromParent,CopyFromParent, CWBackPixel|CWBorderPixel|CWEventMask,&xswa); gcv.background = WhitePixel(dpy,scr); gcv.foreground = BlackPixel(dpy,scr); gcv.function = GXcopy; gc = XCreateGC(dpy,win,(GCForeground|GCBackground|GCFunction),&gcv); XMapWindow(dpy,win); for (;;) { XEvent ev; int x0,y0,x1,y1; XNextEvent(dpy, &ev); switch (ev.type) { case Expose: while (XCheckTypedEvent(dpy,Expose,&ev)); XClearWindow(dpy,win); break; case ButtonPress: printf("button press\n"); if (ev.xbutton.button == 3) exit(0); x0=ev.xbutton.x; y0=ev.xbutton.y; break; case ButtonRelease: printf("button release\n"); x1=ev.xbutton.x; y1=ev.xbutton.y; XDrawLine(dpy,win,gc,x0,y0,x1,y1); break; default: break; } } } |
図形エディタなどでは、図形の大きさを指定するときに、 臨時の(「ゴム紐」のような)直線を描画したい場合があります。 そのような場合は GXinvert や GXxor などを Functionに 指定したグラフィック・コンテクストを用います。
diff -c x5.c x6.c |
*** x5.c Mon May 22 19:50:39 2006 --- x6.c Mon May 22 19:50:46 2006 *************** *** 6,12 **** Display *dpy; int scr; Window win; ! GC gc; XGCValues gcv; XSetWindowAttributes xswa; char *xservname=NULL; --- 6,12 ---- Display *dpy; int scr; Window win; ! GC gc, gc2; XGCValues gcv; XSetWindowAttributes xswa; char *xservname=NULL; *************** *** 18,24 **** xswa.background_pixel = WhitePixel(dpy,scr); xswa.border_pixel = BlackPixel(dpy,scr); xswa.event_mask = ! ExposureMask | ButtonPressMask | ButtonReleaseMask; win=XCreateWindow(dpy,RootWindow(dpy,scr),0,0,320,240,1, CopyFromParent,CopyFromParent,CopyFromParent, CWBackPixel|CWBorderPixel|CWEventMask,&xswa); --- 18,24 ---- xswa.background_pixel = WhitePixel(dpy,scr); xswa.border_pixel = BlackPixel(dpy,scr); xswa.event_mask = ! ExposureMask | ButtonPressMask | ButtonReleaseMask | ButtonMotionMask; win=XCreateWindow(dpy,RootWindow(dpy,scr),0,0,320,240,1, CopyFromParent,CopyFromParent,CopyFromParent, CWBackPixel|CWBorderPixel|CWEventMask,&xswa); *************** *** 26,31 **** --- 26,33 ---- gcv.foreground = BlackPixel(dpy,scr); gcv.function = GXcopy; gc = XCreateGC(dpy,win,(GCForeground|GCBackground|GCFunction),&gcv); + gcv.function = GXinvert; + gc2 = XCreateGC(dpy,win,(GCForeground|GCBackground|GCFunction),&gcv); XMapWindow(dpy,win); for (;;) { XEvent ev; *************** *** 41,53 **** --- 43,65 ---- if (ev.xbutton.button == 3) exit(0); x0=ev.xbutton.x; y0=ev.xbutton.y; + x1=x0; y1=y0; + XDrawLine(dpy,win,gc2,x0,y0,x1,y1); break; case ButtonRelease: printf("button release\n"); + XDrawLine(dpy,win,gc2,x0,y0,x1,y1); x1=ev.xbutton.x; y1=ev.xbutton.y; XDrawLine(dpy,win,gc,x0,y0,x1,y1); break; + case MotionNotify: + printf("pointer motion\n"); + XDrawLine(dpy,win,gc2,x0,y0,x1,y1); + x1=ev.xbutton.x; + y1=ev.xbutton.y; + XDrawLine(dpy,win,gc2,x0,y0,x1,y1); + break; default: break; } |
複数のウィンドウを利用するプログラムでは, イベント構造体の中の window フィールドを見て、 どのウィンドウに起きたイベントであるかを 判断する必要があります。
x7.c |
#include <stdio.h> #include <X11/Xos.h> #include <X11/Xlib.h> #include <X11/Xutil.h> struct _menudata { int x, y, width, height; char *name; Window win; } menu[] = { { 0, 0, 80, 30, "Line"}, { 0, 30, 80, 30, "Rectange"}, { 0, 60, 80, 30, "Circle"} }; int figure=0; #define min(x,y) (((x)<(y)) ? (x) : (y)) #define max(x,y) (((x)>(y)) ? (x) : (y)) #define N_MENU (sizeof(menu)/sizeof(struct _menudata)) void DrawFig(Display *dpy,Window win,GC gc,int x0,int y0,int x1,int y1) { int x, y, w, h; x = min(x0,x1); y = min(y0,y1); w = max(x0,x1) - min(x0,x1) +1; h = max(y0,y1) - min(y0,y1) +1; switch (figure) { case 0: XDrawLine(dpy,win,gc,x0,y0,x1,y1); break; case 1: XDrawRectangle(dpy,win,gc,x,y,w,h); break; case 2: XDrawArc(dpy,win,gc,x,y,w,h,0,360*64); break; default: fprintf(stderr,"unknown figure %d\n",figure); } } int main() { Display *dpy; int scr,i; Window win,menuwin; GC gc, gc2; XGCValues gcv; XSetWindowAttributes xswa; char *xservname=NULL; if ((dpy = XOpenDisplay(xservname)) == NULL) { fprintf(stderr, "cant open display %s\n",XDisplayName(xservname)); exit(1); } scr = DefaultScreen(dpy); xswa.background_pixel = WhitePixel(dpy,scr); xswa.border_pixel = BlackPixel(dpy,scr); xswa.event_mask = ExposureMask | ButtonPressMask | ButtonReleaseMask | ButtonMotionMask; win=XCreateWindow(dpy,RootWindow(dpy,scr),0,0,320,240,1, CopyFromParent,CopyFromParent,CopyFromParent, CWBackPixel|CWBorderPixel|CWEventMask,&xswa); menuwin=XCreateWindow(dpy,RootWindow(dpy,scr),0,0,menu[0].width, menu[N_MENU-1].y+menu[N_MENU-1].height,1, CopyFromParent,CopyFromParent,CopyFromParent, CWBackPixel|CWBorderPixel|CWEventMask,&xswa); for (i=0; i<N_MENU; ++i) { menu[i].win=XCreateWindow(dpy,menuwin,menu[i].x,menu[i].y, menu[i].width, menu[i].height, 1, CopyFromParent,CopyFromParent,CopyFromParent, (CWBackPixel|CWBorderPixel|CWEventMask),&xswa); } gcv.background = WhitePixel(dpy,scr); gcv.foreground = BlackPixel(dpy,scr); gcv.function = GXcopy; gc = XCreateGC(dpy,win,(GCForeground|GCBackground|GCFunction),&gcv); gcv.function = GXinvert; gc2 = XCreateGC(dpy,win,(GCForeground|GCBackground|GCFunction),&gcv); XMapWindow(dpy,win); XMapWindow(dpy,menuwin); XMapSubwindows(dpy,menuwin); for (;;) { XEvent ev; int x0,y0,x1,y1; XNextEvent(dpy, &ev); switch (ev.type) { case Expose: while (XCheckTypedWindowEvent(dpy,ev.xany.window,Expose,&ev)); XClearWindow(dpy,ev.xany.window); for (i=0; i<N_MENU; ++i) { if (menu[i].win == ev.xany.window) { XDrawString(dpy,ev.xany.window,gc,5,20,menu[i].name, strlen(menu[i].name)); break; } } break; case ButtonPress: printf("button press\n"); if (ev.xany.window == win) { if (ev.xbutton.button == 3) exit(0); x0=ev.xbutton.x; y0=ev.xbutton.y; x1=x0; y1=y0; DrawFig(dpy,win,gc2,x0,y0,x1,y1); } else { for (i=0; i<N_MENU; ++i) { if (menu[i].win == ev.xany.window) { figure = i; break; } } } break; case ButtonRelease: printf("button release\n"); if (ev.xany.window == win) { DrawFig(dpy,win,gc2,x0,y0,x1,y1); x1=ev.xbutton.x; y1=ev.xbutton.y; DrawFig(dpy,win,gc,x0,y0,x1,y1); } break; case MotionNotify: printf("pointer motion\n"); if (ev.xany.window == win) { DrawFig(dpy,win,gc2,x0,y0,x1,y1); x1=ev.xbutton.x; y1=ev.xbutton.y; DrawFig(dpy,win,gc2,x0,y0,x1,y1); } break; default: break; } } } |
XChangeGC関数で線の太さを変える XGCValues xgcv; xgcv.line_width = 整数値; XChangeGC(dpy,gc,GCLineWidth,&xgcv); /* このgcを使って絵を描く */
![]()
[提出物]
課題が完成したら、x10.c をp2r9@nw.tsuda.ac.jp へ送って下さい。
コンパイルできなかったり、きちんと動作しないものを送っても
提出とは認めませんので注意して下さい。
上記の Email アドレス宛に送ったメイルは http://nw.tsuda.ac.jp/cgi-bin/cgiwrap/p2r9/mailhead で参照できます。Emailを送ったあとで、正しく提出されたかどうか 確認しておいて下さい。
提出期限は来週木曜日の 8:50a.m. です。