制作按钮图?

时间:2014-09-06 15:26:04

标签: c# graphics png paint.net

我如何做以下我不是要求具体的代码,但我需要一些方向,因为我已经绞尽脑汁待了好几个星期。简单地说,我想制作一个例如地图。美国和每个州都是不同的图片或区域,可以被点击和点击。我试着用png和透明胶片玩,但我已经走到了尽头。更雄心勃勃的是,我想把州首府的标签拖到每个州,然后将它们放在那里,然后有一个过程,如果标签/大写与正确的状态匹配,否则它不是。

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

1 个答案:

答案 0 :(得分:0)

首先是好消息:编程部分并不那么难,即使使用旧的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。将这些坐标转换为适合您的地图将是一项任务,但比从头开始创建它们要容易得多。我已将代码更改为包含维基百科源代码中的一个cordinate列表。猜猜州!

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

解决方案2

您可以准备彩色地图,并将颜色用作Dictionary<Color, string>Dictionary<Color, StateInfo>的关键字,而不是多边形列表。您必须确保每个状态都具有一个唯一的颜色,并且该图像不会被压缩为jpeg,这会引入工件并弄乱键映射。

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

最后,您可以在已创建的词典中查找单击的颜色:

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

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

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

一旦你开始工作,就可以玩拖放。在这里,您需要在DragDrop上进行测试,或者在Mouseup上进行测试,以查看丢弃Label的位置。

这是一个很好的项目,非常值得创建一些类,以使事情更容易和更容易扩展..!

对于真正的按钮,你可以通过WPF获得幸运。