-1

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

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

4

1 回答 1

0

The good news first: The programming part is not so hard and even with good old Winforms you can do the core checks in a few lines. The clickable areas can't be Buttons in Winforms, however.

Here are two solutions:

Solution 1 : You can define a list of areas, called regions and test if one got clicked.

Here is a start: I define a very simple Rectangle Region and a not so simple Polygon Region and test on each click if one was hit. If it was hit I output its data into the Form's title text:

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

}

The regions in the test programm are not visible. For testing you may want to add something like this:

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

But now for the bad news: You can define regions to be complicated polygons that look like real states, however that is a lot of work! There are ready-made image map editors out there in the web for making clickable maps on websites. Your best course might be to use one of these to create all those polygons and then convert the html output to a list of points you can read into your program. You may even get lucky and find ready image maps for the USA, but I haven't looked..

Update: There are many image maps of the USA out there. One is even on wikipedia. Converting these coordinates to fit your map will be a task but lot easier than creating them from scratch, imo. I have changed the code to include one list of cordinates from the wikipedia source. Guess the state!

I have implmented a program that lets you click on a state and displays the name in 78 lines of code, excluding the text file with the 50 states.

Solution 2:

Instead of a list of polygons you can prepare a colored map and use the colors as keys into a Dictionary<Color, string> or Dictionary<Color, StateInfo>. You must make sure that each state has one unique color and that the image is not compressed as jpeg, which would introduce artifacts and mess up the key mapping.

Next you map each color to the related info; this is the real work because you must know those states to create the Dictionary ;-)

Finally you can look up the clicked color in the Dictionary you have created:

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

If you are using a class or struct as your value in the dictionary you can include the capital etc..

You can zoom but must scale the click location accordingly; you can even display a geographical Image if you look up the key color not in the PictureBox but in an invisible color code bitmap. All in all an even simpler solution imo.. your pick!

Once you got that working, you can play with drag&drop. Here you'll want to test on DragDrop or maybe on Mouseup to see where you have dropped the Label.

This is a nice project and well worth of creating a few classes to make things easier and more expandable..!

For real Buttons you may get lucky with WPF.

于 2014-09-06T17:56:35.937 回答