C# Can';不要使用GDI+;。是否可以使用Windows API调用在位图上绘制线条? 我们有一个应用C++编写的应用程序,它在交通地图上填满空白多边形,显示当前的交通状况。绿色表示良好,黄色表示更拥挤,等等

C# Can';不要使用GDI+;。是否可以使用Windows API调用在位图上绘制线条? 我们有一个应用C++编写的应用程序,它在交通地图上填满空白多边形,显示当前的交通状况。绿色表示良好,黄色表示更拥挤,等等,c#,bitmap,bitmapdata,C#,Bitmap,Bitmapdata,“壳贴图”是使用矩形和多边形的道路位图,这些矩形和多边形中没有填充任何内容。数据从道路传感器(导线感应器回路)收集,多边形根据回路检测器数据填充 当贴图更改时,必须有人在paint中手动放大位图,并获取每个新形状内部的坐标,其中将填充拥塞颜色。构成地图骨架的多边形均以海军蓝绘制,背景为白色 我制作了一个应用程序。其中,当用户单击多边形白色部分内的任何位置时,将向用户显示内部周长的点,并显示一个放大的缩略图,显示绘制的内部许可 在.Net中,周界绘制得非常完美 在C++ 6应用程序中,一些Poon

“壳贴图”是使用矩形和多边形的道路位图,这些矩形和多边形中没有填充任何内容。数据从道路传感器(导线感应器回路)收集,多边形根据回路检测器数据填充

当贴图更改时,必须有人在paint中手动放大位图,并获取每个新形状内部的坐标,其中将填充拥塞颜色。构成地图骨架的多边形均以海军蓝绘制,背景为白色

我制作了一个应用程序。其中,当用户单击多边形白色部分内的任何位置时,将向用户显示内部周长的点,并显示一个放大的缩略图,显示绘制的内部许可

在.Net中,周界绘制得非常完美

在C++ 6应用程序中,一些Poon点应用程序。收集的数据不能正确显示

我查看了msPaint,而.Net绘制点的方式与msPaint不同

这里有一个简单的例子。代码来自一个带有一个按钮和一个标签的表单。在位图上画一条线,位图被“放大”以便您可以看到它,并显示在标签上

如果使用相同的两点在绘制中绘制直线,则绘制的线段与在MS Paint中绘制的线段不同

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

<无论应用什么样的设置,C语言中都没有模仿MS画图的方法,但是在C++ 6中,模仿MS的画法是完美的。 是否有任何类型的windows API可以调用以在现有位图上绘制


提前感谢您的回复。

使用数字差分分析器(DDA)或Bresenham算法将产生与GDI+相同的结果,但如果您查看标准GDI线条绘制实现,您会注意到标准GDI实现实际上绘制的线条比您指定的短一个像素,引用MSDN

“LineTo函数从当前位置到指定点(但不包括指定点)绘制一条直线。”

因此,使用GDI绘制线是从(1,3)-(4,1)开始的,如果在GDI+中使用这些相同的坐标,您将看到线的像素结构与较早版本的Paint中看到的相匹配,当然,(5,1)处的最后一个像素没有绘制。像Paint这样的程序只需添加额外的像素即可完成线条

使用直接GDI需要处理创建笔的互操作、将对象选择到DC中删除对象等。所有这些都是非常可能的,但最终都会带来不便。您可以在GDI+中模拟这一点,方法是绘制一条短一像素的线,然后从该端点到最终端点绘制一条线,这将填充最后一个像素

注意:我说的是油漆的旧版本,因为如果你在Windows7中使用油漆,你会看到画的线是正确的

为了好玩,我想我会很快向您展示如何使用.NET中的经典GDI,下面是一些互操作代码

[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);      
}
请注意,这条线实际上短了一个像素。就我个人而言,我会使用一个使用图形设备的原生.NET解决方案,只需绘制正确的线坐标即可复制clasic GDI功能

我想你可能有兴趣知道为什么GDI去掉了最后一个像素,通常使用XOR在屏幕上画一条线,这会使删除同一条线变得非常简单,只需使用XOR重新绘制这条线,并在原始背景完整的情况下删除它。当然,这意味着您需要小心不要在像素上画两次,否则会在屏幕上留下瑕疵


由于使用多个
LineTo
调用绘制形状是很常见的,因此现在可以调用LineTo 3次来绘制三角形,而不必担心每条线的第一个点会与前一条线的最后一个点重叠,并在使用XOR(例如)时导致所述瑕疵,对LineTo的后续调用可以安全地从上一行结束的位置开始,因为上一行的最后一个像素没有绘制。

使用数字差分分析器(DDA)或Bresenham算法将产生与GDI+相同的结果,但是,如果您查看标准GDI线条绘制实现,您会注意到标准GDI实现实际上绘制的线条比您指定的短一个像素(引用MSDN)

“LineTo函数从当前位置到指定点(但不包括指定点)绘制一条直线。”

因此,使用GDI绘制线是从(1,3)-(4,1)开始的,如果在GDI+中使用这些相同的坐标,您将看到线的像素结构与较早版本的Paint中看到的相匹配,当然,(5,1)处的最后一个像素没有绘制。像Paint这样的程序只需添加额外的像素即可完成线条

使用直接GDI需要处理创建笔的互操作、将对象选择到DC中删除对象等。所有这些都是非常可能的,但最终都会带来不便。您可以在GDI+中模拟这一点,方法是绘制一条短一像素的线,然后从该端点到最终端点绘制一条线,这将填充最后一个像素

注意:我说的是油漆的旧版本,因为如果你在Windows7中使用油漆,你会看到画的线是正确的

为了好玩,我想我会很快向您展示如何使用.NET中的经典GDI,下面是一些互操作代码

[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);      
}
请注意,这条线实际上短了一个像素。就我个人而言,我会使用一个使用图形设备的原生.NET解决方案,只需绘制正确的线坐标即可复制clasic GDI功能

我想你会的