简体   繁体   中英

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

I am working on a custom UI editor. The editor allows us to place background images on buttons. But, unlike the VS editor, we can't place foreground images.

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).

Then you should add some sections to your OnPaint method to draw your foreground image. 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:

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. You could create separate methods for PaintBackgroundImage(Graphics g) and 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) . Then you would call these methods from within the OnPaint method.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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