65.9K
CodeProject 正在变化。 阅读更多。
Home

循环选择按钮

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.07/5 (10投票s)

2005年3月28日

3分钟阅读

viewsIcon

80581

downloadIcon

431

本文介绍了一个CycleButton控件。

Cycle button

引言

开发人员经常需要为一个按钮分配多个功能,例如,使用单个按钮打印不同的报表。开发人员必须在窗体上放置复选框列表或组合框来选择要打印的报表。此外,这需要开发人员付出额外的努力和时间,并且对于用户来说点击多个控件也不是很方便。

一种解决方案是将按钮和选择控件组合成一个。它节省了窗体上的空间,减少了开发人员的工作量,并且对最终用户来说很方便。用户可以通过右键单击按钮来选择按钮应执行的操作。每次右键单击后,按钮的标题、图像及其应执行的操作都会发生变化。如果您左键单击按钮的右下角,也可以实现相同的功能。会出现一个上下文菜单,您可以从中选择操作。此功能类似于标准ToolBar按钮的功能。但是工具栏按钮仅在工具栏内工作,而CycleButton可以独立于其他控件在窗体的任何位置使用。

使用控件

首先,将编译后的控件添加到工具箱。使用选项的标题填充Captions属性。可选地,您可以设置CaptionsImageList ImageList,每个标题一个图像。在Click事件处理程序中,检查Index属性并执行相应的操作。

使用代码

首先,在CycleButton构造函数中,我们应该定义MouseDownPaint事件处理程序。然后,我们加载一个表示按钮右下角箭头的位图。

//Here image resource is extracted and loaded into image.

System.Resources.ResourceManager myManager = 
   new System.Resources.ResourceManager(typeof(CycleButton));
Stream st = 
   Assembly.GetExecutingAssembly().GetManifestResourceStream("AO.arrow.bmp");
loadedImage = System.Drawing.Image.FromStream(st);

Paint事件处理程序中,我们绘制一个箭头,然后根据当前标题索引设置标题文本和图像。箭头的绘制和图像的绘制类似。唯一的区别在于我们将箭头绘制为嵌入式资源,而标题图像则取自由CaptionsImageList属性设置的ImageList

//Preparation of parallelogram that locates the image on the screen
Point ulCorner = new Point(this.ClientSize.Width-15,this.ClientSize.Height/2-5);
Point urCorner = new Point(this.ClientSize.Width-4,this.ClientSize.Height/2-5);
Point llCorner = new Point(this.ClientSize.Width-15,this.ClientSize.Height/2+3);
Point[] destPara = {ulCorner, urCorner, llCorner};

//Make the background of the button invisible
System.Drawing.Color lowerColor = System.Drawing.Color.FromArgb(255,255,255);
System.Drawing.Color upperColor = System.Drawing.Color.FromArgb(255,255,255);
System.Drawing.Imaging.ImageAttributes imageAttr = 
                              new System.Drawing.Imaging.ImageAttributes();
imageAttr.SetColorKey(lowerColor, upperColor, 
                              System.Drawing.Imaging.ColorAdjustType.Default);

//Drawing itself
System.Drawing.Graphics deviceContext = e.Graphics;
deviceContext.DrawImage(loadedImage, destPara, 
      new Rectangle(0, 0, 11, 8), GraphicsUnit.Pixel, imageAttr);

//Assign text according to the current caption index.
if (captionsarray.GetLength(0)>0)
{
    this.Text=captionsarray[index];

    //Drawing custom image
    // just to check we won't get out of bounds of the array
    // we can't use standrart Image property,
    // so image should be drawn from client code
    if ((captionsImageList!=null) && 
        (captionsImageList.Images.Count==captionsarray.Length))
    {
        //ident based on size of the image
        int topident=ClientSize.Height - captionsImageList.ImageSize.Height > 0 ? 
                    (ClientSize.Height-captionsImageList.ImageSize.Height)/2 : 0;

        //preparation of parallelogram that locates the image on the screen
        //image strictly aligned at left middle, 
        //as right part of the button is used for arrow
        Point ulCorner1 = new Point(4,topident);
        Point urCorner1 = new Point(captionsImageList.ImageSize.Width+4,topident);
        Point llCorner1 = new Point(4,captionsImageList.ImageSize.Height+topident);
        Point[] destPara1 = {ulCorner1, urCorner1, llCorner1};

        //drawing itself
        System.Drawing.Graphics deviceContext1 = e.Graphics;
        deviceContext.DrawImage(captionsImageList.Images[index],destPara1,
        new Rectangle(0,0, captionsImageList.ImageSize.Width, 
                      captionsImageList.ImageSize.Height, GraphicsUnit.Pixel);
    }

OnMouseDown函数中,我们处理左键单击和右键单击。左键单击检查用户是否单击了箭头,如果是,则从标题数组动态构建菜单,最后显示它。每个菜单项都连接到OnClick方法。在OnClick方法中,分配当前索引,然后通过调用用户分配的OnClick事件处理程序来模拟按钮的单击。

右键单击只是循环递增计数器并设置相应的标题和图像。

switch (e.Button)
{
    case MouseButtons.Right:
    // Circle counter incriment and caption change

        if (captionsarray.GetLength(0)>0)
        {
            if ((captionsarray.GetLength(0))==index+1)
            {
                index=0;
                this.Text=captionsarray[index];
                return;
            }
        }
        this.Text=captionsarray[++index];
        break;

    case MouseButtons.Left:
    // checks whether user clicks on the arrow or somewhere else

        if ((e.X>this.ClientSize.Width-15) && (captionsarray.GetLength(0)>0))
        {
            // creates menu from captionsarray array and displays it
            cm=new ContextMenu();
            foreach (string str in captionsarray)
            {
                cm.MenuItems.Add(str,new EventHandler (OnClick));
            }
            cm.MenuItems[index].Checked=true;
            cm.Show(this, new Point(this.ClientSize.Width-15, 
                      this.ClientSize.Height/2-5));
        }
        break;

因此,用户有两种激活按钮的方法。第一种,右键单击几次,然后左键单击执行操作;第二种,左键单击箭头并从菜单中选择相应的项目。

关注点

七年前,当我开发一个Delphi应用程序时,我遇到了一个问题:如何用一个按钮打印多个报表。因此,我开发了这样一个控件,并且在两年前,我将该控件的逻辑转移到了.NET。现在我决定在CodeProject上发布它。

© . All rights reserved.