Solved

Picture box event handling with strange effect

Posted on 2011-09-15
7
639 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
  • 3
  • 2
  • 2
7 Comments
 
LVL 6

Accepted Solution

by:
Chuck Yetter earned 250 total points
Comment Utility
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 85

Expert Comment

by:Mike Tomlinson
Comment Utility
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
Comment Utility
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
Top 6 Sources for Identifying Threat Actor TTPs

Understanding your enemy is essential. These six sources will help you identify the most popular threat actor tactics, techniques, and procedures (TTPs).

 
LVL 1

Author Comment

by:sae1962at
Comment Utility
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
Comment Utility
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
Comment Utility
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 85

Expert Comment

by:Mike Tomlinson
Comment Utility
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

What Is Threat Intelligence?

Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

Join & Write a Comment

Introduction Hi all and welcome to my first article on Experts Exchange. A while ago, someone asked me if i could do some tutorials on object oriented programming. I decided to do them on C#. Now you may ask me, why's that? Well, one of the re…
This article is for Object-Oriented Programming (OOP) beginners. An Interface contains declarations of events, indexers, methods and/or properties. Any class which implements the Interface should provide the concrete implementation for each Inter…
Here's a very brief overview of the methods PRTG Network Monitor (https://www.paessler.com/prtg) offers for monitoring bandwidth, to help you decide which methods you´d like to investigate in more detail.  The methods are covered in more detail in o…
This tutorial demonstrates a quick way of adding group price to multiple Magento products.

728 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

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now