[ 永遠的UNIX::UNIX技術資料的寶庫 ]   GB | BIG5

首頁 > 編程技術 > 其它 > 正文
X Window 程式設計入門--第五章 Window
http://cnpa.yzu.edu.tw/~thinker 作者:李圭烽 (Thinker; Thinker.bbs@bbs.yzu.edu.tw) (2001-06-02 00:16:10)
Window
作 者 : Thinker
E-Mail: Thinker.bbs@bbs.yzu.edu.tw 
--------------------------------------------------------------------------------
    
Index:
Create windows/Destroy windows 
    Class 
    Visual Types 
    Depth 
    Create 
    Destroy 
Map windows/Unmap windows 
    Events 
    SubstructureRedirectMask 
    Mapping/UnMapping Fuctions 
Configure windows 
    XWindowChanges 
    Convenient functions 
Change the stacking order 
Change window attributes 
    background 
    border 
    bit-gravity 
    win-gravity 
    backing-store 
    save-under 
    event-mask 
    do-not-propagate-mask 
    override-redirect 
    colormap 
    cursor 

--------------------------------------------------------------------------------


Create windows/Destroy windows
Class
X Window 系統的視窗可分為兩類(兩種 Class),InputOnly 和 InputOutput。 InputOnly 的視窗,
顧名思意就是只能做為 Input 使用,也就是 client 程式只能透過這個視窗來收取 event,但是不
能在這個視 窗做任何的輸出。而 InputOutput 視窗則不只可以接受輸入而己, 而且也可以使用該
視窗做輸出。你可以在 InputOutput 視窗上輸出 文字圖形,卻不能在 InputOnly 視窗上這麼做。
InputOnly 視窗 由於並沒有輸出的能力,所以並不會出現在畫面上。雖然如此,實 際上它還是存在
的。其主要功能是用來做輸入的控制,例如讓 標進入其區域時,立即變成另一種的形式。這樣的可
以讓使用者感 覺到標在 parent 視窗的某個區域採用不同的標。既然 InputOnly 沒有輸出的能力,
所以 InputOnly 視窗也不能做為 drawable 使用。

Visual
在有些硬體上可能提供多種顏色的對映方式。例如有些硬體可能提供 了 16bits 的模式,也就是顯示
出來的每個點使用 16bits 長度的 pixel 值表示。同時也可能提供 8bits 的模式,每個點的顏色使用
 8bits 長度的 pixel 值表示。這種 pixel 值的大小稱 depth,例如 使用 8bits 來表示顏色,則其 
 depth 為 8。除了表示的位元數不同外 ,顏色和 pixel 值之間的對映方式也不同。像一般以 RGB 為
 基礎的 硬,如果採用 8bits 的模式可能 3bits 對映為 red,3bits 對映 為 green,2bits 對映為 
 blue。這種對映的方式稱為 visual。

Xlib 使用 Visual 這個結構存放對映的 visual 資料,而 Visual 實際內容被包裝起來,不讓使用者
直接接觸。Xlib 提供一些應用的 函數和巨集,讓 programmer 透過這些功能來操作 Visual 結構。 
下面是所有的 visual 種類及其對 colormap 和 RGB 的影。 
PseudoColor 
pixel 值對映到 colormap 而產生 RGB 值,RGB 值可以隨時更改而不 影到已輸出的點。 
GrayScale 
和 PseudoColor 差不多,主要的不同在 RGB 值不能更改,否則會影 到已輸出的點的顏色。 
DirectColor 
pixel 被分成 R,G,B 三個部分,這三個部分分別對映 colormap 得到 三個值。從 colormap 得到的
三個值,可以組合成對映的顏色值。 colormap 的 RGB 值可以隨時更換,並且不會因而影項到已輸出 
的點之顏色。 
TrueColor 
和 DirectColor 近似,但是 colormap 內的 RGB 值是內定的,而且不能更改。不同的硬所提供的 
colormap 不盡相同,但在 RGB 各個原色的 colormap 中,大多會提供線性或接進線性變化的 RGB 值。 
StaticColor 
和 PseudoColor 的不同在於其 colormap 的 RGB 值是預定的,無法修改的。 
StaticGray 
和 StaticColor 相似,但任何單一點的 RGB 值都一樣,其實就是單色的意思。 
Depth
depth 就如先前所說的,用以表示對映顏色的資料長度。以 8bits 的 pixel 值表示對映顏色,則 
depth 為 8。 
Create
Xlib 提供 XCreateWindow 建立 unmapped 的視窗: 
--------------------------------------------------------------------------------

     Window XCreateWindow(display, parent, x, y, width, height,
border_width, depth, class, visual, valuemask, attributes)
           Display *display;
           Window parent;
           int x, y;
           unsigned int width, height;
           unsigned int border_width;
           int depth;
           unsigned int class;
           Visual *visual
           unsigned long valuemask;
           XSetWindowAttributes *attributes;


--------------------------------------------------------------------------------
如果成功建立視窗的話,XCreateWindow 會傳回一 Window ID,用以 往後指定視窗,並且產生 
CreateNotify event。新建立的視窗,會是 parent 參數所指定之視窗的子 視窗(subwindow)。x 和 y 
則指定視窗左上角相對於 parent 視窗左 上角的座標。width 和 hieght 指定視窗的寬和高。border_width 
和 depth 分別是視窗邊框的寬度和視窗的 depth,depth 並不需要和 parent 一樣。視窗的 class 為 
InputOnly ,border_width 和 depth 必需指定為零,否則會產生 BadMatch error。InputOutput 視窗的 
parent 規定必需也是 InputOutput,否則會產生 BadMatch error,InputOnly 則無這種限 制。visual 
必需設為硬體有提供的 visual。valuemask 和 attributes 則合力指定視窗的屬性,在後面會談到。

XCreateSimpleWindow 則是簡易版,用於建立 InputOutput 視窗: 
--------------------------------------------------------------------------------

     Window XCreateSimpleWindow(display, parent, x, y, width, height,
      border_width, border, background)
           Display *display;
           Window parent;
           int x, y;
           unsigned int width, height;
           unsigned int border_width;
           unsigned long border;
           unsigned long background;


--------------------------------------------------------------------------------
參數的指定和 XCreateWindow 都差不多,border 是指定邊框的 pixel 值,background 指定背景的 
pixel 值。

Destroy
任何一個視窗被關掉(移除; destroy)都會產生 DestroyNotify event。 parent 視窗被關掉,子視窗也
會因而被關掉,而且會 parent 視窗關 掉之前先自動關掉子視窗。這時,任何被關掉的視窗,包括子視窗
和 parent 視窗,都會產生 DestroyNotify event。

XDestroyWindow 是用以關閉指定之視窗及其子視窗。 
--------------------------------------------------------------------------------

  XDestroyWindow(display, w)
        Display *display;
        Window w;


--------------------------------------------------------------------------------


XDestroySubwindows 關閉指定視窗的所有子視窗,但不包括指定 之視窗。 
--------------------------------------------------------------------------------

  XDestroySubwindows(display, w)
        Display *display;
        Window w;


--------------------------------------------------------------------------------

Map windows/Unmap windows
Events
視窗被建立之後,並不會立即出現在螢幕上,在顯示之前還要經過一個 稱為 mapping 的動作。map 一個
子視窗後,如果其任何一個 ancest 視窗(先視窗)是在 unmapped 狀態(未曾被 map, 或者曾被 map 但又
 被 unmap 了)則子視窗還是不會顯示出來,我們稱之為 unviewable。 子視窗必需等到其所有 ancest 
 視窗都在 mapped 的狀態下時,才會從 unviewable 的狀態進入到 viewable 狀況。視窗只有在 viewable 
 的狀 態下才會被顯示。將視窗 unmap 會使的視窗和其子視窗都隱形起來。任 何一個視窗只要有任何一個
  ancest 視窗被 unmap,都會使該視窗從顯 示器上消失(隱形起來),也就是進入 unviewable 的狀態。

當視窗被 map 時,X Server 會產生 MapNotify evnet。而 unmap 時,會 產件 UnmapNotify event。當視
窗由 unviewable 進入 viewable 狀態, 並且沒有全部被其它視窗遮住,則 X Server 會產生 Expose event。
 任何時候,只要視窗的任何一部分從在顯示上看不到 的狀態變成看的到的狀態,就會產生 Expose evnet。

SubstructureRedirectMask
如果有 client 程式對 parent 視窗設定 SubstructureRedirectMask,則其它的 client 對子視窗發出的
 Map request 都會被轉送給設定 SubstructureRedirectMask 的 client,而且該 Map request 並不會被
 進行。Window Manager 就是採用這個方式,對 root 視窗設定 SubstructureRedirectMask ,因而能攫取
 其它 client 對 root 視窗的子視窗(top window)所送 出的 Map request,而收到 MapRequest Event。
 透過這樣的方式, Window Manager 能控制視窗的外觀和行為。但,事情並不完全這樣 的,如果子視窗
 (child window)的 override-redirect flag 被設為 True,會使這種轉送(redirect)機制失效,其它視窗
 所產生的 Map request 將不再被轉送給在父視窗設定 SubstructureRedirectMask 的 client。

類似於 SubstructureRedirectMask 的情形也發生在 ResizeRedirectMask。如果有 client 對 parent window
 設定 ResizeRedirectMask,則其它 client 對 child window 的 Resize request 同樣也會被轉送給對 
 parent window 設定 ResizeRedirectMask 的 client。如果 child window 的 override-redirect flag 被
 設為 True,同樣的,這種轉送機制 也會失效。

Mapping/UnMapping Fuctions

--------------------------------------------------------------------------------

  XMapWindow(display, w)
        Display *display;
        Window w;

  XMapRaised(display, w)
        Display *display;
        Window w;

  XMapSubwindows(display, w)
        Display *display;
        Window w;


--------------------------------------------------------------------------------
XMapRaised() 除了 map 指定的視窗之外,還會使的視窗上到 window stack 的最上面,使的視窗出現在畫面
的最上面,不會被 其它的視窗擋住。而 XMapSubwindows() 則是 map 指定視窗的所 有子視窗。

Configure windows
XWindowChanges

--------------------------------------------------------------------------------

     /* Configure window value mask bits */
     #define   CWX                         (1<<0)
     #define   CWY                         (1<<1)
     #define   CWWidth                     (1<<2)
     #define   CWHeight                    (1<<3)
     #define   CWBorderWidth               (1<<4)
     #define   CWSibling                   (1<<5)
     #define   CWStackMode                 (1<<6)
     /* Values */

     typedef struct {
          int x, y;
          int width, height;
          int border_width;
          Window sibling;
          int stack_mode;
     } XWindowChanges;


--------------------------------------------------------------------------------

x,y 
顧名思意, x,y 欄位設定視窗的左上角位置. 
width,height 
視窗的寬(width)和高(height) 
border_width 
視窗邊框的寬度 
sibling,stack_mode 
sibling 和 stack_mode 是相關的, 在 sibling 設定一個 window ID, 此視窗和 欲設定其屬性的視窗
為兄弟(sibling;同一個 parent window). stack_mode 指定 視窗重疊順序如何調整. 
我們可以使用 XConfigureWindow 來對視窗設定一些屬性. 
--------------------------------------------------------------------------------

     XConfigureWindow(display, w, value_mask, values)
           Display *display;
           Window w;
           unsigned int value_mask;
           XWindowChanges *values;


--------------------------------------------------------------------------------
values 傳入一些視窗的屬性, 是一個 (XWindowChanges *)的指標. XWindowChanges 請參考上表. 
value_mask 用以表示被修改的 屬性部分. 若指定 values->sibling 和 values->stack_mode, 則 w 
視窗的重疊次序會如下改變: 
Above 
w 視窗的重疊次序會重新排在 sibling 的上面. 
Below 
w 視窗的重疊次序會重新排在 sibling 的下面. 
TopIf 
若 sibling 視窗完全蓋住 w 視窗, 則 w 視窗的次序會重新排在最上面. 
ButtomIf 
若 w 視窗完全蓋住 sibling 視窗, 則 w 視窗的次序會重新排在最下面. 
Opposite 
若 sibling 視窗完全蓋住 w 視窗, 則 w 視窗的次序會重新排在最上面. 若 w 視窗完全蓋住 sibling
 視窗, 則 w 視窗的次序會重新排在最下面. 
若只指定 values->stack_mode, 而未指定 values->sibling, 則 w 視窗的重疊次序會如下改變: 
Above 
w 視窗的重疊次序會重新排在任何其它兄弟視窗的上面(最上面;top). 
Below 
w 視窗的重疊次序會重新排在任何其它兄弟視窗的下面(最下面;buttom). 
TopIf 
若有任何其它兄弟視窗蓋住 w, 則 w 的重疊次序會重新排在最上面. 
ButtomIf 
若 w 蓋住任何其它兄弟視窗, 則 w 的重疊次序會重新排在最下面. 
Opposite 
若有任可其它兄弟視窗蓋住 w, 則 w 的重疊次序會重新排在最上面. 若 w 蓋住任何其它兄弟視窗, 
則 w 的重疊次序會重新排在最下面. 

--------------------------------------------------------------------------------

#include 
#include 
#include 
#include 
#include 


Display *display;
Window window;
GC gc;


void
draw()
{
XDrawRectangle(display, window, gc, 10, 10, 100, 100);

XDrawLine(display, window, gc, 200, 10, 200, 290);
}


main()
{
XSetWindowAttributes attr;
Colormap colormap;
XColor color1, color2;
XGCValues gcvalue;
XSizeHints *sz;
unsigned int vmask;
XWindowChanges values;

display = XOpenDisplay("0:0");

colormap = DefaultColormap(display, DefaultScreen(display));
color1.red = color1.blue = 0xffff;
color1.green = 0;
color2.red = color2.green = color2.blue = 0xff;
color1.flags = color2.flags = DoRed | DoGreen | DoBlue; 
XAllocColor(display, colormap, &color1);
XAllocColor(display, colormap, &color2);

attr.background_pixel = color2.pixel;
window = XCreateWindow(display, XDefaultRootWindow(display),
50, 100, 400, 300, 2, XDefaultDepth(display, 0),
InputOutput, CopyFromParent, CWBackPixel, &attr);

XStoreName(display, window, "hello!! world!!");
sz = XAllocSizeHints();
sz->x = 50;
sz->y = 100;
sz->width = 400;
sz->height = 300;
sz->flags = USPosition | USSize;
XSetNormalHints(display, window, sz);
XMapWindow(display, window);
XFlush(display);

gc = XCreateGC(display, window, 0, &gcvalue);
XSetLineAttributes(display, gc, 5, LineOnOffDash,
CapButt, JoinRound);
XSetForeground(display, gc, color1.pixel);
XSetBackground(display, gc, color2.pixel);
XFlush(display);
sleep(2);
draw();
XFlush(display);
sleep(3);

printf("XConfigureWindow()\n");
values.x = 100;
values.y = 50;
values.width = 300;
values.height = 200;
vmask = CWX | CWY | CWWidth | CWHeight;
XConfigureWindow(display, window, vmask, &values);
XFlush(display);
sleep(2);
draw();
XFlush(display);
sleep(3);

XDestroyWindow(display, window);
XFlush(display);

XCloseDisplay(display);
}


--------------------------------------------------------------------------------
上例是改變視窗的位置和大小, 位置在螢幕上 (100, 50) 的位置, 大小為寬高各為 300 和 200. 
Convenient functions

--------------------------------------------------------------------------------

     XMoveWindow(display, w, x, y)
           Display *display;
           Window w;
           int x, y;

     XResizeWindow(display, w, width, height)
           Display *display;
           Window w;
           unsigned int width, height;

     XMoveResizeWindow(display, w, x, y, width, height)
           Display *display;
           Window w;
           int x, y;
           unsigned int width, height;

     XSetWindowBorderWidth(display, w, width)
           Display *display;
           Window w;
           unsigned int width;


--------------------------------------------------------------------------------

XMoveWindow, XResizeWindow, XMoveResizeWindow, XSetWindowBorderWidth, 分別為移動視窗, 
改變視窗大小, 移動並改變視窗大小, 和設定視窗的外框的 寬度, 是一些簡單方便的函數, 可以簡
化 XConfigureWindow 的使用. 
Change the stacking order
在 X 的 window 常因為相互重疊, 而使的視窗部方的畫面被其它視窗擋 住. 這種視窗重疊的上下次
序稱為 stack order. 
--------------------------------------------------------------------------------

  XRaiseWindow(display, w)
        Display *display;
        Window w;

  XLowerWindow(display, w)
        Display *display;
        Window w;


--------------------------------------------------------------------------------
上面兩個函數正是把視窗在 stack 的順序移至最上面(raise)和 最下面(lower). 
--------------------------------------------------------------------------------

  XCirculateSubwindows(display, w, direction)
        Display *display;
        Window w;
        int direction;


--------------------------------------------------------------------------------
XCirculateSubwindows 改變有子視窗的 stack order, 'direction ' 為 移動的方向, RaiseLowest 把
所有視窗往上移動一個位子, 最上面的視窗 則回到 stack 的最下面, LowerHighest 則反之. 
--------------------------------------------------------------------------------

  XCirculateSubwindowsUp(display, w)
        Display *display;
        Window w;

  XCirculateSubwindowsDown(display, w)
        Display *display;
        Window w;


--------------------------------------------------------------------------------
和 XCirculateSubwindows 功能重, 但比較易於使用. 
--------------------------------------------------------------------------------

  XRestackWindows(display, windows, nwindows);
        Display *display;
        Window windows[];
        int nwindows;


--------------------------------------------------------------------------------
透過 XRestackWindows 可以直接指定 stack order. windows 傳入 依次序存放的 Window 陣列, 
nwindows 則是陣列的長度. 
Change window attributes
視窗除了位置和大小之外, 還有其它不同的屬性, 控制視窗的外觀和行為. 
--------------------------------------------------------------------------------

     /* Window attribute value mask bits */
     #define   CWBackPixmap                (1L<<0)
     #define   CWBackPixel                 (1L<<1)
     #define   CWBorderPixmap              (1L<<2)
     #define   CWBorderPixel               (1L<<3)
     #define   CWBitGravity                (1L<<4)
     #define   CWWinGravity                (1L<<5)
     #define   CWBackingStore              (1L<<6)
     #define   CWBackingPlanes             (1L<<7)
     #define   CWBackingPixel              (1L<<8)
     #define   CWOverrideRedirect          (1L<<9)
     #define   CWSaveUnder                 (1L<<10)
     #define   CWEventMask                 (1L<<11)
     #define   CWDontPropagate             (1L<<12)
     #define   CWColormap                  (1L<<13)
     #define   CWCursor                    (1L<<14)
     /* Values */

  typedef struct {
       Pixmap background_pixmap;/* background, None, or ParentRelative */
       unsigned long background_pixel;/* background pixel */
       Pixmap border_pixmap;    /* border of the window or CopyFromParent */
       unsigned long border_pixel;/* border pixel value */
       int bit_gravity;         /* one of bit gravity values */
       int win_gravity;         /* one of the window gravity values */
       int backing_store;       /* NotUseful, WhenMapped, Always */
       unsigned long backing_planes;/* planes to be preserved if possible */
       unsigned long backing_pixel;/* value to use in restoring planes */
       Bool save_under;         /* should bits under be saved? (popups) */
       long event_mask;         /* set of events that should be saved */
       long do_not_propagate_mask;/* set of events that should not propagate */
       Bool override_redirect;  /* boolean value for override_redirect */
       Colormap colormap;       /* color map to be associated with window */
       Cursor cursor;           /* cursor to be displayed (or None) */
  } XSetWindowAttributes;


  XChangeWindowAttributes(display, w, valuemask, attributes)
        Display *display;
        Window w;
        unsigned long valuemask;
        XSetWindowAttributes *attributes;


--------------------------------------------------------------------------------
XChangeWindowAttributes 設定視窗的各種屬性, 各種屬性的意義在後面 的小節會一一介紹. 'valuemask' 
是根據設定的 attributes 欄位而 定, 把有設定的欄位的對應 mask 做 OR 運算. 
--------------------------------------------------------------------------------

Display *d;
Window w;
XSetWindowAttributes attr;
unsigned long vmask;

...............
........

attr.save_under = True;
attr.override_redirect = False;
vmask = CWOverrideRedirect | CWSaveUnder;
XChangeWindowAttributes(d, w, vmask, &attr);


--------------------------------------------------------------------------------

background
視窗的背景可以塗上單一顏色, 或者是貼上不同的圖案. 
--------------------------------------------------------------------------------

  XSetWindowBackground(display, w, background_pixel)
        Display *display;
        Window w;
        unsigned long background_pixel;

  XSetWindowBackgroundPixmap(display, w, background_pixmap)
        Display *display;
        Window w;
        Pixmap background_pixmap;


--------------------------------------------------------------------------------
XSetWindowBackground 用以設定背景顏色, 'background_pixel' 則為 背景的顏色. 功能和設定 
XSetWindowAttributes 中的 background_pixel 欄位的功能相同. XSetWindowBackgroundPixmap 
則是設定背景為一張圖 (pixmap), 相當於設定 background_pixmap 欄位. 
border
設定視窗的外框顏色或圖形. 
--------------------------------------------------------------------------------

  XSetWindowBorder(display, w, border_pixel)
        Display *display;
        Window w;
        unsigned long border_pixel;

  XSetWindowBorderPixmap(display, w, border_pixmap)
        Display *display;
        Window w;
        Pixmap border_pixmap;


--------------------------------------------------------------------------------

bit-gravity
設定視窗的 bit-gravity, bit-gravity 控制 InputOutput 視窗 resize 時, 視窗的內容如何維持. 
當視窗的大小改變時, 視窗的內容不會改變, 但是會因為視窗大小的改變而移動其在視窗內的相對位置
(相對於左上角). 當視窗的寬和高改變了 w 和 h, 則任何一點(x,y)的位置會如下改變: 
NorthWestGravity (0,0) 
NorthGravity (w/2,0) 
NorthEastGravity (w,0) 
WestGravity (0,h/2) 
CenterGravity (w/2,h/2) 
EastGravity (w,h/2) 
SouthWestGravity (0,h) 
SouthGravity (w/2,h) 
SouthEastGravity (w,h) 

win-gravity
win-gravity 和 bit-gravity 類似, 但控制的對像是視窗內的子視窗的位置. 
backing-store
有些 X Server 會幫視窗儲存其內容, 當視窗的內容 lost 而需要重繪時, Server 會使用先前儲存的
內容自動補回去, 這樣的動作稱為 backing store. backing-store 控制這項功能是否作用, 其狀態可
為 NotUseful (default), WhenMapped, Always.

backing-store 為 NotUseful, 則議 X Server 不要進行 backing store. 但這只是議, X Server 可能
還是選擇進行 backing store. WhenMapped 則議 X Server 在視窗映射時(mapped)進行 backing store,
 同樣的, 這也只是議, 並不保 X Server 一定會進行, 所以 client 還是得注 意 Expose evnet.Always
  則是議隨時都進行 backing store, 不論是 映射(mapped)或未映射. 
save-under
save under 和 backing store 類似, 但其處理的對象是被指定視窗蓋住 的其它視窗內容. save-under 
可為 True 或 False(default), 為 True, X Server 會自動維護被該視窗蓋到的其它視窗內容, 在該部分
重新 Expose 時, 自動回補. 
event-mask
do-not-propagate-mask
do-not-propagate-mask 是一個 KeyPress, KeyRelease, ButtonPress, ButtonRelease, PointerMotion, 
Button1Motion, Button2Motion, Button3Motion, Button4Motion, Buttton5Motion, ButtonMotion 的 
bitwise inclusive or. 當視窗產生或從子視窗 propagate 一個被 mask 的 event, 該 event 將不會繼續
往 parent propagate. 
override-redirect
將使的 parent 上設定 SubstructureRedirectMask 失效. 
colormap

--------------------------------------------------------------------------------

  XSetWindowColormap(display, w, colormap)
        Display *display;
        Window w;
        Colormap colormap;


--------------------------------------------------------------------------------

cursor
cursor 指定標進入視窗後所使用的指標, 指標可用 XCreatePixmapCursor 建立. 
--------------------------------------------------------------------------------

  Cursor XCreatePixmapCursor(display, source, mask,
  foreground_color, background_color, x, y)
Display *display;
Pixmap source;
Pixmap mask;
XColor *foreground_color;
XColor *background_color;
unsigned int x, y;


--------------------------------------------------------------------------------
XCreatePixmapCursor 可由 pixmap 建立一個新的標, source 是標的 圖案, mask 則是圖形的 mask, 用以 
mask 標的圖形, 以定義圖形內那 一部分屬於標圖形(設為1), 那一部分不屬於(設為0), 建立不規則形狀的 
標. 

(http://www.fanqiang.com)
    進入【UNIX論壇

相關文章
X Window 程式設計入門--第六章 Inter-Client Communication (2001-06-02 18:08:00)
X Window 程式設計入門--第五章 Window (2001-06-02 00:16:10)
X Window 程式設計入門--第四章 Event (2001-06-01 21:04:00)
X Window 程式設計入門--第三章 繪圖(Graphic) (2001-06-01 20:10:00)
X Window 程式設計入門--第二章 X Programming 的第一步 (2001-06-01 19:00:01)
X Window 程式設計入門--第一章 什麼是 X Window (2001-06-01 18:08:00)
X Window 程式設計入門 (2001-06-01 17:04:00)
 

★  樊強制作 歡迎分享  ★