8 强制结束并关闭窗口(harib20h)

眼看天色已晚,本打算今天就到此结束的,却突然发现了一个问题。

在运行walk.hrb和lines.hrb时,如果不按回车键结束,而是按Shift+F1强制结束程序的话,窗口就会残留在画面上。话说回来,强制结束的时候还并没有执行api_closewin,窗口会留在画面上也是意料之中的事情,不过应用程序已经强制结束,内存空间也已经被回收,而窗口却还留在上面,这可不太好。

带着这样的问题肯定没办法睡个好觉,说不定还会做噩梦,所以我们还是在今晚把它搞定吧。

8 强制结束并关闭窗口(harib20h) - 图1

强制结束harib20g后就变成这样了!

■■■■■

到底该怎么办呢?首先,我们在struct SHEET中添加一个用来存放task的成员,当应用程序结束时,查询所有的图层,如果图层的task为将要结束的应用程序任务,则关闭该图层。

这个功能不仅是在强制结束的时候起作用,在正常结束时一样有效,因此,即便程序本身忘记加上关闭窗口的代码,系统也会自动将窗口关闭,进一步说,应用程序甚至可以完全依靠系统的这个功能,而不必特地调用api_closewin来关闭窗口了。

本次的bootpack.h节选

  1. struct SHEET {
  2. unsigned char *buf;
  3. int bxsize, bysize, vx0, vy0, col_inv, height, flags;
  4. struct SHTCTL *ctl;
  5. struct TASK *task; /*这里!*/
  6. };

本次的sheet.c节选

  1. struct SHEET *sheet_alloc(struct SHTCTL *ctl)
  2. {
  3. struct SHEET *sht;
  4. int i;
  5. for (i = 0; i < MAX_SHEETS; i++) {
  6. if (ctl->sheets0[i].flags == 0) {
  7. sht = &ctl->sheets0[i];
  8. sht->flags = SHEET_USE; /*正在使用的标记*/
  9. sht->height = -1; /*不显示*/
  10. sht->task = 0; /*不使用自动关闭功能*/ /*这里!*/
  11. return sht;
  12. }
  13. }
  14. return 0; /*所有的图层都正在使用*/
  15. }

本次的console.c节选

  1. int *hrb_api(int edi, int esi, int ebp, int esp, int ebx, int edx, int ecx, int eax)
  2. {
  3. (中略)
  4. } else if (edx == 5) {
  5. sht = sheet_alloc(shtctl);
  6. sht->task = task; /*这里!*/
  7. sheet_setbuf(sht, (char *) ebx + ds_base, esi, edi, eax);
  8. make_window8((char *) ebx + ds_base, esi, edi, (char *) ecx + ds_base, 0);
  9. sheet_slide(sht, 100, 50);
  10. sheet_updown(sht, 3); /*图层高度为3,在task_a之上*/
  11. reg[7] = (int) sht;
  12. } else if (edx == 6) {
  13. (中略)
  14. }

本次的console.c节选

  1. int cmd_app(struct CONSOLE *cons, int *fat, char *cmdline)
  2. {
  3. (中略)
  4. struct SHTCTL *shtctl; /*从此开始*/
  5. struct SHEET *sht; /*到此结束*/
  6. (中略)
  7. if (finfo != 0) {
  8. /*找到文件的情况*/
  9. p = (char *) memman_alloc_4k(memman, finfo->size);
  10. file_loadfile(finfo->clustno, finfo->size, p, fat, (char *) (ADR_DISKIMG + 0x003e00));
  11. if (finfo->size >= 36 && strncmp(p + 4, "Hari", 4) == 0 && *p == 0x00) {
  12. (中略)
  13. start_app(0x1b, 1003 * 8, esp, 1004 * 8, &(task->tss.esp0));
  14. shtctl = (struct SHTCTL *) *((int *) 0x0fe4); /*从此开始*/
  15. for (i = 0; i < MAX_SHEETS; i++) {
  16. sht = &(shtctl->sheets0[i]);
  17. if (sht->flags != 0 && sht->task == task) {
  18. /*找到被应用程序遗留的窗口*/
  19. sheet_free(sht); /*关闭*/
  20. }
  21. } /*到此结束*/
  22. memman_free_4k(memman, (int) q, segsiz);
  23. } else {
  24. cons_putstr0(cons, ".hrb file format error.\n");
  25. }
  26. memman_free_4k(memman, (int) p, finfo->size);
  27. cons_newline(cons);
  28. return 1;
  29. }
  30. /*没有找到文件的情况*/
  31. return 0;
  32. }

这样就大功告成了。

■■■■■

我们来试验一下,“make run”,然后运行lines.hrb,按Shift+F1强制结束。运行成功了!

8 强制结束并关闭窗口(harib20h) - 图2

看,窗口不见了吧?

下面我们再用winhelo3.hrb试试看,这个程序中我们没有调用closewin,不知道窗口能不能自动关闭呢?哦哦,关闭了,虽说这样就完全看不清窗口显示的内容了(笑),但只要像lines和walk那样加上等待键盘输入再结束的功能就好了。

8 强制结束并关闭窗口(harib20h) - 图3

winhelo3.hrb在程序结束时窗口也会被关闭哦

好了,我们已经成功实现了强制结束时也能关闭窗口的功能,这下可以睡个好觉了,大家晚安……