LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 4423|回复: 5

Xwindows开发学习

[复制链接]
发表于 2005-3-14 21:58:07 | 显示全部楼层 |阅读模式
Xwindows开发学习

作者: Komtas 无双 发表于wsue.org loveunix.net
转载请注明出处

最好不要有30秒回贴

不然自己到
http://www.wsue.org/blog/?p=252&page=1
或是loveunix.net上查找

昨天想写一个支持xim的客户端

不过找现成的例子来都试不出输入法

没法 从头开始学习xwindows编程吧


开始编程前先要有一个好的开发工具 可以快速的查找函数与宏定义及结构定义
我推荐vim

然后是要随时准备看man 基本上x开发不难 但是看man理解每个函数
那对以后的开发会更快

下面先开始vim相关的配置
1 创建/usr/include目录下的定义索引
cd /usr/include
ctags *
2 创建 /usr/include/X11目录下的定义索引
cd /usr/include/X11
ctags *

3 编辑你的~/.vimrc

vi ~/.vimrc 增加下面两行
set path+=.,./include,../include,/usr/include,/usr/include/**,/usr/X11R6/include,/usr/local/include
set tags=./tags,../tags,../../tags,/usr/include/tags,/usr/include/X11/tags

4 快速的使用vim的一些技巧
在x开发中 可能会看到很多结构或是宏定义
这时可以在你想查找的定义上使用
ctrl-w-]键跳转到它的定义处
:q退出定义窗口
ctrl-P 单词完成

快速的make与改错
在vim下输入:
:mak
然后使用
cn或cp浏览错误

编译
gcc -L/usr/X11R6/lib -lX11 filename.c -o filename.o
 楼主| 发表于 2005-3-14 21:58:53 | 显示全部楼层
Xwindows开发学习

第一个程序
hello world

每个Xwindows程序都由三个部分组成
1 Desplay 这个就是X服务器
2 Win 程序的窗口 可能有一个或多个
3 gc 图形上下文 如果你想在程序窗口中输出内容时 你就需要到这个东西

每个程序的流程就是
1 打开显示
2 创建窗口
3 创建GC
4 选择窗口关心的事件
5 映射窗口 这时在屏幕上显示程序界面
6 进程事件循环读事件并处理
下面就是hello world的流程


  1. #include ≶X11/Xlib.h>
  2. #include ≶X11/Xutil.h>
  3. #include ≶X11/Xos.h>
  4. #include ≶X11/Xatom.h>

  5. #define DUMP_ERR printf

  6. int main()
  7. {
  8. Display *display;
  9. int screennum;
  10. int width;
  11. int height;

  12. const char *strdraw = “hello world”;

  13. Window win;
  14. GC gc;
  15. //打开显示 没有指明打开哪个显示时使用环境变量中的DESPLAY
  16. display = XOpenDisplay(NULL);
  17. if( !display ){
  18. DUMP_ERR(”call XOpenDisplay(%s) fail\n”,XDisplayName(NULL));
  19. return 1;
  20. }

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

  27. //创建窗口
  28. // create window
  29. win = XCreateSimpleWindow(display,
  30. RootWindow(display,screennum),
  31. 0,0,width,height,3,
  32. BlackPixel(display,screennum),
  33. WhitePixel(display,screennum));

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

  39. //创建GC(图形上下文)
  40. // create gc
  41. {
  42. unsigned long valuemask = 0;
  43. XGCValues values;
  44. gc = XCreateGC(display,win,valuemask,&values);
  45. }

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

  49. //进入事件循环
  50. // event loop
  51. while(1){
  52. XEvent event;
  53. XNextEvent(display,&event); // 读一个事件

  54. switch(event.type){
  55. case Expose: // expose window 显示事件
  56. if( event.xexpose.count != 0) break;
  57. XDrawString(display,win,gc,10,10,
  58. strdraw,strlen(strdraw));
  59. break;

  60. // 按键事件
  61. case ButtonPress:
  62. case KeyPress:
  63. XFreeGC(display,gc);
  64. XCloseWindow(win);
  65. XCloseDisplay(display);
  66. return 0;
  67. default:
  68. break;
  69. }
  70. }
  71. }
复制代码
回复 支持 反对

使用道具 举报

 楼主| 发表于 2005-3-14 21:59:35 | 显示全部楼层
Xwindows开发学习

上面是一个最基本的例子 基本上除了hello world外什么事也不做
下面开始介绍在X上画图的例子
上面说过GC 画图就是在gc上输出内容
每个gc都有属性 可以通过XChangeGC修改或是通过其它修改gc性能的函数

XSetLineAttributes修改
这两个的效果是一样的

  1. #include <X11/Xlib.h>
  2. #include <X11/Xutil.h>
  3. #include <X11/Xos.h>
  4. #include <X11/Xatom.h>

  5. #define DUMP_ERR printf

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

  7. int main()
  8. {
  9. Display *display;
  10. int screennum;
  11. int width;
  12. int height;
  13. Atom protocols;

  14. const char *strdraw = “hello world”;

  15. Window win;
  16. GC gc;

  17. display = XOpenDisplay(NULL);
  18. if( !display ){
  19. DUMP_ERR(”call XOpenDisplay(%s) fail\n”,XDisplayName(NULL));
  20. return 1;
  21. }

  22. // get default screen
  23. screennum = DefaultScreen(display);
  24. width = DisplayWidth(display,screennum)/2;
  25. height = DisplayHeight(display,screennum)/2;

  26. // create window
  27. win = XCreateSimpleWindow(display,
  28. RootWindow(display,screennum),
  29. 0,0,width,height,3,
  30. BlackPixel(display,screennum),
  31. WhitePixel(display,screennum));

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

  35. // select event
  36. XSelectInput(display,win,
  37. ExposureMask|KeyPressMask
  38. |ButtonPressMask|StructureNotifyMask);

  39. // create gc
  40. {
  41. unsigned long valuemask = 0;
  42. XGCValues values;
  43. gc = XCreateGC(display,win,valuemask,&values);
  44. }

  45. // show window
  46. XMapWindow(display,win);

  47. // event loop
  48. while(1){
  49. XEvent event;
  50. XNextEvent(display,&event);

  51. switch(event.type){
  52. case Expose: // expose window
  53. if( event.xexpose.count != 0) break;
  54. draw(display,win,gc,width,height);
  55. //XDrawString(display,win,gc,10,10,
  56. //strdraw,strlen(strdraw));
  57. break;

  58. case ConfigureNotify: // when the window’s size change
  59. width = event.xconfigure.width;
  60. height = event.xconfigure.height;
  61. break;
  62. case ClientMessage :
  63. if(event.xclient.data.l[0] == protocols){
  64. DUMP_ERR(”recv destroy notify\n”);
  65. XFreeGC(display,gc);
  66. XDestroyWindow(display, win);
  67. XCloseDisplay(display);
  68. }
  69. return 0;

  70. default:
  71. break;
  72. }
  73. }
  74. }
复制代码

// 使用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)
{
int i,x,y;
unsigned int ling_width = 0;
int line_style = LineSolid;// 是实线
int cap_style = CapRound; // 端点类型是圆的
int join_style = JoinRound;// 接点类型是圆的

XPoint points[5] = {
{400,200},
{600,200},
{450,300},
{500,150},
{550,300},
};

// draw point
for(i = 0;i< width;i++)
XDrawPoint(display,win,gc,i,10);

// draw line
y = 30;
for(i = 0;i<10;i+=2){
// int XSetLineAttributes(Display *display, GC gc, unsigned int
// line_width, int line_style, int cap_style, int join_style);
XSetLineAttributes(display,gc,i,line_style,cap_style,join_style);
// int XDrawLine(Display *display, Drawable d, GC gc, int x1, int y1, int
//x2, int y2);
XDrawLine(display,win,gc,10,y,width-10,y);
y += 20;
}

set_gc_values(display,gc);
XDrawRectangle(display,win,gc,10,y,50,50);
XDrawRectangle(display,win,gc,100,y,200,200);

XDrawArc(display,win,gc,100,y,200,200,0,90*64);
XFillArc(display,win,gc,100,y,200,200,90*64,120*64);

XFillPolygon(display,win,gc,points,5,Complex,EvenOddRule);
}
回复 支持 反对

使用道具 举报

发表于 2005-3-15 20:37:21 | 显示全部楼层
不错呀,无双兄什么时候搞起xwindow编程了!
回复 支持 反对

使用道具 举报

 楼主| 发表于 2005-3-16 21:41:35 | 显示全部楼层
正在学写xim 编程

昨天写出了第一个可跑的例子
有没兴趣参加开源项目啊kj兄
回复 支持 反对

使用道具 举报

发表于 2008-7-21 00:05:59 | 显示全部楼层
受教了!
对向我这样的新手很有用!
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表