📄 基于 linux 和 minigui 的嵌入式系统软件开发指南(五).htm
字号:
y 坐标相等。
<LI>区域中矩形的排列,首先是在 x 方向(在一个条带中)从左到右排列,然后按照 y 坐标从上到下排列。 </LI></UL><BR><BR>
<P>在 GDI 函数进行绘图输出时,可以利用 x-y-banned
区域的特殊性质进行绘图的优化。在将来版本中添加的绘图函数,将充分利用这一特性进行绘图输出上的优化。</P>
<P>新的 GDI 增加了如下接口,可用于剪切区域的运算(include/gdi.h):</P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc
border=1><TBODY>
<TR>
<TD><PRE><CODE>BOOL GUIAPI PtInRegion (PCLIPRGN region, int x, int y);
BOOL GUIAPI RectInRegion (PCLIPRGN region, const RECT* rect);
BOOL GUIAPI IntersectRegion (CLIPRGN *dst, const CLIPRGN *src1, const CLIPRGN *src2);
BOOL GUIAPI UnionRegion (PCLIPRGN dst, const CLIPRGN* src1, const CLIPRGN* src2);
BOOL GUIAPI SubtractRegion (CLIPRGN* rgnD, const CLIPRGN* rgnM, const CLIPRGN* rgnS);
BOOL GUIAPI XorRegion (CLIPRGN *dst, const CLIPRGN *src1, const CLIPRGN *src2);
</CODE>
</PRE></TD></TR></TBODY></TABLE><BR><BR>
<UL class=n01>
<LI>PtInRegion 函数可用来检查给定点是否位于给定的区域中。
<LI>RectInRegion 函数可用来检查给定矩形是否和给定区域相交。
<LI>IntersectRegion 函数对两个给定区域进行求交运算。
<LI>UnionRegion 函数可合并两个不同的区域,合并后的区域仍然是 x-y-banned 的区域。
<LI>SubstractRegion 函数从一个区域中减去另外一个区域。
<LI>XorRegion 函数对两个区域进行异或运算,其结果相当于 src1 减 src2 的结果 A 与 src2 减 src1 的结果 B
之间的交。 </LI></UL>
<P>在 MiniGUI 1.1.0 版本正式发布时,我们将添加从多边形、椭圆或圆弧等封闭曲线中生成剪切域的 GDI 函数。这样,就可以实现将
GDI 输出限制在特殊封闭曲线的效果。</P>
<P><SPAN class=atitle3>4.2
光栅操作</SPAN><BR>光栅操作是指在进行绘图输出时,如何将要输出的象素点和屏幕上已有的象素点进行运算。最典型的运算是下面要讲到的 Alpha
混和。这里的光栅操作特指二进制的位操作,包括与、或、异或和直接的设置(覆盖)等等。应用程序可以利用
SetRasterOperation/GetRasterOperation
函数设置或者获取当前的光栅操作。这两个函数的原型如下(include/gdi.h):</P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc
border=1><TBODY>
<TR>
<TD><PRE><CODE>#define ROP_SET 0
#define ROP_AND 1
#define ROP_OR 2
#define ROP_XOR 3
int GUIAPI GetRasterOperation (HDC hdc);
int GUIAPI SetRasterOperation (HDC hdc, int rop);
</CODE>
</PRE></TD></TR></TBODY></TABLE>在设置了新的光栅操作之后,其后的一般图形输出将受到设定的光栅操作的影响,这些图形输出包括:SetPixel、LineTo、Circle、Rectangle、FillRect
和 FillCircle 等等。需要注意的是,新的 GDI 函数引入了一个新的矩形填充函数――FillRect。如上所述,FillRect
函数是受当前光栅操作影响的,而原先的 FillBox 函数则不受当前的光栅操作影响。这是因为 FillBox
函数会利用硬件加速功能实现矩形填充,并且该函数的填充速度要比 FillRect 函数快。<BR><BR>
<P><SPAN class=atitle3>4.3 内存 DC 和 BitBlt</SPAN><BR>新的 GDI 函数增强了内存 DC
操作函数。GDI 函数在建立内存 DC 时,将调用 GAL 的相应接口。如前所述,GAL 将尽量把内存 DC
建立在显示卡的显示内存当中。这样,可以充分利用显示卡的硬件加速功能,实现显示内存中两个不同区域之间位块的快速移动、复制等等,包括透明处理和
Alpha 混和。应用程序可以建立一个具有逐点 Alpha 特性的内存 DC(每个点具有不同的 Alpha 值),也可以通过
SetMemDCAlpha 设置内存 DC 所有象素的 Alpha 值(或者称为"Alpha 通道"),然后利用 BitBlt 和
StretchBlt 函数实现 DC 之间的位块传送。应用程序还可以通过 SetMemDCColorKey 函数设置源 DC 的透明色,从而在进行
BitBlt 时跳过这些透明色。</P>
<P>有关内存 DC 的 GDI 函数有(include/gdi.h):</P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc
border=1><TBODY>
<TR>
<TD><PRE><CODE>#define MEMDC_FLAG_NONE 0x00000000 /* None. */
#define MEMDC_FLAG_SWSURFACE 0x00000000 /* DC is in system memory */
#define MEMDC_FLAG_HWSURFACE 0x00000001 /* DC is in video memory */
#define MEMDC_FLAG_SRCCOLORKEY 0x00001000 /* Blit uses a source color key */
#define MEMDC_FLAG_SRCALPHA 0x00010000 /* Blit uses source alpha blending */
#define MEMDC_FLAG_RLEACCEL 0x00004000 /* Surface is RLE encoded */
HDC GUIAPI CreateCompatibleDC (HDC hdc);
HDC GUIAPI CreateMemDC (int width, int height, int depth, DWORD flags,
Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask);
BOOL GUIAPI ConvertMemDC (HDC mem_dc, HDC ref_dc, DWORD flags);
BOOL GUIAPI SetMemDCAlpha (HDC mem_dc, DWORD flags, Uint8 alpha);
BOOL GUIAPI SetMemDCColorKey (HDC mem_dc, DWORD flags, Uint32 color_key);
void GUIAPI DeleteMemDC (HDC mem_dc);
</CODE>
</PRE></TD></TR></TBODY></TABLE><BR><BR>
<P>CreateCompatibleDC 函数创建一个和给定 DC 兼容的内存 DC。兼容的含义是指,新创建的内存 DC
的象素格式、宽度和高度与给定 DC 是相同的。利用这种方式建立的内存 DC 可以快速 Blit 到与之兼容的 DC 上。</P>
<P>这里需要对象素格式做进一步解释。象素格式包含了颜色深度(即每象素点的二进制位数)、调色板或者象素点中
RGBA(红、绿、蓝、Alpha)四个分量的组成方式。其中的 Alpha 分量,可以理解为一个象素点的透明度,0 表示完全透明,255
表示完全不透明。在 MiniGUI 中,如果颜色深度低于 8,则 GAL 会默认创建一个调色板,并且可以调用 SetPalette
函数修改调色板。如果颜色深度高于 8,则通过四个变量分别指定象素点中 RGBA 分量所占的位。如果是建立兼容 DC,则兼容内存 DC 和给定 DC
具有一样的颜色深度,同时具有一样的调色板或者一样的 RGBA 分量组成方式。</P>
<P>如果调用 CreateMemDC 函数,则可以指定新建内存 DC 的高度、宽度、颜色深度,以及必要的 RGBA 组成方式。在 MiniGUI
中,是通过各自在象素点中所占用的位掩码来表示 RGBA 四个分量的组成方式的。比如,如果要创建一个包含逐点 Alpha 信息的16 位内存
DC,则可以用每分量四个二进制位的方式分配 16 位的象素值,这样,RGBA 四个分量的掩码分别为:0x0000F000, 0x00000F00,
0x000000F0, 0x0000000F。</P>
<P>ConvertMemDC 函数用来将一个任意的内存 DC 对象,根据给定的参考 DC 的象素格式进行转换,使得结果 DC 具有和参考 DC
一样的象素格式。这样,转换后的 DC 就能够快速 Blit 到与之兼容的 DC 上。</P>
<P>SetMemDCAlpha 函数用来设定或者取消整个内存 DC 对象的 Alpha 通道值。我们还可以通过
MEMDC_FLAG_RLEACCEL 标志指定内存 DC 采用或者取消 RLE 编码方式。Alpha 通道值将作用在 DC
的所有象素点上。</P>
<P>SetMemDCColorKey 函数用来设定或者取消整个内存 DC 对象的 ColorKey,即透明象素值。我们还可以通过
MEMDC_FLAG_RLEACCEL 标志指定内存 DC 采用或者取消 RLE 编码方式。</P>
<P>内存 DC 和其他 DC 一样,也可以调用 GDI 的绘图函数向内存 DC 中进行任意的绘图输出,然后再 BitBlt 到其他 DC
中。下面的程序段演示了如何使用内存 DC 向窗口 DC 进行透明和 Alpha 混和的 Blitting 操作:</P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc
border=1><TBODY>
<TR>
<TD><PRE><CODE> /* 逐点 Alpha 操作 */
mem_dc = CreateMemDC (400, 100, 16, MEMDC_FLAG_HWSURFACE | MEMDC_FLAG_SRCALPHA,
0x0000F000, 0x00000F00, 0x000000F0, 0x0000000F);
/* 设置一个不透明的刷子并填充矩形 */
SetBrushColor (mem_dc, RGBA2Pixel (mem_dc, 0xFF, 0xFF, 0x00, 0xFF));
FillBox (mem_dc, 0, 0, 200, 50);
/* 设置一个 25% 透明的刷子并填充矩形 */
SetBrushColor (mem_dc, RGBA2Pixel (mem_dc, 0xFF, 0xFF, 0x00, 0x40));
FillBox (mem_dc, 200, 0, 200, 50);
/* 设置一个半透明的刷子并填充矩形 */
SetBrushColor (mem_dc, RGBA2Pixel (mem_dc, 0xFF, 0xFF, 0x00, 0x80));
FillBox (mem_dc, 0, 50, 200, 50);
/* 设置一个 75% 透明的刷子并填充矩形 */
SetBrushColor (mem_dc, RGBA2Pixel (mem_dc, 0xFF, 0xFF, 0x00, 0xC0));
FillBox (mem_dc, 200, 50, 200, 50);
SetBkMode (mem_dc, BM_TRANSPARENT);
/* 以半透明的象素点输出文字 */
SetTextColor (mem_dc, RGBA2Pixel (mem_dc, 0x00, 0x00, 0x00, 0x80));
TabbedTextOut (mem_dc, 0, 0, "Memory DC with alpha.\n"
"The source DC have alpha per-pixel.");
/* Blit 到窗口 DC 上 */
start_tick = GetTickCount ();
count = 100;
while (count--) {
BitBlt (mem_dc, 0, 0, 400, 100, hdc, rand () % 800, rand () % 800);
}
end_tick = GetTickCount ();
TellSpeed (hwnd, start_tick, end_tick, "Alpha Blit", 100);
/* 删除内存 DC */
DeleteMemDC (mem_dc);
/* 具有 Alpha 通道 的内存 DC:32 位,RGB 各占 8 位,无 Alpha 分量 */
mem_dc = CreateMemDC (400, 100, 32, MEMDC_FLAG_HWSURFACE | MEMDC_FLAG_SRCALPHA | MEMDC_FLAG_SRCCOLORKEY,
0x00FF0000, 0x0000FF00, 0x000000FF, 0x00000000);
/* 输出填充矩形和文本到内存 DC 上 */
SetBrushColor (mem_dc, RGB2Pixel (mem_dc, 0xFF, 0xFF, 0x00));
FillBox (mem_dc, 0, 0, 400, 100);
SetBkMode (mem_dc, BM_TRANSPARENT);
SetTextColor (mem_dc, RGB2Pixel (mem_dc, 0x00, 0x00, 0xFF));
TabbedTextOut (mem_dc, 0, 0, "Memory DC with alpha.\n"
"The source DC have alpha per-surface.");
/* Blit 到窗口 DC 上 */
start_tick = GetTickCount ();
count = 100;
while (count--) {
/* 设置内存 DC 的 Alpha 通道 */
SetMemDCAlpha (mem_dc, MEMDC_FLAG_SRCALPHA | MEMDC_FLAG_RLEACCEL, rand () % 256);
BitBlt (mem_dc, 0, 0, 400, 100, hdc, rand () % 800, rand () % 800);
}
end_tick = GetTickCount ();
TellSpeed (hwnd, start_tick, end_tick, "Alpha Blit", 100);
/* 填充矩形区域, 并输出文字 */
FillBox (mem_dc, 0, 0, 400, 100);
SetBrushColor (mem_dc, RGB2Pixel (mem_dc, 0xFF, 0x00, 0xFF));
TabbedTextOut (mem_dc, 0, 0, "Memory DC with alpha and colorkey.\n"
"The source DC have alpha per-surface.\n"
"And the source DC have a colorkey, \n"
"and RLE accelerated.");
/* 设置内存 DC 的透明象素值 */
SetMemDCColorKey (mem_dc, MEMDC_FLAG_SRCCOLORKEY | MEMDC_FLAG_RLEACCEL,
RGB2Pixel (mem_dc, 0xFF, 0xFF, 0x00));
/* Blit 到窗口 DC 上 */
start_tick = GetTickCount ();
count = 100;
while (count--) {
BitBlt (mem_dc, 0, 0, 400, 100, hdc, rand () % 800, rand () % 800);
CHECK_MSG;
}
end_tick = GetTickCount ();
TellSpeed (hwnd, start_tick, end_tick, "Alpha and colorkey Blit", 100);
/* 删除内存 DC 对象 */
DeleteMemDC (mem_dc);
</CODE>
</PRE></TD></TR></TBODY></TABLE><BR><BR>
<P><SPAN class=atitle3>4.4 增强的 BITMAP 操作</SPAN><BR>新的 GDI 函数增强了 BITMAP
结构,添加了对透明和 Alpha 通道的支持。通过设置 bmType、bmAlpha、bmColorkey 等成员,就可以使得 BITMAP
对象具有某些属性。然后可以利用 FillBoxWithBitmap/Part 函数将 BITMAP 对象绘制到某个 DC 上。你可以将 BITMAP
对象看成是在系统内存中建立的内存 DC 对象,只是不能向这种内存 DC 对象进行绘图输出。下面的示例程序从图象文件中装载一个位图对象,然后设置透明和
Alpha 通道值,最后使用 FillBoxWithBitmap 函数输出到窗口 DC 上:</P>
<TABLE cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc
border=1><TBODY>
<TR>
<TD><PRE><CODE> int tox = 800, toy = 800;
int count;
BITMAP bitmap;
unsigned int start_tick, end_tick;
if (LoadBitmap (hdc, &bitmap, "res/icon.bmp"))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -