/*
* $file : mginit.c
* $desc : simplest MiniGUI server
* $author : rockins(ybc2084@163.com)
* $date : Sun Apr 15 17:42:58 CST 2007
* $copyright : all copyrights(c) reserved by rockins.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <time.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <minigui/common.h>
#include <minigui/minigui.h>
#include <minigui/gdi.h>
#include <minigui/window.h>
#include <minigui/control.h>
#include <minigui/mgext.h>
int
MiniGUIMain (int args, const char* arg[])
{
MSG msg;
OnNewDelClient = NULL;
OnChangeLayer = NULL;
#if _MINIGUI_VERSION_CODE < _VERSION_CODE (1, 3, 0)
if (!ServerStartup ()) {
fprintf (stderr, "Can not start the server of MiniGUI-Lite: mginit./n");
return 1;
}
#endif
if (SetDesktopRect (650, 490, 660, 500) == 0) {
fprintf (stderr, "Empty desktop rect./n");
return 1;
}
if (!InitMiniGUIExt ()) {
fprintf (stderr, "Can not init mgext library./n");
return 1;
}
while (GetMessage (&msg, HWND_DESKTOP)) {
DispatchMessage (&msg);
}
MiniGUIExtCleanUp ();
return 0;
}
/*
* $file : mginit.c
* $desc : simplest MiniGUI server
* $author : rockins(ybc2084@163.com)
* $date : Sun Apr 15 17:42:58 CST 2007
* $copyright : all copyrights(c) reserved by rockins.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <time.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <minigui/common.h>
#include <minigui/minigui.h>
#include <minigui/gdi.h>
#include <minigui/window.h>
#include <minigui/control.h>
#include <minigui/mgext.h>
int
MiniGUIMain (int args, const char* arg[])
{
MSG msg;
OnNewDelClient = NULL;
OnChangeLayer = NULL;
#if _MINIGUI_VERSION_CODE < _VERSION_CODE (1, 3, 0)
if (!ServerStartup ()) {
fprintf (stderr, "Can not start the server of MiniGUI-Lite: mginit./n");
return 1;
}
#endif
if (SetDesktopRect (650, 490, 660, 500) == 0) {
fprintf (stderr, "Empty desktop rect./n");
return 1;
}
if (!InitMiniGUIExt ()) {
fprintf (stderr, "Can not init mgext library./n");
return 1;
}
while (GetMessage (&msg, HWND_DESKTOP)) {
DispatchMessage (&msg);
}
MiniGUIExtCleanUp ();
return 0;
}
无论是服务器程序还是客户端程序,MiniGUI程序的入口点都是MiniGUIMain()。上文中,在MiniGUIMain()函数中定义了一个MiniGUI消息结构msg,在消息循环中,从窗口消息队列获取的消息将存放到此消息结构中并将其交给相应的窗口过程函数去处理。
OnNewDelClient和OnChangeLayer是MiniGUI定义的两个全局函数指针,它们只能用于MiniGUI服务器中。可以将它们指向定制的处理函数,当有客户端与mginit服务器建立连接或者断开连接的时候就将调用OnNewDelClient所指的函数,而当层(Layer)发生改变的时候就将调用OnChangeLayer所指的函数。由于在本示例中不需要关心客户端的变化和层的变化,因此将这两个函数指针都置为NULL。
ServerStartup()函数的功能是启动服务器,其完成的工作主要是打开一个Unix域套接口/var/tmp/minigui并在其上监听来自MiniGUI客户端的连接。如果ServerStartup()执行成功,将返回TRUE,否则返回FALSE表示失败。注意:在采用MiniGUI-Lite时,系统中只能有一个MiniGUI服务器——也即这里的mginit,如果同时启动多个mginit,则只有第一次启动的mginit会成功,其它都将失败。
SetDesktopRect()函数的作用是设定由mginit程序独占的桌面区域。这里设定的区域为(650, 490, 660, 500)。各位看官可能会对此感到奇怪,因为在前面的两篇拙文中,已经提到Sitsang评估板的液晶显示屏的分辨率大小为640x480,显然,这里为mginit设置的独占区域已经在屏幕可见的范围之外了。实际上,背后的原因是这样的:对于MiniGUI客户端程序而言,只能在服务器mginit独占的区域之外进行绘制。由于作者打算把整个屏幕都留给客户端程序使用,因此就不能让mginit占用屏幕上的可见区域,而是指定了一个屏幕范围之外的区域,这个区域的具体位置并不重要,只要在屏幕可见范围之外即可。MiniGUI允许服务器独占的桌面区域位于可见的屏幕区域之外。另外,任何时候客户端程序都不能在服务器独占的桌面区域上进行绘制输出,而服务器程序尽管设定了桌面区域,却可以在任何时候在屏幕的任何位置进行绘制输出。显然,服务器mginit的权力比客户端程序的权力要大。
InitMiniGUIExt()函数初始化了mgext库,这个库对应的动态共享库文件为libmgext-1.3.so.3.0.0,它提供了对MiniGUI核心库libminigui-1.3.so.3.0.0的扩展支持。主要是提供了一些扩展控件和皮肤界面的支持。如果要使用这些扩展空间或者皮肤界面,必须在调用任何mgext库的API函数之前调用InitMiniGUIExt()完成相关的初始化工作。当InitMiniGUIExt()函数执行成功时,返回TRUE,否则返回FALSE。由于本例中并未使用到mgext库的功能,因此这里这是为了起到演示的目的。
在MiniGUIMain()函数快要结束的地方实现了整个服务器的消息循环。在这个循环中,GetMessage()函数首先从桌面窗口的消息队列中取出消息。桌面窗口HWND_DESKTOP是所有窗口的祖先窗口。只要取出的消息不为MSG_QUIT,那么GetMessage()就将把消息复制到msg中,并且GetMessage()函数将会返回非零值,同时复制到msg消息结构中的消息将被DispatchMessage()分发给对应的主窗口,由该主窗口的窗口过程函数进行处理;如果GetMessage()发现取出的消息为MSG_QUIT,那么GetMessage()函数将返回0。这将导致mginit退出消息循环。在DispatchMessage()中,不需要再指明消息要分发到的主窗口,因为MSG消息结构中已经包含了消息要发往的主窗口的句柄(handle)。
最后,MiniGUIExtCleanUp()函数的作用是清理mgext库占用的资源。当不再需要使用任何mgext的API函数时,应该调用此函数。
可以看到,实现一个最最简单的MiniGUI-Lite服务器程序实际上只需要几十行代码就够了。“麻雀虽小,五脏俱全”。