30天自制操作系统——第二十三天窗口操作
窗口及輸入切換
我們先來實現用鍵盤切換窗口,按下F11鍵,將最下面的窗口移動到最上面,這里F11按鍵的編碼為0x57。
bootpack.c節選:
void HariMain(void) {(略)for (;;) {(略)if (fifo32_status(&fifo) == 0) {(略)} else {(略)if (256 <= i && i <= 511) { /* 鍵盤數據 */(略)if (i == 256 + 0x57 && shtctl->top > 2) { /* F11 */sheet_updown(shtctl->sheets[1], shtctl->top - 1);}(略)} else if (512 <= i && i <= 767) { /* 鼠標數據 */(略)} else if (i <= 1) { /* 光標用定時器 */(略)}}} }shtctl->top是最上面的一個圖層,這個圖層是用于繪制鼠標指針,要將窗口放在鼠標指針圖層的下一個圖層。
接下來實現鼠標點擊來切換窗口的功能,鼠標點擊畫面時,要從上到下判斷鼠標點擊的是哪個圖層,接著判斷鼠標點擊的位置落在哪個圖層范圍內。
bootpack.c節選
if ((mdec.btn & 0x01) != 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);break;}}} }make run一下,可以用F11鍵和鼠標點擊切換窗口了。
現在雖然已經將窗口切換過來了,但是輸入狀態還是命令行窗口,現在將輸入也切換到應用程序窗口吧。使用key_win變量存放當前處于輸入模式的窗口地址,當處于輸入模式的窗口被關閉時,系統自動切換到最上層的窗口。新建keywin_on和kinwin_off兩個函數,控制窗口標題欄的顏色,選中的窗口標題欄為藍色,未選中的窗口標題欄為灰色。
鼠標在選中窗口上點擊一下,該選中窗口就會被切換到畫面的最上方,同時鍵盤輸入也會自動切換到該窗口。
bootpack.c節選
/* 按下左鍵 */ if (mmx < 0) {/* 按照從上到下的順序尋找鼠標所指向的圖層 */for (j = shtctl->top - 1; j > 0; j--) {(略)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 (sht != key_win) {cursor_c = keywin_off(key_win, sht_win, cursor_c, cursor_x);key_win = sht;cursor_c = keywin_on(key_win, sht_win, cursor_c);}if (3 <= x && x < sht->bxsize - 3 && 3 <= y && y < 21) {mmx = mx; /* 進入窗口移動模式 */mmy = my;}if (sht->bxsize - 21 <= x && x < sht->bxsize - 5 && 5 <= y && y < 19) {/* 點擊"×"按鈕 */(略) }break;}}} }make run執行一下——
移動窗口
接下來實現像windows一樣的方式來移動窗口,左鍵點擊窗口,若點擊的位置剛好位于窗口的標題欄區域則進入移動模式。窗口跟隨著鼠標移動,當鼠標左鍵松開時,退出移動模式。這里添加了兩個變量mmx和mmy ,用于記錄移動之前的坐標。當mmx為負數時,代表當前不處于窗口移動模式。
bootpack.c節選:
if ((mdec.btn & 0x01) != 0) {/* 按下左鍵 */ 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;} }關閉窗口
實現鼠標左鍵點擊窗口上的“ × ” 按鈕后關閉窗口,這里先判斷鼠標左鍵點擊的位置剛好位于窗口上的“ × ” 位置,若處于該位置則強制結束。
bootpack.c節選
if (sht->bxsize - 21 <= x && x < sht->bxsize - 5 && 5 <= y && y < 19) {/* 點擊“×” 按鈕 */if (sht->task != 0) { /* 判斷該窗口是否為應用程序 */ cons = (struct CONSOLE *) *((int *) 0x0fec);cons_putstr0(cons, "\nBreak(mouse) :\n");io_cli(); /* 禁止中斷發生 */task_cons->tss.eax = (int) &(task_cons->tss.esp0);task_cons->tss.eip = (int) asm_end_app;io_sti();} }定時器
窗口切換,窗口移動,輸入切換的操作已經全部完成了,現在我們來用命令開啟一個定時器的窗口吧,可以用它來記個時。
void HariMain(void) {char *buf, s[12];int win, timer, sec = 0, min = 0, hou = 0;api_initmalloc();buf = api_malloc(150 * 50);win = api_openwin(buf, 150, 50, -1, "timers");timer = api_alloctimer();api_inittimer(timer, 128);for (;;) {sprintf(s, "%5d:%02d:%02d", hou, min, sec);api_boxfilwin(win, 28, 27, 115, 41, 7 /* 白色 */);api_putstrwin(win, 28, 27, 0 /* 黑色 */, 11, s);api_settimer(timer, 100); /* 1秒 */if (api_getkey(1) != 128) {break;}sec++;if (sec == 60) {sec = 0;min++;if (min == 60) {min = 0;hou++;}}}api_end(); }執行make run——
注:本文參照《30天自制操作系統》制作,感謝各位的持續關注,原著源碼鏈接見第十九篇。
總結
以上是生活随笔為你收集整理的30天自制操作系统——第二十三天窗口操作的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使用docker创建属于你的ChatGP
- 下一篇: 移动医疗 超越想象