前言
关键字:.NetCF 半透明、AlphaBlend
用C#开放Windows Mobile刚好满一个月,一直是边看文章边写点小例子,而这些例子里面半透明效果是最让人心动的,本文主要收集和实践了关于.Net CF半透明效果例子,以及自己一点点经验和需要注意的问题。
正文
一、绘制透明标签控件(Label)
1.1 效果图
1.2 代码
1.2.1 实现代码
///
<summary>
///
透明Label控件
///
注意,将Label的Visible设置为false;适合背景为图片(PictureBox)
///
</summary>
///
<param name="label"></param>
///
<param name="g"></param>
public
static
void
TransparentLabel(Label label, Graphics g)
{
Rectangle rect
=
label.Bounds;
SolidBrush sb
=
new
SolidBrush(label.ForeColor);
SizeF size;
//
计算字符串的位置
switch
(label.TextAlign)
{
case
ContentAlignment.TopLeft:
break
;
case
ContentAlignment.TopCenter:
//
计算字符串长度
size
=
g.MeasureString(label.Text, label.Font);
rect.X
+=
(
int
)((rect.Width
-
size.Width)
/
2
);
rect.Y
+=
(
int
)((rect.Height
-
size.Height)
/
2
);
break
;
case
ContentAlignment.TopRight:
size
=
g.MeasureString(label.Text, label.Font);
rect.X
+=
rect.Width
-
(
int
)size.Width;
rect.Y
+=
rect.Height
-
(
int
)size.Height;
break
;
}
g.DrawString(label.Text, label.Font, sb, rect);
sb.Dispose();
}
1.2.2 调用代码
private
void
pictureBox1_Paint(
object
sender, PaintEventArgs e)
{
TransparentLabel(
this
.label1, e.Graphics);
}
1.2.3 代码说明
虽然本节说的是Label透明化,实际上可以看得出并没有将字透明化,只是"去掉"了Label的背景。这里Label控件充当了保存字符串信息的作用,实际调用DrawString直接画在屏幕上去的。
a). 因为是Label是在PictureBox上,所以在其Paint事件中绘制Label中的字符串;如果没有PictureBox作为背景,而是直接在Form窗体上,那么把这段代码写到窗体的OnPain中即可。
1.3 注意问题
1.3.1 需要将Label的Visiable设置为false!
二、绘制透明图片(PictureBox)
2.1 效果图
2.2 代码
2.2.1 实现代码
///
<summary>
///
绘制透明图片
///
</summary>
///
<param name="gxBuffer"></param>
///
<param name="barImage"></param>
///
<param name="barRect"></param>
///
<param name="transp"></param>
public
static
void
DrawAlpha(Graphics gxBuffer, Image barImage, Rectangle barRect,
byte
transp)
{
using
(Graphics gxSrc
=
Graphics.FromImage(barImage))
{
IntPtr hdcDst
=
gxBuffer.GetHdc();
IntPtr hdcSrc
=
gxSrc.GetHdc();
BlendFunction blendFunction
=
new
BlendFunction();
blendFunction.BlendOp
=
(
byte
)BlendOperation.AC_SRC_OVER;
blendFunction.BlendFlags
=
(
byte
)BlendFlags.Zero;
blendFunction.SourceConstantAlpha
=
transp;
blendFunction.AlphaFormat
=
(
byte
)
0
;
AlphaBlend(hdcDst, barRect.Left, barRect.Top, barRect.Size.Width, barRect.Size.Height, hdcSrc,
0
,
0
, barImage.Width, barImage.Height, blendFunction);
gxBuffer.ReleaseHdc(hdcDst);
gxSrc.ReleaseHdc(hdcSrc);
}
}
///
<summary>
///
绘制透明图象
///
</summary>
///
<param name="hdcDest">
生成画面的Handle
</param>
///
<param name="xDest">
生成画面的x
</param>
///
<param name="yDest">
生成画面的y
</param>
///
<param name="cxDest">
生成画面的width
</param>
///
<param name="cyDest">
生成画面的height
</param>
///
<param name="hdcSrc">
原图的Handle
</param>
///
<param name="xSrc">
原图的x
</param>
///
<param name="ySrc">
原图的y
</param>
///
<param name="cxSrc">
原图的width
</param>
///
<param name="cySrc">
原图的height
</param>
///
<param name="blendFunction">
控制 Alpha 混合的结构
</param>
///
<returns></returns>
[DllImport(
"
coredll.dll
"
)]
extern
public
static
Int32 AlphaBlend(IntPtr hdcDest, Int32 xDest, Int32 yDest, Int32 cxDest, Int32 cyDest, IntPtr hdcSrc, Int32 xSrc, Int32 ySrc, Int32 cxSrc, Int32 cySrc, BlendFunction blendFunction);
2.2.2 调用代码
private
void
pictureBox1_Paint(
object
sender, PaintEventArgs e)
{
CFControlUtility.DrawAlpha(e.Graphics, pbBar.Image, pbBar.Bounds,
170
);
}
2.2.3 代码说明
a). transp值为0-255,0为完全透明,255为无透明效果。
2.3 注意问题
将需要透明效果图片的Visiable设置为false!
三、绘制透明表格
3.1 效果图
3.2 实现代码
private
void
pictureBox1_Paint(
object
sender, PaintEventArgs e)
{
Bitmap offBitmap
=
new
Bitmap(
100
,
100
);
Graphics gxBuffer
=
Graphics.FromImage(offBitmap);
//
清空底色
gxBuffer.Clear(
this
.BackColor);
Pen pen
=
new
Pen(Color.DodgerBlue);
Font font
=
new
Font(
"
Arial
"
,
10
, FontStyle.Regular);
SolidBrush brush
=
new
SolidBrush(Color.Black);
int
width, height
=
0
;
//
绘制2列4行数据
for
(
int
i
=
0
; i
<
4
; i
++
)
{
width
=
0
;
for
(
int
j
=
0
; j
<
2
; j
++
)
{
//
绘制数据
gxBuffer.DrawString(
"
测试数据
"
, font, brush, width, height);
width
+=
50
;
//
绘制竖线
if
(i
==
0
)
gxBuffer.DrawLine(pen, width,
0
, width, offBitmap.Height);
}
height
+=
25
;
//
绘制横线
gxBuffer.DrawLine(pen,
0
, height, offBitmap.Width, height);
}
brush.Dispose();
font.Dispose();
pen.Dispose();
gxBuffer.Dispose();
//
将内存中的图片绘制到界面上来
DrawAlpha(e.Graphics, offBitmap,
new
Rectangle(
50
,
100
, offBitmap.Width, offBitmap.Height),
170
);
//
e.Graphics.DrawImage(offBitmap, 50, 100);
}
3.3 代码说明
a). 这里在内存中绘制了临时图片offBitmap,然后再将临时图片绘制显示到设备上面来的,这样可以极大提高性能,大家可以直接用e.Graphics一笔笔绘制比较看下性能。
b). 用完绘图对象相关对象之后记得Dispose掉,或者用using代码块。
四、 其他
4.1 屏幕闪烁问题
protected
override
void
OnPaintBackground(PaintEventArgs e)
{
//
base.OnPaintBackground(e);
}
4.2 直接用e.Graphics绘制文字+图片的时候可能出现闪烁的问题
在绘制完文字后再覆盖一张透明度为0的空图片即可,用内存临时图片不会有这问题的。
4.3 绘制控件透明时,千万记得把控件的Visible设置为false。该控件只是充当绘制信息存储作用,其鼠标事件(Mouse)全部会没有(这不废话- - #,控件都隐藏了),所以要做判断得再PictureBox或窗体的相关事件里面做判断,然后再判断点击的位置来识别到底是否点击的透明控件。
4.4 Graphics相关方法需要都弄清楚用熟练了,非常有用,比如MeasureString可以计算字符串的长度,可以控制绘制字符串的位置;FillRectangle可以填充矩阵,画行的背景色的时候可以用。
4.5 如果大规模的绘制透明效果,需要特别注意性能问题,可以采取措施如临时图片、内存缓存数据等。
4.6 通过取消单色显示来达到透明效果,但是效果不太理想,相关的对象:ImageAttributes。
结束语
如果被这种透明效果吸引甚至打算在项目中使用,那么要做好吃苦耐劳的准备,大部分控件都要重绘,处理非常多的逻辑判断,比较麻烦- - #。
本博相关文章 1. .netcf 图片区域拷贝[图片切割]