非不荒谬窗口首借使把窗体的某有个别用透明色来表现,并且使得鼠标点击窗口关闭按钮后

putstr函数有八个职能,当输入字符在’a’到’h’之间时,它依据点阵表charset,通过安装有个别像素点的水彩来绘制图像。在这之中参数x,y是图像起首坐标,最终二个参数s用来决定图像绘制的章程,例如当最后的s内容为”abcd”时,该函数从charset表中取出前四行数据,在那之中每一个数值都在告知代码在绘制哪1个像素点,它的绘图原理与早前大家上课的怎样绘制字符是一样的。大家先看看上边代码运维起来后的动静:

struct SHEET {
    unsigned char *buf;
    int bxsize, bysize, vx0, vy0, col_inv, height, flags;
    struct TASK *task;
};

公海赌船网址 1

此地写图片描述

此处写图片描述

void  show_mouse_info(struct SHTCTL *shtctl, struct SHEET *sht_back,struct SHEET *sht_mouse) {
....
if (mouse_decode(&mdec, data) != 0) {
         computeMousePosition(shtctl, sht_back, &mdec);

         sheet_slide(shtctl, sht_mouse, mx, my);
         if ((mdec.btn & 0x01) != 0) { 
         ....
         if (sht->bxsize - 21 <= x && x < sht->bxsize - 5 && 5 <= y && y < 19 && sht->task != 0) {
         //如果鼠标左键点击时,鼠标位于右上角的按钮范围内,则结束窗口对应的进程,同时将窗口从桌面上清除
                                    io_cli();
                                    sheet_free(shtctl, sht);
                                    int addr_code32 = get_code32_addr();
                                    sht->task->tss.eip = (int)kill_process - addr_code32;
                                    io_sti();
                            }
                            break;
         ....
         }
}
....
}

从上面我们得以观望,飞机挪到左边时,外星人移动到右手。接着我们要达成用户按下空格键时,飞机能发出炮弹,并且判断一旦炮弹击中外星人后,外星人会被扑灭掉,那一个效果的落实重庆大学借助上面代码:

至于鼠标的拍卖,都在函数show_mouse_info里面达成,所以大家要修改该函数的代码:

愈多技术音讯,包罗操作系统,编写翻译器,面试算法,机器学习,人工智能,请看管笔者的群众号:

按键q的扫描码是0x10,当主进度接收到按键新闻,并且判断按下的正是’q’键,那么它调用sheet_updown函数把处于最底部的窗口挪到尾数第3高的岗位,处于最底部的窗口是shtctl->sheets[1],
shtctl->sheets[0]对应的是桌面,同时处于处于最高地方的图层必须是鼠标,它对应的莫斯中国科学技术大学学正是shtctl->top,大家进步窗口的惊人时,不可让窗口高过鼠标,要不然鼠标挪如窗口时,窗口会把鼠标给盖住。上边的代码编写翻译进基本,在虚拟机上加载后,运营如下:

nextgroup:
    ix =  7;
    iy = 1;
    int invline = 6;
    for (i = 0; i < 3; i++) {
        for (j = 0; j < 20; j++) {
            invstr[i * 32 + j] = invstr0[j];
        }
        putstr(win, winbuf,charset, ix, iy + i, 2, invstr + i * 32);
    }

公海赌船网址 2

 if (ly > 0) {
                char c[2] = {'h', 0};
                putstr(win, winbuf,charset, lx, ly, 3, c);
            } // if(ly > 0)

公海赌船网址 3

公海赌船网址 4

启航应用程序时,应用程序窗口会处在控制台窗口之上,此时点击一下键盘上的’q’键,低下的决定台窗口会跳出来覆盖住应用程序窗口:

restart:
    fx = 18;
    char fly[8] = {'e', 'f', 'g', 0};
    putstr(win, winbuf, charset, 18, 11, 6, fly);

在创设窗体时,把相应的进程对象跟窗口句柄关联起来:

void main () {
....
    for(;;) {
        waitting(4, timer, keyflag);
        ....
                //move aliens
        if (movewait != 0) {
            movewait--;
        } else {
            movewait = movewait0;
            if (ix + idir > 12 || ix + idir < 1) {
                if (iy + invline == 13) {
                   //game over
                   break;
                }
                idir = -idir;
                putstr(win, winbuf, charset,ix + 1, iy, 0, "  ");
                iy++;
            } else {
                ix += idir;
            }
            for (i = 0; i < invline; i++) {
                putstr(win, winbuf,charset, ix, iy + i, 2, invstr + i * 32);
            }
        } 
    }   
}
static int mx = 0, my = 0, mmx = -1, mmy = -1;
....
static struct SHEET *mouse_clicked_sht;

日前,大家的系统已经进化到了肯定较为圆满的程度,当然最好3个练习系统,它不容许跟正式的windows或linux比较,但麻雀虽小五腑俱全,大家的系统恐怕能协助用户在其上边开发出不少繁杂但又幽默的应用程序的,它所展现的成效完全能够称得上是多个鲁棒的操作系统。

公海赌船网址 5

地点代码使得,当用户点击空格键时,程序就准备从飞机处发射出导弹。代码片段:

void CMain(void) {
....
for(;;) {
    if (fifo8_status(&keyinfo) + fifo8_status(&mouseinfo) +
           fifo8_status(&timerinfo) == 0) {
        ....
        if (data == 0x10) {
           sheet_updown(shtctl, shtctl->sheets[1], shtctl->top - 1);
        }
        ....
   }
}
....
}

接下去大家再看看三个更有意思的用户程序,线团火球!在app.c中添加代码如下:

公海赌船网址,基本开发到前日,我们早已足以透过应用程序达成多少个窗口的创制。当前存在的题材是,窗口与窗口之间不能互相切换,同时鼠标也无能为力用来运动窗口,更令人烦躁的是,窗口的右上角有个小叉叉,可是用鼠标去点击时,窗口并不曾像设想中的这样关闭掉,本节我们要增加相互功用,让鼠标能够拖拽窗体,并且使得鼠标点击窗口关闭按钮后,窗口能立刻没有。

那边写图片描述

若是那时候您再一次点击’q’键,底下的应用程序窗口会再也跳出来,覆盖控制台窗口。接下来大家看看,怎么样利用鼠标拖拽窗口。要兑现窗口拖拽,首先要一口咬住不放鼠标落在窗体上,而且是落在窗体的非透明区域,并且再判断鼠标是不是落在窗口的标题栏,那一个个条件满意后,系统起先记录鼠标在窗体标题栏按下左键时所作的地点坐标,当鼠标移动后,系计算算移动后的岗位相对于左键按下时地方的偏移,然后把窗体依据偏移举行活动就可以了。相关代码达成如下,在根本的C语言部分write_vga_desktop.c中,先添加三个全局变量,用于记录鼠标左键按下时的坐标:

此地写图片描述

公海赌船网址 6

公海赌船网址 7

形成那项代码后,系统就足以支撑鼠标与窗口的竞相了,大家系统的八面玲珑和充分性又升高了成千成万。

void putstr(int win, char *winbuf,char * charset,
 int x, int y, int col, unsigned char *s) {
 ....
 }

 void waitting(int i, int timer, char* keyflag) {
    int j;
    if (i > 0) {
        api_settimer(timer, i);
        i = 128;
    } else {
        i = 0x1c;
    }

    for(;;) {
        j = api_getkey(1);
        if (i == j) {
            break;
        }

        if (j == 0x24) {
          //key j
            keyflag[0] = 1;
        }
        if (j == 0x25) {
            //key k
            keyflag[1] = 1;
        }
        if (j == 0x39) {
            //key space
            keyflag[2] = 1;
        }
    }

    return;
}

void main() {
    char keyflag[6];
    ....
    nextgroup:
    ....
    keyflag[0] = 0;
    keyflag[1] = 0;
    keyflag[2] = 0;

    for(;;) {
        waitting(4, timer, keyflag);
        if (keyflag[0] != 0 && fx > 1) {
           //fighter fly to left
           fx--;
           fly[0] = 'e', fly[1] = 'f', fly[2] = 'g', fly[3] = ' ';
           fly[4] = 0;
           putstr(win, winbuf, charset, fx, 11, 6, fly); 
           keyflag[0] = 0;
        }
        if (keyflag[1] != 0 && fx < 24) {
           fx++;
           fly[0] = ' ', fly[1] = 'e', fly[2] = 'f', fly[3] = 'g';
           fly[4] = 0;
           putstr(win, winbuf, charset, fx, 11, 6, fly);
           keyflag[1] = 0;
        }
    }
}

执行应用程序,运转多个窗口,把鼠标挪到窗口的右上角按钮,鼠标左键点击后,窗口会被关闭:

公海赌船网址 8

完了地方代码,把基础编写翻译加载到虚拟机后,情状如下:

绘图出来的美术是还是不是很是惊艳,卓殊灿烂,我们的系统平台依旧蛮给力的。

先前控制台窗口始终位于桌面包车型地铁左上角,下边代码完毕自笔者,大家得以透过鼠标把控制台窗体拖拽到其余岗位。

跟着大家要想艺术让图像动起来,这就需求使用到大家前面做过的定时器。首先,大家先添加代码,让飞机遵照大家按键输入以便达成左右活动,因而我们添加日下代码:

窗体右上角的叉叉按钮存在了好久了,你是还是不是间接想去点击一下,以便把窗口关闭呢,接下去,大家做到点击右上角按钮关闭窗体的效劳。首先大家把各个窗口句柄跟发生它的经过对象关联起来,现在win_sheet.h和win_sheet.c中添加如下内容:

更详实的教师和代码调节和测试演示过程,请参考摄像
Linux kernel 哈克er,
从零创设自个儿的基石

鼠标左键点击时,内核须要看清当时鼠标所在地方是或不是位于右上角按钮内,如果是,那么停止窗口所在经过,并把窗口从桌面上清除,代码如下:

则是绘制了图画上方的三排外星人。

此处写图片描述

公海赌船网址 9

公海赌船网址 10

公海赌船网址 11

增加产量代码的逻辑在诠释中早已详细表明了,把地点的代码编写翻译如木本后,运维起来效果如下:

从上海教室能够看来,橄榄棕的竖线块就是飞机发射出的导弹,中间那排外星人被击毙了,所以在显示器上尚未突显出来。即使外星人下落到飞机所在中度,那么有玩乐停止,如果外星人全部被击毙,那么战机成功保卫地球,游戏也甘休:

为了调节方便,大家先支付多少个小作用,点击一下键盘上的按键‘q’后,系统能把地处最底部的窗口放到最上面,相关落到实处代码如下,在write_desktop_vga.c中添加如下代码:

for(;;) {
       if (laserwait != 0) {
            laserwait--;
            keyflag[2] = 0;
        }
        ....
       //draw laser bullet
        if (ly > 0) {
            if (ly < 8) {
                if (ix < lx && lx < ix + 25 && iy <= ly && ly < iy + invline) {
                    putstr(win, winbuf, charset, ix, ly, 2, invstr + (ly - iy) * 32);
                }//if (ix < lx ...)
                else {
                    putstr(win, winbuf, charset, lx, ly, 0, "  ");
               }
            }//if(ly < 13)
            ly--;
            if (ly > 0) {
                char c[2] = {'h', 0};
                putstr(win, winbuf,charset, lx, ly, 3, c);
            } // if(ly > 0)

            if (ix < lx && lx < ix + 25 && iy <= ly && ly < iy + invline) {
               p = invstr + (ly - iy) * 32 + (lx - ix);
               if (*p != ' ' ) {
                   //hit
                   for(p--; *p != ' '; p--) {}
                   for (i = 1; i < 5; i++) {
                       p[i] = ' ';
                   }
                  putstr(win, winbuf, charset, ix, ly, 2, invstr+(ly-iy)*32);
                  for(; invline > 0; invline--) {
                      for(p = invstr + (invline-1)*32; *p != 0; p++) {
                          if (*p != ' ') {
                              goto alive;
                          }
                      }
                  } 
            gameover:
                  //hit all 
                  movewait0 -= movewait0 / 3;
                  char gameover[12] = {'G','A','M','E',' ','O','V','E','R'};
                  putstr(win, winbuf, charset, 15, 6, 1, gameover);
                  waitting(10, timer, keyflag);

                  goto nextgroup;
            alive:
                  ly = 0;
               }
            } //if(ix < lx...)

        }//if (ly > 0)
    }
}
void  show_mouse_info(struct SHTCTL *shtctl, struct SHEET *sht_back,struct SHEET *sht_mouse) {
   ....
   int j; 
   struct SHEET *sht = 0;
   ....
   if (mouse_decode(&mdec, data) != 0) {
         computeMousePosition(shtctl, sht_back, &mdec);
        //挪动鼠标图案
         sheet_slide(shtctl, sht_mouse, mx, my);
         if ((mdec.btn & 0x01) != 0) { 
           //鼠标左键被按下时进入这里
            if (mmx < 0) {
                //遍历所以窗体,看鼠标当前落入哪个窗体区域
                for (j = shtctl->top - 1; j > 0; j--) {
                    sht = shtctl->sheets[j];
                    x = mx - sht->vx0;
                    y = my - sht->vy0;
                    if (0 <= x && x < sht->bxsize && 0 <= y && y < sht->bysize) {
                        if (sht->buf[y * sht->bxsize + x] != sht->col_inv) {
                        //找到包含鼠标的窗体,并且鼠标所在的窗体区域不属于窗体的透明区,那么调整窗体高度,让他显示在桌面上
                            sheet_updown(shtctl ,sht, shtctl->top - 1);
                            if (3 <= x && x <sht->bxsize - 3 && 3 <= y && y < 21) {
                            //如果鼠标落入窗体的标题栏,记录当前鼠标所在坐标,以及当前窗体的句柄
                                mmx = mx;
                                mmy = my;
                                mouse_clicked_sht = sht;
                            }
                            break;
                        }
                    }   
                }
            } else {
                //鼠标挪动后,计算当前位置与鼠标点击时所在位置的偏移,然后根据偏移挪动窗体
                x = mx - mmx;
                y = my - mmy;
                sheet_slide(shtctl, mouse_clicked_sht, mouse_clicked_sht->vx0 + x, mouse_clicked_sht->vy0 + y);
                mmx = mx;
                mmy = my;
            }  
         } else {
           //鼠标左键松开后,把mmx重置为-1
            mmx = -1;
          // showString(shtctl, sht_back, 0, 207, COL8_FFFFFF, "set mmx to -1");
         }
    }
}

咱俩看看第3个有趣的应用程序:不规则窗口。
不少独居特色的应用程序,一大特征之一就是反常窗口,奇形怪状的窗体形态确实不难给人耳目一新的感觉到,不规则窗口主假如把窗体的某部分用透明色来显现,今后大家就来品尝一下,在app.c中形成以下代码:

struct SHEET *sheet_alloc(struct SHTCTL *ctl) {
    struct SHEET *sht;
    int i;
    for (i = 0; i < MAX_SHEETS; i++) {
        if (ctl->sheets0[i].flags == 0) {
            sht = &ctl->sheets0[i];
            ctl->sheets[i] = sht;
            sht->flags = SHEET_USE;
            sht->height = -1;
            sht->task = task_now();
            return sht;
        }
    }

    return 0;
}

以此星球大战游戏是系统基本开发到此,大家做过的格外复杂的客户程序,它调用了大致全数api,例如窗口绘制,字符串输出,时钟,键盘监听等等,那些纷纷程序的中标运营,在放任自流水平上标明,大家的系统基本具备一定水准的繁杂和鲁棒性,尽管它不行与标准操作系统同日而语,但即便它再不难,再繁杂,它也对得起1个“操作系统”的称呼。

此处写图片描述

绘制的正是画画底部的歼击机,而代码片段:

那里写图片描述

#define win_width 240

void putstr(int win, char *winbuf,char * charset,
 int x, int y, int col, unsigned char *s) {
    int c, x0, i = 0, j;
    char *p, *q, t[2];
    x = x*8+8;
    y = y*16+29;
    x0 = x;
    while (s[i] != 0) {
        i++;
    }

    api_boxfilwin(win, 8, y, win_width - 8 , y+15, 0);

    q = winbuf + y * win_width; 
    t[1] = 0;
    for (;;) {
        c = *s;
        if (c == 0) {
            break;
        }

        if (c != ' ') {
            if ('a' <= c && c <= 'h') {
                p = charset + 16 * (c-'a');
                q += x;
                for (i = 0; i < 16; i++) {

                    if ((p[i] & 0x80) != 0) {q[0] = col;}
                    if ((p[i] & 0x40) != 0) {q[1] = col;}
                    if ((p[i] & 0x20) != 0) {q[2] = col;}
                    if ((p[i] & 0x10) != 0) {q[3] = col;}
                    if ((p[i] & 0x08) != 0) {q[4] = col;}
                    if ((p[i] & 0x04) != 0) {q[5] = col;}
                    if ((p[i] & 0x02) != 0) {q[6] = col;}
                    if ((p[i] & 0x01) != 0) {q[7] = col;}

                    q += win_width; 
                }
                q -= win_width * 16 + x;
            } else if((c>='i' && c <= 'z') || (c>='A' && c <= 'Z')){
                t[0] = *s;
                api_putstrwin(win, x, y, col,1,t);
            }
        }

        s++;
        x += 8;
    }

    api_refreshwin(win,  8, y, win_width - 8, y+15);
}



void main() {
    int win, i, j, ix, iy, fx;
    char winbuf[win_width * 237], invstr[32*6], s[12];
    char* p = winbuf;

    char invstr0[36] = {' ' , 'a','b','c','d',' ' ,'a','b','c','d', ' ',
                         'a','b','c','d',' ',  'a','b','c','d',' ',
                           'a','b','c','d', ' ',
                         0};

    char charset[18 * 8] = {
    0x00, 0x00, 0x00, 0x43, 0x5f, 0x5f, 0x5f, 0x7f,
    0x1f, 0x1f, 0x1f, 0x1f, 0x00, 0x20, 0x3f, 0x00,

    0x00, 0x0f, 0x7f, 0xff, 0xcf, 0xcf, 0xcf, 0xff,
    0xff, 0xe0, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0x00,

    0x00, 0xf0, 0xfe, 0xff, 0xf3, 0xf3, 0xf3, 0xff,
    0xff, 0x07, 0xff, 0xff, 0x03, 0x03, 0x03, 0x00,

    0x00, 0x00, 0x00, 0xc2, 0xfa, 0xfa, 0xfa, 0xfe,
    0xf8, 0xf8, 0xf8, 0xf8, 0x00, 0x04, 0xfc, 0x00,

    0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
    0x01, 0x43, 0x47, 0x4f, 0x5f, 0x7f, 0x7f, 0x00,

    0x18, 0x7e, 0xff, 0xc3, 0xc3, 0xc3, 0xc3, 0xff,
    0xff, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xff, 0x00,

    0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
    0x80, 0xc2, 0xe2, 0xf2, 0xfa, 0xfe, 0xfe, 0x00,

    0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
    0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00
    };

    win = api_openwin(winbuf, win_width, 237, -1, "invader");
    api_boxfilwin(win, 8, 29, win_width - 6, 228, 0);
    //putstr(win, winbuf, 22, 0, 7, "HIGH:00000000");

restart:
    fx = 18;
    char fly[8] = {'e', 'f', 'g', 0};
    putstr(win, winbuf, charset, 18, 11, 6, fly);

nextgroup:
    ix =  7;
    iy = 1;
    int invline = 6;
    for (i = 0; i < 3; i++) {
        for (j = 0; j < 20; j++) {
            invstr[i * 32 + j] = invstr0[j];
        }
        putstr(win, winbuf,charset, ix, iy + i, 2, invstr + i * 32);
    }


    api_refreshwin(win, 8, 29, 207, 228);

    for(;;) {
        if (api_getkey(1) == 0x1c) {
            break;
        }
    }

    api_closewin(win);

    return;
}

公海赌船网址 12

接下去我们要放大招,开发四个诙谐的星战游戏。星战是一款像素级游戏,它的形态让自家纪念早年,大约是98年,所谓电脑刚传入中中原人民共和国,系统大概DOS时,当时上电脑课最喜爱的其实有游戏可玩。代码相比长,大家分段完毕,首先在app.c中输入以下代码:

越多技术新闻,包含操作系统,编写翻译器,面试算法,机器学习,人工智能,请看管小编的民众号:

void main() {
    int win;
    char buf[150*70];
    win = api_openwin(buf, 150, 70, 255, "noterec");
    api_boxfilwin(win, 0, 50, 34, 69, 255);
    api_boxfilwin(win, 115, 50, 149, 69, 255);
    api_boxfilwin(win, 50, 30, 99, 49, 255);
    for (;;) {
        if (api_getkey(1) == 0x1c) {
            break;
        }
    }
    api_closewin(win);
    return;
}

那边写图片描述

此间写图片描述

更详细的执教和代码调节和测试演示进度,请参考录像
Linux kernel 哈克er,
从零构建自身的基业

公海赌船网址 13

那边写图片描述

struct POINT {
    int x;
    int y;
};

void main() {
    int win;
    char buf[216*237];
    struct POINT table[18] = {
    {204,129},{195,90},{172,58},{137,38},{98,34},
    {61,46},{31,73},{15,110},{15,148},{31,185},
    {61,212},{98,224},{137,220},{172,200},{195,168},
    {204,129}
    };

    win = api_openwin(buf, 216, 237, -1, "bball");
    api_boxfilwin(win, 8, 29, 207, 228, 255);
    int i = 0, j = 0, dis = 0;
    for (i = 0; i <= 14; i++) {
      for(j = i+1; j <= 15; j++) {
          dis = j - i;
          if (dis >= 8) {
             dis = 15 - dis;
          }
          if (dis != 0) {
             api_linewin(win, table[i].x, table[i].y,
                         table[j].x, table[j].y, 8-dis);
          }
      }
    }

    api_refreshwin(win, 8, 29, 207, 228);
    for (;;) {
        if (api_getkey(1) == 0x1c) {
            break;
        }
    }
    api_closewin(win);

    return;    
}

上边代码先创制二个窗体,然后把窗体的多少个部分填充成透明色,于是窗体形态变成二个有意思的非矩形,下边代码完成后,运营起来意况如下:

公海赌船网址 14

那里写图片描述

它的效应是,如果用户点击了空格,同时外星人还尚未侵犯到飞机所在的势力范围,那么大家就绘制二个从最底层向上发射的炮弹,接下去的文山会海代码是,当炮弹发射后,判断炮弹是不是击中外星人,如若打到了,被击中的外星人要从荧屏上海消防失掉,那有的逻辑实现的景色如下:

地方代码运营后效果如下:

飞机能移动后,大家需求外星人也飘飘起来,由此大家添加如下代码:

代码绘制了三排外星人和一架战斗机,在main函数中,代码:

游戏截止后,”GAME OVE路虎极光”会打字与印刷到界面上,然后一切游戏重来一次。

地点代码先把外星人向右移动,直到边缘时,iy++,那就使得外星人向下活动,与此同时idir
= -idir;
使得外星人初阶反向运动,一直到左手边缘,这种活动一贯在进展,直到外星人的y坐标做够大时,游戏截至。

那里写图片描述

waitting
函数的成效是伺机定时器放回结果,同时监察和控制键盘按键,若是用户在键盘上点击按键’j’,那么它通过调用api_getkey就能收获对应扫描码,也正是0x24,
如若用户点击按键’k’,那么相应的扫描码为0x25,在main函数里,我们抬高3个for循环,在里边我们调用waitting函数获取用户按键音讯,当用户按下’j’后,大家把飞机向左移动二个单位,然后刷新窗口,如若用户点击的是k,那么大家把飞机向右移动三个单位,然后刷新窗口,上边代码实现后,编写翻译加载到虚拟机,运行程序后,尝试按下按键’j’,大家得以窥见飞机一直向左移动,知道抵达窗口左边界结束,效果如下:

此间写图片描述

此处写图片描述

相关文章