MiniGUI概要设计说明书.docx
《MiniGUI概要设计说明书.docx》由会员分享,可在线阅读,更多相关《MiniGUI概要设计说明书.docx(26页珍藏版)》请在冰点文库上搜索。
MiniGUI概要设计说明书
MiniGUI特性说明书
本文档说明MiniGUI所支持的功能特性。
一、概述
MiniGUI是Linux控制台上运行的,基于SVGALib和LinuxThread库的多窗口图形用户界面支持系统。
MiniGUI采用了类Win32的API接口,实现了简化的类Windows98风格的图形用户界面。
图形用户界面在许多情况下都优于字符界面,其最大的优点是使应用程序的操作简单易学。
在MiniGUI中,图形用户界面包括如下基本元素:
图1.1图形用户界面的基本元素
1.1窗口
MiniGUI中的窗口基本分四类,分别为主窗口、对话框、控件和主窗口中的窗片。
MiniGUI中的主窗口和Windows应用程序的主窗口概念类似,但略微有些不同,MiniGUI中的每个主窗口对应于一个单独的线程,通过函数调用可建立主窗口以及对应的线程。
每个线程有一个消息队列,主窗口从这一消息队列中获取消息并由窗口过程(回调函数)进行处理。
MiniGUI中的对话框是一种特殊的窗口,对话框一般和控件一起使用,这两个概念和Windows的相关概念是类似的。
MiniGUI支持的控件类型有:
✓静态框:
文本、图标或矩形框等。
这种控件的属性一般不会在运行时发生变化。
✓文本框:
单行或多行的文本编辑框。
✓按钮:
单选钮、复选框和一般按钮等。
✓其他特殊控件。
窗片是MiniGUI所特有的,窗片实际是主窗口的子窗口,只存在于主窗口中。
为了处理上的方便,主窗口的子窗口只以平铺的形式出现,因此我们将这种子窗口称为“窗片”或“窗格”。
窗片可以是私有的控件类型,也可以是标准的控件类型。
1.2消息和消息循环
在Windows系列操作系统中,广泛使用了消息驱动的概念。
在MiniGUI中,我们也使用了消息驱动作为应用程序的创建构架。
在消息驱动的应用程序中,计算机外设发生的事件,例如键盘键的敲击、鼠标键的按击等,都由支持系统收集,将其以事先的约定格式翻译为特定的消息。
应用程序一般包含有自己的消息队列,系统将消息发送到应用程序的消息队列中。
应用程序可以建立一个循环,在这个循环中读取消息并处理消息,一直处理到特定的消息传来为止。
这样的循环称为消息循环。
一般地,消息由代表消息的一个整型数和消息的附加参数组成。
例如,鼠标左键的按下消息,可能由133这个数来表示,其附加参数可能包含按下时的鼠标所在位置信息。
例如,MiniGUI中如下定义消息:
typedefstruct
{
HWNDhwnd;
intmessage;
WPARAMwParam;
LPARAMlParam;
...
}MSG;
message指定了特定的消息类型,wParam是以unsignedint类型定义的消息的短参数,lParam是以long类型定义的消息长参数。
应用程序一般要提供一个处理消息的标准函数。
在消息循环中,系统可以调用此函数,应用程序在此函数中处理相应消息。
图1.2是一个消息驱动的应用程序的简单构架示意。
图1.2消息驱动的应用程序的简单构架
在MiniGUI中,消息分为如下几种类型:
✓系统消息,为系统内部管理使用。
✓鼠标消息,鼠标的点击、移动等产生的消息。
✓键盘消息,键盘的按键消息。
✓窗口消息,窗口管理消息。
✓菜单消息,菜单管理消息。
✓命令消息等。
1.3窗口过程和窗口类
窗口过程是用来处理窗口消息的函数过程。
对于同一类型的控件,其窗口过程一般是一样的。
因此,系统一般利用窗口的窗口类名来区分不同的窗口类并调用不同的窗口过程。
由于几乎每一个主窗口均和其他窗口有着不同的窗口过程,因此,在MiniGUI中,窗口类的概念只存在于控件和窗片中。
对于主窗口来说,其窗口过程在建立主窗口时指定,而对控件和窗片来说,则在注册窗口类时指定,而在建立窗片或控件时指定所属窗口类。
1.4句柄
句柄是MiniGUI用来标识对象的标识符。
句柄和指针概念类似,但它不一定是指针值。
利用句柄,MiniGUI将系统变量从应用项目中分离了出来,因为程序员只能通过句柄访问对象,因而就没有利用指针是可能发生的因非法访问而导致的数据不一致问题。
在MiniGUI中,窗口、控件、设备环境、菜单、图标等均使用句柄访问。
二、窗口
2.1应用程序和主窗口
我们将基于MiniGUI的一个会话(session)称为一个应用项目,而其中每个单独的线程或线程组称为应用。
每个应用项目可建立多个应用。
主窗口是建立在MiniGUI基础上的应用的主界面。
MiniGUI为每个主窗口建立单独的消息队列,在该主窗口基础上派生出的窗片、对话框及其控件均使用同一消息队列。
在MiniGUI中,每个应用对应于一个线程。
理论上讲,每个应用可以具备多个主窗口,但在MiniGUI中,主窗口均以单独的线程实现。
但多个主窗口对应单一线程的情况也是可以在MiniGUI中实现的。
每个应用项目有一个MiniGUIMain函数,在这个函数中,可建立初始的应用线程。
在调用MiniGUIMain之前,MiniGUI启动自己的桌面窗口(Desktop)。
桌面窗口作为MiniGUI的窗口管理器而存在。
下面的代码段在MiniGUIMain中启动了三个主窗口线程:
intMiniGUIMain(intargs,char*arg[])
{
pthread_tthread,thread2,thread3;
CreateThreadForMainWindow(&thread,NULL,TestWindowMain,0);
CreateThreadForMainWindow(&thread2,NULL,TestWindowMain2,0);
CreateThreadForMainWindow(&thread3,NULL,TestWindowMain3,0);
return0;
}
CreateThreadForMainWindow函数为主窗口建立线程,并返回线程标识符。
其中的第三个参数是线程的入口函数地址。
如下的代码段定义了上述代码中第一个主窗口线程的入口函数:
voidInitCreateInfo(PMAINWINCREATEpCreateInfo)
{
pCreateInfo->dwStyle=WS_THICKFRAME;
pCreateInfo->spCaption="Thefirstmainwindow";
pCreateInfo->hMenu=0;
pCreateInfo->hCursor=GetSystemCursor
(2);
pCreateInfo->hIcon=LoadIconFromFile("res/table.ico");
pCreateInfo->MainWindowProc=TestMainWinProc;
pCreateInfo->lx=50;
pCreateInfo->ty=50;
pCreateInfo->rx=300;
pCreateInfo->by=480;
pCreateInfo->iBkColor=COLOR_lightwhite;
pCreateInfo->dwAddData1=0;
pCreateInfo->dwAddData2=0;
}
void*TestWindowMain(void*data)
{
MSGMsg;
MAINWINCREATECreateInfo;
HWNDhMainWnd;
InitCreateInfo(&CreateInfo);
if(!
(hMainWnd=CreateMainWindow(&CreateInfo)))
returnNULL;
ShowWindow(hMainWnd,SW_SHOWNORMAL);
while(GetMessage(&Msg,hMainWnd)){
DispatchMessage(&Msg);
}
MainWindowThreadCleanup(hMainWnd);
returnNULL;
}
在上面的代码段中,该线程首先调用CreateMainWindow建立了主窗口,然后调用ShowWindow显示了主窗口,最后启动了消息循环。
当消息循环因为接收到MSG_QUIT消息而终止时,该函数调用了MainWindowThreadCleanup清除了相关的线程数据。
从上述代码中可看出主函数不支持窗口类,在调用CreateMainWindow函数时直接指定主窗口的窗口过程地址。
我们也可以从中看到主窗口所支持的其他属性:
1.窗口风格。
表2.1给出了所支持的窗口风格
表2.1MiniGUI支持的主窗口风格
风格
描述
WS_BORDER
创建一个具有单线边框的窗口
WS_THICKFRAME
创建一个具有宽边框的窗口
WS_THINFRAME
创建一个具有细边框的窗口
WS_CAPTION
创建一个具有标题栏的窗口
WS_HSCROLL
创建一个具有水平滚动条的窗口
WS_MAXMIZEBOX
创建一个具有最大化框的窗口
WS_MINIMIZEBOX
创建一个具有最小化框的窗口
WS_SYSMENU
创建一个具有系统菜单的窗口
WS_VSCROLL
创建一个具有垂直滚动条的窗口
WS_DISABLED
创建一个初始为禁止的窗口
WS_MAXIMIZE
创建一个初始最大化的窗口
WS_MINIMIZE
创建一个初始最小化的窗口
WS_VISIBLE
创建一个初始可见的窗口
WS_EX_TOPMOST
创建一个顶层窗口,这是一个Win32的扩展风格
2.窗口标题。
3.窗口菜单。
4.窗口图标。
5.窗口背景色。
2.2主窗口过程
主窗口过程实际是一个回调函数,一般由DispatchMessage函数调用,用来处理应用的消息。
主窗口过程一般如下定义:
intTestMainWinProc(HWNDhWnd,intmessage,WPARAMwParam,LPARAMlParam)
{
HDChdc;
intx,y;
RECTclient;
staticBITMAPbitmap;
staticBOOLfValid=FALSE;
staticintpaintCount=0;
switch(message){
caseMSG_CREATE:
SetTimer(hWnd,100,20);
if(LoadBitmap(&bitmap,"res/mnls.bmp")<0)
fprintf(stderr,"TestMainWin:
Loadingbitmapfailure!
\n");
else
fValid=TRUE;
break;
caseMSG_PAINT:
hdc=BeginPaint(hWnd);
testdc(hdc,fValid?
&bitmap:
NULL);
EndPaint(hWnd,hdc);
break;
caseMSG_LBUTTONDBLCLK:
hdc=GetClientDC(hWnd);
TextOut(hdc,0,0,"Leftbuttondoubleclicked");
ReleaseDC(hdc);
PostMessage(hWnd,MSG_CLOSE,0,0);
return0;
caseMSG_TIMER:
if(ISINBACKGROUND)
break;
paintCount++;
if(paintCount%10!
=0){
hdc=GetClientDC(hWnd);
GetClientRect(hWnd,&client);
x=random()%(RECTW(client));
y=random()%(RECTH(client));
SetBrushColor(hdc,RGB2Index(hdc,random()%256,
random()%256,
random()%256));
FillBox(hdc,x,y,random()%RECTW(client),
random()%RECTH(client));
ReleaseDC(hdc);
}
else
InvalidateRect(hWnd,NULL,FALSE);
break;
caseMSG_CLOSE:
KillTimer(hWnd,100);
UnloadBitmap(&bitmap);
DestroyMainWindow(hWnd);
PostQuitMessage(hWnd);
return0;
}
returnDefaultMainWinProc(hWnd,message,wParam,lParam);
}
主窗口有四个入口参数,分别是消息的目标窗口句柄、消息、消息的WPARAM(即unsignedint)型参数和LPARAM(即longint)型参数。
在32位系统中,消息的两个参数实际是等长度的。
主窗口的窗口过程处理应用感兴趣的消息,将其他消息传递给DefaultMainWindProc函数处理。
2.3桌面的应用项目接口
当用户在桌面上单击鼠标右键时可弹出浮动式菜单,应用项目可通过桌面提供的接口在该菜单中添加菜单项,从而提供一定的灵活性。
要利用桌面的应用项目接口,应用项目要实施两个函数:
voidCustomizeDesktopMenu(HMENUhmnu,intiPos);
intCustomDesktopCommand(intid);
通过CustomizeDesktopMenu函数,应用项目可在桌面的浮动式菜单中添加菜单及菜单项。
当用户选择了定制的菜单项时,MiniGUI将调用CustomDesktopCommand函数,这时,应用项目就可以处理该菜单命令。
2.4对话框和控件
对话框实际是一种特殊的主窗口。
一般而言,对话框中包含有许多系统提供的控件。
对话框和控件的设计目标是提供和Win32在源代码级上的完全兼容。
但某些复杂的控件不打算支持,对话框页也不支持。
MiniGUI支持的控件有:
✓静态控件。
✓按钮控件。
✓编辑控件。
✓列表控件。
✓滚动条控件。
✓组合框控件。
同时,MiniGUI将提供标准的公共对话框:
✓文件打开对话框。
✓文件保存对话框。
2.6消息框
MiniGUI将提供和Win32完全兼容的消息框调用接口。
2.6窗片
窗片是主窗口中子窗口的简化支持,为了避免子窗口之间的互相剪切,而采用了平铺式的子窗口实现,不考虑子窗口的互相剪切,因而也就不提供多文档接口。
也因为这个原因,我们将这种子窗口称为窗片或窗格。
窗片的建立和控件的建立方法一致。
2.7滚动支持
将提供和Win32完全兼容的主窗口或子窗口的滚动支持。
三、对话框、窗片和控件
该部分功能尚未实现,其目标是提供和WIN32的80%兼容。
需要提供的接口分为如下几类(注,我们将窗片和控件统称为窗口,并严格区分“主窗口”和“窗口”这两个名词):
✓窗口类的注册和注销。
✓窗口的创建和销毁。
✓对话框和控件管理。
✓常见控件消息、操作接口等的实现。
四、消息及消息队列
在MiniGUI中,基本实现了Win32的消息处理函数。
消息可通过如下函数发送:
✓通过PostMessage发送。
消息发送到消息队列后立即返回。
这种发送方式称为“邮寄”消息。
如果消息队列中的邮寄消息缓冲区满,则该函数返回错误值。
✓通过PostSyncMessage发送。
该函数用来向不同于调用该函数的线程消息队列邮寄消息,并且只有该消息被处理之后,该函数才能返回,因此这种消息称为“同步消息”。
✓通过SendMessage发送。
该函数可以向任意一个窗口发送消息,消息处理完成之后,该函数返回。
如果目标窗口所在线程和调用线程是同一个线程,该函数直接调用窗口过程,如果处于不同的线程,则利用PostSyncMessage函数发送同步消息。
✓通过SendNotifyMessage发送。
该函数向指定的窗口发送通知消息,将消息放入消息队列后立即返回。
由于这种消息和邮寄消息不同,是不允许丢失的,因此,系统以链表的形式处理这种消息。
✓通过SendAsyncMessage发送。
利用该函数发送的消息称为“异步消息”,系统直接调用目标窗口的窗口过程。
五、图形设备接口
图形设备接口,即GDI,MiniGUI中用来实现图形输出的模块。
5.1基本概念
5.1.1图形设备
在MiniGUI中,采用了在Windows和XWindow中普遍采用的图形设备概念。
每个图形设备定义了计算机显示屏幕上的一个矩形输出区域。
在调用图形输出函数时,均要求指定经初始化,或经建立的图形设备上下文,或设备环境(DC)。
每个图形输出均局限在图形设备指定的矩形区域内。
在多窗口系统中,各个图形设备之间的输出互相剪切,以避免图形输出之间互相影响。
5.1.2剪切域
剪切域就是在图形设备上定义的一个区域,所有在该图形设备上进行的图形输出,超过剪切域的部分,均被裁剪。
只有在剪切域上的图形输出才是可见的输出。
MiniGUI中的剪切域,定义为矩形剪切域的集合。
5.1.3映射模式
映射模式指定了特定图形输出的坐标值如何映射到图形设备的坐标值。
图形设备的坐标系原点定义为图形设备矩形区域的左上角。
向右为正X坐标轴方向;向下为正Y坐标轴方向。
这一坐标系称为设备坐标系。
通过GDI模块的映射模式操作函数,可定义自己的逻辑坐标系。
逻辑坐标系可以是设备坐标系的水平或垂直反转,缩放,或者偏移。
多数GDI输出函数指定的是逻辑坐标系。
默认情况下,逻辑坐标系和设备坐标系是重合的。
5.2GDI功能特性的分类说明
5.2.1图形设备能力
通过调用函数GetGDCapability,可获得图形设备的如下能力:
✓颜色数目;
✓水平和竖直方向的象素点数;
✓设备坐标系中可见点的最大x和y坐标值。
5.2.2创建、销毁或获取、释放图形设备接口
和Win32类似,MiniGUI中也有一个DC的缓冲区,应用可调用GetDC或GetClientDC函数从DC缓冲区中获取图形设备环境,在结束使用DC之后,应当调用ReleaseDC函数释放DC。
应用也可以建立自己私有的DC,这种DC可以是全局有效的DC,由于免除了获取和释放以及初始化等工作,因此,利用这种DC可加速图形显示。
当应用不再使用私有DC时,应当利用DeletePrivateDC删除私有DC。
下面的代码即利用了这种DC:
intTestMainWinProc2(HWNDhWnd,intmessage,WPARAMwParam,LPARAMlParam)
{
staticHDChdc;
HDChPaintDC;
intx,y;
RECTclient;
staticintcount=0;
staticBITMAPbitmap;
staticBOOLfValid=FALSE;
staticintpaintCount=0;
switch(message){
caseMSG_CREATE:
SetTimer(hWnd,100,20);
SetTimer(hWnd,200,5);
if(LoadBitmap(&bitmap,"res/j11b.BMP")<0)
fprintf(stderr,"TestMainWin:
Loadingbitmapfailure!
\n");
else
fValid=TRUE;
break;
caseMSG_SHOWWINDOW:
if(wParam==SW_SHOWNORMAL)
hdc=CreatePrivateClientDC(hWnd);
break;
caseMSG_PAINT:
hPaintDC=BeginPaint(hWnd);
testdc(hPaintDC,fValid?
&bitmap:
NULL);
EndPaint(hWnd,hPaintDC);
break;
caseMSG_LBUTTONDBLCLK:
return0;
caseMSG_TIMER:
if(ISINBACKGROUND)
break;
if(wParam==100){
paintCount++;
if(paintCount%10!
=0){
GetClientRect(hWnd,&client);
x=random()%(RECTW(client));
y=random()%(RECTH(client));
SetPenColor(hdc,RGB2Index(hdc,random()%256,
random()%256,
random()%256));
LineTo(hdc,x,y);
}
else
InvalidateRect(hWnd,NULL,TRUE);
}
elseif(wParam==200){
if(count<5)
{
Ping();
count++;
}
else
KillTimer(hWnd,200);
}
break;
caseMSG_CLOSE:
KillTimer(hWnd,100);
KillTimer(hWnd,200);
UnloadBitmap(&bitmap);
DeletePrivateDC(hdc);
DestroyMainWindow(hWnd);
PostQuitMessage(hWnd);
return0;
}
returnDefaultMainWinProc(hWnd,message,wParam,lParam);
}
上述代码在应用主窗口建立时创建了私有DC,然后在定时器消息中利用私有DC进行绘制,最后在关闭窗口时删除了私有DC。
MiniGUI也支持内存中的虚拟DC,可通过CreateCompatibleDC建立内存DC,利用这种DC,可加速绘制过程,并减少绘制过程中闪烁现象。
应用可使用DeleteCompatibleDC函数删除内存