簡単チャート(ChartCtrl) 簡単なグラフ作成用.Net2.0ユーザーコントロール、「簡単チャート」をベクターにアップしていました。これを使って、音のリアルタイム表示を使用としましたが思ったように行きません。そこで手直しをしました。 「簡単チャート(ChartCtrl)」 1.簡単チャートとは?2Dの作図用の、プログラムから呼び出すダイナミックリンクライブラリ(DLL)です。.Netの世界では、アセンブリと言うようです。ユーザーコントロールになっていて、Visual Studioのデザイナで、Formにコントロールとして貼り付けて使います。 特徴は、「いつでも」、「簡単に」グラフが描けることです。 1.1.「いつでも」について Windowsの世界では、イベントドリブンと言う事で、PAINTのイベントが発生したときに全てを描画する必要があります。 Formにボタンを貼って、そのクリックイベントで、描画するサンプルがありますが、別のウインドウの陰になって、再表示された時には、消えることになります。 アプリケーションプログラムがPAINTイベント処理以外の任意のタイミングで描画するには、裏で、描画内容を保存して、PAINTイベントで再生する仕組みが必要だと言うことです。
ダメなプログラムの例です。
Formに100x100pixelのpanel1が貼り付けてあります。 ボタン「button1」をクリックすると、斜め、横、縦に線を引きます。
しかし、他の窓でカクレて、再度アクチブになったときには、消えてしまいます。

private void button1_Click(object sender, EventArgs e) { Graphics g = panel1.CreateGraphics(); Pen pen = new Pen(Color.Red, 2); g.Transform = new Matrix(10, 0, 0, 1, 0, 0);
g.DrawLine(pen, 0, 0, 10, 100); g.DrawLine(pen, 0, 50, 10, 50); g.DrawLine(pen, 5, 0, 5, 100); } 
1.2.「簡単に」について 当然ながら、.Netのグラフィックスもいろいろな座標変換をします。スケーリングしたり、回転したりしてくれます。プログラムを作ったときに、表示を見て私が意外に思ったのは、線幅や文字までスケーリングされることです。当たり前と言えばその通りですが。 たとえば100x100pixelの矩形を、取り扱うデータに合わせて、Xの範囲(0,10),Yの範囲(0,100)にマップしたいと考えると、前述のプログラムのように、 g.Transform = new Matrix(10, 0, 0, 1, 0, 0); として、座標変換できます。 線幅は、 Pen pen = new Pen(Color.Red, 2); で、2と指定してあります。 左図を見ると、縦、横でスケーリングが異なるので、線幅も縦、横で変わっています。

私の期待は、最後の図です。この図は、単に Pen pen = new Pen(Color.Red, 1); と、線幅に1を指定したものです。期待通りではあるのですが、線幅1以外は使えないことになります。 また、このことは、一律にスケーリングされていないことを意味します。線幅1がスケーリングされないだけではなく、1以下の線幅になる場合は1にしたり、なかなかインテリジェントに処理しているようです。 最初は、線幅指定を逆にスケーリングして合わせるように作って見たのですが当然ながら、うまくいきません。 2.簡単チャートの特徴2.1.座標系X軸が右向き、Y軸が上向きの、一般的な座標で描画します。スケーリングは、クライアント領域のサイズと、描画するデーターのX、Yそれぞれの最大/最小値を元に指定します。 2.2.線幅など線幅は、Pixel単位で指定し、スケーリングされません。文字もスケーリングされません。 2.3.描画タイミング描画用のメソッドは、Graphicsのメンバと同様、Formのロードイベントなど、Windowsのイベントドリブンなメソッドから呼び出される必要があります。BeginDrawing()とEndDrawing()と言うメソッドを用意しました。EndDrawing()が呼び出されるまで、実際の表示は行われません。ボタン押下で、追加を行う場合などを想定して、ResumeDrawing()を用意しました。 2.4.描画タイミングの補足Windowsの世界では、Paintイベントの処理で描画した内容が、表示されます。2回のPaint イベントで、それぞれ異なる位置に線を引いたとすると、2本表示されるとは限りません。2回のPaintイベントの間で、他のウインドウの背後に回った場合は、最初の描画内容は失われます。Paint イベントでは、常に毎回、完全なサーフェイスを描画する必要があります。(複数のウインドウの表示や、リサイズしたりしないなら別ですが。) EndDrawing()は、Paintイベントにそなえて描画データを準備します。 2.5.矩形の指定方法GraphicsのDrawRectangle()は負の幅、高さを扱わないようです。(x,y)が矩形のどの隅かを指定するようになっているものと思います。ChartRectクラスを用意しました。負の幅、高さが使えます。(x,y)は常に左下隅を示します。 2.6.文字列の描画文字はスケーリングされません。 AlignString 列挙体で、(x,y)が文字列のどの位置を指すか指定するようにしました。 文字の囲みと背景色の指定を付けました。 文字を傾けて表示できますが、角度(度)の指定が反時計回りなのに注意してください。 2.7.コピー、ファイル出力、印刷私自身は必要性を感じていませんが、Windowsアプリケーションらしく一通りできるように考えて見ました。マウスボタンを押してみてください。メニューが表示されます。実際には親のウインドウに実装するものだと思います。 |