今までの知識を基に、簡単なお絵書きツールを作ることができます。

| 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. です。