8 强制结束并关闭窗口(harib20h)
眼看天色已晚,本打算今天就到此结束的,却突然发现了一个问题。
在运行walk.hrb和lines.hrb时,如果不按回车键结束,而是按Shift+F1强制结束程序的话,窗口就会残留在画面上。话说回来,强制结束的时候还并没有执行api_closewin,窗口会留在画面上也是意料之中的事情,不过应用程序已经强制结束,内存空间也已经被回收,而窗口却还留在上面,这可不太好。
带着这样的问题肯定没办法睡个好觉,说不定还会做噩梦,所以我们还是在今晚把它搞定吧。
强制结束harib20g后就变成这样了!
■■■■■
到底该怎么办呢?首先,我们在struct SHEET中添加一个用来存放task的成员,当应用程序结束时,查询所有的图层,如果图层的task为将要结束的应用程序任务,则关闭该图层。
这个功能不仅是在强制结束的时候起作用,在正常结束时一样有效,因此,即便程序本身忘记加上关闭窗口的代码,系统也会自动将窗口关闭,进一步说,应用程序甚至可以完全依靠系统的这个功能,而不必特地调用api_closewin来关闭窗口了。
本次的bootpack.h节选
struct SHEET {
unsigned char *buf;
int bxsize, bysize, vx0, vy0, col_inv, height, flags;
struct SHTCTL *ctl;
struct TASK *task; /*这里!*/
};
本次的sheet.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];
sht->flags = SHEET_USE; /*正在使用的标记*/
sht->height = -1; /*不显示*/
sht->task = 0; /*不使用自动关闭功能*/ /*这里!*/
return sht;
}
}
return 0; /*所有的图层都正在使用*/
}
本次的console.c节选
int *hrb_api(int edi, int esi, int ebp, int esp, int ebx, int edx, int ecx, int eax)
{
(中略)
} else if (edx == 5) {
sht = sheet_alloc(shtctl);
sht->task = task; /*这里!*/
sheet_setbuf(sht, (char *) ebx + ds_base, esi, edi, eax);
make_window8((char *) ebx + ds_base, esi, edi, (char *) ecx + ds_base, 0);
sheet_slide(sht, 100, 50);
sheet_updown(sht, 3); /*图层高度为3,在task_a之上*/
reg[7] = (int) sht;
} else if (edx == 6) {
(中略)
}
本次的console.c节选
int cmd_app(struct CONSOLE *cons, int *fat, char *cmdline)
{
(中略)
struct SHTCTL *shtctl; /*从此开始*/
struct SHEET *sht; /*到此结束*/
(中略)
if (finfo != 0) {
/*找到文件的情况*/
p = (char *) memman_alloc_4k(memman, finfo->size);
file_loadfile(finfo->clustno, finfo->size, p, fat, (char *) (ADR_DISKIMG + 0x003e00));
if (finfo->size >= 36 && strncmp(p + 4, "Hari", 4) == 0 && *p == 0x00) {
(中略)
start_app(0x1b, 1003 * 8, esp, 1004 * 8, &(task->tss.esp0));
shtctl = (struct SHTCTL *) *((int *) 0x0fe4); /*从此开始*/
for (i = 0; i < MAX_SHEETS; i++) {
sht = &(shtctl->sheets0[i]);
if (sht->flags != 0 && sht->task == task) {
/*找到被应用程序遗留的窗口*/
sheet_free(sht); /*关闭*/
}
} /*到此结束*/
memman_free_4k(memman, (int) q, segsiz);
} else {
cons_putstr0(cons, ".hrb file format error.\n");
}
memman_free_4k(memman, (int) p, finfo->size);
cons_newline(cons);
return 1;
}
/*没有找到文件的情况*/
return 0;
}
这样就大功告成了。
■■■■■
我们来试验一下,“make run”,然后运行lines.hrb,按Shift+F1强制结束。运行成功了!
看,窗口不见了吧?
下面我们再用winhelo3.hrb试试看,这个程序中我们没有调用closewin,不知道窗口能不能自动关闭呢?哦哦,关闭了,虽说这样就完全看不清窗口显示的内容了(笑),但只要像lines和walk那样加上等待键盘输入再结束的功能就好了。
winhelo3.hrb在程序结束时窗口也会被关闭哦
好了,我们已经成功实现了强制结束时也能关闭窗口的功能,这下可以睡个好觉了,大家晚安……