操作系统内核开发:使用图层技术开发一个MessageBox

具体的代码讲解和调试请参看视频:
Linux kernel Hacker, 从零构建自己的内核

我还记得,早年学习win32 GUI编程,通过调用一个API 叫MessageBox, 使得程序能快速弹出一个小窗口,当看到这个小窗口出现在屏幕上时,开心得不得了,觉得非常不可思议,它生动形象,跟原来在控制台上运行的,只能给出黑底白色结果的dos程序完全不同,从此,我从黑色单调的世界进入了称之为“图形界面“的色彩斑斓的绝妙空间。

一直以来,我心中困惑着,这些形象生动而又具有立体感的小窗口到底是怎么实现的,知道现在,有能力,有条件,开发一个系统内核时,我才能从底层原理上,理解这些动人小窗口的前世今生,这里,我想和大家分享一下,他们是怎么来到这个世界的。

前面几节,我们花了不少精力去实现图层的技术效果,现在,我们可以基于图层的基础上,看看那些花哨的界面是如何制作出来的,这节,我们看看,小小的MessageBox是怎么创造出来的,先让大家看看本节代码运行后的效果:


这里写图片描述

一个小巧可爱的MessageBox跃然于桌面上,下面我们看看它的实现代码:

void make_window8(struct SHTCTL *shtctl, struct SHEET *sht,  char *title) {
                
    static char closebtn[14][16] = {
  "OOOOOOOOOOOOOOO@", 
  "OQQQQQQQQQQQQQ$@",
  "OQQQQQQQQQQQQQ$@",
  "OQQQ@@QQQQ@@QQ$@",
  "OQQQQ@@QQ@@QQQ$@",
  "OQQQQQ@@@@QQQQ$@",
  "OQQQQQQ@@QQQQQ$@",
  "OQQQQQ@@@@QQQQ$@",
  "OQQQQ@@QQ@@QQQ$@",
  "OQQQ@@QQQQ@@QQ$@",
  "OQQQQQQQQQQQQQ$@",
  "OQQQQQQQQQQQQQ$@",
  "O$$$$$$$$$$$$$$@",
  "@@@@@@@@@@@@@@@@"
 };

    int x, y;
    char c;
    int bxsize = sht->bxsize;
    int bysize = sht->bysize;
    boxfill8(sht->buf, bxsize, COL8_C6C6C6, 0, 0, bxsize - 1, 0);
    boxfill8(sht->buf, bxsize, COL8_FFFFFF, 1, 1, bxsize - 2, 1);
    boxfill8(sht->buf, bxsize, COL8_C6C6C6, 0, 0, 0,         bysize - 1);
    boxfill8(sht->buf, bxsize, COL8_FFFFFF, 1, 1, 1,         bysize - 1);
    boxfill8(sht->buf, bxsize, COL8_848484, bxsize - 2, 1, bxsize - 2, bysize - 2);
    boxfill8(sht->buf, bxsize, COL8_000000, bxsize - 1, 0, bxsize - 1, bysize - 1);
    boxfill8(sht->buf, bxsize, COL8_C6C6C6, 2, 2, bxsize - 3, bysize - 3);
    boxfill8(sht->buf, bxsize, COL8_000084, 3, 3, bxsize - 4, 20);
    boxfill8(sht->buf, bxsize, COL8_848484, 1, bysize - 2, bxsize - 2, bysize - 2);
    boxfill8(sht->buf, bxsize, COL8_000000, 0, bysize - 1, bxsize - 1, bysize - 1);
    
    showString(shtctl, sht, 24, 4, COL8_FFFFFF, title);

    for (y = 0; y < 14; y++) {
        for (x = 0; x < 16; 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[(5+y) * sht->bxsize + (sht->bxsize - 21 + 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, 160 * 68);
    sheet_setbuf(sht_win, buf_win, 160, 68, -1);

    make_window8(shtctl, sht_win, title);
    
    showString(shtctl, sht_win, 24, 28, COL8_000000, "Welcome to");
    showString(shtctl, sht_win, 24, 44, COL8_000000, "MyOS");
    
    sheet_slide(shtctl, sht_win, 80, 72);
    sheet_updown(shtctl, sht_win, 1);
}

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, 0);
  
   sheet_updown(shtctl, sht_mouse, 100);

   io_sti();
   ....
}

在入口函数中,我们调研message_box,这样,一旦系统启动之后,小窗口就会出现,注意到 sheet_updown(shtctl, sht_mouse, 100); 这一句,我们把鼠标的高度设置成100,这样鼠标就可以出现在当前所有窗体的上方,我们可以做个有趣的小实验,把鼠标的高度改成1,把小窗台的高度改成2,我们可以得到下面的效果:


这里写图片描述

我们看到,鼠标移动到小窗台区域时,它跑到了窗体的底部而不是上头,这个效果也充分显示了图层高度的相应效果。

经过一系列的努力,我们已经成功进入到了色彩斑斓的GUI世界,这个世界还有很多奇妙秘密等待我们开发和挖掘,让我们继续努力吧_!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,033评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,725评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,473评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,846评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,848评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,691评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,053评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,700评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,856评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,676评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,787评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,430评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,034评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,990评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,218评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,174评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,526评论 2 343

推荐阅读更多精彩内容