Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. .NET (Core and Framework)
  4. Error when Painting (long message) [modified]

Error when Painting (long message) [modified]

Scheduled Pinned Locked Moved .NET (Core and Framework)
graphicsdata-structureshelp
8 Posts 2 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • R Offline
    R Offline
    ricecake
    wrote on last edited by
    #1

    I have created a Form that has a PictureBox in it used for displaying multiple images. The constructor for the Form receives an array of filenames. The Form will then display the first image, Sleep() for a user-specified interval, then show the second image, Sleep(), etc. This all works find and dandy in the normal case. However, if I am dragging another window and it overlaps the Form while trying to change the image, I get an InvalidOperationException telling me that "the object is in use elsewhere", but it won't tell me which object, and then the area where the picture is supposed to be turns into a big red X. The entire class is about 550 lines so I won't post it here, but here are some relevant code snippets: [Everything looks OK in the preview but it looks like it eats my whitespace in the <pre> tags when it actually gets posted]

    System::Void initialize_thread()
    {
    using System::Threading::Thread;
    using System::Threading::ThreadStart;

    draw\_images\_thread = new Thread(new ThreadStart(this, &PlotDisplayWindow::draw\_images));
    draw\_images\_thread->IsBackground = true;
    

    }

    System::Void draw_image(int image_num) {
    picturebox->Image = __try_cast(images_[image_num]);
    Text = filenames_[image_num];
    graphics = this->CreateGraphics();
    graphics->DrawImage(images_[image_num],
    AutoScrollPosition.X, AutoScrollPosition.Y,
    images_[image_num]->Width, images_[image_num]->Height);
    graphics->Dispose();
    }

    __delegate System::Void DrawImageDelegate(int image_num);

    System::Void draw_images()
    {
    //using System::IAsyncResult;
    using System::Threading::Thread;

    while (running) {
        if (picturebox->InvokeRequired) {
            DrawImageDelegate\* draw\_image\_delegate = new DrawImageDelegate(this, &PlotDisplayWindow::draw\_image);
            draw\_image\_delegate->Invoke(image\_number);
            //IAsyncResult\* async\_result = draw\_image\_delegate->BeginInvoke(image\_number, 0, 0);
            //draw\_image\_delegate->EndInvoke(async\_result);
        }
        else {
            draw\_image(image\_number);
        }
    
        Thread::Sleep(sleep\_time\_ms);
    
        ++image\_number;
        if (image\_number == filenames\_->Length) {
            image\_number = 0;
        }
    }
    

    }

    System::Void PlotDisplayWindow_Paint(System::Object* /*sender*/, System::Windows::Forms::PaintEventArgs* e)
    {
    usin

    R 1 Reply Last reply
    0
    • R ricecake

      I have created a Form that has a PictureBox in it used for displaying multiple images. The constructor for the Form receives an array of filenames. The Form will then display the first image, Sleep() for a user-specified interval, then show the second image, Sleep(), etc. This all works find and dandy in the normal case. However, if I am dragging another window and it overlaps the Form while trying to change the image, I get an InvalidOperationException telling me that "the object is in use elsewhere", but it won't tell me which object, and then the area where the picture is supposed to be turns into a big red X. The entire class is about 550 lines so I won't post it here, but here are some relevant code snippets: [Everything looks OK in the preview but it looks like it eats my whitespace in the <pre> tags when it actually gets posted]

      System::Void initialize_thread()
      {
      using System::Threading::Thread;
      using System::Threading::ThreadStart;

      draw\_images\_thread = new Thread(new ThreadStart(this, &PlotDisplayWindow::draw\_images));
      draw\_images\_thread->IsBackground = true;
      

      }

      System::Void draw_image(int image_num) {
      picturebox->Image = __try_cast(images_[image_num]);
      Text = filenames_[image_num];
      graphics = this->CreateGraphics();
      graphics->DrawImage(images_[image_num],
      AutoScrollPosition.X, AutoScrollPosition.Y,
      images_[image_num]->Width, images_[image_num]->Height);
      graphics->Dispose();
      }

      __delegate System::Void DrawImageDelegate(int image_num);

      System::Void draw_images()
      {
      //using System::IAsyncResult;
      using System::Threading::Thread;

      while (running) {
          if (picturebox->InvokeRequired) {
              DrawImageDelegate\* draw\_image\_delegate = new DrawImageDelegate(this, &PlotDisplayWindow::draw\_image);
              draw\_image\_delegate->Invoke(image\_number);
              //IAsyncResult\* async\_result = draw\_image\_delegate->BeginInvoke(image\_number, 0, 0);
              //draw\_image\_delegate->EndInvoke(async\_result);
          }
          else {
              draw\_image(image\_number);
          }
      
          Thread::Sleep(sleep\_time\_ms);
      
          ++image\_number;
          if (image\_number == filenames\_->Length) {
              image\_number = 0;
          }
      }
      

      }

      System::Void PlotDisplayWindow_Paint(System::Object* /*sender*/, System::Windows::Forms::PaintEventArgs* e)
      {
      usin

      R Offline
      R Offline
      Robert Rohde
      wrote on last edited by
      #2

      Hi, to be honest I didn't even try to understand the whole code but I most probably know the problem: Don't mix threading and painting! Dragging another window over your form will trigger dozens of paint events and generally its not safe to access the GUI from a different thread that it was created in. In your case a simple Timer should be all you need.

      R 1 Reply Last reply
      0
      • R Robert Rohde

        Hi, to be honest I didn't even try to understand the whole code but I most probably know the problem: Don't mix threading and painting! Dragging another window over your form will trigger dozens of paint events and generally its not safe to access the GUI from a different thread that it was created in. In your case a simple Timer should be all you need.

        R Offline
        R Offline
        ricecake
        wrote on last edited by
        #3

        Thanks.

        Dragging another window over your form will trigger dozens of paint events

        Yeah, that's pretty much what I thought was happening but I couldn't see a way to make it safe. I originally tried using a Timer but I couldn't get it to work right so I switched to the Threaded approach. However, this seems to add too much complexity. I will look at Timers again. I assume I should use System::Windows::Forms::Timer instead of System::Threading::Timer or System::Timers::Timer, but I am still a little unclear on the differences among the three. -- Marcus Kwok

        R R 2 Replies Last reply
        0
        • R ricecake

          Thanks.

          Dragging another window over your form will trigger dozens of paint events

          Yeah, that's pretty much what I thought was happening but I couldn't see a way to make it safe. I originally tried using a Timer but I couldn't get it to work right so I switched to the Threaded approach. However, this seems to add too much complexity. I will look at Timers again. I assume I should use System::Windows::Forms::Timer instead of System::Threading::Timer or System::Timers::Timer, but I am still a little unclear on the differences among the three. -- Marcus Kwok

          R Offline
          R Offline
          ricecake
          wrote on last edited by
          #4

          Well, I did find an article[^] discussing the differences in the timers. Time to start reading... -- Marcus Kwok

          1 Reply Last reply
          0
          • R ricecake

            Thanks.

            Dragging another window over your form will trigger dozens of paint events

            Yeah, that's pretty much what I thought was happening but I couldn't see a way to make it safe. I originally tried using a Timer but I couldn't get it to work right so I switched to the Threaded approach. However, this seems to add too much complexity. I will look at Timers again. I assume I should use System::Windows::Forms::Timer instead of System::Threading::Timer or System::Timers::Timer, but I am still a little unclear on the differences among the three. -- Marcus Kwok

            R Offline
            R Offline
            Robert Rohde
            wrote on last edited by
            #5

            Use the windows forms Timer. Basically I would just set some member variable to the image you want to show and then call Invalidate on your form/control in the Tick eventhandler. In the paint function you could then draw the image according to the field.

            R 1 Reply Last reply
            0
            • R Robert Rohde

              Use the windows forms Timer. Basically I would just set some member variable to the image you want to show and then call Invalidate on your form/control in the Tick eventhandler. In the paint function you could then draw the image according to the field.

              R Offline
              R Offline
              ricecake
              wrote on last edited by
              #6

              Robert, Thank you for your advice. I was able to get the System::Windows::Forms::Timer to work, and it works well, and is much cleaner than my threaded solution. I am now getting some flickering and a little bit of weirdness when painting, but these problems are orthogonal to my original issue so I will do my research and start a new thread (no pun intended) once I figure out some stuff. Thanks. -- Marcus Kwok

              R 1 Reply Last reply
              0
              • R ricecake

                Robert, Thank you for your advice. I was able to get the System::Windows::Forms::Timer to work, and it works well, and is much cleaner than my threaded solution. I am now getting some flickering and a little bit of weirdness when painting, but these problems are orthogonal to my original issue so I will do my research and start a new thread (no pun intended) once I figure out some stuff. Thanks. -- Marcus Kwok

                R Offline
                R Offline
                Robert Rohde
                wrote on last edited by
                #7

                Look for double buffering and SetStyle from the Control class ;).

                R 1 Reply Last reply
                0
                • R Robert Rohde

                  Look for double buffering and SetStyle from the Control class ;).

                  R Offline
                  R Offline
                  ricecake
                  wrote on last edited by
                  #8

                  Thanks, I will take a look. -- Marcus Kwok

                  1 Reply Last reply
                  0
                  Reply
                  • Reply as topic
                  Log in to reply
                  • Oldest to Newest
                  • Newest to Oldest
                  • Most Votes


                  • Login

                  • Don't have an account? Register

                  • Login or register to search.
                  • First post
                    Last post
                  0
                  • Categories
                  • Recent
                  • Tags
                  • Popular
                  • World
                  • Users
                  • Groups