30天自制操作系统——自写设计

写在前面:这是我在学习了一个学期的《30天自制操作系统》之后,用了差不多一个周的时间,所写出来的一个纸娃娃操作系统,有一个小的开机动画,可以输入密码,然后有一个小的画图程序。现在把他写出来,只是为了记录这一个学期的学习经历吧,至少证明自己学有所成,所有所获。

一、实验环境

硬件环境:计算机,无特殊配置要求
软件环境:QEMU虚拟机、批处理文件、相关编译工具等
语言环境:C语言、汇编语言

二、功能介绍及运行效果截图

1、开机:
a、通过使用定时器timer3实现对时间的严格把控
在这里插入图片描述
每0.1秒向缓冲区发送一个“1”
b、通过定义图层,实现开机动画
在这里插入图片描述
每一个图层都是开机动画的一帧,都是由一个85x80的数组实现的,写在我新建立的start.c文件中,通过不同的符号表示不同的颜色,来实现一张图案的绘制,多个图案连在一起,就构成了一段开机动画,并且可以色彩变换:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
c、首先定义图层的级别,最先要展示的图层设置为0级,其余的图层设置为-1级进行隐藏。同时,将每个图层的位置设置为(0,0)左上角。
在这里插入图片描述
然后,通过一个while死循环,跳出循环的条件是我所设置的一个标志量flagtime为10,而flagtime会在每次timer3向缓冲区输入一个1的时候进行增加,并且每0.6秒增加一次,然后根据不同的flagtime的值,来将不同的图层的级别设置为1,表示进行展示,而将当前的图层设置为-1,即进行隐藏
在这里插入图片描述
就可以设置一个长达6秒的开机动画。
d、在开机动画结束后,注意要将当前图层设置为隐藏的-1级别,而将我们下面要用的密码图层设置为1展示级别
在这里插入图片描述
由于为了让我的动画更炫酷一点,我增加了一个圆形的加载形式
并且,因为如果将所有的代码放到bootpack.c文件中,代码会运行的很慢,所以我在start.c文件中实现了对所有的开机动画图层的初始化:
在这里插入图片描述
而增加的一个圆形的加载,是在这里实现的
在这里插入图片描述
可以实现一个类似于圆形加载的效果,只不过更炫酷一点
效果如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
然后,为了能够比较平滑的连接到密码输入界面,我需要考虑如何将这个开机动画回归到黑色的界面。
首先,加一个剑的移动的函数分支:
在这里插入图片描述
增加了这个函数分支之后,随着我给的时间表胡子良flagtime(在函数中为形参t)随时间增大,将会进入50的分支,进入该分支后,将会对剑图案的位置进行移动。
同时,需要对圆环的位置进行移动,增加一个分支:
在这里插入图片描述
通过这个分支,可以实现圆环的移动。
仅仅移动是不够的,我还要实现退出,在这里做一个雪花飘落的样子,就是增加如下的函数分支:
在这里插入图片描述
在这里插入图片描述
通过取余操作,可以实现类似于雪花的效果,最终结果如下所示:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
2、输入密码:
a、首先通过字符数组的形式定义一个正确的账号和密码:
在这里插入图片描述
b、再定义另外两个字符数组用来存储我们所输入的字符
在这里插入图片描述
c、在一个while死循环内,跳出循环的条件是标志量flagkaiji为1,即输入正确的账号和密码并且同时按下了回车键。
首先会对缓冲区进行判断,如果缓冲区中有值并且这个值在256到511之间,表示此时是键盘输出产生的中断,然后我们对中断进行判断,用sprintf函数将整型数据转换为两位十六进制类型,然后用我写的panduan函数进行判断是什么按键被按下:
在这里插入图片描述
在这里插入图片描述
如果按下的按键并不是break或者是shift这种功能键,就进行判断。
如果是回车键,需要通过strcmp函数判断当前输入的字符串与正确的字符串,如果相等就对标志量flagkaiji进行赋值为1,并将当前的密码图层设置为隐藏的-1级别。
在这里插入图片描述
如果不相等,需要判断有没有输完,如果只是输完了账号一栏,说明我们还需要输入密码一栏,将我们的输入位置j和h调整为密码栏的位置即可:
在这里插入图片描述
如果已经输入完全了,说明此时输入者并不知道密码是什么,或者说输入的密码和账号是错误的,这里就可以将输入栏和密码栏进行刷新,然后将输入为止重新进行调整为开头,并输出一行提示错误的字符串“passwords error!!!”,注意,还需要将我们的存储数组进行清空。
在这里插入图片描述
最终结果如下:
输入密码界面:
在这里插入图片描述
如果输入错误的界面,会出现叉号,并可以重新输入:
在这里插入图片描述在这里插入图片描述
重新输入正确的密码则会开机,同样的,在这里设计了一个比较厉害的动画:
在这里插入图片描述在这里插入图片描述在这里插入图片描述
4、程序:
这里我的程序是直接使用的节点考试时所编写的画图程序,实现功能很多,这里会直接根据我的主函数,花费大量篇幅进行讲解,每一个功能会进行标红加粗处理:

  if (flagshuangji == 0) {shuangji++;}
  if (shuangji == 10000) {
   flagshuangji = 1;
   shuangji = 0;}
  sprintf(s, "%010d", shuangji);
  sheet_refresh(sht_back, 100, 80, 320, 100);

这是我用来判断双击和函数,通过标志量flagshaungji的值来表示两次鼠标左键点击之间的时间间隔,如果时间间隔足够小,说明是双击。

  io_cli();//关闭终端
  if (fifo32_status(&fifo) == 0) { io_sti();//如果缓冲区为空则开启中断
  } else {//如果缓冲区不为空,说明有服务请求运行,或者有中断发生
   i = fifo32_get(&fifo);//取出缓冲区的值,进行判断
   io_sti();
   if (256 <= i && i <= 511) { //如果是键盘操作
    sprintf(s, "%02X", i - 256);
    putfonts8_asc_sht(sht_back, 0, 16, COL8_FFFFFF, COL8_008484, s, 2);
panduan(s);

功能1、键盘输入:可以通过键盘输入字符,通过我自己编写的panduan函数判断所按下的按键是哪一个按键,并作出相应的操作

    if (strcmp(sss, "break") != 0 && strcmp(sss, "left shift") != 0 && strcmp(sss, "return") != 0 && flagwenben == 2 && flagguanbi == 0) {
     if (strcmp(sss, "hc") == 0) {
      boxfill8(buf_bigwin, binfo->scrnx, dise, j + 3, 16 * (h), j + 3, 16 * (h + 1) - 1);
      jj[h] = j;
      h = h + 1;
      if (h >= binfo->scrny/16-1) {h = binfo->scrny/16-1;}
      j = wbj;
      boxfill8(buf_bigwin, binfo->scrnx, zise, j + 3, 16 * (h), j + 3, 16 * (h + 1) - 1);}
/*如果按下的是回车键,那么需要实现换行操作,同时记录当前光标的位置,为下面的删除键操作做铺垫*/
     else if (strcmp(sss, "tg") == 0) {
      boxfill8(buf_bigwin, binfo->scrnx, dise, j + 3, 16 * (h), j + 3, 16 * (h + 1) - 1);
      j = j - 8*zihao;
      if (j < wbj) {h = h - 1;
       if (h < 2) {
        h = 2;
        j = wbj;
       }else {
        if (jj[h] <= wbj) {j = wbj;
        }else {
         if (jj[h] <= wbj) {j = wbj;
         }else {j = jj[h];
         }}}}
      boxfill8(buf_bigwin, binfo->scrnx, dise, j + 3, 16 * h, j + 3 + 8*zihao, 16 * h + 16);
      boxfill8(buf_bigwin, binfo->scrnx, zise, j + 3, 16 * (h), j + 3, 16 * (h + 1) - 1);}
/*如果按下的是删除键,那么就对前一个字符的位置(8*16像素)进行背景色的填充处理,但需要判断的是是否需要返回上一行,如果是则取出之前在回车处理中所存储的jj数组的相应位置的值*/
     else if (strcmp(sss, "dx") == 0) {
      flagdx = !flagdx;}
/*如果按下的是大小写切换键,那么就需要将标志量设置为相反的,以便为下面的输出做准备*/
     else {
      boxfill8(buf_bigwin, binfo->scrnx, dise, j + 3, 16 * h, j + 3 + 8*zihao, 16 * h + 16);
      if (flagdx == 0) {dahuaxiao(sss);}
      putfonts8_num(buf_bigwin, binfo->scrnx, j + 3, 16 * h, zise, sss,zihao);
      j = j + 8*zihao;
      if (j >= binfo->scrnx-5) {
       jj[h] = j - 8*zihao;
       h = h + 1;
       if (jj[h] <= wbj) {j = wbj;
       }else {j = jj[h];}}
      boxfill8(buf_bigwin, binfo->scrnx, zise, j + 3, 16 * h, j + 3, 16 * h + 16 - 1);
     }}
    sheet_refresh(sht_bigwin, 0, 0, binfo->scrnx, binfo->scrny-20);} 
/*如果是正常的按键输入,那么就通过我所写的函数进行字符的打印输出,这里就是我实现的第二个功能:*/

功能2、改变字号:通过我专门编写的putfonts8_num函数,可以输出不同字号的字符,打印在相应的位置,要注意的是需要判断是否需要换行

else if (512 <= i && i <= 767) { //如果是鼠标操作
    if (mouse_decode(&mdec, i - 512) != 0) {
     sprintf(s, "[lcr %4d %4d]", mdec.x, mdec.y);//打印鼠标的位置
     if ((mdec.btn & 0x01) != 0) {s[1] = 'L';}//判断按键状态
     if ((mdec.btn & 0x02) != 0) {s[3] = 'R';}
     if ((mdec.btn & 0x04) != 0) {s[2] = 'C';}
     putfonts8_asc_sht(sht_back, 32, 16, COL8_FFFFFF, COL8_008484, s, 15);

功能3、正常窗口拖动:可以拖动正常大小(180x140像素)的窗口,并且和鼠标一样,左边和上边不能出界,下边和右边可以出界

     if ((wx + 0 <= mx && mx <= wx + 120 && wy + 3 <= my && my <= wy + 20) && flag2 == 1 && flag == 1 && (mdec.btn & 0x01) != 0 && flagguanbi == 0) {//如果鼠标在窗口任务栏位置发生了点击并移动的操作
      mx += mdec.x;
      my += mdec.y;
      wx += mdec.x;
      wy += mdec.y;}

功能4、正常窗口画细线:可以在正常大小的窗口中实现画细线的操作,并且限定了画线的范围,随着鼠标的移动和点击,实现画线操作

     else if ((wx + 5 <= mx && mx <= wx + 175 && wy + 25 <= my && my <= wy + 135) && flag2 == 1 && flag == 1 && flagxiangpi == 0 && flagcu == 0 && flagguanbi == 0 && flagquse == 0 && flagtianchong == 0) {//如果鼠标在窗口的范围内并且窗口处于正常的打开状态
      fx = mx;
      fy = my;
      mx += mdec.x;
      my += mdec.y;
      int ax = mx, ay = my;
      if ((mdec.btn & 0x01) != 0) {
       if (wx + 5 <= mx && mx <= wx + 175 && wy + 25 <= my && my <= wy + 135) {
        if ((fx > mx && my > fy) || (fx < mx && my < fy)) {
         xian(buf_window, 180, zise, min(fx, mx) - wx, min(fy, my) - wy, max(fx, mx) - wx, max(fy, my) - wy, 1);
         xian(buf_bigwin, binfo->scrnx, zise, min(fx, mx) - wx, min(fy, my) - wy, max(fx, mx) - wx, max(fy, my) - wy, 1);}
        else {
         xian(buf_window, 180, zise, min(fx, mx) - wx, min(fy, my) - wy, max(fx, mx) - wx, max(fy, my) - wy, 0);
         xian(buf_bigwin, binfo->scrnx, zise, min(fx, mx) - wx, min(fy, my) - wy, max(fx, mx) - wx, max(fy, my) - wy, 0);}}
       else {
        if (mx < wx + 5) {mx = wx + 5;}
        if (mx > wx + 175) {mx = wx + 175;}
        if (my < wy + 25) {my = wy + 25;}
        if (my > wy + 135) {my = wy + 135;}
        if ((fx > mx && my > fy) || (fx < mx && my < fy)) {
         xian(buf_window, 180, zise, min(fx, mx) - wx, min(fy, my) - wy, max(fx, mx) - wx, max(fy, my) - wy, 1);
         xian(buf_bigwin, binfo->scrnx, zise, min(fx, mx) - wx, min(fy, my) - wy, max(fx, mx) - wx, max(fy, my) - wy, 1);
        }else {
         xian(buf_window, 180, zise, min(fx, mx) - wx, min(fy, my) - wy, max(fx, mx) - wx, max(fy, my) - wy, 0);
         xian(buf_bigwin, binfo->scrnx, zise, min(fx, mx) - wx, min(fy, my) - wy, max(fx, mx) - wx, max(fy, my) - wy, 0);}
        mx = ax;
        my = ay;
       }}}
/*画线并不是一个简单地任务,因为考虑到鼠标一次的移动距离绝对超过了两个像素点,所以不能简单地将鼠标所在位置的像素点涂色,而需要一个专门的画线函数。这是一个难点,下面是我的画线函数。
void xian(unsigned char* vram, int xsize, unsigned char c, int x0, int y0, int x1, int y1, int flag) {
//我画线的思路是,竖线和横线很简单,难点是如何画出斜线,我的处理方法是将需要画斜线的两点通过一个一个阶梯状的直线实现
 float x, y;
 if (x0 == x1) {boxfill8(vram, xsize, c, x0, y0, x1, y1);}
 else if (y0 == y1) {boxfill8(vram, xsize, c, x0, y0, x1, y1);}
//首先处理的是只是横线或者竖线的情况
 else {//然后处理斜线的情况
  if (flag == 0) {//由于撇和捺的函数的算法不一样,需要分开
   if ((x1 - x0) >= (y1 - y0)) {//由于x比y长的时候,有可能一个y的像素对应了多个x的像素,所以需要分开进行讨论
    int n = (x1 - x0) / (y1 - y0);
    x = x0;
    for (y = y0; y < y1; y++) {//每一个y,进行多个x像素点的绘制
     boxfill8(vram, xsize, c, x, y, x + n, y);
     x = x + n;}
    boxfill8(vram, xsize, c, x, y1, x1, y1);
   }else {//由于y比x长的时候,有可能一个x的像素对应了多个y的像素,所以需要分开进行讨论
    int n = (y1 - y0) / (x1 - x0);
    y = y0;
    for (x = x0; x < x1; x++) {//每一个x,进行多个y像素点的绘制
     boxfill8(vram, xsize, c, x, y, x, y + n);
     y = y + n;}
    boxfill8(vram, xsize, c, x1, y, x1, y1);}
  }else {//由于捺和撇的函数的算法不一样,需要分开
   if ((x1 - x0) >= (y1 - y0)) {//由于x比y长的时候,有可能一个y的像素对应了多个x的像素,所以需要分开进行讨论
    int n = (x1 - x0) / (y1 - y0);
    x = x0;
    for (y = y1; y > y0; y--) {//每一个y,进行多个x像素点的绘制,注意是从下向上画
     boxfill8(vram, xsize, c, x, y, x + n, y);
     x = x + n;}
    boxfill8(vram, xsize, c, x, y0, x1, y0);
   }else {//由于y比x长的时候,有可能一个x的像素对应了多个y的像素,所以需要分开进行讨论
    int n = (y1 - y0) / (x1 - x0);
    y = y0;
    for (x = x1; x > x0; x--) {//每一个x,进行多个y像素点的绘制,注意是从右向左画
     boxfill8(vram, xsize, c, x, y, x, y + n);
     y = y + n;}
    boxfill8(vram, xsize, c, x0, y, x0, y1);
   }}}}

功能5、大窗口画细线:在最大化窗口中随着鼠标的移动画出细线,因为考虑到最大化窗口和正常窗口之间的信息一致,需要进行多次绘制,主要还是使用了之前的xian函数,这里不再赘述

else if ((5 <= mx && mx <= binfo->scrnx-5 && 25 <= my && my <= binfo->scrny-5) && flag2 == 0 && flag == 1 && flagxiangpi == 0 && flagcu == 0 && flagzhi != 2 && flagguanbi == 0 && flagquse == 0 && flagtianchong == 0) {
......

功能6、大窗口画粗线:在上面的函数的基础上进行的改进,通过标志量flagcu来表明是否需要画粗线,如果需要画粗线,则多次进行画线函数,通过调整画线函数的其实位置,可以得到类似于钢笔笔触的效果

。。。
xian(buf_window, 180, zise, min(fx, mx) + 1, min(fy, my) + 1, max(fx, mx) + 1, max(fy, my) + 1, 1);
xian(buf_window, 180, zise, min(fx, mx), min(fy, my), max(fx, mx), max(fy, my), 1);
xian(buf_window, 180, zise, min(fx, mx) - 1, min(fy, my) - 1, max(fx, mx) - 1, max(fy, my) - 1, 1);      
。。。   

功能7、鼠标移动:是一个比较基础的功能,这里通过规定范围使鼠标可以实现上边和左边的不超限,与下面和右边的隐藏。而上文的窗口的拖动与隐藏,也是在这里进行设置的

     else {//鼠标位置进行改变
      mx += mdec.x;
      my += mdec.y;}//鼠标位置是否超范围进行判定
     if (mx < 0) {mx = 0;}
     if (my < 0) {my = 0;}
     if (mx > binfo->scrnx - 1) {mx = binfo->scrnx - 1;}
     if (my > binfo->scrny - 1) {my = binfo->scrny - 1;}
     if (wx < 0) {wx = 0;}
     if (wy < 0) {wy = 0;}
     if (wx > binfo->scrnx - 10) {wx = binfo->scrnx - 10;}
     if (wy > binfo->scrny - 10) {wy = binfo->scrny - 10;}
     sheet_slide(sht_window, wx, wy);

功能8、画矩形:通过boxfill函数可以比较容易的实现画矩形,而这里是实现通过规定了范围的情况下,在两次鼠标点击确定的左上角与右下角之间进行矩形状颜色填充的效果,仅仅在最大化窗口中有效

     int ax1, ax2, ay1, ay2;
     if (flagzhengfang == 1) {//如果是画一个正方形,且正在找第一个点
      if ((3 <= mx && mx <= binfo->scrnx-2 && 23 <= my && my <= binfo->scrny-2) && flag2 == 0 && flag == 1 && (mdec.btn & 0x01) != 0 && flagguanbi == 0) {//如果在最大化的区域内
       ax1 = mx;
       ay1 = my;
       flagzhengfang = 2;}}
     else if (flagzhengfang == 2) {//如果是画正方形,且找第二个点
      if ((3 <= mx && mx <= binfo->scrnx-2 && 23 <= my && my <= binfo->scrny-2) && flag2 == 0 && flag == 1 && (mdec.btn & 0x01) != 0 && flagguanbi == 0) {
       ax2 = mx;
       ay2 = my;
       flagzhengfang = 0;
       boxfill8(buf_bigwin, binfo->scrnx, zise, ax1, ay1, ax2, ay2);
       yansetihuan(buf_bigwin, binfo->scrnx, COL8_008484, COL8_FFFFFF, 0 + binfo->scrnx-180, 5, 15 + binfo->scrnx-180, 20);}}//画一个矩形,并且对按键位置进行颜色替换,用来人性化的表示已经绘制完成

功能9、画圆:通过我之前所写的一个圆的判定函数,可以实现圆形的绘制

     int yx1, yx2, yy1, yy2, rr;
     if (flagyuan == 1) {//如果是圆,且在找第一个点(圆心)
      if ((3 <= mx && mx <= binfo->scrnx-2 && 23 <= my && my <= binfo->scrny-2) && flag2 == 0 && flag == 1 && (mdec.btn & 0x01) != 0 && flagguanbi == 0) {
       yx1 = mx;
       yy1 = my;
       flagyuan = 2;}}
     else if (flagyuan == 2) {//如果是圆,且在找第二个点(半径)
      if ((3 <= mx && mx <= binfo->scrnx-2 && 23 <= my && my <= binfo->scrny-2) && flag2 == 0 && flag == 1 && (mdec.btn & 0x01) != 0 && flagguanbi == 0) {
       yx2 = mx;
       yy2 = my;
       flagyuan = 0;
       rr = sqrt((yx2 - yx1) * (yx2 - yx1) + (yy2 - yy1) * (yy2 - yy1));
       yuan(buf_bigwin, binfo->scrnx, zise, yx1, yy1, rr);
       yansetihuan(buf_bigwin, binfo->scrnx, COL8_008484, COL8_FFFFFF, -20 + binfo->scrnx-180, 5, -5 + binfo->scrnx-180, 20);}}
//通过sqrt函数得到半径的大小,并且通过yuan函数实现对原型的绘制,并通过颜色替换函数实现人性化的提示绘制完成    

功能10、画直线:通过直线函数实现直线的绘制,这里的重点是直线函数

     int zx1, zx2, zy1, zy2;
     if (flagzhi == 1) {//如果是画直线且找第一个点的位置
      if ((3 <= mx && mx <= binfo->scrnx-2 && 23 <= my && my <= binfo->scrny-2) && flag2 == 0 && flag == 1 && (mdec.btn & 0x01) != 0 && flagcu == 0 && flagguanbi == 0) {//确定是在范围内
       zx1 = mx;
       zy1 = my;
       flagzhi = 2;}}
     else if (flagzhi == 2) {//如果是画直线且在找第二个点的位置
      if ((3 <= mx && mx <= binfo->scrnx-2 && 23 <= my && my <= binfo->scrny-2) && flag2 == 0 && flag == 1 && (mdec.btn & 0x01) != 0 && flagcu == 0 && flagguanbi == 0) {//确定是在范围内
       zx2 = mx;
       zy2 = my;
       flagzhi = 0;
       zhixian(buf_bigwin, binfo->scrnx, zise, zx1, zy1, zx2, zy2);
/*这里的直线函数需要进行讲解,代码如下:
void zhixian(unsigned char* vram, int xsize, unsigned char yanse, int x0, int y0, int x1, int y1) {
 int x, y, i = 0;
 if (abs(x1 - x0) <= 12) {//如果两点的横坐标之间相差不到12,画横直线
  if (x0 >= 0 && x0 < xsize && y0 >= 23 && y0 < binfo->scrny - 22 && x1 >= 0 && x1 < xsize && y1 >= 23 && y1 < binfo->scrny - 22) {
   boxfill8(vram, xsize, yanse, x0, min(y0, y1), x0, max(y0, y1));}}
 else if (abs(y1 - y0) <= 12) {//如果两点的纵坐标相差不超过12,说明是画纵直线
  if (x0 >= 0 && x0 < xsize && y0 >= 23 && y0 < binfo->scrny - 22 && x1 >= 0 && x1 < xsize && y1 >= 23 && y1 < binfo->scrny - 22) {
   boxfill8(vram, xsize, yanse, min(x0, x1), y0, max(x0, x1), y0);}}
 else {//如果两个点横纵坐标相差均超过了12,说明是画斜线
  if (x0 >= 0 && x0 < xsize && y0 >= 23 && y0 < binfo->scrny - 22 && x1 >= 0 && x1 < xsize && y1 >= 23 && y1 < binfo->scrny - 22) {
   if ((x0 > x1 && y1 > y0) || (x0 < x1 && y1 < y0)) {//如果是撇
    for (x = max(x0, x1), y = min(y0, y1), i = 0; x > min(x0, x1), y < max(y0, y1), i < 13; x -= ((max(x0, x1) - min(x0, x1)) / 13), y += ((max(y0, y1) - min(y0, y1)) / 13), i++) {//一样,通过阶梯状实现,不过要分多次阶梯,这里是为了让斜线更好看一些
     xian(vram, xsize, yanse, x - (max(x0, x1) - min(x0, x1)) / 13, y, x, y + (max(y0, y1) - min(y0, y1)) / 13, 1);}
    xian(vram, xsize, yanse, min(x0, x1), y, x, max(y0, y1), 1);}
   else {//如果是捺
    for (x = min(x0, x1), y = min(y0, y1), i = 0; x < max(x0, x1), y < max(y0, y1), i < 13; x += ((max(x0, x1) - min(x0, x1)) / 13), y += ((max(y0, y1) - min(y0, y1)) / 13), i++) {//一样,通过阶梯状实现,不过要分多次阶梯,这里是为了让斜线更好看一些

     xian(vram, xsize, yanse, x, y, (max(x0, x1) - min(x0, x1)) / 13 + x, (max(y0, y1) - min(y0, y1)) / 13 + y, 0);}
    xian(vram, xsize, yanse, x, y, max(x0, x1), max(y0, y1), 0);}}}}
*/
       yansetihuan(buf_bigwin, binfo->scrnx, COL8_008484, COL8_FFFFFF, -40 + binfo->scrnx-180, 5, -25 + binfo->scrnx-180, 20);}}
//小窗口的直线绘制类似,这里不再赘述
      if ((3 <= mx && mx <= binfo->scrnx-2 && 23 <= my && my <= binfo->scrny-2) && flag2 == 0 && flag == 1 && (mdec.btn & 0x01) != 0 && flagcu == 1 && flagguanbi == 0) {
。。。

功能11、文本输入:可以通过按钮控制在图形绘制区域的内部的任意位置实现文本的输入,具体实现是在下面的键盘输入部分实现,这里只是实现了控制

     if (flagwenben == 1) {
      if ((3 <= mx && mx <= binfo->scrnx-2 && 23 <= my && my <= binfo->scrny-2) && flag2 == 0 && flag == 1 && (mdec.btn & 0x01) != 0 && flagguanbi == 0) {//判断是否在区域内的点击,并对书写位置进行更新
       wbj = mx;
       wbh = my;
       j = wbj;
       h = wbh / 16;
       flagwenben = 2;}}

功能12、小窗口取色器:通过记录点击位置的颜色,对颜色控制进行更新

     if (flagquse == 1) {
      if ((3 <= mx && mx <= 178 && 23 <= my && my <= 138) && flag2 == 1 && flag == 1 && (mdec.btn & 0x01) != 0 && flagguanbi == 0) {
       int pzise = zise;
       zise = buf_window[my * 180 + mx];
       yansetihuan(buf_window, 180, pzise, zise, wx + 101, wy + 7, wx + 114, wy + 18);
       yansetihuan(buf_bigwin, binfo->scrnx, pzise, zise, binfo->scrnx-180 + 101, 7, binfo->scrnx-180 + 114, 18);
       flagquse = 0;
       yansetihuan(buf_window, 180, COL8_008484, COL8_FFFFFF, wx + 81, wy + 7, wx + 94, wy + 18);
       yansetihuan(buf_bigwin, binfo->scrnx, COL8_008484, COL8_FFFFFF, binfo->scrnx-180 + 81, 7, binfo->scrnx-180 + 94, 18);}}//这里多次使用了颜色替换函数仅仅是为了窗口的人性化

功能13、大窗口取色器:本质上与上面的小窗口一致,这里不再赘述

      if ((3 <= mx && mx <= binfo->scrnx-2 && 23 <= my && my <= binfo->scrny-2) && flag2 == 0 && flag == 1 && (mdec.btn & 0x01) != 0 && flagguanbi == 0)

功能14、小窗口颜色填充:这里主要是通过调用我所编写的递归函数实现对像素点的递归式赋值,终止条件是遇到不同颜色的像素点,但问题是无法对背景赋值(可能是递归层数过多)

     if (flagtianchong == 1) {
      if ((3 <= mx && mx <= 178 && 23 <= my && my <= 138) && flag2 == 1 && flag == 1 && (mdec.btn & 0x01) != 0 && flagguanbi == 0) {
       int pzise = buf_bigwin[my * binfo->scrnx + mx];
       tianchong(buf_window, 180, 140, zise, pzise, mx - wx, my - wy, 0);
       tianchong(buf_bigwin, binfo->scrnx, binfo->scrny, zise, pzise, mx, my, 0);
       flagtianchong = 0;
       yansetihuan(buf_window, 180, COL8_008484, COL8_FFFFFF, wx + 61, wy + 7, wx + 74, wy + 18);
       yansetihuan(buf_bigwin, binfo->scrnx, COL8_008484, COL8_FFFFFF, binfo->scrnx-180 + 61, 7, binfo->scrnx-180 + 74, 18);}}
/*这里详细讲解一下我的tianchogn函数,代码如下:*/
void tianchong(unsigned char* vram, int xsize, int ysize, unsigned char yanse, unsigned char jiuyanse, int x0, int y0, int i) {
 if (x0 > 3 && x0 < xsize - 2 && y0>23 && y0 < ysize - 3) {//区域限定
  if (vram[y0 * xsize + x0] == jiuyanse) {
   vram[y0 * xsize + x0] = yanse;
   if (i == 0) {//如果,是第一个最开始的像素点,需要向四方向延伸
    tianchong(vram, xsize, ysize, yanse, jiuyanse, x0 - 1, y0, 1);
    tianchong(vram, xsize, ysize, yanse, jiuyanse, x0 + 1, y0, 2);
    tianchong(vram, xsize, ysize, yanse, jiuyanse, x0, y0 - 1, 3);
    tianchong(vram, xsize, ysize, yanse, jiuyanse, x0, y0 + 1, 4);
   }else if (i == 1) {//如果是左像素点,则不向右延伸
    tianchong(vram, xsize, ysize, yanse, jiuyanse, x0 - 1, y0, 1);
    tianchong(vram, xsize, ysize, yanse, jiuyanse, x0, y0 - 1, 3);
    tianchong(vram, xsize, ysize, yanse, jiuyanse, x0, y0 + 1, 4);
   }else if (i == 2) {//如果是右像素点,则不向左延伸
    tianchong(vram, xsize, ysize, yanse, jiuyanse, x0 + 1, y0, 2);
    tianchong(vram, xsize, ysize, yanse, jiuyanse, x0, y0 - 1, 3);
    tianchong(vram, xsize, ysize, yanse, jiuyanse, x0, y0 + 1, 4);
   }else if (i == 3) {//如果是上像素点,则不向下延伸
    tianchong(vram, xsize, ysize, yanse, jiuyanse, x0, y0 - 1, 3);
    tianchong(vram, xsize, ysize, yanse, jiuyanse, x0 - 1, y0, 1);
    tianchong(vram, xsize, ysize, yanse, jiuyanse, x0 + 1, y0, 2);
   }else if (i == 4) {//如果是下像素点,则不向上延伸
    tianchong(vram, xsize, ysize, yanse, jiuyanse, x0, y0 + 1, 4);
    tianchong(vram, xsize, ysize, yanse, jiuyanse, x0 - 1, y0, 1);
    tianchong(vram, xsize, ysize, yanse, jiuyanse, x0 + 1, y0, 2);
   }}}}
/*通过五个分支的递归,实现指定区域内部的颜色填充,递归好用,但不要滥用*/

功能14、大窗口颜色填充:与上文原理相同,这里不再赘述

      if ((3 <= mx && mx <= binfo->scrnx-2 && 23 <= my && my <= binfo->scrny-2) && flag2 == 0 && flag == 1 && (mdec.btn & 0x01) != 0 && flagguanbi == 0) {。。。

功能15&16、小窗口大橡皮&小橡皮:这里是实现了小窗口里大型橡皮的擦书,通过记录鼠标移动过的位置实现16x16区域性的擦除功能。由于window系统中的画图程序一样会出现断续的情况,所以并没有对断续进行处理,如果需要,实际上也可以通过对上文的xian函数进行修改得到

     if ((wx + 3 <= mx && mx <= wx + 160 && wy + 23 <= my && my <= wy + 140 - 3 - 16) && flag2 == 1 && flag == 1 && flagxiangpi == 1 && flagguanbi == 0) {//确定区域
      if ((mdec.btn & 0x01) != 0) {
       if (flagdaxiao == 0) {//进行大小窗口信息同步的擦除处理
        boxfill8(buf_window, 180, COL8_C6C6C6, mx - wx, my - wy, mx + 16 - wx, my + 16 - wy);
        boxfill8(buf_bigwin, binfo->scrnx, COL8_C6C6C6, mx - wx, my - wy, mx + 16 - wx, my + 16 - wy);}
       else {
        boxfill8(buf_window, 180, COL8_C6C6C6, mx - wx, my - wy, mx + 8 - wx, my + 8 - wy);
        boxfill8(buf_bigwin, binfo->scrnx, COL8_C6C6C6, mx - wx, my - wy, mx + 8 - wx, my + 8 - wy);}}}

功能17&18、大窗口大橡皮&小橡皮:与上文原理相同,不再赘述

     else if ((3 <= mx && mx <= binfo->scrnx-2 - 16 && 23 <= my && my <= binfo->scrny-2 - 16) && flag2 == 0 && flag == 1 && flagxiangpi == 1 && flagguanbi == 0) {。。。

功能19、小窗口关闭:通过对图层的调整实现窗口的关闭

     else if ((wx + 160 <= mx && mx <= wx + 175 && wy + 3 <= my && my <= wy + 20) && flag2 == 1 && flag == 1 && flagguanbi == 0) {//在区域内
      if ((mdec.btn & 0x01) != 0) {//点击后,对现有的图层进行刷新
       sheet_updown(sht_window, -1);
       sheet_updown(sht_xiaoxiangpi, -1);
       sheet_updown(sht_xiangpi, -1);
       sheet_updown(sht_mouse, 2);
       flagguanbi = 1;}}

功能20、大窗口关闭:与上文基本相同,这里不再赘述

else if ((160 + binfo->scrnx-180 <= mx && mx <= 175 + binfo->scrnx-180&& 3 <= my && my <= 20) && flag2 == 0 && flag == 1 && flagguanbi == 0){。。。

功能21、窗口打开:通过双击桌面上的图标可以实现窗口的打开,这里限制了只能够打开一次窗口,后续的点击是无效的,并且需要快速双击

     else if ((10 <= mx && mx <= 40 && binfo->scrny - 80 <= my && my <= binfo->scrny - 40) && flagguanbi == 1) {//区域判断
      if ((mdec.btn & 0x01) != 0 && flagshuangji == 1) {//双击判断
       flagshuangji = 0;}
      else if ((mdec.btn & 0x01) != 0 && flagshuangji == 0 && shuangji <= 1000) {//如果确实需要打开,对所有的参数进行初始化
       flagshuangji = 1;
       flag = 1;
       flag2 = 1;
       flagdx = 0;
       flagxiangpi = 0;
       flagdaxiao = 0;
       flagcu = 0;
       flagzhengfang = 0;
       flagyuan = 0;
       flagzhi = 0;
       flagwenben = 0;
       flagguanbi = 0;
       wx = 0;
       wy = 0;
       window(buf_window, 180, 140);
       bigwindow(buf_bigwin, binfo->scrnx, binfo->scrny-20, 0);
       sheet_slide(sht_window, wx, wy);
       sheet_updown(sht_window, 1);
       sheet_updown(sht_bigwin, -1);
       shuangji = 0;}
      else if ((mdec.btn & 0x01) != 0 && flagshuangji == 0 && shuangji > 1000) {
       flagshuangji = 1;
       shuangji = 0;}}

功能22、正常窗口最大化:基本上是对按钮区域点击的反应及图层的调整

     else if ((wx + 140 <= mx && mx <= wx + 155 && wy + 3 <= my && my <= wy + 20) && flag2 == 1 && flag == 1 && flagguanbi == 0) {
      if ((mdec.btn & 0x01) != 0) {
       sheet_updown(sht_window, -1);
       sheet_updown(sht_bigwin, 1);
       flag2 = 0;}}

功能23、大窗口变正常窗口:与上文原理类似,不再赘述

else if ((140 + binfo->scrnx-180 <= mx && mx <= 155 + binfo->scrnx-180&& 3 <= my && my <= 20) && flag2 == 0 && flag == 1 && flagguanbi == 0) {
      if ((mdec.btn & 0x01) != 0) {
       sheet_updown(sht_window, 1);
       sheet_updown(sht_bigwin, -1);
       flag2 = 1;}}

功能24、小窗口颜色选择:通过对按钮区域的点击判定,可以对颜色进行修改,修改范围是16种基本颜色,并且小窗口的颜色选择可以同步映射到大窗口的颜色选择

else if ((wx + 100 <= mx && mx <= wx + 115 && wy + 3 <= my && my <= wy + 20) && flag2 == 1 && flag == 1 && flagguanbi == 0) {//点击区域判定
      if ((mdec.btn & 0x01) != 0) {//如果点击,首先调整图层
       sheet_updown(sht_mouse, 2);
       sheet_updown(sht_xiangpi, -1);
       sheet_updown(sht_xiaoxiangpi, -1);
       flagxiangpi = 0;
       int pzise = zise;
       zise += 1;//对颜色进行调整
       if (zise > 15) {zise = 0;}//防止颜色超出范围
       yansetihuan(buf_window, 180, pzise, zise, wx + 101, wy + 7, wx + 114, wy + 18);//人性化显示颜色
       yansetihuan(buf_bigwin, binfo->scrnx, pzise, zise, binfo->scrnx-180 + 101, 7, binfo->scrnx-180 + 114, 18);}}

功能25、大窗口颜色选择:与上文原理相同,这里不再赘述

else if ((100 + binfo->scrnx-180 <= mx && mx <= 115 + binfo->scrnx-180&& 3 <= my && my <= 20) && flag2 == 0 && flag == 1 && flagguanbi == 0){。。。

功能26、大窗口清屏:一键清屏并初始化所有变量

else if ((20 + binfo->scrnx-180 <= mx && mx <= 35 + binfo->scrnx-180 && 3 <= my && my <= 20) && flag2 == 0 && flag == 1 && flagguanbi == 0) {
      if ((mdec.btn & 0x01) != 0) {
       bigwindow(buf_bigwin, binfo->scrnx, binfo->scrny - 20, 0);       window(buf_window, 180, 140);
       yansetihuan(buf_window, 180, COL8_FFFFFF, zise, wx + 101, wy + 7, wx + 114, wy + 18);
       yansetihuan(buf_bigwin, binfo->scrnx, COL8_FFFFFF, zise, binfo->scrnx-180 + 101, 7, binfo->scrnx-180 + 114, 18);
       if (flagcu == 0) {yansetihuan(buf_bigwin, binfo->scrnx, COL8_008484,COL8_FFFFFF,40+binfo->scrnx-180,5, 55 + binfo->scrnx-180, 20);}
       else if(flagcu == 1){yansetihuan(buf_bigwin,binfo->scrnx,COL8_FFFFFF,COL8_008484,40+binfo->scrnx-180,5,55 + binfo->scrnx-180, 20);}
       if (flagzhengfang == 1){yansetihuan(buf_bigwin,binfo->scrnx,COL8_FFFFFF,COL8_008484,0+binfo->scrnx-180,5,15+binfo->scrnx-180,20); }
       else if (flagzhengfang == 0) {yansetihuan(buf_bigwin, binfo->scrnx, COL8_008484, COL8_FFFFFF, 0 + binfo->scrnx-180, 5, 15 + binfo->scrnx-180, 20);}
       if (flagyuan == 1) {yansetihuan(buf_bigwin, binfo->scrnx, COL8_FFFFFF,COL8_008484,-20+binfo->scrnx-180,5,-5+binfo->scrnx-180, 20);}
       else if (flagyuan == 0) {yansetihuan(buf_bigwin, binfo->scrnx, COL8_008484, COL8_FFFFFF, -20 + binfo->scrnx-180, 5, -5 + binfo->scrnx-180, 20);}
       if(flagzhi == 1){yansetihuan(buf_bigwin,binfo->scrnx,COL8_FFFFFF, COL8_008484,-40 + binfo->scrnx-180,5,-25+ binfo->scrnx-180, 20);}
       else if (flagzhi == 0) {yansetihuan(buf_bigwin, binfo->scrnx, COL8_008484, COL8_FFFFFF, -40 + binfo->scrnx-180, 5, -25 + binfo->scrnx-180, 20);}}}

功能27、大窗口字号改变:通过鼠标的左键或者右键点击指定区域,实现对输入文本的字号进行调整,这里设置了四个档位

     else if ((-80 + binfo->scrnx - 180 <= mx && mx <= -65 + binfo->scrnx - 180 && 3 <= my && my <= 20)&&flag2 == 0&&flag == 1 && flagguanbi == 0){
      if ((mdec.btn & 0x01) != 0) {//如果是左键点击
       zihao--;//字号缩小
       if (zihao <= 1) {zihao = 1;}}//判定字号范围
      else if ((mdec.btn & 0x02) != 0) {//如果是右键点击
       zihao++;//字号变大
       if (zihao >= 4) {zihao = 4;}}}//规定字号范围

功能28、小窗口最小化:通过指定范围的鼠标点击,实现正常窗口的最小化处理,实际上就是图层的调整

     else if ((wx + 120 <= mx && mx <= wx + 135 && wy + 3 <= my && my <= wy + 20) && flag2 == 1 && flag == 1 && flagguanbi == 0) {
      if ((mdec.btn & 0x01) != 0) {
       sheet_updown(sht_window, -1);//隐藏当前正常窗口
       sheet_updown(sht_miniwin, 1);//显示最小化窗口
       flag = 0;}}

功能29、大窗口最小化:与上文原理相同,这里不再赘述

else if ((120 + binfo->scrnx-180 <= mx && mx <= 135 + binfo->scrnx-180&& 3 <= my && my <= 20) && flag2 == 0 && flag == 1 && flagguanbi == 0){。。。

功能30、小窗口最小化恢复:与上文的原理相反,图层的反向设置

     else if ((65 <= mx && mx <= 125 && binfo->scrny-23 <= my && my <= binfo->scrny-3) && flag2 == 1 && flag == 0 && flagguanbi == 0) {
      if ((mdec.btn & 0x01) != 0) {
       sheet_updown(sht_window, 1);//显示正常窗口
       sheet_updown(sht_miniwin, -1);//隐藏最小化窗口
       flag = 1;}}

功能31、大窗口最小化恢复:与上文原理相同,这里不再赘述

else if ((65 <= mx && mx <= 125 && binfo->scrny-23 <= my && my <= binfo->scrny-3) && flag2 == 0 && flag == 0 && flagguanbi == 0){。。。

功能32、定时器时钟:通过定时器来实现一个时钟,时钟初始为23:59:40

   else if (i == 3) { //如果定时器向缓冲区输入的是3
    timeer++;//时间进行增加
    if (timeer == 24 * 60 * 60) {timeer = 0;}//时间不能超过24:00:00
    miao = timeer % 60;//改变显示的秒针部分
    fen = timeer / 60 % 60;//改变显示的分针部分
    shi = timeer / (60 * 60) % 24;//改变显示的时针部分
    sprintf(mi, "%d", miao);//将整型数据转换为字符串类型来输出
    sprintf(fe, "%d", fen);
    sprintf(sh, "%d", shi);
    putfonts8_asc_sht(sht_back, binfo->scrnx - 20, 8, COL8_FFFFFF, COL8_008484, mi, 2);
    putfonts8_asc_sht(sht_back, binfo->scrnx - 20 - 10, 8, COL8_FFFFFF, COL8_008484, ":", 1);
    putfonts8_asc_sht(sht_back, binfo->scrnx - 20 - 10 - 20, 8, COL8_FFFFFF, COL8_008484, fe, 2);
    putfonts8_asc_sht(sht_back, binfo->scrnx - 20 - 10 - 20 - 10, 8, COL8_FFFFFF, COL8_008484, ":", 1);
    putfonts8_asc_sht(sht_back, binfo->scrnx - 20 - 10 - 20 - 10 - 20, 8, COL8_FFFFFF, COL8_008484, sh, 2);//输出
    timer_init(timer2, &fifo, 3); //定时器初始化,继续进行
timer_settime(timer2, 100);}}}

功能33、图形化时钟:这是我增加的一个,没有设立新的图层,直接在sht_back图层的基础上实现了一个方形的图形化的时钟,时针、分针、秒针都可以运动,并且互不干扰,这是通过一个大的switch-case实现的,这里只展示针对秒针所实现的switch-case
ii = miao % 5;

	switch (miao / 5) {
		case 24://由于24点与0点,12点的指针是一致的,所以一起讨论
		case 12:
		case 0: {zhixian2(vram, x, COL8_FF0000, x - 100 +5*ii, y / 2 -50 +5, x - 100, y / 2);	break;}//通过我之前所写的zhixian函数来实现指针的绘制。下文同,不再赘述。
		case 13:
		case 1: {zhixian2(vram, x, COL8_FF0000, x - 100, y / 2, x - 100 + 50 / 2 + 5 * ii, y / 2 - 50 + 5 * ii);	break;}
		case 14:
		case 2: {zhixian2(vram, x, COL8_FF0000, x - 100, y / 2, x - 100 + 50 + 2, y / 2 - 50 / 2 + 2 + 5 * ii);	break;}
		case 15:
		case 3: {zhixian2(vram, x, COL8_FF0000, x - 100, y / 2, x - 100 + 50, y / 2 + 2 + 5 * ii);	break;}
		case 16:
		case 4: {zhixian2(vram, x, COL8_FF0000, x - 100, y / 2, x - 100 + 50 + 2-5*ii, y / 2 + 50 / 2 + 2+5*ii);	break;}
		case 17:
		case 5: {zhixian2(vram, x, COL8_FF0000, x - 100, y / 2, x - 100 + 50 / 2 + 2-5*ii, y / 2 + 50 + 2);	break;}
		case 18:
		case 6: {zhixian2(vram, x, COL8_FF0000, x - 100, y / 2, x - 100 + 2-5*ii, y / 2 + 50);	break;}
		case 19:
		case 7: {zhixian2(vram, x, COL8_FF0000, x - 100, y / 2, x - 100 - 50 / 2 + 2-5*ii, y / 2 + 50 -5-5*ii);	break;}
		case 20:
		case 8: {zhixian2(vram, x, COL8_FF0000, x - 100, y / 2, x - 100 - 50 + 2, y / 2 + 50 / 2 + 2-5*ii);	break;}
		case 21:
		case 9: {zhixian2(vram, x, COL8_FF0000, x - 100, y / 2, x - 100 - 45, y / 2 + 2-5*ii);	break;}
		case 22:
		case 10: {zhixian2(vram, x, COL8_FF0000, x - 100, y / 2, x - 100 - 50 + 2+5*ii, y / 2 - 50 / 2 + 2-5*ii);	break;}
		case 23:
		case 11: {	zhixian2(vram, x, COL8_FF0000, x - 100, y / 2, x - 100 - 50 / 2 + 2+5*ii, y / 2 - 50 + 2);	break;}}

最终,可以实现一个图形化的方形时钟,但是,由于我的zhixian函数对于小范围内的直线绘制并不是很适合,所以指针的形状比较鬼畜,不是标准的直线。
功能34、动态桌面:这个本来是我在实现了所有的程序功能和时钟功能之后,闲来无事写着玩的,没想到真的实现了。。。

void dongtaibeijing(char* vram, int x, int y, int t) {/*我的背景*/
	boxfill8(vram, x, COL8_848484, 0, 0, x - 1, y - y / 3 * 2 + 10);//灰色背景
	int x0, y0;
	for (y0 = 0; y0 < y - 25; y0++) {
		for (x0 = 0; x0 < x; x0++) {
			if ((x0>=x - 100 - 60 && x0<=x - 100 + 60) && (y0>=y / 2 - 60 && y0<=y / 2 + 60+20)) {
			}else {//如果不是钟表的区域,那么就在其余其余画出海浪的样子
				if (y0 > 9 * sin(0.05 * x0 + t) + y - y / 3 * 2) {
					vram[y0 * x + x0] = COL8_000084;}
				if (y0 > 12 * sin(0.02 * x0 - t) + y - y / 5 * 3) {
					vram[y0 * x + x0] = COL8_0000FF;}
				if (y0 > 7 * sin(0.08 * x0 + t) + y - y / 5 * 2) {
					vram[y0 * x + x0] = COL8_848484;}
				if (y0 > 15 * sin(0.03 * x0 - t) + y - y / 5 * 1) {
					vram[y0 * x + x0] = COL8_008484;}}}}
	//程序图标,防止程序图标被盖住,也可以用上面的if判断语句来实现
	char hua[3] = { 'P','&','W' };
	boxfill8(vram, x, COL8_FFFFFF, 10, y - 80, 40, y - 40);
	yuan(vram, x, COL8_0000FF, 15, y - 80 + 5, 3);
	yuan(vram, x, COL8_00FF00, 30, y - 80 + 5, 5);
	yuan(vram, x, COL8_FF0000, 20, y - 80 + 15, 10);
	yuan(vram, x, COL8_00FFFF, 25, y - 80 + 10, 7);
	yuan(vram, x, COL8_FFFF00, 33, y - 80 + 15, 7);
	putfonts8_asc(vram, x, 15, y - 80 + 25, COL8_000000, hua);
	putfonts8_asc(vram, x, 15 + 1, y - 80 + 25 + 1, COL8_848484, hua);}

最终,我实现了以下的32个功能,有大有小,有难有易,但都不轻松:
功能1、键盘输入
功能2、改变字号
功能3、正常窗口拖动
功能4、正常窗口画细线
功能5、大窗口画细线
功能6、大窗口画粗线
功能7、鼠标移动
功能8、画矩形
功能9、画圆
功能10、画直线
功能11、文本输入
功能12、小窗口取色器
功能13、大窗口取色器
功能14、小窗口颜色填充
功能14、大窗口颜色填充
功能15&16、小窗口大橡皮&小橡皮
功能17&18、大窗口大橡皮&小橡皮
功能19、小窗口关闭
功能20、大窗口关闭
功能21、窗口打开
功能22、正常窗口最大化
功能23、大窗口变正常窗口
功能24、小窗口颜色选择
功能25、大窗口颜色选择
功能26、大窗口清屏
功能27、大窗口字号改变
功能28、小窗口最小化
功能29、大窗口最小化
功能30、小窗口最小化恢复
功能31、大窗口最小化恢复
功能32、定时器时钟
功能33、图形化时钟
功能34、动态桌面
而演示动画我以视频的形式进行展示,这里展示视频中的部分截图:
在这里插入图片描述在这里插入图片描述
在这里插入图片描述在这里插入图片描述

三、遇到的问题及解决方法

问题1:递归问题:我的那个填充函数,之前一直采用的是四方向同时递归的方式,结果却发现总是要么纵向无法实现完全填充,要么是横向无法实现完全填充。

解决方法:经过测试发现,如果是四方向同时递归的方法,由于我们并没有办法实现四个方向的并行,而且没有办法记录之前的涂层的每个像素点的状态,所以会发生左右先行,导致部分上层的像素点被提前涂上了颜色,而在后续进行上下的递归的时候,被误认为已经到达了边界而停止递归。所以,需要将每个方向中的反方向取消递归。

问题2:递归问题:无法实现背景的填充。

解决方法:有可能是因为需要的递归层数太多,所以无法实现整个背景的递归,现在也无法进行解决,或许后续可以通过精简代码的方式实现?但说真的,我感觉可能性不大。从我现在所学的知识中,我对于递归的改进方式是修改为for循环以及栈的形式,而不管是哪一种形式,似乎都无法避免的出现层数太多的问题,通过递归的方式,似乎无法从根本上解决。
而如果不适用递归的方式,或许还有方法。比方说,从我们所点击的位置,划分为一个二维坐标系,划分为四个区域,通过四个for循环,逐步查找每一个像素点的颜色,这样可以实现不通过递归的颜色填充。但是这样的话算法的长度将会进一步的增加,是福是祸,我现在还不好说,或许可以在后续的时间中实现更新与优化。

问题3:代码长度问题:当到最后的时候我发现,如果代码的长度太长(目前我已经达到了一千三百多行的代码),或者代码的逻辑太过复杂,可能会导致最后产生的汇编代码的长度太长,无法完全装进BIOS,导致OS在启动的时候会有很长的一段黑屏的时间。

解决方法:可以通过精简代码实现这段黑屏时间的缩短,或者通过将部分代码从主函数代码bootpack.c文件中转移至其他的文件比方说window.c文件,也可以实现一定程度上的减轻。但很不幸的是,这个问题也导致了我的代码长度基本上到达了极限,虽然可以运行,但会有将近一分钟的黑屏时间,我可能无法在进行功能上的增加,只能进行优化了。

P.S.:目前,我已经将我的黑屏时间问题基本上解决了,采用的是将原本的图层初始化函数和图层内存分配函数全都放到非主程序的.c文件中去,这样我运行程序的时候基本上就不会遇到黑屏问题。

问题4:分辨率问题:前文已经提到了,我的程序针对所有的分辨率是普适的,只需要在nas文件中修改参数,就可以实现不同分辨率的操作系统。这是因为我的所有有关于尺寸的参数都是相对参数和相对距离,这是一个好习惯,希望我能够保持。但是,如果我的分辨率太大,我的电脑将不支持,程序完全无法运行,直接黑屏,无法启动qemu。

解决方法:无法解决,建议选择小的分辨率。

四、结语
说实话,这门课我学到了很多。
首先呢,是从这门课开始,我开始写CSDN博客的。通过将每一天的代码过程与心得体会进行记录,我不得不每天对我所学的知识进行梳理,而正是在这一次一次的梳理的过程中,我逐渐学到了其中的精髓,这也可能是我之所以能够这么快写出这个综合设计的原因之一吧。从之前的小白看客,到现在有将近200粉丝和1万3千多访问量的小小小博主,我也逐渐变强了呢。
然后呢,这门课说到底,是一门实验课,而我这个人,对于如何使用自己所学到的知识,还是比较擅长的,至少比考试擅长。所以,每一次,我基本上都能写出一些稀奇古怪的东西,像第三天我写出来的动态的五星红旗,以及蹦蹦跳跳的“末影人”,无不说明了这一点,我的想法就是,既然别人能够写出来的东西,不管人家是不是大牛,不管人家用了多久,我一样可以写出来啊。
最后呢,是这门课真正的教给了我什么东西,这门课让我能够有机会使用我在操作系统理论课上所学到的东西。比方说,在第十天我们学习的是如何对内存进行分配并进行优化,这实际上就是我们操作系统理论课上所学习的内存分配方法中的单区间分配方法的最佳适应方法,我在学这一天的时候很激动,真的很激动,因为我真的发现,我能看懂作者想干什么,作者的思想是什么样的,与我的思想频率同步了,这是一种很奇妙的体验。当然,那一天我的创新就是完成作者可能会继续的事情,我将最佳适应方法修改为了首次适应方法,很小的一个修改,但是我知道,如果没有真正的看懂这一天讲的是什么,你,写不出来。
最后的最后,感谢老师这一个学期来的教导,教会了我很多的东西,在我遇到困难与问题的时候也很细心的给予我帮助。

写在后面:如果,你真的看到了这里,谢谢,谢谢你有这样的耐心看完了这将近三万字的博客,也希望我的这篇文章对你能够有所帮助。本人说到底,只不过是一个普通的大三学生,我不是天才,甚至称不上优秀,所以,很荣幸你能看完这篇文章。
所谓代码,我个人的理解,不仅仅是单词的组合,而是代表着代码作者的逻辑,算法,解决问题的方式,我曾跟我的父母说过,初级程序员,学的是代码,写的是符号;中级程序员,学的是架构,写的是算法;高级程序员,学的是思想,写的是理论;而顶级程序员,学的是哲学,写的是艺术。代码写到最后,是真的能够体现作者的思想,行为,方式的。

发布了205 篇原创文章 · 获赞 110 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_40851744/article/details/103663701
今日推荐