分类: LINUX
2009-05-16 19:08:00
wm.c 以 image.c 为范本,wm.c 执行后在画面上只会看到图片图(没有窗口标题列与边框),并且可使用鼠标来拖曳图片。本范例主要在展示以下的 Nano-X API 程序设计方法:
˙ 如何设定窗口属性(window manager)。
˙ 如何与使用者做互动(human interactive)。
要写出「托曳图片」的功能,首先必须把窗口的标题列与边框去除,否则只能在标题列上托曳整个「窗口」。做法非常简单,只要在建立窗口时设定 window manager 即可:
wid = GrNewWindowEx(GR_WM_PROPS_APPWINDOW |
GR_WM_PROPS_NODECORATE |
GR_WM_PROPS_NOAUTOMOVE,
NULL,
GR_ROOT_WINDOW_ID,
0, 0,
image_jollen.width, /* 图片宽度 */
image_jollen.height /* 图片高度 */,
0xFFFFFF);
粗体字的地方是新加入的 window manager 属性,为了达到我们的要求,我们指定了3个属性值:
· GR_WM_PROPS_APPWINDOW:使用 window manager 的外观。
· GR_WM_PROPS_NODECORATE:不要有窗口边框。
· GR_WM_PROPS_NOAUTOMOVE:第一次显示窗口时不移动窗口。
由于我们并未指定 GR_WM_PROPS_CAPTION,因此不会有窗口标题列。在处理使用者互动上,我们需要自行处理3个鼠标事件:
· GR_EVENT_MASK_MOUSE_POSITION:鼠标移动事件。
· GR_EVENT_MASK_BUTTON_UP:放开鼠标按键。
· GR_EVENT_MASK_BUTTON_DOWN:按下鼠标按键。
因此选择事件的程序代码应修改成:
GrSelectEvents(wid, GR_EVENT_MASK_MOUSE_POSITION |
GR_EVENT_MASK_BUTTON_UP |
GR_EVENT_MASK_BUTTON_DOWN);
接下来,要特别注意的地方是「显示图片的时机」。我们在这里设计成在窗口显示后、进入 event loop 前处理。首先是显示图片的程序写法:
GrMapWindow(wid);
GrDrawImageBits(wid, gc, 0, 0, &image_jollen);
接着,修改 event loop,并加上处理以上 3 个事件(粗体字部份)的程序代码:
void event_handler (GR_EVENT *event)
{
switch (event->type)
{
case GR_EVENT_TYPE_CLOSE_REQ:
GrClose();
case GR_EVENT_TYPE_MOUSE_POSITION:
position_event(&event->mouse);
break;
case GR_EVENT_TYPE_BUTTON_UP:
case GR_EVENT_TYPE_BUTTON_DOWN:
button_event(&event->button);
break;
default: break;
}
}
对于鼠标按键的处理方式为:当鼠标被按下时,便记录鼠标的新坐标,然后将窗口移到最上层;若此时使用者移动鼠标,则将整个「窗口」移到新坐标位置。如此一来,使用者就会看到「整个图片被托曳」的效果。
处理鼠标按键的程序写法如下:
void button_event(GR_EVENT_BUTTON *e)
{
if (e->type == GR_EVENT_TYPE_BUTTON_DOWN) {
newx = e->x;
newy = e->y;
button_down = 1;
GrRaiseWindow(e->wid);
} else {
button_down = 0;
}
}
先判断目前所产生的事件是否为 GR_EVENT_TYPE_BUTTON_DOWN;如果是,才记录新坐标,并将 button_down 设为 1。若不是 GR_EVENT_TYPE_BUTTON_DOWN 事件,表示鼠标按键已放开,此时将 button_down 设为 0。
处理鼠标移动事件的程序写法如下:
void position_event(GR_EVENT_MOUSE *e)
{
if (!button_down) return;
GrMoveWindow(e->wid, e->rootx-newx, e->rooty-newy);
}
先判断 button_down 是否为 false,若 button_down等于0,表示鼠标按键是放开的,因此不做任何动作。反正,若 button_down 为true,代表鼠标按键仍「持续」按住,此时才能呼叫 GrMoveWindow() 移动窗口。
以下是 wm.c 的完整程序,粗体字是新加入或修改过的程序代码。
/*
* Copyright(c) 2003,2004
*
* - Nano-X API example.
* - wm.c
*
*/
#include
#define MWINCLUDECOLORS
#include
#include
GR_WINDOW_ID wid;
GR_GC_ID gc;
/* 外部影像 */
extern GR_IMAGE_HDR image_jollen;
void event_handler (GR_EVENT *event);
/* 鼠标坐标 */
int newx, newy;
int button_down;
int main (void)
{
if (GrOpen() < 0) {
fprintf (stderr, "GrOpen failed");
return -1;
}
gc = GrNewGC();
GrSetGCForeground (gc, 0xFF0000);
wid = GrNewWindowEx(GR_WM_PROPS_APPWINDOW |
GR_WM_PROPS_NODECORATE |
GR_WM_PROPS_NOAUTOMOVE,
NULL,
GR_ROOT_WINDOW_ID,
0, 0,
image_jollen.width, /* 影像宽度 */
image_jollen.height /* 影像高度 */,
0xFFFFFF);
GrSelectEvents(wid, GR_EVENT_MASK_MOUSE_POSITION |
GR_EVENT_MASK_BUTTON_UP |
GR_EVENT_MASK_BUTTON_DOWN);
GrMapWindow(wid);
GrDrawImageBits(wid, gc, 0, 0, &image_jollen);
GrMainLoop(event_handler);
return 0;
}
void button_event(GR_EVENT_BUTTON *e)
{
if (e->type == GR_EVENT_TYPE_BUTTON_DOWN) {
newx = e->x;
newy = e->y;
button_down = 1;
GrRaiseWindow(e->wid);
} else {
button_down = 0;
}
}
void position_event(GR_EVENT_MOUSE *e)
{
if (!button_down) return;
GrMoveWindow(e->wid, e->rootx-newx, e->rooty-newy);
}
void event_handler (GR_EVENT *event)
{
switch (event->type)
{
case GR_EVENT_TYPE_CLOSE_REQ:
GrClose();
case GR_EVENT_TYPE_MOUSE_POSITION:
position_event(&event->mouse);
break;
case GR_EVENT_TYPE_BUTTON_UP:
case GR_EVENT_TYPE_BUTTON_DOWN:
button_event(&event->button);
break;
default: break;
}
}