Answered Fill a complex external shape on a PictureBox

Leden

Member
Joined
Jul 24, 2020
Messages
9
Programming Experience
10+
Hi, I am quite new to C# and would like to re-write an app that I have developed in VBA recently.
I have several complex shapes drawn externally in PowerPoint and saved as .png and/or .bmp pictures. I have loaded one of them manually on the pictureBox1. Now I want to fill solidcolor it by a control, say a slider at a rate of app 5-10 RGB colors per second over a range (there are 250+ colors over the entire range of the vertical slider).
How can I do this? Most of the 'Fill Color' examples I've found on the web deal with drawing a rectangle/oval and then filling it. Since I already have a shape loaded on the Form how can I introduce it and then change the color? My picture consists of two parts: Outer block - a rectangle working as a background and an irregular inner shape which needs to be painted/filled. To give the Fill effect of a Paint program am I supposed to define a pixel inside the inner shape first?
Thank you..
 
Hello, and welcome to the forums.

So what is the problem? I don't see any code above in your post to show what you've tried.

Since I already have a shape loaded on the Form how can I introduce it and then change the color?
Since you are coming to C# from VBA. I think you need to specify which project type you are planning on designing this new application? If you are choosing Winforms, I'd say you are wasting your time, as Winforms is EOL and dated, and secondly, I would suggest undertaking this in WPF. WPF provide shapes which might be better for you to work with depending on what exactly it is you are trying to do. WPF is also faster and designed for working with shapes and drawing. . .

Whats the purpose of your picturebox?
 
Last edited:
The app I have in VBA mainly consists of a Form with an Image Control in the center. Then there are two sliders, horizontal one changes the Shapes (from 1 to 7) whereas the vertical one changes the color of the shape over a temperature color-scheme. Together they form the correct picture which the user decides. In other words, the correct picture is the correct shape filled with the desired temp-color. Once the picture is fixed the User selects other parameters on the Form from ListBox or Radio Button controls and finally clicking the Calculate button you get the calculated equipment capacity. It is a kind of engineering calculator. I cannot attach any code because all I have is an incomplete form but no code yet. All I try yield errors.. Maybe the screen view of the VBA Excel form gives you a better visualization of my problem, which I attach.. I have included just three cases out of several options.
 

Attachments

  • VBA Form to convert to C#.pdf
    361.5 KB · Views: 26
As I kinda suspected. Ok so don't use Winforms because its old and dated and EOL.

WPF out-performs it with speed alone and its specifically designed for projects which include drawing and working with shapes.

In WPF you can take advance of rectangles fill property. In Xaml, you'd do something like :

C#:
<Rectangle Width="650" Height="320">
    <Rectangle.Fill>
        <SolidColorBrush Color="Blue" />
    </Rectangle.Fill>
</Rectangle>
Or code behind :
C#:
Rectangle_Obkect.Fill = new SolidColorBrush(Color.FromRgb(0, 130, 222));

More on that here : Shape.Fill Property (System.Windows.Shapes)

For drawing shapes and such, you can see : Shapes and basic drawing overview - WPF

So overall, WPF is the goto project in my opinion. Hope you find the links helpful. If you get stuck, you will need to post back with some actual code and show what you've tried. (y)
 
Great.. Thank you very much. I'll follow your advice. Hope that I can tackle this critical point and the rest is more straightforward!

Mod edit: No need to quote whole quotes. Select the portion you want to quote instead. Otherwise it take up unnecessary space for mobile users.
 
Last edited by a moderator:
Although you suggested I should go WPF, unfortunately I couldn't get even this far there.. At least, I can change the 7 pictures with the horizontal slider. My pictures are loaded in the Resources as Part1.png to Part7.png and I select and retrieve them within the Method ActivePicture() which is called by the scroll-event handler of the hor slider, as in the following:

C#:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApp5
{
    public partial class Form1 : Form
    {        
        public Form1()
        {
            InitializeComponent();
            
            label1.Text = "Part" + (hScrollBar1.Value / 10);
            label2.Text = "" + (hScrollBar1.Value / 10);

            ActivePicture();

        }
        private void ActivePicture()
        {
            int caseSwitch = (hScrollBar1.Value / 10);

            switch (caseSwitch)
            {
                case 1:
                    pictureBox1.Image = Properties.Resources.Part1;
                    break;
                case 2:
                    pictureBox1.Image = Properties.Resources.Part2;
                    break;
                case 3:
                    pictureBox1.Image = Properties.Resources.Part3;
                    break;
                case 4:
                    pictureBox1.Image = Properties.Resources.Part4;
                    break;
                case 5:
                    pictureBox1.Image = Properties.Resources.Part5;
                    break;
                case 6:
                    pictureBox1.Image = Properties.Resources.Part6;
                    break;
                default:
                    pictureBox1.Image = Properties.Resources.Part7;
                    break;
            }
        }


        private void hScrollBar1_Scroll(object sender, ScrollEventArgs e)
        {
            ActivePicture();
            
            label1.Text = "Part" + (hScrollBar1.Value / 10);
            label2.Text  = "" + (hScrollBar1.Value / 10);
        }
        private void vScrollBar1_Scroll(object sender, ScrollEventArgs e)
        {
            ActivePicture();

            //FillPathEllipse();
        }
        public void FillPathEllipse(PaintEventArgs e)
        {
            // Create solid brush.
            SolidBrush redBrush = new SolidBrush(Color.Red);

            // Create graphics path object and add ellipse.
            GraphicsPath graphPath = new GraphicsPath();
            graphPath.AddEllipse(0, 0, 200, 100);

            // Fill graphics path to screen.
            e.Graphics.FillPath(redBrush, graphPath);
        }
    }
}

Q1) Is there a better way to replace my method ActivePicture() that I have used caseSwitch? I have tried array of images with no success
Q2) This is the more important part. Now I want the vSliderBar1 to change the color of the part selected by the hSliderBar1 several times (250+ RGB colors) along the scroll movement up. I have tried several methods through your suggested links but unfortunately I failed. I was hoping to fill a small ellipse in the center of the Pictures but it also throws error which somehow I cannot get to working.

If I get a successful result (Q2) in WinForms my next challenge would be to try the same in WPF.. Thanks
 
Last edited by a moderator:
We can't help you with Q2 if you don't tell us what the errors your are getting are. What are they?

Can we assuming that you have attached FillPathEllipse() to the Paint event of the picture box?

As for Q1, when you have code that looks like that the go to data structure would be an array or dictionary. Can you show us your attempt at using an array?
 
Ref to Q2..
I have attached the FillPathEllipse() to the Scroll event of the vertical Slider and the error I get:

C#:
        private void vScrollBar1_Scroll(object sender, ScrollEventArgs e)
        {
            ActivePicture();
            FillPathEllipse();  // This is where the error throws as "there is no argument given that corresponds to

            // the required formal parameter  'e' of 'Form1.FillPathEllipse(PaintEventArgs)'

        }
        public void FillPathEllipse(PaintEventArgs e)
        {
            // Create solid brush.
            SolidBrush redBrush = new SolidBrush(Color.Red);
            // Create graphics path object and add ellipse.
            GraphicsPath graphPath = new GraphicsPath();
            graphPath.AddEllipse(0, 0, 200, 100);

            // Fill graphics path to screen.

            e.Graphics.FillPath(redBrush, graphPath);
        }
 
Last edited by a moderator:
Ref to Q1..

I have tried the Picture array as follows, which I got from another similar case in this forum:

C#:
        public Form1()
        {
            InitializeComponent();
            
            label1.Text = "Part" + (hScrollBar1.Value / 10);
            label2.Text = "" + (hScrollBar1.Value / 10);

            //ActivePicture();

            pictureBox1.Image = getImages(0);  // error message: No overload for method 'getImages' takes 1 arguments

        }

        private Image[] getImages()
        {
            Image[] images = new Image[7];

            images[0] = Properties.Resources.Part1;
            images[1] = Properties.Resources.Part2;
            images[2] = Properties.Resources.Part3;
            images[3] = Properties.Resources.Part4;
            images[4] = Properties.Resources.Part5;
            images[5] = Properties.Resources.Part6;
            images[6] = Properties.Resources.Part7;

            return images;
        }
 
Line 9 tells you what it is if you read your own code.
Thank you! But please don't bother to help if you don't want to be a bit more explicit in your answers to a newcomer...
No use of repeating what the error messages already tells. If I could do with them I wouldn't be here at the first place!
 
Back
Top Bottom