2009年5月12日星期二

完全用Xlib写的时钟程序


我不多说了,请看代码:

//编译参数:gcc -o X11helloworld X11helloworld.c -I/usr/X11R6/include -L/usr/X11R6/lib -lX11 -lm

#include
#include
#include
#include
#include
#include // for signal()
#include // struct itimeral. setitimer()
#include //数学函数库

#define DUMP_ERR printf

//设为全局
Display *display;
Window win;

static void draw(Display *display,Window win,GC gc,int width,int height);

void printMsg(int);

int main()
{
int screennum;
int width;
int height;
Atom protocols;

const char *strdraw = "hello World";

GC gc;
//打开显示 没有指明打开哪个显示时使用环境变量中的DESPLAY
display = XOpenDisplay(NULL);
if( !display ){
DUMP_ERR("call XOpenDisplay(%s) fail\n",XDisplayName(NULL));
return 1;
}

//得到系统当前的屏幕 (如果使用虚拟屏幕的话 一般会有几个)
// get default screen
screennum = DefaultScreen(display);
//根据屏幕的大小决定窗口的大小
width = DisplayWidth(display,screennum)/4;
height = width;

//创建窗口
// create window
win = XCreateSimpleWindow(display,
RootWindow(display,screennum),
0,0,width,height,3,
BlackPixel(display,screennum),
WhitePixel(display,screennum));

//增加这个代码是捕获程序退出事件
protocols = XInternAtom(display,"WM_DELETE_WINDOW", True);
XSetWMProtocols(display, win, &protocols, 1);

//选择窗口关心的事件
// select event
XSelectInput(display,win,
ExposureMask|KeyPressMask
|ButtonPressMask|StructureNotifyMask);

//创建GC(图形上下文)
// create gc
{
unsigned long valuemask = 0;
XGCValues values;
gc = XCreateGC(display,win,valuemask,&values);
}

// 映射窗口 只有map后窗口才会在屏幕上显示
// show window
XMapWindow(display,win);

//设置定时器
int res = 0;
// Register printMsg to SIGALRM
signal(SIGALRM, printMsg);

struct itimerval tick;
// Initialize struct
memset(&tick, 0, sizeof(tick));

// Timeout to run function first time
tick.it_value.tv_sec = 1; // sec
tick.it_value.tv_usec = 0; // micro sec.
// Interval time to run function
tick.it_interval.tv_sec = 1;
tick.it_interval.tv_usec = 0;
// Set timer, ITIMER_REAL : real-time to decrease timer,
// send SIGALRM when timeout
res = setitimer(ITIMER_REAL, &tick, NULL);
if (res) {
printf("Set timer failed!!\n");
}

//进入事件循环
// event loop
while(1){
XEvent event;
XNextEvent(display,&event); // 读一个事件

switch(event.type){
case Expose: // expose window 显示事件
if( event.xexpose.count != 0) break;
draw(display,win,gc,width,height);
//XDrawString(display,win,gc,10,10,
//strdraw,strlen(strdraw));
break;

case ConfigureNotify: // when the window’s size change
width = event.xconfigure.width;
height = event.xconfigure.height;
break;
case ClientMessage :
if(event.xclient.data.l[0] == protocols){
DUMP_ERR("recv destroy notify\n");
XFreeGC(display,gc);
XDestroyWindow(display, win);
XCloseDisplay(display);
}
return 0;
default:
break;
}
}
}

// 使用changeGC修改属性的代码 只有valuemask被设置的属性才会根据XCGValues里面的值进行修改
static void set_gc_values(Display *display,GC gc)
{
XGCValues values;
values.line_width = 2;
values.line_style = LineSolid;
values.cap_style = CapRound;
values.join_style = JoinRound;

XChangeGC(display,gc,GCLineWidth|GCLineStyle,//|GCCapStyle|GCFillStyle,
&values);
}

// 画画的代码
static void draw(Display *display,Window win,GC gc,int width,int height)
{
XClearWindow(display,win);

//画一个圆
XDrawArc(display,win,gc,(width-height)/2+height/16,height/16,height/16*14,height/16*14,0,360*64);
//获取系统时间
long ct;
struct tm *currtime;
ct=time(&ct);
currtime=(struct tm *)localtime(&ct);
//计算表针位置,从alltraxclock.c里抄来的。
int second_hand_x = (int) (sin((currtime->tm_sec * 3.14159 * 2) / 60) * (height/16*5));
int second_hand_y = (int) (cos((currtime->tm_sec * 3.14159 * 2) / 60) * (height/16*5));
int big_hand_x = (int) (sin((currtime->tm_min * 3.14159 * 2) / 60) * (height/16*4));
int big_hand_y = (int) (cos((currtime->tm_min * 3.14159 * 2) / 60) * (height/16*4));
//计算时针的时候,要把分钟也加上。
int little_hand_x = (int) (sin(((currtime->tm_hour+currtime->tm_min/60.0) * 3.14159 * 2) / 12) * (height/16*3));
int little_hand_y = (int) (cos(((currtime->tm_hour+currtime->tm_min/60.0) * 3.14159 * 2) / 12) * (height/16*3));
//画一个表针
XDrawLine(display,win,gc,width/2,height/2,width/2+second_hand_x,height/2-second_hand_y);
XDrawLine(display,win,gc,width/2,height/2,width/2+big_hand_x,height/2-big_hand_y);
XDrawLine(display,win,gc,width/2,height/2,width/2+little_hand_x,height/2-little_hand_y);
printf("%d:%d\n",width,height);
}

void printMsg(int num) {
//让窗口重画
XEvent event;
memset(&event,0,sizeof(XEvent));
event.type=Expose;
XSendEvent(display,win,True,0x0,&event);
XFlush(display);
//获取系统时间
long ct;
struct tm *currtime;
ct=time(&ct);
currtime=(struct tm *)localtime(&ct);
printf("%d:%d:%d\n",currtime->tm_hour,currtime->tm_min,currtime->tm_sec);
}

大家有不清楚的地方,请去网上搜索,因为我写出这个程序已经很勉强了,有好多地方我是猜着写的。

没有评论:

发表评论

关注者