Question

Ok, I'm having an issue that I'm not even sure exactly what is happening. Basically: I have a mouseup event for clicking on a button. That event will remove 1 button and physically move all the buttons on the screen to fill the gap. So if you have 2 rows of 2 buttons

Button1 Button2
Button3 Button4

and you click Button1, it moves the last 3 so you now have

Button2 Button3
Button4

Ok, so, at the end of this event handler it takes a screenshot and saves it (replacing the previous image of buttons 1-4 with the new image of buttons 2-4).

The event handler looks like this

    public void Handle_Button_MouseUp(object sender, MouseEventArgs e)
    {
         //Get rid of the button that was clicked
         ...some unnecessary to the question code here...

        //Rearrange the remaining buttons to fill the gap
        Rearrange_Buttons_In_Tray(element);

        //Save the screenshot
        imageBox.Image = SavePanel1Screenshot();
    }

The screenshot code is

    public Image SavePanel1Screenshot()
    {
        int BorderWidth = (this.Width - this.ClientSize.Width) / 2;
        int TitlebarHeight = this.Height - this.ClientSize.Height - BorderWidth;

        Rectangle rect = new Rectangle(0, 0, panel1.Width, panel1.Height);
        Bitmap bmp = new Bitmap(panel1.Width, panel1.Height, PixelFormat.Format32bppArgb);
        Graphics g = Graphics.FromImage(bmp);
        g.CopyFromScreen(this.Left + panel1.Left + BorderWidth, this.Top + panel1.Top + TitlebarHeight, 0, 0, bmp.Size, CopyPixelOperation.SourceCopy);

        Image screenShot;

        screenShot = (Image)bmp;
        return screenShot;
    }

.

    public void Rearrange_Buttons_In_Tray(int element)
    {
        for (int i = element; i < buttonList.Count; i++)
        {
            Place_Button_In_Tray(buttonList[i].buttonSaved, i, true);
            buttonList[i].element = i;
        }
    }

Cleaned out some unnecessary to the question parts to avoid clutter. Sorry for the messed up indentation. NOTE: The buttons are not IN the panel, just on top of it. I just use the panel for measurement and aesthetic purposes

private void Place_Button_In_Tray(Button button, int element, bool isReArrange)
    {
            button.Width = bigButtonWidth;
            button.Height = bigButtonHeight;

            Image buttonImage = button.Image;

        int numButtonsHoriz = panel1.Width / button.Width;
        int numButtonsVerti = panel1.Height / button.Height;
        int extraSpaceHoriz = (panel1.Width % button.Width) / (numButtonsHoriz);
        int extraSpaceVerti = (panel1.Height % button.Height) / numButtonsHoriz;

        int buttonCount;

        if (!isReArrange)
            buttonCount = buttonList.Count - 1;
        else
            buttonCount = element;

        if ((buttonCount) < numButtonsHoriz)
        {
            button.Location = new Point(panel1MinX + (button.Width * (buttonCount)) + extraSpaceHoriz, (panel1MinY + extraSpaceVerti));

        }
        else
        {
            int newLine = (buttonCount) % numButtonsHoriz;
            button.Location = new Point(panel1MinX + (button.Width * (newLine)) + extraSpaceHoriz, ((panel1MinY + extraSpaceVerti) + (button.Height * ((buttonCount) / 2) - ((buttonCount) % 2))));
        }

And now my problem: The image is of a blank screen. It's not that it isn't taking the picture- it's taking the picture before buttons 2-4 are visible on the screen (I can visibly see this happen as I step through the program. At the time the screenshot is taken, the screen is completely blank. Only after it takes do the buttons reappear on the screen)! For some reason, they are not rendering until AFTER the event handler is finished. Once the final piece of code in the event handler is done (the screenshot saving), the buttons all reappear in their respective spots, despite the fact that the visibility of the buttons is not modified at all during this entire process (thus they remain visible the entire time).

I'm a little confused as to what exactly is happening and, more importantly, how to go about getting that screenshot after the event handler takes place. >_> Does anyone have any suggestions on what might be going on and, more importantly, how to get that screenshot?

EDIT: My description is somewhat difficult to understand. I do apologize. It's hard to articulate exactly what I'm trying to do and what is happening. Here's a more compact and to the point version:

Basically, I'm only trying to hide 1 button out of 4. The other 3 on the screen are moved to new locations. For some reason, when they get moved, they vanish from the screen. They don't reappear until after the mouseup function completes, despite me never having modified whether they are visible or not. I only change their location. I want the screenshot to contain those 3 buttons, but for some reason they aren't popping back into existence until after the entire mouseup function ends. >_> So my screenshot is of an empty screen, devoid of buttons

Was it helpful?

Solution

It's a bit confusing what you are describing. I clicked a button to hide it, run your screen shot code, and the image did not show the button.

Anyway, to "delay" the screen shot to after the event is called, you can try using BeginInvoke:

this.BeginInvoke(new Action(() => { imageBox.Image = SavePanel1Screenshot(); }));

I think you need to call a Refresh after moving your controls:

if ((buttonCount) < numButtonsHoriz) {
  button.Location = new Point(panel1MinX + (button.Width * (buttonCount)) + extraSpaceHoriz, (panel1MinY + extraSpaceVerti));
} else {
  int newLine = (buttonCount) % numButtonsHoriz;
  button.Location = new Point(panel1MinX + (button.Width * (newLine)) + extraSpaceHoriz, ((panel1MinY + extraSpaceVerti) + (button.Height * ((buttonCount) / 2) - ((buttonCount) % 2))));
}
panel1.Refresh();

OTHER TIPS

You're doing your work in the UI thread. See How to force Buttons, TextBoxes to repaint on form after a MessageBox closes in C#. I'd suggest you move the screenshot to a background thread if you can.

You may also need to wait until the buttons have rendered, either using the blunt expedient of sleeping for 100ms or so, or by investigating the Paint event and using some sort of flag to indicate that both required events have occurred and the screenshot can be taken.

Alternatively, you could force it to redraw: How do I call paint event?

as long as you only need the pixels of your own form ...

private void button1_Click(object sender, EventArgs e)
{
    //Button magic
    button1.Visible = false;
    button2.Location = button1.Location;

    Bitmap bmp = new Bitmap(this.Width, this.Height);

    this.DrawToBitmap(bmp, new Rectangle(0, 0, this.Width, this.Height));

    pictureBox1.Image = bmp;
    //or do whatever you want with the bitmap
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top