2011-01-01 9 views
1

C++ 6で書かれたアプリは、トラフィックマップ上の空白のポリゴンで塗りつぶされ、現在の交通状況を表示します。緑色が良い、黄色がより渋滞しているなどGDI +は使用できません。 Windows API呼び出しを使用してビットマップに線を描くことはできますか?

"シェルマップ"は、何も埋め込まれていない矩形とポリゴンを使用した道路のビットマップです。データは道路センサ(ワイヤインダクタループ)から収集され、ポリゴンはループ検出器データに基づいて塗りつぶされます。

マップが変更されると、ペイントのビットマップを手動で拡大し、渋滞の色が塗りつぶされる新しい形状の内側の座標を取得する必要があります。マップスケルトンを作成するポリゴンはすべて白い背景に紺色で描かれています。

アプリを作った。ユーザーがポリゴンの白い部分の内側のどこかをクリックすると、内側の境界線の点がユーザーに表示され、縮小されたサムネイルがペイントされた内側のペインタを示します。

.Netでは、周囲が完全に塗りつぶされています。

C++ 6アプリでは、ポリゴンの一部が私のアプリを指しています。収集が正しく表示されません。

私はmsPaintを見て、.NetはMS Paintと同じ方法でポイントを描画しません。

ここに簡単な例があります。コードは1つのボタンと1つのラベルを持つ1つのフォームからです。ビットマップ上に線が描かれ、ビットマップが表示されるようにビットマップが拡大され、ラベルに表示されます。

同じ2つのポイントを使用してペイントに線を描画すると、描かれた線分がMSペイントで描いた線分と同じになりません。どんなに私が適用されますどのような設定

alt text

private void button1_Click(object sender, EventArgs e) 
    { 
     Bitmap bm = new Bitmap(16, 16); 
     Graphics g = Graphics.FromImage(bm); 
     //g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.Half; 
     //g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality; 
     //g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighSpeed; 
     //g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.None; 
     g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.Default; 
     Point pt = new Point(1, 3); 
     Point pt2 = new Point(5, 1); 
     // If you reverse the points, the same line is drawn. 
     g.DrawLine(Pens.Orange, pt, pt2); 
     // label1.Image = bm; 
     Bitmap bm2 = ZoomMap(8, bm); 
     g.Dispose(); 
     bm.Dispose(); 
     label1.Image = bm2; 
    } 

    private Bitmap ZoomMap(int zoomValue, Bitmap bm) 
    { 
     Bitmap zoomedBitMap; 
     Size sz = bm.Size;// new Size(75, 75); 
     Size newSize = new Size(sz.Width * zoomValue, sz.Height * zoomValue); 
     zoomedBitMap = new Bitmap(newSize.Width, newSize.Height); 
     Graphics gr = Graphics.FromImage(zoomedBitMap); 
     gr.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor; 
     gr.PageUnit = GraphicsUnit.Pixel; 
     gr.DrawImage(bm, 1, 1, newSize.Width, newSize.Height); 
     gr.Dispose(); 
     return zoomedBitMap; 
    } 

は、MSは、C#でペイント模倣する方法はありませんが、C++で6つの模倣MSは完全にペイントします。

既存のビットマップに描画するために呼び出せるウィンドウAPIはありますか?

お返事ありがとうございます。

+1

180度以上の.Netで描画された画像を回転させると、同じ結果が得られます。キャンバスにペイントして回転させ、オーバーレイして見たいものを作り出します。 –

答えて

4

デジタル差分アナライザ(DDA)またはBresenhamアルゴリズムを使用すると、GDI +と同じ結果が得られますが、標準のGDI線描画実装を見ると、標準のGDI LineTo実装で実際に線が描画されます指定したよりも1ピクセル短く、MSDNを引用する

'LineTo関数は、指定された点まで現在位置から線を描画します。 '

このためGDIを使用すると、(1,3) - (4,1)から線が引かれます。これらの同じ座標をGDI +で使用すると、線のピクセル構造が、もちろん、(5,1)の最後のピクセルが描かれていないことを除いて、古いバージョンのPaintを参照してください。ペイントのようなプログラムは、ラインを完成させるために追加のピクセルを追加するだけです。

ストレートGDIを使用するには、ペンを作成するためのinteropを処理し、DCにオブジェクトを選択してオブジェクトなどを削除することが非常に可能ですが、究極的には不便です。GDI +で1ピクセル短く線を描き、その端点から最終端点に線を引くことで、これをシミュレートすることができます。これは最後のピクセルを塗りつぶします。

注:Windows 7でPaintを使用すると、たとえば線が正しく描画されるため、古いバージョンのPaintが使用されます。

面白いと思いますが、.NETの古典的なGDIをどのように使用するかをすぐに見ていきたいと思いますが、ここではいくつかのinteropコードがあります。

[DllImport("gdi32")] 
static extern bool MoveToEx(IntPtr hdc, int x, int y, out Point point); 

[DllImport("gdi32")] 
static extern bool LineTo(IntPtr hdc, int x, int y); 

[DllImport("gdi32")] 
static extern IntPtr SelectObject(IntPtr hdc, IntPtr hgdiobj); 

[DllImport("gdi32")] 
static extern IntPtr CreatePen(int penStyle, int width, int color); 

[DllImport("gdi32")] 
static extern bool DeleteObject(IntPtr hgiobj); 

private void Form1_Paint(object sender, PaintEventArgs e) 
{ 
    Point ignore; 
    IntPtr hdc = e.Graphics.GetHdc(); 
    IntPtr pen = CreatePen(1, 1, ColorTranslator.ToWin32(Color.Red)); 
    IntPtr oldPen = SelectObject(hdc, pen); 
    MoveToEx(hdc, 1, 3, out ignore); 
    LineTo(hdc, 5, 1);     
    SelectObject(hdc, oldPen); 
    DeleteObject(pen);  
} 

実際に行が1ピクセル短い方法に注意してください。個人的には、Graphicsデバイスを使用してネイティブの.NETソリューションを使用し、正しいライン座標を決定して、標準のGDI機能を複製するだけです。

GDIが最後のピクセルから離れる理由を知りたいと思っていたかもしれませんが、XORを使って同じ行を非常に単純に削除してXORで線を再描画し、オリジナルの背景をそのまま残して削除されます。もちろん、ピクセルに2回以上描画しないように注意する必要があります。そうしないと、スクリーン上にアーティファクトを残してしまいます。

LineTo複数の呼び出しを使用して図形を描画するのが一般的であるため、たとえば三角形を描くためにLineToを3回呼び出すことができ、各行の最初の点が前の行の最後の点例えば、XORを使用したときに前記アーティファクトが発生すると、LineToへの呼び出しは、前の行の最後のピクセルが描画されなかったために前の行が終了した場所から安全に開始することができます。

+0

こんにちは、ありがとう、クリス。今私はこのアプリを終了することができます! – netcat

+0

申し訳ありませんが、google chromeに入力すると返信しました。あなたが投稿した機能を使用することができました.GDIは、あなたが述べたとおりに正確に動作します。私はビットマップ上にポリゴンを描画し、GDIを使ってそのビットマップにラベルを設定する簡単なサンプルフォームを作った。あなたが投稿した素晴らしい情報とサンプルコードをありがとう。 – netcat

+0

私は自分のコードを投稿することができないように見えます - このページはエラーをスローし続けます。私は後でやり直します。 – netcat

関連する問題