30天自制操作系统(11)
DAY11_制作窗口
1.鼠标显示问题
- 我们系统的鼠标不能够向右或向下移动到画面之外隐藏起来。为此我们修改HariMain
将if (mx > binfo->scrnx - 16) {
mx = binfo->scrnx - 16;
}
if (my > binfo->scrny - 16) {
my = binfo->scrny - 16;
}
修改为if (mx > binfo->scrnx - 1) {
mx = binfo->scrnx - 1;
}
if (my > binfo->scrny - 1) {
my = binfo->scrny - 1;
}
2.实现画面外的支持
3.shtctl的指定省略
仅仅是上下移动图层就必须指定ctl太麻烦了。修改将sheet_refresh、sheet_slide、sheet_free等函数,让它们不再指定ctl
void sheet_refresh(struct SHEET *sht, int bx0, int by0, int bx1, int by1) |
4.显示窗口
- 先准备一张图层,然后在图层缓冲区内描绘一个貌似窗口的图就可以了。
只是对graph.c的init_screen8函数稍微进行修改。void make_window8(unsigned char *buf, int xsize, int ysize, 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;
boxfill8(buf, xsize, COL8_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_848484, xsize - 2, 1, xsize - 2, ysize - 2);
boxfill8(buf, xsize, COL8_000000, xsize - 1, 0, xsize - 1, ysize - 1);
boxfill8(buf, xsize, COL8_C6C6C6, 2, 2, xsize - 3, ysize - 3);
boxfill8(buf, xsize, COL8_000084, 3, 3, xsize - 4, 20 );
boxfill8(buf, xsize, COL8_848484, 1, ysize - 2, xsize - 2, ysize - 2);
boxfill8(buf, xsize, COL8_000000, 0, ysize - 1, xsize - 1, ysize - 1);
putfonts8_asc(buf, xsize, 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;
}
buf[(5 + y) * xsize + (xsize - 21 + x)] = c;
}
}
return;
}
5.小实验
HariMain中有设置图层高度的地方,如果像下面这样,把窗口图层放在最上面,光标图层放在其次,会变成什么样呢?sheet_updown(sht_back, 0);
sheet_updown(sht_mouse, 1);
sheet_updown(sht_win, 2);
鼠标会跑到窗口图层的下面。
6.高速计数器
- 我们要做一个能够计数,并且能够把计数结果显示出来的窗口。
- 但是在刷新的时候,总是先刷新refresh范围内的背景图层,然后再刷新窗口图层,导致数字闪烁。
7.消除闪烁(1)
- 窗口图层刷新是因为窗口的内容有变化,所以要在画面上显示变化后的新内容。基本上来讲,可以认为其他图层的内容没有变化(如果其他图层的内容也变了,那么应该会随后执行该图层的刷新)。
既然如此,图层内容没有变化也进行刷新的话就太浪费了。如果只是窗口变了,那背景就不
用刷新了。假如上面有鼠标,但鼠标的图层没有变化,我们也必须要刷新。窗口的刷新,可能会覆盖鼠标的一部分显示区域。 - 在sheet_slide函数里,图层的移动有时会导致下面的图层露出,所以要从最下面开始刷新。
另一方面,在移动目标处,比新移来的图层位置还要低的图层没有什么变化,而且只是隐藏起来了,所以只要刷新移动的图层和它上面的图层就可以了。 - 但是修改代码后,鼠标放在数字区的时候,鼠标又开始闪烁。
8.消除闪烁(2)
- 闪烁现象是由于一会儿描绘一会儿消除造成的。所以说要想消除闪烁,就要在刷新窗口时避开鼠标所在的地方对VRAM进行写入处理。
方法:先开辟一块儿内存,大小和VRAM一样,这块内存用来表示画面上的点是哪个图层的像素,相当于图层的地图。
今后程序会对照map内容来向VRAM中写入,所以有时没必要从下面开始一直刷新到最上面
一层。- 在sheet_slide函数里,首先重写map,分别对应移动前后的图层,然后调用sheet_refreshsub函数。在移动前的地方,只针对上层图层移走之后而露出的下层图层进行重绘就可以了。在移动目的地处仅重绘了一张移动过去的图层。