0

I have an application which opens an image and displays it in the window. To be exact I store this image in inner field of the form class and draw it in the method attached to Paint event of a Panel placed on that form. It's like this:

private void pnlImage_Paint(object sender, PaintEventArgs e)
{
    var g = e.Graphics;
    if (image != null)
    {
        g.DrawImage(image, imageLocation);
    }
}

The variable image is a field of the form class (of type Image) containing the image after opening; imageLocation is connected to scrolling and scrollbars, which is irrelevant to this case.

On that form I also placed a ToolStrip on the bottom of it, and on this ToolStrip there are some ToolStripLabels, which are supposed to be some indicators about the image. E.g. there is a ToolStripLabel, which I want to show current position of mouse cursor over my image, or - from the other point of view - pixel position (on the image) under the mouse cursor. So I update value of my label(s) in the method attached to the MouseMove event, like this:

private void pnlImage_MouseMove(object sender, MouseEventArgs e)
{
    UpdateCursorAtLabel(e.X, e.Y); // <---- method of interest
    UpdateColorLabel(e.X, e.Y); // other label, showing color of the pixel. It's an identical thing, so I did not mention it
}

And the contents of method UpdateCursorAtLabel(int, int), directly responsible for updating the "cursor at" label is:

void UpdateCursorAtLabel(int cursorX, int cursorY)
{
    lblCursorAtValue.Text = image != null ? 
        String.Format("{0}, {1}", scbHorizontal.Value + cursorX, scbVertical.Value + cursorY) :
        nullText;
    lblCursorAtValue.Invalidate();
}

lblCursorAtValue - this is the label which should show position of pixel under mouse, e.g. "234, 117". scbHorizontal, scbVertical - just some scrollbars, irrelevant, I just need them to calculate position. nullText - const string, equals "---".

And at the beginning there was no using of Invalidate() method. When I made this all, I noticed, that as I move cursor over my panel, contents of the label does not change at all! Only when I stop moving cursor, I can see the new value of label. So I added lblCursorAtValue.Invalidate() to enforce redrawing of label. Still the same problem. I even checked one more thing - attached a method to the Paint event of this label, not filling it, and put there a breakpoint. In runtime debugger stopped there only after I stopped moving cursor, or got it out of bounds of the Panel. There are no such methods on the ToolStripLabel as Update() or Refresh(), so I can't use anything stronger than Invalidate(). I really don't get why this is happening, and how could I fix it.

4

1 回答 1

0

解决了。我忘记了一件关键的事情。而且该UpdateColorLabel(int, int)方法并不像一开始看起来那样无关紧要。因为它就像:

void UpdateColorLabel(int cursorX, int cursorY)
{
    if (image == null)
    {
        lblColorValue.Text = nullText;
    }
    else
    {
        var imageCursorLocation = new Point(scbHorizontal.Value + cursorX, scbVertical.Value + cursorY);
        var px = new Bitmap(image).GetPixel(imageCursorLocation.X, imageCursorLocation.Y);
        lblColorValue.Text = String.Format("R = {0}, G = {1}, B = {2}", px.R, px.G, px.B);
    }            
}

里面有一行,把一切都搞砸了:

var px = new Bitmap(image).GetPixel(imageCursorLocation.X, imageCursorLocation.Y);

是的,在这一行中,我正在创建全新的位图,每次鼠标移动一个像素后!!!!创建位图是相当耗时的操作。所以应用程序没有时间更新我的标签的外观,因为它正忙于创建数百个位图......

我通过存储位图而不是图像来修复它,所以我不必为了获得像素颜色而创建它。

于 2013-03-01T23:02:40.440 回答