Solved

Picture box event handling with strange effect

Posted on 2011-09-15
7
653 Views
Last Modified: 2013-12-17
Hello!

I am currently employed the first time in a C# .NET Frameworks project with Windows Forms. All the subjects are new to me. I am prototyping to find out how to solve different parts of the GUI so that they can first be specified (functional specification) and then implemented in the next six month or so.

One of the more involved dialogues has a coordinate system with a number of waveforms displayed. What I want to do is to change the vertical scaling (A, V, VA, W, etc.), if the user double-clicks on one of the waveforms.

To start the drawing of the waves, I use the following code:
 
/// <summary>
        /// Standard constructor
        /// </summary>
        public SignalsForm()
        {
[...]
            // Now, draw the waveforms, the surrounding box so that excessive waveforms going
            // out of bounds are not visible, and the coordinates:
            Pen pen = new Pen(Color.Gray);

            DrawWaveforms(pen);
            SolidBrush brush = new SolidBrush(Color.White);

            DrawSurroundingAreas(pen, brush);
            DrawCoordinates(pen, brush, usINCREMENT);
        }
[...]

Open in new window


All the code worked fine till the problem arose that I am going to ask you.

Details
To catch the mouse double-click event, I use the event handler by clicking on the control -a picture box- and selecting the events button under the properties in the Microsoft Visual Studio 2010 Premium - a button with a lightning symbol on it.

Here is the code for it:
 
private void pictureBox_MouseDoubleClick(object sender, MouseEventArgs meas)
        {
            ClearBottom();
            ClearLeft();
        }

Open in new window


Interestingly, ClearBottom() & ClearLeft() used inside the pictureBox_MouseDoubleClick(...) method is also used in the SignalsForm class constructor indirectly (DrawSurroundingAreas(...)). (SignalsForm is the waveform dialogue class where the problem occurs.)

 
/// <summary>
        /// Draws the white box around the coordinate system and the white
        /// border to the left and bottom.
        /// </summary>
        /// <param name="pen">
        /// Pen needed to write text.
        /// </param>
        /// <param name="brush">
        /// Solid brush needed to fill areas.
        /// </param>
        private void DrawSurroundingAreas(Pen pen, SolidBrush brush)
        {
            Rectangle rectangle = new Rectangle(m_usSPACE_RIGHT, 0,
                pictureBox.Bounds.Right - m_usSPACE_RIGHT - 26,    // 26??
                pictureBox.Bounds.Bottom - m_usSPACE_BOTTOM);
            pen.Color = Color.White;

            m_Graphics.DrawRectangle(pen, rectangle);

            ClearBottom();
            ClearLeft();

            // Draw the gray line around the waveforms:
            pen.Color = Color.Gray;
            pen.Width = 1;
            rectangle.X -= 2;
            rectangle.Y = -1;
            rectangle.Height = pictureBox.Bounds.Bottom - m_usSPACE_BOTTOM + 2;
            rectangle.Width += 1;

            m_Graphics.DrawRectangle(pen, rectangle);
        }

Open in new window


Here, the private methods ClearBottom() and ClearLeft() run properly.
 
/// <summary>
        /// Clears the bottom of the signal waveform screen.
        /// </summary>
        private void ClearBottom()
        {
            Rectangle rectangle = new Rectangle(m_usSPACE_RIGHT,
                pictureBox.Bounds.Bottom - m_usSPACE_BOTTOM,
                pictureBox.Bounds.Right - m_usSPACE_RIGHT, m_usSPACE_BOTTOM);
            SolidBrush brush = new SolidBrush(Color.Cyan);

            m_Graphics.FillRectangle(brush, rectangle);
        }

        /// <summary>
        /// Clears the left of the signal waveform screen.
        /// </summary>
        private void ClearLeft()
        {
            Rectangle rectangle = new Rectangle(0, 0, 45, pictureBox.Bounds.Bottom);
            SolidBrush brush = new SolidBrush(Color.Red);   // White);

            m_Graphics.FillRectangle(brush, rectangle);
        }

Open in new window


When calling the same two methods from the event handler method pictureBox_MouseDoubleClick(...), however, nothing happens at all.

How I tried to solve my problem
I thought that the problem may result somehow from using a Graphics member, called m_Graphics. So, I created another private method called ClearBottom2() that uses it's own Graphics object. It initialises it the same way as it is done in the constructor with a
             Graphics g = Graphics.FromImage(pictureBox.Image);

But this try for a workaround turned out to be of no use.

My question
How can I clear the left and bottom of the PictureBox object, when a mouse double click occurs? Or in other words: What can be the reason why the small routines function very well when called from the constructor of the waveform class (SignalsForm), but not at all when called from the event handler method part of the same class?

Thank you for your help!
0
Comment
Question by:sae1962at
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 3
  • 2
  • 2
7 Comments
 
LVL 6

Accepted Solution

by:
Chuck Yetter earned 250 total points
ID: 36542352
Try calling Invalidate() on the picture box after the drawing code.  On an unrelated note, it's also a good idea to always dispose brushes when done painting.
0
 
LVL 86

Expert Comment

by:Mike Tomlinson
ID: 36542767
It's probably an instancing issue...but we can't tell that without seeing how all those snippets fit together as a whole.  Can you show all the code together?  Is all of that code in the form?...or is some in a form and some in a different class?  Can't tell what "SignalsForm" is...a form or a different class.
0
 
LVL 1

Author Comment

by:sae1962at
ID: 36542904
Yes, here is the coherent code listing... Both ClearBottom() & ClearLeft() work in the constructor part, but not in event handling (pictureBox_MouseDoubleClick(...) or rTxtBoxSignalName_TextChanged(...)).

public partial class SignalsForm : MyForm
    {
[...]
        /// <summary>
        /// Graphics object used to draw on the background.
        /// </summary>
        private Graphics m_Graphics = null;

        /// <summary>
        /// Active waveform index.
        /// </summary>
        private ushort m_usCurrentWaveform;

        /// <summary>
        /// Graphical equivalent in pixels for 1 ms.
        /// </summary>
        private ushort m_usPIXEL2TIME = 10; // Each time step = 10 pixels (= ms)

        /// <summary>
        /// Standard constructor
        /// </summary>
        public SignalsForm()
        {
            const string strMETHOD = "SignalsForm:SignalsForm: ";
            Colors.ResetColors();

            InitializeComponent();

            // Read the background image:
            ReadSignalBackground();
[...]

            // Put the waveform names into the text box
            try
            {
                rTxtBoxSignalName.Font = new Font(rTxtBoxSignalName.Font.Name, 11, FontStyle.Bold);
                rTxtBoxSignalName.Text = m_Info.GetSignalsInfo()[m_usCurrentWaveform][0];
            }
            catch (ArgumentOutOfRangeException aoore)
[...]
            catch (Exception e)
            {
                MessageBox.Show(strMETHOD + "unhandled exception: " + e);
                throw e;
            }

            const ushort usINCREMENT = 5;
            m_Graphics = Graphics.FromImage(pictureBox.Image);

[...]

            // Now, draw the waveforms, the surrounding box so that excessive waveforms going
            // out of bounds are not visible, and the coordinates:
            Pen pen = new Pen(Color.Gray);

            DrawWaveforms(pen);
            SolidBrush brush = new SolidBrush(Color.White);

            DrawSurroundingAreas(pen, brush);
            DrawCoordinates(pen, brush, usINCREMENT);
        }
[...]

        /// <summary>
        /// Clears the bottom of the signal waveform screen.
        /// </summary>
        private void ClearBottom()
        {
            Rectangle rectangle = new Rectangle(m_usSPACE_RIGHT,
                pictureBox.Bounds.Bottom - m_usSPACE_BOTTOM,
                pictureBox.Bounds.Right - m_usSPACE_RIGHT, m_usSPACE_BOTTOM);
            SolidBrush brush = new SolidBrush(Color.White);

            m_Graphics.FillRectangle(brush, rectangle);
        }

        /// <summary>
        /// Clears the left of the signal waveform screen.
        /// </summary>
        private void ClearLeft()
        {
            Rectangle rectangle = new Rectangle(0, 0, 45, pictureBox.Bounds.Bottom);
            SolidBrush brush = new SolidBrush(Color.White);

            m_Graphics.FillRectangle(brush, rectangle);
        }
[...]
        /// <summary>
        /// Draws the white box around the coordinate system and the white
        /// border to the left and bottom.
        /// </summary>
        /// <param name="pen">
        /// Pen needed to write text.
        /// </param>
        /// <param name="brush">
        /// Solid brush needed to fill areas.
        /// </param>
        private void DrawSurroundingAreas(Pen pen, SolidBrush brush)
        {
            Rectangle rectangle = new Rectangle(m_usSPACE_RIGHT, 0,
                pictureBox.Bounds.Right - m_usSPACE_RIGHT - 26,    // 26??
                pictureBox.Bounds.Bottom - m_usSPACE_BOTTOM);
            pen.Color = Color.White;

            m_Graphics.DrawRectangle(pen, rectangle);

            ClearBottom();
            ClearLeft();

            // Draw the gray line around the waveforms:
            pen.Color = Color.Gray;
            pen.Width = 1;
            rectangle.X -= 2;
            rectangle.Y = -1;
            rectangle.Height = pictureBox.Bounds.Bottom - m_usSPACE_BOTTOM + 2;
            rectangle.Width += 1;

            m_Graphics.DrawRectangle(pen, rectangle);
        }
[...]

        /// <summary>
        /// Determines what happens when the picture box is double-clicked.
        /// </summary>
        /// <param name="sender">
        /// Sender object of the event.</param>
        /// <param name="eas">
        /// Generated event's object.
        /// </param>
        private void pictureBox_MouseDoubleClick(object sender, MouseEventArgs meas)
        {
            ClearBottom();
            ClearLeft();
        }
[...]
        /// <summary>
        /// What happens when the text of the text box object changes.
        /// </summary>
        /// <param name="sender">
        /// Sender object of the event.</param>
        /// <param name="eas">
        /// Generated event's object.
        /// </param>
        private void rTxtBoxSignalName_TextChanged(object sender, EventArgs eas)
        {
            ClearLeft();
        }
[...]
    }   // End of SignalsForm

Open in new window

0
Major Incident Management Communications

Major incidents and IT service outages cost companies millions. Often the solution to minimizing damage is automated communication. Find out more in our Major Incident Management Communications infographic.

 
LVL 1

Author Comment

by:sae1962at
ID: 36542933
Thank you, guys!

I added a

 pictureBox.Invalidate();

in the constructor as last line, which solved the problem.

Special thanks to Axshun. Congratulations!
0
 
LVL 1

Author Comment

by:sae1962at
ID: 36543042
A very strange phenomen... I cannot reproduce the solution, although it worked once after adding the pictureBox.Invalidate() comment to the constructor as a last line. That's very strange...
0
 
LVL 6

Expert Comment

by:Chuck Yetter
ID: 36543117
Don't add it in the constructor, add it after the code in ClearBottom(), ClearLeft(), and DrawSurroundingAreas().  I'm assuming these methods are called from other places as well as the constructor.  You may want to put all your drawing code in an OnDraw event handler for the picturebox instead.
0
 
LVL 86

Expert Comment

by:Mike Tomlinson
ID: 36543403
Just thought I'd let you know that there are two basic ways to go about this.

Your approach is manipulating an Image that is being displayed in a PictureBox.  This can be thought of as using paints on a canvas.  Once on the canvas it is there forever.  To "erase" something you have to paint over what is already there.

Another approach is to use the Graphics supplied by the "e" parameter in the Paint() event of the PictureBox.  Using this approach, you can display an Image as the "base" and put things on top.  The Image() property can hold things that don't change, possibly things like the grid and labels.  The Paint() event could be thought of as shining a fast moving laser light on top of the canvas.  You can change what is being displayed by the laser without having to repaint everything underneath.  Things displayed by the laser can be turned "off" by simply not drawing them.
0

Featured Post

SharePoint Admin?

Enable Your Employees To Focus On The Core With Intuitive Onscreen Guidance That is With You At The Moment of Need.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

In my previous two articles we discussed Binary Serialization (http://www.experts-exchange.com/A_4362.html) and XML Serialization (http://www.experts-exchange.com/A_4425.html). In this article we will try to know more about SOAP (Simple Object Acces…
Exception Handling is in the core of any application that is able to dignify its name. In this article, I'll guide you through the process of writing a DRY (Don't Repeat Yourself) Exception Handling mechanism, using Aspect Oriented Programming.
In an interesting question (https://www.experts-exchange.com/questions/29008360/) here at Experts Exchange, a member asked how to split a single image into multiple images. The primary usage for this is to place many photographs on a flatbed scanner…

740 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question