代码改变世界

Wince5.0自定义工具条

2008-03-19 11:43  老羽  阅读(1811)  评论(4编辑  收藏  举报
 

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+方法,所以采取调用GDIAPI函数实现,代码如下:

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,           // handle to DC

          TRIVERTEX[] pVertex,    // array of vertices

          uint dwNumVertex,     // number of vertices

          ref GRADIENT_RECT pMesh,           // array of gradients

          uint dwNumMesh,       // size of gradient array

          uint dwMode           // gradient fill mode

        );

 

        internal static void DrawNiceRectangle(IntPtr graphPort, Rectangle Frame, Color a, Color b)

        {

            // Draw from whitish blue at the top, to a light blue at the bottom

            //TRIVERTEX[] vert = new TRIVERTEX[]{

            //        new TRIVERTEX(Frame.Left,Frame.Top,0xff00,0xff00,0xffff,0xff00),

            //        new TRIVERTEX(Frame.Right,Frame.Bottom,0x0000,0x0000,0xff00,0xff00)};

            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)+比边框色浅一些的颜色,代码如下:

 

//我采取的border color

Color border = Color.FromArgb(0, 0, 128);

//计算填充色

Color fillColor = GetHighlightColor(border);

       

//原理就是将指定的Color淡化,请注意2个系数相加必须=1;用户可以自己调整系数,调节颜色的深度

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事件,上面所做的都是绘制工具条,现在进入正题,如何触发按钮单击事件。我是计算鼠标按下时的位置,然后通过每个ToolBarExButtonRect判断是否为某个button,是则抛出事件。

8.  ToolBarEx代码层次,仅供参考

ToolBarEx;

ToolBarExButton;

ToolBarExButtonClickEventArgs;

ToolBarExButtonCollection;

ToolBarExButtonStyle

ToolBarExTextAlign;

ToolBarExDelegate;

9.             效果如下:(通过PDA抓得图,有点失真,不过大致效果还能看到)

(ToolBarEx效果)                     (CF2.0 ToolBar效果)

 

   题外话,大家可以看到上面有一pda地图的界面。近半年来一直在搞移动地图引擎的开发,希望和从事相关行业的朋友交流,特别是移动地图的效率问题,大地图文件时效率问题。