简体   繁体   English

如何创建自定义属性,例如在C#中的按钮上添加图像?

[英]How to create a custom property like adding image on a button in c#?

I am working on a custom UI editor. 我正在使用自定义UI编辑器。 The editor allows us to place background images on buttons. 编辑器允许我们将背景图像放置在按钮上。 But, unlike the VS editor, we can't place foreground images. 但是,与VS编辑器不同,我们无法放置前景图像。

To add a property in the property bar, we simple add the following code. 要在属性栏中添加属性,我们只需添加以下代码。

        [Browsable(true), Category("Custom controls"), Description("Background Image of Control")]
        //[EditorAttribute(typeof(UIFileNameEditor), typeof(System.Drawing.Design.UITypeEditor))]
        //public UIBitmap UIBackImage
        public UIImageRes UIBackImage
        {
            get { return backImage;  }
            set { backImage = value; Invalidate(); }
        }

Now, to add a background image, we have this code 现在,要添加背景图像,我们有以下代码

        protected override void OnPaint(PaintEventArgs e)
        {
            e.Graphics.TextRenderingHint =
            System.Drawing.Text.TextRenderingHint.AntiAlias;
            e.Graphics.InterpolationMode =
                System.Drawing.Drawing2D.InterpolationMode.HighQualityBilinear;
            e.Graphics.PixelOffsetMode =
                System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
            e.Graphics.SmoothingMode =
                System.Drawing.Drawing2D.SmoothingMode.HighQuality;


            GraphicsUnit units = GraphicsUnit.Pixel;
            if (this.Is9Slice == UISlice.no && this.UIBackImage.UIImagePath != null  && this.UIBackImage.UIImagePath !="" )
            {

                Bitmap BgI = new Bitmap(this.backImage.UIImagePath);
                Rectangle dest = new Rectangle(0, 0, this.Width, this.Height);
                Rectangle src = Rectangle.Empty;
                if (backImage.UIUVRectangle.Width * backImage.UIUVRectangle.Height != 0)
                {
                    src = backImage.UIUVRectangle;
                }
                else
                {
                    src= new Rectangle(0, 0, BgI.Width, BgI.Height);
                }
                e.Graphics.DrawImage(BgI, dest, src, units);
                return;
            }
            if (this.UIBackImage.UIImagePath != null  && this.UIBackImage.UIImagePath != "")
            {
                Bitmap BgImage = new Bitmap(this.backImage.UIImagePath);
                Size BgI = new Size(UIBackImage.UIUVRectangle.Width, UIBackImage.UIUVRectangle.Height);
                Point Offset = new Point(UIBackImage.UIUVRectangle.X, UIBackImage.UIUVRectangle.Y);


                Rectangle dTopLeft, dTopCenter, dTopRight,   //Destination Rectangles
                          dMidLeft, dMidCenter, dMidRight,
                          dBottomLeft, dBottomCenter, dBottomRight;

                Rectangle sTopLeft, sTopCenter, sTopRight,   //Source Rectangles
                          sMidLeft, sMidCenter, sMidRight,
                          sBottomLeft, sBottomCenter, sBottomRight;

                int side_control;
                int side = side_control = (int)(BgI.Width < BgI.Height ? BgI.Width * 0.2f: BgI.Height * 0.2f);


                if (2 * side > this.Size.Width || 2 * side > this.Size.Height)
                    side_control = (int)(this.Width < this.Height ? this.Width / 2 : this.Height / 2);

                if (designScaleFactor != 1.0f)
                    side_control *= (int)designScaleFactor;


                dTopLeft = dTopCenter = dTopRight = dMidLeft = dMidCenter = dMidRight = dBottomLeft = dBottomCenter = dBottomRight = new Rectangle();
                sTopLeft = sTopCenter = sTopRight = sMidLeft = sMidCenter = sMidRight = sBottomLeft = sBottomCenter = sBottomRight = new Rectangle();

                /*  Top Left */
                dTopLeft.Location = new Point(0, 0);
                dTopLeft.Width = dTopLeft.Height = side_control;
                sTopLeft.Location = new Point(0 + Offset.X, 0 + Offset.Y ); // Just add the offset here for reflecting in every other rectangle
                sTopLeft.Width = sTopLeft.Height = side;

                /* Top Center */
                dTopCenter.Location = new Point(dTopLeft.Right, dTopLeft.Top);
                dTopCenter.Width = this.Width - 2 * side_control;
                dTopCenter.Height = dTopLeft.Height;
                sTopCenter.Location = new Point(sTopLeft.Right, sTopLeft.Top);
                sTopCenter.Width = BgI.Width - 2 * side;
                sTopCenter.Height = sTopLeft.Height;

                /* Top Right */
                dTopRight.Location = new Point(dTopCenter.Right, dTopCenter.Top);
                dTopRight.Width = dTopRight.Height = side_control;
                sTopRight.Location = new Point(sTopCenter.Right, sTopCenter.Top);
                sTopRight.Width = sTopRight.Height = side;

                /* Middle Top */
                dMidLeft.Location = new Point(dTopLeft.Left, dTopLeft.Bottom);
                dMidLeft.Width = dTopLeft.Width;
                dMidLeft.Height = this.Height - 2 * side_control;
                sMidLeft.Location = new Point(sTopLeft.Left , sTopLeft.Bottom );
                sMidLeft.Width = sTopLeft.Width;
                sMidLeft.Height = BgI.Height - 2 * side;

                /* Middle Center */
                dMidCenter.Location = new Point(dMidLeft.Right, dMidLeft.Top);
                dMidCenter.Width = this.Size.Width - 2 * side_control;
                dMidCenter.Height = this.Size.Height - 2 * side_control;
                sMidCenter.Location = new Point(sMidLeft.Right , sMidLeft.Top);
                sMidCenter.Width = BgI.Width - 2 * side;
                sMidCenter.Height = BgI.Height - 2 * side;

                /* Middle Right */
                dMidRight.Location = new Point(dMidCenter.Right, dMidCenter.Top);
                dMidRight.Width = side_control;
                dMidRight.Height = this.Size.Height - 2 * side_control;
                sMidRight.Location = new Point(sMidCenter.Right , sMidCenter.Top );
                sMidRight.Width = side;
                sMidRight.Height = BgI.Height - 2 * side;

                /* Bottom Left*/
                dBottomLeft.Location = new Point(dMidLeft.Left, dMidLeft.Bottom);
                dBottomLeft.Width = dBottomLeft.Height = side_control;
                sBottomLeft.Location = new Point(sMidLeft.Left , sMidLeft.Bottom );
                sBottomLeft.Width = sBottomLeft.Height = side;

                /* Bottom Center */
                dBottomCenter.Location = new Point(dBottomLeft.Right, dBottomLeft.Top);
                dBottomCenter.Width = this.Width - 2 * side_control;
                dBottomCenter.Height = side_control;
                sBottomCenter.Location = new Point(sBottomLeft.Right , sBottomLeft.Top );
                sBottomCenter.Width = BgI.Width - 2 * side;
                sBottomCenter.Height = side;

                /* Bottom Right */
                dBottomRight.Location = new Point(dBottomCenter.Right, dBottomCenter.Top);
                dBottomRight.Width = dBottomRight.Height = side_control;
                sBottomRight.Location = new Point(sBottomCenter.Right , sBottomCenter.Top );
                sBottomRight.Width = sBottomRight.Height = side;

                Image BG = (Image)BgImage;

                e.Graphics.DrawImage(BG, dTopLeft, sTopLeft, units);
                e.Graphics.DrawImage(BG, dTopCenter, sTopCenter, units);
                e.Graphics.DrawImage(BG, dTopRight, sTopRight, units);

                e.Graphics.DrawImage(BG, dMidLeft, sMidLeft, units);
                e.Graphics.DrawImage(BG, dMidCenter, sMidCenter, units);
                e.Graphics.DrawImage(BG, dMidRight, sMidRight, units);

                e.Graphics.DrawImage(BG, dBottomLeft, sBottomLeft, units);
                e.Graphics.DrawImage(BG, dBottomCenter, sBottomCenter, units);
                e.Graphics.DrawImage(BG, dBottomRight, sBottomRight, units);

            }

        }

Now, my question is, which methods need to be overridden or written to get a foreground image as well? 现在,我的问题是,还需要重写或编写哪些方法以获取前景图像?

You will need a foreground image property. 您将需要一个前景图像属性。 So taking your background image property as an example it would probably look something like this: 因此,以您的背景图片属性为例,它可能看起来像这样:

[Browsable(true), Category("Custom controls"), Description("Foreground Image of Control")]
public UIImageRes UIForeImage
{
    get { return foreImage;  }
    set { foreImage = value; Invalidate(); }
}

You will need to add the foreImage variable to the same place as the backImage (I guess these are private class variables). 您需要将添加foreImage变量在相同的地方backImage (我猜这些都是私有类变量)。

Then you should add some sections to your OnPaint method to draw your foreground image. 然后,应在OnPaint方法中添加一些部分以绘制前景图像。 Again you should look at how the background image is drawn and do something similar. 同样,您应该查看背景图像的绘制方式,并执行类似的操作。 The order things are drawn is important and so it would be important to make sure that any foreground drawing is done after the background drawing (so that the foreground stuff is drawn on top). 绘制事物的顺序很重要,因此确保在背景绘制之后进行任何前景绘制(将前景事物绘制在顶部)非常重要。 Also note that if the foreground image is opaque and the same size as the background image then you won't see the background image because you will be drawing on top of it. 还要注意,如果前景图像是不透明的,并且与背景图像大小相同,那么您将看不到背景图像,因为您将在背景图像上进行绘制。

From what I can see, it looks like you will need to add these sections to your OnPaint method: 据我所知,您似乎需要将以下部分添加到OnPaint方法中:

if (this.Is9Slice == UISlice.no && this.UIForeImage.UIImagePath != null  && this.UIForeImage.UIImagePath !="" )
{
    // Add foreground drawing code here
}

if (this.UIForeImage.UIImagePath != null  && this.UIForeImage.UIImagePath != "")
{
    // Add foreground drawing code here
}

This may be a good time to refactor the OnPaint method. 这可能是重构OnPaint方法的好时机。 You could create separate methods for PaintBackgroundImage(Graphics g) and PaintForegroundImage(Graphics g) . 您可以为PaintBackgroundImage(Graphics g)PaintForegroundImage(Graphics g)创建单独的方法。 Or you might even be able to just use one method that can be used to draw both the background and foreground images, eg PaintImage(Graphics g, UIImageRes image) . 或者,您甚至可以只使用一种可以绘制背景图像和前景图像的方法,例如PaintImage(Graphics g, UIImageRes image) Then you would call these methods from within the OnPaint method. 然后,您可以从OnPaint方法中调用这些方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM