【问题标题】:Screen not redrawing until end of mousesup event handler在 mousesup 事件处理程序结束之前不会重绘屏幕
【发布时间】:2013-04-09 14:46:25
【问题描述】:

好的,我有一个问题,我什至不确定到底发生了什么。基本上:我有一个用于单击按钮的 mouseup 事件。该事件将删除 1 个按钮并物理移动屏幕上的所有按钮以填补空白。所以如果你有 2 行 2 个按钮

Button1 Button2
Button3 Button4

然后你点击 Button1,它会移动最后 3 个,所以你现在有了

Button2 Button3
Button4

好的,所以,在这个事件处理程序结束时,它会截取屏幕截图并保存(将按钮 1-4 的先前图像替换为按钮 2-4 的新图像)。

事件处理程序如下所示

    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();
    }

截图代码为

    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;
        }
    }

清理了一些不必要的问题部分以避免混乱。很抱歉弄乱了缩进。注意:按钮不在面板中,就在面板顶部。我只是将面板用于测量和美学目的

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))));
        }

现在我的问题是:图像是一个空白屏幕。并不是说它没有拍照——它是在屏幕上显示按钮 2-4 之前拍照(当我逐步执行程序时,我可以明显地看到这种情况发生。在截取屏幕截图时,屏幕是完全空白。只有在需要之后按钮才会重新出现在屏幕上)!出于某种原因,它们直到事件处理程序完成后才会呈现。一旦事件处理程序中的最后一段代码完成(屏幕截图保存),按钮都会重新出现在各自的位置,尽管在整个过程中按钮的可见性根本没有修改(因此它们仍然可见整个时间)。

我有点困惑到底发生了什么,更重要的是,在事件处理程序发生后如何获取该屏幕截图。 >_> 有没有人对可能发生的事情有任何建议,更重要的是,如何获取该屏幕截图?

编辑:我的描述有点难以理解。我深感抱歉。很难准确地说明我正在尝试做什么以及正在发生什么。这是一个更简洁、更中肯的版本:

基本上,我只是想隐藏 4 个按钮中的 1 个。屏幕上的其他 3 个按钮已移动到新位置。由于某种原因,当它们被移动时,它们就会从屏幕上消失。尽管我从未修改过它们是否可见,但它们直到 mouseup 功能完成后才会重新出现。我只是改变他们的位置。我希望屏幕截图包含这 3 个按钮,但由于某种原因,它们直到整个 mouseup 功能结束后才会重新出现。 >_> 所以我的截图是一个空屏幕,没有按钮

【问题讨论】:

  • 您需要屏幕截图,还是需要表单的图像?
  • 我的表单部分的图像。按钮位于面板顶部(不在面板内。面板仅用于测量和美学目的)。我所做的就是抓取该面板的“屏幕截图”。通常,它会显示所有按钮。在这种情况下,按钮会消失并且不会重新出现,直到事件处理程序中的所有代码都完成(这包括屏幕截图代码)。所以当面板的图像被拍摄时,没有按钮可以拍照!

标签: c# event-handling rendering screenshot mouseup


【解决方案1】:

您所描述的内容有点令人困惑。我单击了一个按钮将其隐藏,运行您的屏幕截图代码,图像没有显示该按钮。

无论如何,要将屏幕截图“延迟”到调用事件之后,您可以尝试使用 BeginInvoke:

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

我认为您需要在移动控件后调用 Refresh:

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();

【讨论】:

  • 抱歉,描述不明确。这是一个难以描述的场景。基本上,我只是想隐藏 1 个按钮。屏幕上的其他 3 个已移动到新位置。由于某种原因,当它们被移动时,它们就会从屏幕上消失。尽管我从未修改过它们是否可见,但它们直到 mouseup 功能完成后才会重新出现。我希望屏幕截图包含这 3 个按钮,但由于某种原因,它们直到整个 mouseup 功能结束后才会重新出现。 >_> 所以我的截图是一个空屏幕,没有按钮。
  • @GGati 仍然无法复制它。在屏幕截图调用之前,我将按钮移到了 Point(0, 0),图像在点 (0, 0) 处显示了按钮。您可能需要展示您的 Rearrange_Buttons_In_Tray(element); 方法。
  • 好的!一秒。我不想把它弄乱。我现在就这样做。
  • @GGati 更新了帖子。移动控件后尝试调用panel1.Refresh()
【解决方案2】:

您正在 UI 线程中进行工作。见How to force Buttons, TextBoxes to repaint on form after a MessageBox closes in C#。如果可以的话,我建议您将屏幕截图移至后台线程。

您可能还需要等到按钮渲染完毕,或者使用休眠 100 毫秒左右的直截了当的权宜之计,或者通过调查 Paint 事件并使用某种标志来指示两个必需的事件都已发生并且可以截图。

或者,您可以强制它重绘:How do I call paint event?

【讨论】:

    【解决方案3】:

    只要你只需要自己表单的像素就行了……

    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
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-10-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-05
      • 1970-01-01
      • 2019-08-22
      相关资源
      最近更新 更多