gpt4 book ai didi

c# - 不能使用 GDI+。可以使用 Windows API 调用在位图上绘制一条线吗?

转载 作者:太空宇宙 更新时间:2023-11-03 22:17:22 28 4
gpt4 key购买 nike

我们有一个用 C++ 6 编写的应用程序,可以填充交通 map 上的空白多边形以显示当前的交通状况。绿色表示良好,黄色更拥挤等。

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

本地图发生变化时,必须有人在paint中手动放大位图,并获取每个新形状内部周围的坐标,并在此处填充拥塞颜色。构成 map 骨架的多边形均已绘制海军蓝色,白色背景。

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

在 .Net 中,完美绘制了周边。

在 C++ 6 应用程序中,一些多边形指向我的应用程序。收藏未正确显示。

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

这是一个简单的例子。代码来自具有一个按钮和一个标签的一种形式。在位图上绘制一条线,位图被“放大”以便您可以看到它,并显示在标签上。

在Paint中用相同的两点画线,画出的线段与在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;
}

alt text

无论我应用什么设置,都无法在 C# 中模仿 MS Paint,但在 C++ 6 中可以完美模仿 MS Paint。

是否可以调用任何类型的 Windows API 来绘制现有位图?

提前感谢您的任何回复。

最佳答案

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

'LineTo 函数从当前位置绘制一条直线,但不包括指定点。'

因此,使用 GDI,您的线是从 (1,3)-(4,1) 绘制的,如果您在 GDI+ 中使用这些相同的坐标,您将看到该线的像素结构与您在旧版本中看到的相匹配Paint 的版本,当然除了 (5,1) 处的最后一个像素未绘制。然后像 Paint 这样的程序会添加额外的像素来完成线条。

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

注意:我说的是旧版本的画图,因为如果您在 Windows 7 中使用画图,您会看到线条绘制正确。

为了好玩,我想我会快速向您展示如何使用来自 .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);
}

注意这条线实际上是如何短一个像素的。就我个人而言,我会选择使用图形设备的 native .NET 解决方案,只需确定正确的线坐标即可复制经典的 GDI 功能。

我想你可能有兴趣知道为什么 GDI 会留下最后一个像素,通常使用 XOR 在屏幕上画一条线,这使得删除同一条线非常简单,只需用 XOR 重新画线即可被移除,原始背景完好无损。当然,您需要注意不要在一个像素上绘制两次,否则您会在屏幕上留下伪影。

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

关于c# - 不能使用 GDI+。可以使用 Windows API 调用在位图上绘制一条线吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4573527/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com