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 石仔