发布于 

30天自制操作系统(24)

DAY24_窗口操作

1.窗口切换(1)

  • 目标:实现切换窗口顺序得功能。
  • 先实现按下F11时,将最下面得那个窗口放到最上面。

修改bootpack.c

if (i == 256 + 0x57 && shtctl->top > 2) { /* F11 */ 
sheet_updown(shtctl->sheets[1], shtctl->top - 1);
}

2. 窗口切换(2)

我们需要按照从上到下得顺序,判断鼠标得位置落在哪个图层得范围内,并且还需要确保该位置不是透明色区域。

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(sht, shtctl->top - 1);
break;
}
}
}

3.移动窗口

当鼠标左键点击窗口时,如果点击位置位于窗口的标题栏区域,则进入“窗口移动模式”,使窗口的位置追随鼠标指针的移动,当放开鼠标左键时,退出“窗口移动模式”,返回通常模式。

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(sht, shtctl->top - 1);
if (3 <= x && x < sht->bxsize - 3 && 3 <= y && y < 21) {
mmx = mx; /*进入窗口移动模式*/
mmy = my;
}
break;
}
}
}

} else {
/*如果处于窗口移动模式*/
x = mx - mmx; /*计算鼠标的移动距离*/
y = my - mmy;
sheet_slide(sht, sht->vx0 + x, sht->vy0 + y);
mmx = mx; /*更新为移动后的坐标*/
mmy = my;
}
} else {
/*没有按下左键*/
mmx = -1; /*返回通常模式*/
}

4.用鼠标关闭窗口

5.将输入切换到应用程序窗口

按下Tab键时将键盘输入切换到当前输入窗口下面一层的窗口中,若当前窗口为最下层,则切换到最上层窗口。


if (key_win == sht_win) { /*发送至任务A */ 
if (cursor_x < 128) {
/*显示一个字符并将光标后移一位*/
s[1] = 0;
putfonts8_asc_sht(sht_win, cursor_x, 28, COL8_000000, COL8_FFFFFF, s, 1);
cursor_x += 8;
}
} else { /*发送至命令行窗口*/
fifo32_put(&key_win->task->fifo, s[0] + 256);
}
}
if (i == 256 + 0x0e) { /*退格键*/
if (key_win == sht_win) { /*发送至任务A */
if (cursor_x > 8) {
/*用空格擦除光标后将光标前移一位*/
putfonts8_asc_sht(sht_win, cursor_x, 28, COL8_000000, COL8_FFFFFF, "
", 1);
cursor_x -= 8;
}
} else { /*发送至命令行窗口*/
fifo32_put(&key_win->task->fifo, 8 + 256);
}
}
if (i == 256 + 0x1c) { /*回车键*/
if (key_win != sht_win) { /*发送至命令行窗口*/
fifo32_put(&key_win->task->fifo, 10 + 256);
}
}
if (i == 256 + 0x0f) { /* Tab键*/
cursor_c = keywin_off(key_win, sht_win, cursor_c, cursor_x);
j = key_win->height - 1;
if (j == 0) {
j = shtctl->top - 1;
}
key_win = shtctl->sheets[j];
/*到此结束*/ cursor_c = keywin_on(key_win, sht_win, cursor_c);
}

6.用鼠标切换输入窗口

目标:让操作系统可以通过简单的点击就能完成输入切换。

7.定时器API

获取定时器(alloc)
EDX=16
EAX=定时器句柄(由操作系统返回)

设置定时器的发送数据(init)
EDX=17
EBX=定时器句柄
EAX=数据

定时器时间设定(set)
EDX=18
EBX=定时器句柄
EAX=时间

释放定时器(free)
EDX=19
EBX=定时器句柄

8.取消定时器

问题:
应用程序设置了一个1秒的定时器,当定时器到达指定时间时会产生超时,并向任务发送事先设置的数据。问题是,如果这时应用程序已经结束了,定时器的数据就会被发送到命令行窗口,而命令行窗口肯定是一头雾水。