0

画像を開いてウィンドウに表示するアプリケーションがあります。正確には、この画像をフォームクラスの内部フィールドに保存し、そのフォームに配置されたPaintイベントに添付されたメソッドで描画します。Panelこんな感じです:

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

変数は、開いた後の画像を含むimage(型の) フォーム クラスのフィールドです。スクロールとスクロールバーに接続されていますが、この場合には関係ありません。ImageimageLocation

そのフォームToolStripの下部にも を配置しました。これToolStripにはToolStripLabels、画像に関するいくつかの指標であるはずの がいくつかあります。たとえばToolStripLabel、画像上のマウス カーソルの現在の位置、または別の観点からは、マウス カーソルの下の (画像上の) ピクセル位置を表示したい があります。MouseMoveしたがって、次のように、イベントに添付されたメソッドでラベルの値を更新します。

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
}

UpdateCursorAtLabel(int, int)また、「cursor at」ラベルの更新を直接担当するmethod の内容は次のとおりです。

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

lblCursorAtValue- これは、マウスの下のピクセルの位置を示すラベルです (例: "234, 117")。 scbHorizontalscbVertical-関係のないスクロールバーだけです。位置を計算するために必要です。 nullText- const string、「---」に等しい。

そして、最初はInvalidate()メソッドの使用はありませんでした。これをすべて作成したとき、カーソルをパネルの上に移動しても、ラベルの内容がまったく変化しないことに気付きました! カーソルの移動を停止したときにのみ、ラベルの新しい値が表示されます。そこでlblCursorAtValue.Invalidate()、ラベルの再描画を強制するために追加しました。それでも同じ問題です。もう 1 つ確認しましたPaint。このラベルのイベントにメソッドを追加し、それを埋めるのではなく、そこにブレークポイントを配置しました。ランタイム デバッガーは、カーソルの移動を停止した後、またはパネルの境界外に移動した後に停止しました。ToolStripLabelasUpdate()やにはそのようなメソッドがないRefresh()ので、より強力なものは使えませんInvalidate()。なぜこれが起こっているのか、どうすれば修正できるのか、私には本当にわかりません。

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

その中には、すべてを台無しにしていた 1 行があります。

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

はい、この行では、マウスが 1 ピクセル移動するたびに、まったく新しい bitmapを作成していました!!! ビットマップの作成は、かなり時間のかかる操作です。何百ものビットマップを作成するのに忙しいため、アプリケーションはラベルの外観を更新する時間がありませんでした...

イメージではなくビットマップを保存することで修正したため、ピクセルの色を取得するためだけに作成する必要はありません。

于 2013-03-01T23:02:40.440 に答える