转载于https://www.cnblogs.com/pcode/articles/1687313.html
在学习C#编程应用到广州微嵌的wince平板的过程中,想做个透明图片一直不可得,搜索到一篇比较有参考价值的博文及无需积分可下载的例程。详细如下:
问题:
需要在wince5.0下实现图形化界面,用于功能导航,用过GPS导航就知道了,类似的界面。众所周知gif,PNG等图片,都是可以实现透明背景的,在win下这应该不是个问题。但在ce5.0下,无论是透明背景的ICON、PNG、GIF都无法简单实现透明背景,alpha通道会丢失。网上搜索了些资料,当然也有办法解决,大家可以查一下,但性能较低。最终按微软SDK自带的一个计算器的源码思路解决了透明背景按钮问题。
要点:
- 如何画透明背景的BMP
- 如何画按钮并实现事件
思路及解决:
- 画按钮的思路:
ImageAttributes imageAttr=new ImageAttributes();
imageAttr.SetColorKey(Color.FromArgb(255, 0, 255),Color.FromArgb(255, 0, 255));
然后使用Graphics.DrawImage(,,,,,imageAttr)函数在指定的位置上画出透明的图片。
2. 事件驱动的思路:
事先定义好各按钮的指令
public enum Command {
cmd1 = 0,//无操作
cmd2,//第一项操作
cmd3,//第二项操作
cmd4,//可自己扩展
max
}
在创建按钮的同时明确以下几个参数 容器控件、资源存放的目录、X坐标、Y坐标、背景图片、按钮的标题、非激活时的文字颜色、激活时的文字颜色、触发的指令。创建窗口,针对窗体事件做如下定义
- 在Form_Load时生成按钮,
- 在Form_OnPaint时使用按钮自身的Render函数根据自己状态(有没有被点中)重画,
- 在MouseDown时判断点击位置是否在某个按钮的内部,如果是在它内部就改变它的状态,设置状态的同时调用窗口控件的Graphics局部重画这个按钮,
- 在Form_MouseUp时判断现在的位置是不是在按钮内部,如果按下了,抬起时又移出了范围则不处理。如果按下与抬起都是在同一个按钮的边界内部则执行这个按钮所设置的指令。
以下是我使用的资源,将作为按钮的图片需要透明的部分设置成RGB(255,0,255),那种非常刺眼的颜色。以下图片可以另存为BMP使用,设置的分辨是800*600的CE设备。
按钮未点击时背景:
按钮点中时背景:
窗体抬头的背景:
放置按钮的大背景:
第三步:代码实现
创建窗体名称ImageButton,设置窗体的Menu为空TopMost=true,Size=800,600,ControlBox=false,FormBorderStyle=None
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
|
using
System;
using
System.Collections.Generic;
using
System.ComponentModel;
using
System.Data;
using
System.Drawing;
using
System.Text;
using
System.Windows.Forms;
using
System.IO;
using
System.Reflection;
namespace
DZB
{
public
partial
class
ImageButton : Form
{
private
IList<IButton> btnlist;
private
IButton capturedButton;
private
Font windowFont =
new
Font(FontFamily.GenericSansSerif, 12, FontStyle.Regular);
private
string
CurrentPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().GetName().CodeBase);
private
Bitmap bg, title;
public
ImageButton()
{
InitializeComponent();
}
private
void
ImageButton_Load(
object
sender, EventArgs e)
{
title =
new
Bitmap(CurrentPath +
@"\Resources\title.bmp"
);
bg =
new
Bitmap(CurrentPath +
@"\Resources\mainbg.bmp"
);
btnlist =
new
List<IButton>();
btnlist.Add(
new
IButton(
this
, CurrentPath +
@"\Resources\"
, 100, 100, "button.bmp
", "
按钮1", Color.White, Color.Blue, Command.cmd1));
btnlist.Add(
new
IButton(
this
, CurrentPath +
@"\Resources\"
, 100, 200, "button.bmp
", "
按钮2", Color.White, Color.Blue, Command.cmd1));
btnlist.Add(
new
IButton(
this
, CurrentPath +
@"\Resources\"
, 100, 300, "button.bmp
", "
按钮3", Color.White, Color.Blue, Command.cmd2));
btnlist.Add(
new
IButton(
this
, CurrentPath +
@"\Resources\"
, 100, 400, "button.bmp
", "
按钮4", Color.White, Color.Blue, Command.cmd2));
btnlist.Add(
new
IButton(
this
, CurrentPath +
@"\Resources\"
, 400, 100, "button.bmp
", "
按钮5", Color.White, Color.Blue, Command.cmd2));
btnlist.Add(
new
IButton(
this
, CurrentPath +
@"\Resources\"
, 400, 200, "button.bmp
", "
按钮6", Color.White, Color.Blue, Command.cmd2));
btnlist.Add(
new
IButton(
this
, CurrentPath +
@"\Resources\"
, 400, 300, "button.bmp
", "
按钮7", Color.White, Color.Blue, Command.cmd2));
btnlist.Add(
new
IButton(
this
, CurrentPath +
@"\Resources\"
, 400, 400, "button.bmp
", "
按钮8", Color.White, Color.Blue, Command.cmd3));
}
private
void
ImageButton_Paint(
object
sender, PaintEventArgs e)
{
// Buttons
Graphics graphics;
graphics = e.Graphics;
graphics.DrawImage(title, 0, 0);
graphics.DrawImage(bg, 0, 63);
// Edit line
foreach
(IButton btn
in
btnlist)
{
btn.Render(graphics);
}
}
protected
override
void
OnPaintBackground(PaintEventArgs paintArgs)
{
//gr.DrawImage(img, 0, 0);
base
.OnPaintBackground(paintArgs);
}
~ImageButton()
{
windowFont.Dispose();
}
private
void
ImageButton_MouseDown(
object
sender, MouseEventArgs e)
{
foreach
(IButton btn
in
btnlist)
{
if
(btn.IsHit(e.X, e.Y))
{
btn.IsSelected =
true
;
capturedButton = btn;
break
;
}
}
}
private
void
ImageButton_MouseMove(
object
sender, MouseEventArgs e)
{
if
(capturedButton !=
null
)
{
capturedButton.IsSelected = capturedButton.IsHit(e.X, e.Y);
}
}
private
void
ImageButton_MouseUp(
object
sender, MouseEventArgs e)
{
if
(capturedButton !=
null
)
{
if
(capturedButton.IsHit(e.X, e.Y))
DoCommand(capturedButton.Cmd);
try
{
capturedButton.IsSelected =
false
;
capturedButton =
null
;
}
catch
{
}
}
}
/// <summary>
/// 执行指令
/// </summary>
/// <param name="command"></param>
private
void
DoCommand(Command command)
{
switch
(command)
{
case
Command.cmd1:
//0
// this.Close();
break
;
case
Command.cmd2:
//1
MessageBox.Show(
"cmd2"
);
break
;
case
Command.cmd3:
//2
this
.Close();
break
;
case
Command.cmd4:
//3
{
Line nl =
new
Line();
nl.Show();
}
break
;
default
:
break
;
}
}
}
}
|
IButton.cs 类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
|
//======================================================================
//
// Copyright (C) 2008-2009 PCODE TEAM. All rights reserved.
//
// CLR Version: 2.0.50727.1433
// NameSpace: DZB FileName: IButton.Cs
//
// Created by Jy at 2009/9/10 22:07:34
// Email:jy@cjlu.edu.cn
//
//======================================================================
using
System;
using
System.Collections.Generic;
using
System.Text;
using
System.Windows.Forms;
using
System.Drawing;
using
System.Drawing.Imaging;
namespace
DZB {
public
class
IButton {
private
Control MainForm;
private
Font sFont =
new
Font(FontFamily.GenericSansSerif,16, FontStyle.Bold);
private
Font sFont_ =
new
Font(FontFamily.GenericSansSerif, 16, FontStyle.Bold);
private
bool
IsSelectedValue;
private
Command ButtonCommand;
private
Rectangle selfRec;
private
string
_caption;
private
float
_cx, _cy;
//画标题的位置
private
Bitmap btnbg, btnbg_;
private
string
_CurrentPath;
Color transpColor = Color.FromArgb(255, 0, 255);
//资源文件的透明色
ImageAttributes imageAttr;
Color _ncolor, _fcolor;
Graphics g, g_;
/// <summary>
/// 初始化
/// </summary>
/// <param name="form">容器名称</param>
/// <param name="CurrentPath">当前程序路径</param>
/// <param name="x">按钮位置X</param>
/// <param name="y">按钮位置Y</param>
/// <param name="bgfilename">按钮图片名称</param>
/// <param name="caption">标题</param>
/// <param name="nColor">正常颜色</param>
/// <param name="fColor">激活颜色</param>
/// <param name="cmd">指令</param>
public
IButton(Control form,
string
CurrentPath,
int
x,
int
y,
string
bgfilename,
string
caption,Color nColor,Color fColor, Command cmd) {
MainForm = form;
_ncolor = nColor;
_fcolor = fColor;
ButtonCommand = cmd;
_caption = caption;
_CurrentPath = CurrentPath;
string
bg = CurrentPath + bgfilename;
string
bg_ = CurrentPath +System.IO.Path.GetFileNameWithoutExtension(bg) +
"_.bmp"
;
btnbg =
new
Bitmap(bg);
selfRec =
new
Rectangle(x, y, btnbg.Width,btnbg.Height);
g = Graphics.FromImage(btnbg);
_cx = (219 - g.MeasureString(_caption, sFont).Width) / 2;
_cy = (48 - g.MeasureString(_caption, sFont).Height) / 2;
btnbg_=
new
Bitmap(bg_);
g_ = Graphics.FromImage(btnbg_);
imageAttr =
new
ImageAttributes();
imageAttr.SetColorKey(transpColor, transpColor);
}
public
void
Render(Graphics graphics) {
if
(IsSelectedValue) {
//点下的状态
g_.DrawString(_caption, sFont_,
new
SolidBrush(_fcolor), _cx,_cy);
graphics.DrawImage(btnbg_, selfRec, 0, 0, selfRec.Width, selfRec.Height, GraphicsUnit.Pixel, imageAttr);
}
else
{
g.DrawString(_caption, sFont,
new
SolidBrush(_ncolor),_cx, _cy);
graphics.DrawImage(btnbg, selfRec, 0, 0, selfRec.Width, selfRec.Height, GraphicsUnit.Pixel, imageAttr);
}
}
private
static
Color GetTransparentColor(Image image) {
return
((Bitmap)image).GetPixel(image.Width - 1, image.Height - 1);
}
public
bool
IsHit(
int
x,
int
y) {
return
(x >= selfRec.X &&
x < selfRec.X +selfRec.Width &&
y >= selfRec.Y &&
y <selfRec.Y+selfRec.Height);
}
public
bool
IsSelected {
get
{
return
IsSelectedValue;
}
set
{
Graphics graphics;
if
(value != IsSelectedValue) {
IsSelectedValue = value;
// Redraw right away
graphics = MainForm.CreateGraphics();
this
.Render(graphics);
graphics.Dispose();
}
}
}
public
Command Cmd {
get
{
return
(ButtonCommand);
}
}
}
}
|
最终效果:
透明背景的按钮实现成功
总结:
此方案的优点:
- 思路简单,实现过程没有特别复杂的技术环节
- 因是局部重画,即使在800*600这样的分辨率下也能达到不闪烁的效果
- 按钮可配置性高,更换资源文件即可实现对按钮及整体风格的改变
此方案的缺点:
- 按钮图片与背景间不能实现ALPHA的渐透明
- 按钮的驱动虽然实现,但没有很OO。(微软也是这么写代码的,所以也不算大问题)
- 资源图片要按像素级处理透明色,有些麻烦。(项目组有美工的话还好做些)
以下再列几个我自己做的风格给大家参考
山水皮肤
冬奥皮肤
希望我的综合对大家有帮助。