2007-3-18 Wince5.0自定义ToolBar
做WinCE的开发时,碰到一很头疼的事(Coolpad机器)。它的菜单很难看,字体很大,样式也太简单,就选用了 CF2.0中的ToolBar控件。用户使用后反应很大,普遍说是用不方便,因为Toolbar没有文本,只有图标。所以自定义一个Toolbar,这里不方便提供所有源码,只是讲述开发过程中碰到的几点问题(主要问题),相信对其他朋友有帮助。
自定工具条ToolBarEx,我是模仿vs2005的工具条做,增加了文本功能。
1.高度25像素,图标16×16;
2.vs2005的工具条中,头部有4个点,我模仿做时,发现是8个方块(4*4像素),4个灰色方块,4个白色方块;白色方块向右下偏移1像素,这样画出来,就跟vs2005的工具条效果一致了;
3.分隔线(Separator button)。v s2005的工具条,分隔线高度20像素,颜色我选用的是Gray;
4.背景色选用渐变的颜色,CF2.0中没有提供渐变的GDI+方法,所以采取调用GDI的API函数实现,代码如下:
- WinApi.DrawNiceRectangle(hdc, frame);
- internal class WinApi
- {
- private const uint
- GRADIENT_FILL_RECT_H = 0x00000000,
- GRADIENT_FILL_RECT_V = 0x00000001,
- GRADIENT_FILL_TRIANGLE = 0x00000002,
- GRADIENT_FILL_OP_FLAG = 0x000000ff;
-
- [DllImport("coredll")]
- private static extern bool GradientFill(
- IntPtr hdc,
- TRIVERTEX[] pVertex,
- uint dwNumVertex,
- ref GRADIENT_RECT pMesh,
- uint dwNumMesh,
- uint dwMode
- );
-
- internal static void DrawNiceRectangle(IntPtr graphPort,
- Rectangle Frame, Color a, Color b)
- {
-
-
-
-
- TRIVERTEX[] vert = new TRIVERTEX[]{
- new TRIVERTEX(Frame.Left,Frame.Top,ToColor16(a.R),ToColor16(a.G),
- ToColor16(a.B),(ushort)(0)),
- new TRIVERTEX(Frame.Right,Frame.Bottom,ToColor16(b.R) ,ToColor16(b.G ),
- ToColor16(b.B) ,(ushort)(0))};
-
- GRADIENT_RECT gRect =
- new GRADIENT_RECT(0, 1);
-
- WinApi.GradientFill(graphPort, vert, 2, ref gRect, 1, WinApi.GRADIENT_FILL_RECT_V);
- }
-
- private static ushort ToColor16(byte value)
- {
- return (ushort)((int)value << 8);
- }
-
-
- internal static void DrawNiceRectangle(IntPtr graphPort, Rectangle Frame)
- {
- Color a = Color.FromArgb(239, 239, 239);
- Color b = Color.FromArgb(139, 139, 139);
- DrawNiceRectangle(graphPort, Frame, a, b);
- }
- }
这里采取的是从上至下的渐变,因为渐变高度的问题,所以有些颜色可能看不到效果,测试时可以调整高度,会看到效果。
5.点击ToolBarExButton时的效果,vs2005中的效果是深色的边框(border color)+比边框色浅一些的颜色,代码如下:
-
- Color border = Color.FromArgb(0, 0, 128);
-
- Color fillColor = GetHighlightColor(border);
-
-
- private Color GetHighlightColor(Color cl)
- {
- int num1 = (int)(cl.R * 0.2);
- int num4 = (int)(cl.G * 0.2);
- int num7 = (int)(cl.B * 0.2);
- int num2 = (int)(Color.White.R * 0.8);
- int num5 = (int)(Color.White.G * 0.8);
- int num8 = (int)(Color.White.B * 0.8);
- return Color.FromArgb(num1 + num2, num4 + num5, num7 + num8);
- }
6. 当Enabled=false时的效果,这个当初也是困扰我很久,如何灰显图标,因为我一直不愿意做个工具条,还用2套图标(正常和灰显);灰显图标的方法:
- private static bool GrayImage(Bitmap b)
- {
- BitmapData bmData = b.LockBits(new Rectangle(0, 0, b.Width, b.Height),
- ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
- int stride = bmData.Stride;
- System.IntPtr Scan0 = bmData.Scan0;
- unsafe
- {
- byte* p = (byte*)(void*)Scan0;
- int nOffset = stride - b.Width * 3;
- byte red, green, blue;
- for (int y = 0; y < b.Height; ++y)
- {
- for (int x = 0; x < b.Width; ++x)
- {
- blue = p[0];
- green = p[1];
- red = p[2];
- p[0] = p[1] = p[2] = (byte)(.299 * red + .587 * green + .114 * blue);
- p += 3;
- }
- p += nOffset;
- }
- }
- b.UnlockBits(bmData);
- return true;
- }
7. ToolBarExButtonClick事件,上面所做的都是绘制工具条,现在进入正题,如何触发按钮单击事件。我是计算鼠标按下时的位置,然后通过每个ToolBarExButton的Rect判断是否为某个button,是则抛出事件。
8. ToolBarEx代码层次,仅供参考。
ToolBarEx;
ToolBarExButton;
ToolBarExButtonClickEventArgs;
ToolBarExButtonCollection;
ToolBarExButtonStyle;
ToolBarExTextAlign;
ToolBarExDelegate;
9.效果如下:(通过PDA抓得图,有点失真,不过大致效果还能看到)
(ToolBarEx效果) (CF2.0中 ToolBar效果)
题外话,大家可以看到上面有一pda地图的界面。近半年来一直在搞移动地图引擎的开发,希望和从事相关行业的朋友交流,特别是移动地图的效率问题,大地图文件时效率问题。
(michael-zhangyu) |