天天看點

作業系統核心開發:使用圖層技術開發一個MessageBox

具體的代碼講解和調試請參看視訊:

Linux kernel Hacker, 從零建構自己的核心

我還記得,早年學習win32 GUI程式設計,通過調用一個API 叫MessageBox, 使得程式能快速彈出一個小視窗,當看到這個小視窗出現在螢幕上時,開心得不得了,覺得非常不可思議,它生動形象,跟原來在控制台上運作的,隻能給出黑底白色結果的dos程式完全不同,從此,我從黑色單調的世界進入了稱之為“圖形界面“的色彩斑斓的絕妙空間。

一直以來,我心中困惑着,這些形象生動而又具有立體感的小視窗到底是怎麼實作的,知道現在,有能力,有條件,開發一個系統核心時,我才能從底層原理上,了解這些動人小視窗的前世今生,這裡,我想和大家分享一下,他們是怎麼來到這個世界的。

前面幾節,我們花了不少精力去實作圖層的技術效果,現在,我們可以基于圖層的基礎上,看看那些花哨的界面是如何制作出來的,這節,我們看看,小小的MessageBox是怎麼創造出來的,先讓大家看看本節代碼運作後的效果:

作業系統核心開發:使用圖層技術開發一個MessageBox

一個小巧可愛的MessageBox躍然于桌面上,下面我們看看它的實作代碼:

void make_window8(struct SHTCTL *shtctl, struct SHEET *sht,  char *title) {

    static char closebtn[][] = {
        "[email protected]", 
        "OQQQQQQQQQQQQQ[email protected]",
        "OQQQQQQQQQQQQQ[email protected]",
        "[email protected]@[email protected]@QQ[email protected]",
        "[email protected]@[email protected]@QQQ[email protected]",
        "[email protected]@@@QQQQ[email protected]",
        "[email protected]@QQQQQ[email protected]",
        "[email protected]@@@QQQQ[email protected]",
        "[email protected]@[email protected]@QQQ[email protected]",
        "[email protected]@[email protected]@QQ[email protected]",
        "OQQQQQQQQQQQQQ[email protected]",
        "OQQQQQQQQQQQQQ[email protected]",
        "O$$$$$$$$$$$$$[email protected]",
        "@@@@@@@@@@@@@@@@"
    };

    int x, y;
    char c;
    int bxsize = sht->bxsize;
    int bysize = sht->bysize;
    boxfill8(sht->buf, bxsize, COL8_C6C6C6, , , bxsize - , );
    boxfill8(sht->buf, bxsize, COL8_FFFFFF, , , bxsize - , );
    boxfill8(sht->buf, bxsize, COL8_C6C6C6, , , ,         bysize - );
    boxfill8(sht->buf, bxsize, COL8_FFFFFF, , , ,         bysize - );
    boxfill8(sht->buf, bxsize, COL8_848484, bxsize - , , bxsize - , bysize - );
    boxfill8(sht->buf, bxsize, COL8_000000, bxsize - , , bxsize - , bysize - );
    boxfill8(sht->buf, bxsize, COL8_C6C6C6, , , bxsize - , bysize - );
    boxfill8(sht->buf, bxsize, COL8_000084, , , bxsize - , );
    boxfill8(sht->buf, bxsize, COL8_848484, , bysize - , bxsize - , bysize - );
    boxfill8(sht->buf, bxsize, COL8_000000, , bysize - , bxsize - , bysize - );

    showString(shtctl, sht, , , COL8_FFFFFF, title);

    for (y = ; y < ; y++) {
        for (x = ; x < ; x++) {
            c = closebtn[y][x];
            if (c == '@') {
                c = COL8_000000;
            } else if (c == '$') {
                c = COL8_848484;
            } else if (c == 'Q') {
                c = COL8_C6C6C6;
            } 
            else {
                c = COL8_FFFFFF;
            }

            sht->buf[(+y) * sht->bxsize + (sht->bxsize -  + x)] = c;
        }

    }

    return;
}
           

make_window8 函數是專門用來繪制這個小視窗的,大家可以猜到,closebtn這個數組,對應的是小視窗右上角的X按鈕,這個數組中,@元素所對應的就是圖像中關閉按鈕的小叉叉。該調用函數中,參數sht對應的就是該小視窗的圖層,代碼中,boxfill8這幾個函數的調用,作用是繪制視窗的主窗體,showString調用用來顯示小視窗上方的小标題,下面的兩個for循環這是用來繪制小窗台右上角的關閉按鈕。

接下來,我們再看看這個函數是如何被調用的:

void message_box(struct SHTCTL *shtctl,  char *title) {
    struct SHEET *sht_win;
    unsigned char *buf_win;

    sht_win = sheet_alloc(shtctl);
    buf_win = (unsigned char *)memman_alloc_4k(memman,  * );
    sheet_setbuf(sht_win, buf_win, , , -);

    make_window8(shtctl, sht_win, title);

    showString(shtctl, sht_win, , , COL8_000000, "Welcome to");
    showString(shtctl, sht_win, , , COL8_000000, "MyOS");

    sheet_slide(shtctl, sht_win, , );
    sheet_updown(shtctl, sht_win, );
}
           

message_box函數中,首先為我們的小窗台配置設定一個圖層對象sht_win, 并通過記憶體配置設定接口,配置設定一塊4k可用記憶體,這塊記憶體将用于存儲小窗台的像素資訊,同時把這塊記憶體跟圖層對象關聯起來,兩個showString的調用用來顯示窗體中間的字元串内容,sheet_slide使得窗體的左上角坐标為(80, 72),并且設定該窗體的高度為1,我們還記得,前一節我們将桌面的高度設定為0,把窗體高度設定為1,這樣它才能顯示在桌面之上。

我們看看主入口函數的改變:

void CMain(void) {
   ....
   message_box(shtctl, "windown");

   sheet_updown(shtctl, sht_back, );

   sheet_updown(shtctl, sht_mouse, );

   io_sti();
   ....
}
           

在入口函數中,我們調研message_box,這樣,一旦系統啟動之後,小視窗就會出現,注意到 sheet_updown(shtctl, sht_mouse, 100); 這一句,我們把滑鼠的高度設定成100,這樣滑鼠就可以出現在目前所有窗體的上方,我們可以做個有趣的小實驗,把滑鼠的高度改成1,把小窗台的高度改成2,我們可以得到下面的效果:

作業系統核心開發:使用圖層技術開發一個MessageBox

我們看到,滑鼠移動到小窗台區域時,它跑到了窗體的底部而不是上頭,這個效果也充分顯示了圖層高度的相應效果。

經過一系列的努力,我們已經成功進入到了色彩斑斓的GUI世界,這個世界還有很多奇妙秘密等待我們開發和挖掘,讓我們繼續努力吧^_^!

繼續閱讀