basicwin.c

上一頁 | 首頁

    1 #include <X11/Xlib.h>
    2 #include <X11/Xutil.h>
    3 #include <X11/Xos.h>
    4 #include <stdio.h>
    5 #include <stdlib.h>
    6 
    7 /* main函數中的windows_size的取值,用于表征窗口是否足夠大 */
    8 #define SMALL 1
    9 #define OK 0
   10 
   11 #define BITMAPDEPTH 1
   12 
   13 /* 用bitmap程序生成40x40的位圖 */
   14 #define ICON_WIDTH 40
   15 #define ICON_HEIGHT 40
   16 unsigned char icon_bits[]=
   17 {
   18    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   19    0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0xc0, 0xff, 0x01,
   20    0x00, 0x00, 0xf8, 0xff, 0x0f, 0x00, 0x00, 0xfc, 0xff, 0x1f, 0x00, 0x00,
   21    0xff, 0xff, 0x7f, 0x00, 0x80, 0xff, 0xff, 0xff, 0x00, 0xc0, 0xff, 0xff,
   22    0xff, 0x01, 0xc0, 0xff, 0xff, 0xff, 0x01, 0xe0, 0xff, 0xff, 0xff, 0x03,
   23    0xf0, 0xff, 0xff, 0xff, 0x07, 0xf0, 0xff, 0xff, 0xff, 0x07, 0xf0, 0xff,
   24    0xff, 0xff, 0x07, 0xf8, 0xff, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0xff,
   25    0x0f, 0xf8, 0xff, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0xff, 0x0f, 0xfc,
   26    0xff, 0xff, 0xff, 0x1f, 0xfc, 0xff, 0xff, 0xff, 0x1f, 0xfc, 0xff, 0xff,
   27    0xff, 0x1f, 0xf8, 0xff, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0xff, 0x0f,
   28    0xf8, 0xff, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0xff, 0x0f, 0xf0, 0xff,
   29    0xff, 0xff, 0x07, 0xf0, 0xff, 0xff, 0xff, 0x07, 0xf0, 0xff, 0xff, 0xff,
   30    0x07, 0xe0, 0xff, 0xff, 0xff, 0x03, 0xc0, 0xff, 0xff, 0xff, 0x01, 0xc0,
   31    0xff, 0xff, 0xff, 0x01, 0x80, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff,
   32    0x7f, 0x00, 0x00, 0xfc, 0xff, 0x1f, 0x00, 0x00, 0xf8, 0xff, 0x0f, 0x00,
   33    0x00, 0xc0, 0xff, 0x01, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00,
   34    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
   35 };
   36 
   37 /* Display和screen幾乎是每個Xlib庫函數的參數。因此,將它們定義為全局變量以
   38  * 簡化庫函數調用。若此處還包含其他源代碼文件,則應當將這些變量聲明為extern
   39  */
   40 Display *display;
   41 int screen;
   42 
   43 void get_GC(Window win, GC *gc, XFontStruct *font_info);
   44 void load_font(XFontStruct **font_info);
   45 void draw_text(Window win, GC gc, XFontStruct *font_info,
   46         unsigned int win_windth, unsigned int win_height);
   47 void draw_graphics(Window win, GC gc,
   48         unsigned int window_width, unsigned int window_height);
   49 void TooSmall(Window win, GC gc, XFontStruct *font_info);
   50 
   51 int main(int argc, char **argv)
   52 {
   53     Window win;
   54     unsigned int width, height;  /* 窗口尺寸 */
   55     int x=0, y=0;               /* 窗口坐標 */
   56     unsigned int border_width=4; /* 邊框寬度為4像素 */
   57     unsigned int display_width, display_height;
   58     char *window_name="Basic Window Program";
   59     char *icon_name="basicwin";
   60     Pixmap icon_pixmap;
   61     XSizeHints size_hints;
   62     XEvent report;
   63     GC gc;
   64     XFontStruct *font_info;
   65     char *display_name=NULL;
   66     int window_size=0;          /* 對于顯示內容而言,OK或太SMALL */
   67 
   68     /* 連接X服務器 */
   69     if((display=XOpenDisplay(display_name)) == NULL)
   70     {
   71         fprintf(stderr, "basicwin: 不能連接到X服務器 %s\n",
   72                 XDisplayName(display_name));
   73         exit(-1);
   74     }
   75 
   76     /* 從用于訪問display結構體的宏獲取屏幕尺寸 */
   77     screen=DefaultScreen(display);
   78     display_width=DisplayWidth(display, screen);
   79     display_height=DisplayHeight(display, screen);
   80 
   81     /* 為窗口指定足夠的空間來容納文本 */
   82     width=display_width/3;
   83     height=display_height/4;
   84 
   85     /* 創建不透明的窗口 */
   86     win=XCreateSimpleWindow(display, RootWindow(display, screen),
   87             x, y, width, height, border_width,
   88             BlackPixel(display, screen), WhitePixel(display, screen));
   89 
   90     /* 為圖標創建色深為1的像點圖 */
   91     icon_pixmap=XCreateBitmapFromData(display, win, icon_bits,
   92             ICON_WIDTH, ICON_HEIGHT);
   93 
   94     /* 為窗口管理器初始化標準特性中的尺寸 */
   95     size_hints.flags=PPosition|PSize|PMinSize;
   96     size_hints.x=x;
   97     size_hints.y=y;
   98     size_hints.width=width;
   99     size_hints.height=height;
  100     size_hints.min_width=350;
  101     size_hints.min_height=250;
  102 
  103     /* 為窗口管理器設置標準特性(總是在映射之前進行) */
  104     XSetStandardProperties(display, win, window_name, icon_name,
  105             icon_pixmap, argv, argc, &size_hints);
  106 
  107     /* 選擇所需的事件類型 */
  108     XSelectInput(display, win,
  109             ExposureMask|KeyPressMask|ButtonPressMask|StructureNotifyMask);
  110     load_font(&font_info);
  111 
  112     /* 為文本及繪圖創建GC */
  113     get_GC(win, &gc, font_info);
  114 
  115     /* 顯示窗口 */
  116     XMapWindow(display, win);
  117 
  118     /* 獲取事件,並通過第一個Expose來顯示文本及圖形;通過ConfigureNotify來
  119      * 指出調整後的尺寸;通過ButtonPress或KeyPress來退出 */
  120     while(1)
  121     {
  122         XNextEvent(display, &report);
  123         switch(report.type)
  124         {
  125             case Expose:
  126                 /* 清除隊列中所有其他的顯露事件 */
  127                 while(XCheckTypedEvent(display, Expose, &report));
  128                 if(window_size == SMALL)    /* 若窗口重新調整後的尺寸太小 */
  129                     TooSmall(win, gc, font_info);
  130                 else
  131                 {
  132                     /* 將文本畫到窗口 */
  133                     draw_text(win, gc, font_info, width, height);
  134                     /* 將圖形畫到窗口 */
  135                     draw_graphics(win, gc, width, height);
  136                 }
  137                 break;
  138             case ConfigureNotify:
  139                 /* 已重新調整窗口尺寸,改變width和height的值,在下一顯露事
  140                  * 件發生時傳遞給draw_text和draw_graphics */
  141                 width=report.xconfigure.width;
  142                 height=report.xconfigure.height;
  143                 if(width < size_hints.min_width ||
  144                         height<size_hints.min_height)
  145                     window_size=SMALL;
  146                 else
  147                     window_size=OK;
  148                 break;
  149             case ButtonPress:
  150                 /* 處理方法同KeyPress一樣 */
  151             case KeyPress:
  152                 XUnloadFont(display, font_info->fid);
  153                 XFreeGC(display, gc);
  154                 XCloseDisplay(display);
  155                 exit(1);
  156             default:
  157                 /* 除ConfigureNotify之外,所有被StructureNotifyMask選中的事
  158                  * 件都被忽略。這是由于不去處理與它們相關的東西 */
  159                 break;
  160         }
  161     }
  162 }
  163 
  164 void get_GC(Window win, GC *gc, XFontStruct *font_info)
  165 {
  166     unsigned long valuemask=0;  /* 忽略XGCValues並使用默認值 */
  167     XGCValues values;
  168     unsigned int line_width=6;
  169     int line_style=LineOnOffDash;
  170     int cap_style=CapRound;
  171     int join_style=JoinRound;
  172     int dash_offset=0;
  173     static char dash_list[]={12, 24};
  174     int list_length=2;
  175 
  176     /* 創建默認的圖形信息結構體 */
  177     *gc=XCreateGC(display, win, valuemask, &values);
  178 
  179     /*指定字體 */
  180     XSetFont(display, *gc, font_info->fid);
  181 
  182     /* 指定黑色前景,因為默認情況可能是前景和背景都是白色 */
  183     XSetForeground(display, *gc, BlackPixel(display, screen));
  184 
  185     /* 設置線屬性 */
  186     XSetLineAttributes(display, *gc, line_width, line_style, cap_style,
  187             join_style);
  188 
  189     /* 設置虛線的短橫長度為line_width */
  190     XSetDashes(display, *gc, dash_offset, dash_list, list_length);
  191 }
  192 
  193 void load_font(XFontStruct **font_info)
  194 {
  195     char *fontname="6x13";  /* 可通過xlsfonts命令查詢可用的字體名 */
  196     /* 訪問字體 */
  197     if((*font_info=XLoadQueryFont(display, fontname)) == NULL)
  198     {
  199         fprintf(stderr, "Basic: 不能打開6x13字體\n");
  200         exit(-1);
  201     }
  202 }
  203 
  204 void draw_text(Window win, GC gc, XFontStruct *font_info,
  205         unsigned int win_width, unsigned int win_height)
  206 {
  207     int y=20;   /* 偏離窗口上方的距離 */
  208     char *string1="Hi! I'm a window, who are you?";
  209     char *string2="To terminate program; Press any key";
  210     char *string3="or button while in this window.";
  211     char *string4="Screen Dimensions: ";
  212     int len1, len2, len3, len4;
  213     int width1, width2, width3;
  214     char cd_height[50], cd_width[50], cd_depth[50];
  215     int font_height;
  216     int initial_y_offset, x_offset;
  217 
  218     /* XTextWidth和XDrawString所需的長度 */
  219     len1=strlen(string1);
  220     len2=strlen(string2);
  221     len3=strlen(string3);
  222 
  223     /* 獲取字符串中央至邊緣的寬度 */
  224     width1=XTextWidth(font_info, string1, len1);
  225     width2=XTextWidth(font_info, string2, len2);
  226     width3=XTextWidth(font_info, string3, len3);
  227 
  228     /* 以水平居中對齊的格式輸出文本 */
  229     XDrawString(display, win, gc, (win_width-width1)/2, y, string1, len1);
  230     XDrawString(display, win, gc, (win_width-width2)/2,
  231             (int)(win_height-35), string2, len2);
  232     XDrawString(display, win, gc, (win_width-width3)/2,
  233             (int)(win_height-15), string3, len3);
  234 
  235     /* 將數字復制給字符串變量 */
  236     sprintf(cd_height, "Height - %dpixels", DisplayHeight(display, screen));
  237     sprintf(cd_width, "Width - %dpixels", DisplayWidth(display, screen));
  238     sprintf(cd_depth, "Depth - %dplane(s)", DefaultDepth(display, screen));
  239 
  240     /* 出于同樣的目的,再次檢測字符串的長度 */
  241     len4=strlen(string4);
  242     len1=strlen(cd_height);
  243     len2=strlen(cd_width);
  244     len3=strlen(cd_depth);
  245     font_height=font_info->max_bounds.ascent+font_info->max_bounds.descent;
  246 
  247     /* 為了將字符串垂直居中,我們先放置第一個字符串,以期它的頂部離窗口中心
  248      * 有兩倍于font_height的高度。因為字符串的底線是我們所需要為XDrawString
  249      * 指明的,並且底線與字符頂部的距離是font_info->max_bounds.ascent。以窗
  250      * 口中央為起點的最終偏移量是font_height+descent */
  251     initial_y_offset=win_height/2-font_height-font_info->max_bounds.descent;
  252     x_offset=(int)win_width/4;
  253     XDrawString(display, win, gc, x_offset, initial_y_offset,
  254             string4, len4);
  255     XDrawString(display, win, gc, x_offset, initial_y_offset+font_height,
  256             cd_height, len1);
  257     XDrawString(display, win, gc, x_offset, initial_y_offset+2*font_height,
  258             cd_width, len2);
  259     XDrawString(display, win, gc, x_offset, initial_y_offset+3*font_height,
  260             cd_depth, len3);
  261 }
  262 
  263 void draw_graphics(Window win, GC gc,
  264         unsigned int window_width, unsigned int window_height)
  265 {
  266     int x, y;
  267     unsigned int width, height;
  268 
  269     height=window_height/2;
  270     width=3*window_width/4;
  271     x=window_width/2-width/2;
  272     y=window_height/2-height/2;
  273     XDrawRectangle(display, win, gc, x, y, width, height);
  274 }
  275 
  276 void TooSmall(Window win, GC gc, XFontStruct *font_info)
  277 {
  278     char *str="Too Small";
  279     int y_offset, x_offset;
  280 
  281     y_offset=font_info->max_bounds.ascent+2;
  282     x_offset=2;
  283 
  284     /* 以水平居中格式輸出文本 */
  285     XDrawString(display, win, gc, x_offset, y_offset, str, strlen(str));
  286 }


版權 © 2024 石仔