30天自制操作系统日志第11天_第1页
30天自制操作系统日志第11天_第2页
30天自制操作系统日志第11天_第3页
30天自制操作系统日志第11天_第4页
30天自制操作系统日志第11天_第5页
已阅读5页,还剩16页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、精选优质文档-倾情为你奉上操作系统实验日志学号姓名甘昆禄专业年级班级智能1601实验日期2018.12.05实验项目第11天:制作窗口一、实验主要内容1、为制作窗口做准备我们现在看到鼠标指针头有些地方指不到(最右边和最下面),但是我们应该要能实现鼠标可以点击屏幕的任何地方,所以我们要更改一下。为什么前面不修改而要留到现在才修改呢?一是我们的鼠标用了图层来表示了,就算之前修改了,现在也还要再修改一下。二就是为我们的窗口的制作做准备(我们的窗口也要看起来能移到外面去的效果)。所以我们修改一下鼠标到边界的限制条件。-à-而我们知道原来设置边界条件的作用就是防止鼠标移到外面(实际上显存是连续

2、的,就像多条线组成面就是我们的屏幕),就会到下一行的位置。修改了边界限制也会出现这个“越界”的情况。如下图,所以我们还要对图层在边界外的进行不刷新处理。只有一个函数是能直接改变显存的,我们从根本下手,就修改sheet_refreshsub()函数在进行画面刷新之前,先判断是否已经超过了画面以外,超过画面外的部分不需要进行刷新操作(下面是关键部分的代码)/sheet.c中sheet_refreshsub()节选/判断,刷新像素的范围是否超出了画面if (vx0 < 0) vx0 = 0; if (vy0 < 0) vy0 = 0; if (vx1 > ctl->xsize

3、) vx1 = ctl->xsize; if (vy1 > ctl->ysize) vy1 = ctl->ysize; 很好,这样就可以了,以后移动窗口到画面外也可以正确实现了。诶,很多函数都有一个形参struct SHTCTL *,每次调用函数都要传实参,有点麻烦,所以作者牺牲了一些内存,给每个图层都定义一个指向图层管理的指针,这样就可以减少函数的一个形参了。1、struct SHEET中加入struct SHTCTL *ctl/在图层的结构体定义struct SHEET中,加入图层控制结构体指针struct SHTCTL *ctlstruct SHEET unsig

4、ned char *buf; int bxsize, bysize, vx0, vy0, col_inv, height, flags; struct SHTCTL *ctl; /图层控制结构体指针struct SHTCTL *ctl;2、对函数shtclt_init进行追加/追加内容: 将ctl初始化为图层控制结构体for (i = 0; i < MAX_SHEETS; i+) ctl->sheets0i.flags = 0; /* FLAG=0表示该图层未被使用 */ctl->sheets0i.ctl = ctl; /* 指针ctl指向图层控制结构体 */3、对函数she

5、et_undown进行修改/修改内容:将ctl初始化为图层控制结构体void sheet_updown(struct SHEET *sht, int height) struct SHTCTL *ctl = sht->ctl;/* 指针ctl指向图层控制结构体 */ int h, old = sht->height; /* 记录设置前图层的高度 */ /.这样我们再修改一下使用到struct SHTCTL *作形参的函数,删掉这个形参就好了,就不用送实参进去了。这样我们的窗口准备就完善了。2、制作窗口为制作窗口做了很多准备,所以制作起来并实现功能也简单了很多,我们效仿设计鼠标的显示

6、方法,也开辟了一块跟buf_mouse256一样的缓冲区*buf_win(动态内存),用来保存像素值,需要显示时,可以从里面读出并写到对应的显存里。void make_window8(unsigned char *buf, int xsize, int ysize, char *title) static char closebtn1416 = /窗口关闭按钮X的的数组 "OOOOOOOOOOOOOOO", "OQQQQQQQQQQQQQ$", "OQQQQQQQQQQQQQ$", "OQQQQQQQQQ$", &

7、quot;OQQQQQQQQQ$", "OQQQQQQQQQ$", "OQQQQQQQQQQQ$", "OQQQQQQQQQ$", "OQQQQQQQQQ$", "OQQQQQQQQQ$", "OQQQQQQQQQQQQQ$", "OQQQQQQQQQQQQQ$", "O$", "" ; int x, y; char c; /窗口的颜色填充,(应该是前景) boxfill8(buf, xsize, COL8

8、_C6C6C6, 0, 0, xsize - 1, 0 ); boxfill8(buf, xsize, COL8_FFFFFF, 1, 1, xsize - 2, 1 ); boxfill8(buf, xsize, COL8_C6C6C6, 0, 0, 0, ysize - 1); boxfill8(buf, xsize, COL8_FFFFFF, 1, 1, 1, ysize - 2); boxfill8(buf, xsize, COL8_, xsize - 2, 1, xsize - 2, ysize - 2); boxfill8(buf, xsize, COL8_, xsize - 1,

9、 0, xsize - 1, ysize - 1); boxfill8(buf, xsize, COL8_C6C6C6, 2, 2, xsize - 3, ysize - 3); boxfill8(buf, xsize, COL8_, 3, 3, xsize - 4, 20 ); boxfill8(buf, xsize, COL8_, 1, ysize - 2, xsize - 2, ysize - 2); boxfill8(buf, xsize, COL8_, 0, ysize - 1, xsize - 1, ysize - 1); putfonts8_asc(buf, xsize, 24,

10、 4, COL8_FFFFFF, title);/显示窗口的额标题 for (y = 0; y < 14; y+) for (x = 0; x < 16; x+) /这里对关闭按钮的颜色进行设定 c = closebtnyx; /关闭按钮数组中不同的字符用特定的显示颜色来显示出来 if (c = '') c = COL8_; else if (c = '$') c = COL8_; else if (c = 'Q') c = COL8_C6C6C6; else c = COL8_FFFFFF; buf(5 + y) * xsize +

11、 (xsize - 21 + x) = c;/把这个颜色的值,给VRAM缓冲区 return;这里就写好了制作窗口的函数,接下来我们只要在主函数上实现就好了:/HariMain节选 init_palette();/初始化调色板 shtctl = shtctl_init(memman, binfo->vram, binfo->scrnx, binfo->scrny); sht_back = sheet_alloc(shtctl); sht_mouse = sheet_alloc(shtctl); sht_win = sheet_alloc(shtctl);/为窗口分配内存空间

12、buf_back = (unsigned char *) memman_alloc_4k(memman, binfo->scrnx * binfo->scrny); buf_win = (unsigned char *) memman_alloc_4k(memman, 160 * 68); sheet_setbuf(sht_back, buf_back, binfo->scrnx, binfo->scrny, -1); /* 设置图层缓冲区,没有透明色 */ sheet_setbuf(sht_mouse, buf_mouse, 16, 16, 99); sheet_se

13、tbuf(sht_win, buf_win, 160, 68, -1); /* 设置图层缓冲区,没有透明色 */ init_screen8(buf_back, binfo->scrnx, binfo->scrny);/初始化屏幕界面 init_mouse_cursor8(buf_mouse, 99);/X按钮的功能键 make_window8(buf_win, 160, 68, "window");/制作窗口图层buf_win putfonts8_asc(buf_win, 160, 24, 28, COL8_, "Welcome to");/

14、在图层buf_win中显示两串字符串 putfonts8_asc(buf_win, 160, 24, 44, COL8_, " Haribote-OS!"); sheet_slide(sht_back, 0, 0);/图层上下滑动的函数,因为要让鼠标图层在窗口图层上方移动 mx = (binfo->scrnx - 16) / 2; /* 这里把鼠标放在屏幕中间的位置 */ my = (binfo->scrny - 28 - 16) / 2; sheet_slide(sht_mouse, mx, my);/设置鼠标图层的上下滑动 sheet_slide(sht_w

15、in, 80, 72);/设置窗口图层sht_win的上下滑动 sheet_updown(sht_back, 0);/设定背景图层的高度为0(在最底层) sheet_updown(sht_win, 1);/设置窗口图层的高度为1(在中间层) sheet_updown(sht_mouse, 2);/设置鼠标图层的高度为2(在最上层) sprintf(s, "(%3d, %3d)", mx, my); /在背景层打印出坐标的位置 putfonts8_asc(buf_back, binfo->scrnx, 0, 0, COL8_FFFFFF, s); sprintf(s,

16、"memory %dMB free : %dKB",/打印出内存使用情况 memtotal / (1024 * 1024), memman_total(memman) / 1024); putfonts8_asc(buf_back, binfo->scrnx, 0, 32, COL8_FFFFFF, s); sheet_refresh(sht_back, 0, 0, binfo->scrnx, 48);/刷新屏幕显示3、让窗口有个功能然后改进一下。这里作者给窗口一个计数的功能,程序自动计数。就是要让窗口里显示新定义的变量counter的值就好了。然后数字改变就刷

17、新一下窗口里数值的范围就好了。/HariMain节选 make_window8(buf_win, 160, 52, "counter");/窗口标题:counter sheet_slide(sht_back, 0, 0);/设置背景图层的上下滑动 mx = (binfo->scrnx - 16) / 2; /* 把鼠标放在屏幕中间 */ my = (binfo->scrny - 28 - 16) / 2; sheet_slide(sht_mouse, mx, my);/鼠标图层的上下滑动 sheet_slide(sht_win, 80, 72);/窗口图层的上下

18、滑动 sheet_updown(sht_back, 0); /图层的高度 sheet_updown(sht_win, 1); sheet_updown(sht_mouse, 2); sprintf(s, "(%3d, %3d)", mx, my); /输出坐标位置 putfonts8_asc(buf_back, binfo->scrnx, 0, 0, COL8_FFFFFF, s); sprintf(s, "memory %dMB free : %dKB", memtotal / (1024 * 1024), memman_total(memman

19、) / 1024); putfonts8_asc(buf_back, binfo->scrnx, 0, 32, COL8_FFFFFF, s);sheet_refresh(sht_back, 0, 0, binfo->scrnx, 48);/刷新显示界面诶,我们发现这里窗口其实改变的只有窗口里数值的内容,但是在这个范围内的图层全部都刷新了一遍,但其实我们只要刷新该图层以及它上边的图层(包括鼠标)就好了。那么又要改sheet_refreshsub()了,让它从当前图层开始刷新,所以要加一个形参表示当前图层高度h0。这样我们在循环处更改为:for (h = h0; h <= ct

20、l->top; h+)就好了,然后再一次修改有调用到sheet_refreshsub()的函数就好了。4、消除闪烁map(地图)的定义和初始化:开辟一块和VRAM大小一样的内存-map;这块内存用来表示画面上的点是那个图层的像素,所以相当于是图层的地图。我们要理解作者的用意:map和VRAM设计成大小一样的,就是要把map当做一个中间的缓冲区域(相当于VRAM的一个缓存),这样可以对VRAM的操作进行加速。/bootpack.h和sheet.c节选/定 义:map定义在图层管理结构体中struct SHTCTL unsigned char *vram, *map; int xsize,

21、ysize, top; struct SHEET *sheetsMAX_SHEETS; struct SHEET sheets0MAX_SHEETS;/初始化:在图层管理初始化函数中做相应修改struct SHTCTL *shtctl_init(struct MEMMAN *memman, unsigned char *vram, int xsize, int ysize) /.函数节选: . /开辟一个4KB的内存空间,map指向这个空间起始地址 ctl->map = (unsigned char *) memman_alloc_4k(memman, xsize * ysize); i

22、f (ctl->map = 0) /空间开辟失败,报错前先释放 memman_free_4k(memman, (int) ctl, sizeof (struct SHTCTL); goto err; ctl->vram = vram; /图层管理结构体其他变量的初始化 ctl->xsize = xsize; ctl->ysize = ysize; ctl->top = -1; /* 隐藏,表示现在没有任何图层 */ for (i = 0; i < MAX_SHEETS; i+) ctl->sheets0i.flags = 0; /* 图层标识FLAG=

23、0表示该图层没有被使用 */ ctl->sheets0i.ctl = ctl; /* 初始化图层ctl为图层管理结构体的地址 */ err: return ctl;在map中写入图层号码:我们用当前图层的地址(sht)减去第一块图层的地址(ctl->sheets0)的偏移量来表示该图层的号码sid(sheet ID)void sheet_refreshmap(struct SHTCTL *ctl, int vx0, int vy0, int vx1, int vy1, int h0) int h, bx, by, vx, vy, bx0, by0, bx1, by1; unsign

24、ed char *buf, sid, *map = ctl->map; struct SHEET *sht; if (vx0 < 0) vx0 = 0; if (vy0 < 0) vy0 = 0; if (vx1 > ctl->xsize) vx1 = ctl->xsize; if (vy1 > ctl->ysize) vy1 = ctl->ysize; for (h = h0; h <= ctl->top; h+) sht = ctl->sheetsh; /前图层的地址(sht)减去第一块图层的地址(ctl->sh

25、eets0)的偏移量 sid = sht - ctl->sheets0; /* 将进行减法运算的地址作为图层号码使用 */ buf = sht->buf; bx0 = vx0 - sht->vx0; by0 = vy0 - sht->vy0; bx1 = vx1 - sht->vx0; by1 = vy1 - sht->vy0; if (bx0 < 0) bx0 = 0; if (by0 < 0) by0 = 0; if (bx1 > sht->bxsize) bx1 = sht->bxsize; if (by1 > sh

26、t->bysize) by1 = sht->bysize; for (by = by0; by < by1; by+) vy = sht->vy0 + by; for (bx = bx0; bx < bx1; bx+) vx = sht->vx0 + bx; if (bufby * sht->bxsize + bx != sht->col_inv) /在对需要刷新的部分进行刷新时,不再是写到VRAM中,而是将该像素的sid写到map中 mapvy * ctl->xsize + vx = sid; return;对sheet_refreshs

27、ub进行改写,让它可以使用mapvoid sheet_refreshsub(struct SHTCTL *ctl, int vx0, int vy0, int vx1, int vy1, int h0, int h1) int h, bx, by, vx, vy, bx0, by0, bx1, by1; unsigned char *buf, *vram = ctl->vram, *map = ctl->map, sid; struct SHEET *sht; /* refresh刷新的范围超出了画面 */ /. for (h = h0; h <= h1; h+) /只对h0

28、到h1的图层进行跟新操作 sht = ctl->sheetsh;/当前图层的地址 buf = sht->buf; /当前图层的缓冲区内容 sid = sht - ctl->sheets0;/计算当前图层sid的值 /* 倒推出刷新的范围(不懂看前一天的内容) */ bx0 = vx0 - sht->vx0; by0 = vy0 - sht->vy0; bx1 = vx1 - sht->vx0; by1 = vy1 - sht->vy0; if (bx0 < 0) bx0 = 0; if (by0 < 0) by0 = 0; if (bx1

29、> sht->bxsize) bx1 = sht->bxsize; if (by1 > sht->bysize) by1 = sht->bysize; for (by = by0; by < by1; by+) vy = sht->vy0 + by; for (bx = bx0; bx < bx1; bx+) vx = sht->vx0 + bx; /只有当前sid和map中该像素处sid相等,才将缓存写到VRAM中 if (mapvy * ctl->xsize + vx = sid) vramvy * ctl->xsiz

30、e + vx = bufby * sht->bxsize + bx; return;二、遇到的问题及解决方法1、 我一开始真的真的不知道图层管理里面那个指针数组*sheets,到底是干什么用的,因为我一直找不到它指向结构体数组的地方。当我以为这两可能真没什么联系的时候,我看到了这句:天呐,sheets肯定指向sheets0,那到底是在哪里指向的,不应该初始化的时候就指向它了吗,为什么没有看见,看了半天,原来只有调用updown函数的时候,才让sheets指向sheets0,我一直以为top在图层分配进图层管理的时候就+了,原来是让图层开始显示,做这部初始化的时候才给sheets的用途。如

31、下:看到这才终于明白这个的指向,这样我们队不同窗口进行独立管理的时候也能更方便的找出目前最顶层减1层的是哪一个窗口了。2、 添加窗口的步骤:(1) 开辟一块动态数组给窗口,定义一个指针指向该空间首地址;(2) 制作绘制窗口的函数,即对窗口大小、像素值等的初始化;(3) 将窗口图层分配进图层管理里,定义一个指针指向对应数组的首地址;(4) 窗口图层的初始化sheet_setbuf,规定该图层的大小以及透明色;(5) 给窗口定义初始首坐标;(6) 利用updown函数定义窗口图层高度使其显示。3、 左边鼠标为什么不消失呢?因为在鼠标移动的两步中,首先对原位置进行刷新,再对新位置刷新。而原位置刷新时

32、对底层只有在bx0by1,范围刷新bx1对背景层(底层)也就是绝对坐标,不能大于320,所以在右边界时,对原位置的底层刷新只刷新了鼠标在右边框的那部分。而在刷新原位置时刷到鼠标图层,这时bx1不会到320所以可以正常刷新。再到刷新新位置范围时,情况和刷新原位置相同。这样我们就看到右边鼠标移动没问题,而左边有残影就是这个原因。把鼠标移到左边来这样底层可以正常刷新,也就可以修改到在左边框的显存了。4、 Sid怎么设置的?Sid啊,就是用图层结构体数组对应标号元素的首地址减去图层结构体数组的首地址(跟图层高度根本没有关系!这个我理解了很久的)。这里我们假设每个元素的大小为5字节(当然不可能这么小了,这样好理解),再假设结构体体数组首地址为0X00。每个sheet_alloc放一个图层信息进来占据一个结构体数组(这里sheets指针并没有指向它)。放了一个,那么第零个元素首地址就是结构体数组的首地址,这时sid=0; sheet_alloc第二个图层进来,就是第一个元素,首地址0X05,sid=0X05-0X00=5;依次类推,根据图层sheet_allo

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论