3 移动窗口(harib21c)
窗口切换的功能已经做的差不多了,这次我们来实现窗口的移动。之前我们只能移动task_a的窗口,这次的目标是实现像Windows一样的窗口移动功能。不过要如何才能实现呢……
当鼠标左键点击窗口时,如果点击位置位于窗口的标题栏区域,则进入“窗口移动模式”,使窗口的位置追随鼠标指针的移动,当放开鼠标左键时,退出“窗口移动模式”,返回通常模式。
要实现窗口的移动,我们需要记录鼠标指针所移动的距离,为此我们添加了两个变量:mmx和mmy,mm是“move mode”的缩写,这两个变量所记录的是移动之前的坐标。由于鼠标指针不会跑到画面以外,因此我们规定当mmx为负数时代表当前不处于窗口移动模式。
■■■■■
本次的bootpack.c节选
void HariMain(void)
{
(中略)
int j, x, y, mmx = -1, mmy = -1; /*这里!*/
struct SHEET *sht = 0; /*这里!*/
(中略)
for (;;) {
(中略)
if (fifo32_status(&fifo) == 0) {
(中略)
} else {
(中略)
if (256 <= i && i <= 511) { /*键盘数据*/
(中略)
} else if (512 <= i && i <= 767) { /*鼠标数据*/
if (mouse_decode(&mdec, i - 512) != 0) {
/*鼠标指针移动*/
(中略)
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;
}
} else {
/*没有按下左键*/
/*到此结束*/ mmx = -1; /*返回通常模式*/
}
}
} else if (i <= 1) { /*光标用定时器*/
(中略)
}
}
}
}
虽然代码有点长,不过静下心来仔细读一定能看懂的。
■■■■■
我们来“make run”试试看,能不能成功呢……哦哦,成功了!
可以像这样自由自在地移动哦
不过命令行窗口的移动速度太慢了!这大概是QEMU的原因,在真机环境下窗口的移动一定可以达到可接受的速度。还是有点不放心,于是在真机环境下测试了一下,不错,虽然还是有一点慢,不过这个速度也没什么问题。