【问题标题】:Make a Map of Buttons?制作按钮地图?
【发布时间】:2014-10-31 08:17:56
【问题描述】:

如何执行以下操作我不是要求特定代码,但我需要一些指导,因为我已经为此绞尽脑汁数周了。只是我想制作一张地图。美国和每个州都是不同的图片或区域,可以将鼠标悬停在上面并单击。我尝试使用 png 和透明胶片,但我处于死胡同。更有野心的是,我想将带有州首府的标签拖到每个州上,然后将它们放在那里,然后有一个过程,如果标签/大写与州匹配,则它正确,否则不正确。

我已经尝试过 GIS(?)我想做这个 C#,但到目前为止我无法获得牵引力。任何人都可以帮忙吗?这在 C# 中是否太难了?我应该使用另一种方法吗?请问是什么方法?

【问题讨论】:

    标签: c# graphics png paint.net


    【解决方案1】:

    首先是好消息:编程部分并不难,即使使用良好的旧 Winforms,您也可以在几行代码内完成核心检查。但是,可点击区域不能是 Winforms 中的按钮。

    这里有两种解决方案:

    解决方案 1:您可以定义一个区域列表,称为区域并测试是否被点击。

    这是一个开始:我定义了一个非常简单的Rectangle Region 和一个不那么简单的Polygon Region 并测试每次点击是否被点击。如果它被击中,我会将其数据输出到表单的标题文本中:

    //..
    using System.Drawing.Drawing2D;
    //..
    public Form1()
    {
        InitializeComponent();
        // most real states don't look like rectangles
        Region r = new Region(new Rectangle(0, 0, 99, 99));
        regions.Add(r);
        List<int> coords = new List<int>() {23,137, 76,151, 61,203, 
                           117,283, 115,289, 124,303, 112,329, 76,325, 34,279, 11,162};
        List<Point> points = new List<Point>();
        for (int i = 0; i < coords.Count ; i += 2) 
                            points.Add(new Point(coords[i], coords[i+1]));
        byte[] fillmodes = new byte[points.Count];
        for (int i = 0 ; i < fillmodes.Length; i++) fillmodes[i] = 1;
        GraphicsPath GP = new GraphicsPath(points.ToArray(), fillmodes);
        regions.Add(r);
    
    }
    
    List<Region> regions = new List<Region>();
    
    
    private void pictureBox1_MouseClick(object sender, MouseEventArgs e)
    {
        using (Graphics G = pictureBox1.CreateGraphics() )
        foreach(Region r in regions)
        {
            Region ri = r.Clone();
            ri.Intersect(new Rectangle(e.X, e.Y, 1, 1));
            if (!ri.IsEmpty(G))  // hurray, we got a hit
                { this.Text = r.GetBounds(G).ToString(); break; }
        }
    
    }
    

    测试程序中的区域不可见。为了进行测试,您可能需要添加如下内容:

    private void button1_Click(object sender, EventArgs e)
    {   // paint a non-persistent filling
        using (Graphics G = pictureBox1.CreateGraphics())
            foreach (Region r in regions)
            { G.FillRegion(Brushes.Red, r); }
    }
    

    但现在有个坏消息:您可以将区域定义为看起来像真实状态的复杂多边形,但这是很多工作的!网络上有现成的图像地图编辑器,用于在网站上制作可点击的地图。您最好的课程可能是使用其中一个来创建所有这些多边形,然后将 html 输出转换为您可以读入程序的点列表。你甚至可能会很幸运地找到现成的美国图像地图,但我还没有看过..

    更新:那里许多美国的图像地图。一个甚至在wikipedia 上。将这些坐标转换为适合您的地图将是一项任务,但比从头开始创建它们要容易得多,imo。我已更改代码以包含来自维基百科来源的一个坐标列表。猜猜状态!

    我已经实现了一个程序,它允许您单击一个状态并在 78 行代码中显示名称,不包括具有 50 个状态的文本文件。

    解决方案 2

    您可以准备一个彩色地图并将颜色用作Dictionary&lt;Color, string&gt;Dictionary&lt;Color, StateInfo&gt; 的键,而不是多边形列表。您必须确保每个状态都有一种唯一的颜色,并且图像没有被压缩为 jpeg,否则会引入伪影并弄乱键映射。

    接下来将每种颜色映射到相关信息;这是真正的工作,因为您必须知道这些状态才能创建字典;-)

    最后你可以在你创建的字典中查找点击的颜色:

    Color c = ((Bitmap) pictureBox1.Image).GetPixel(e.X, e.Y)
    string StateName = stateDictionary[c];
    

    如果您使用类或结构作为字典中的值,则可以包括大写字母等。

    您可以缩放,但必须相应地缩放点击位置;如果不是在 PictureBox 中而是在不可见的颜色代码位图中查找关键颜色,您甚至可以显示地理图像。 总而言之,一个更简单的解决方案 imo.. 你的选择!

    一旦你开始工作,你就可以玩拖放了。在这里,您需要在 DragDrop 或 Mouseup 上进行测试,以查看您在哪里放置了标签。

    这是一个不错的项目,值得创建一些类来让事情变得更容易和更可扩展..!

    对于真正的 Button,您可能会幸运地使用 WPF。

    【讨论】:

    • 我花了几天时间试图找到一个可以理解的解决方案。我将逐步尝试您的建议。我的 g_d 将 asp.net 功能添加到 VS Express 的下载量约为 700mb。我打算尝试使用asp,因为大多数图像映射的支持文档都是针对asp的。让我尝试让您的代码建议发挥作用...谢谢。
    • 我收到一个错误:错误 1 ​​当前上下文中不存在名称“区域”我找不到尝试使用 VS 的“区域”中的上限或变体的“添加”方法快车 2010
    • 我知道你在做什么,我会努力让它发挥作用。 C# 很难,希望它的能力与它的学习曲线相匹配......
    • 嗯,值得学习,但是是的,掌握它需要时间和一些努力。它区分大小写。所以添加与添加不同。 Region 是一种类型,regions 是我声明的变量..
    猜你喜欢
    • 1970-01-01
    • 2015-11-04
    • 2021-03-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-16
    • 2021-05-09
    相关资源
    最近更新 更多