C# 调用 Google Earth Com API开发(四)

本篇继续介绍Google Earth COM API开发的基础知识,相对第三篇的改进如下:

1)增加鼠标滚轮支持,可以实现放大、缩小。此功能利用上一篇提供的HookAPI.dll实现

2)读取PlaceMarks(Google Earth界面中的位置)并显示、隐藏

3)读取所有图层,显示并隐藏

下面,继续放代码:

1、鼠标滚轮事件,实现放大、缩小

   1: ...
   2: // 放大
   3: private const long ZoomIn = 0x00780000;
   4: // 缩小
   5: private const long ZoomOut = 0xFF880000;
   6: ...
   7: mouseHook.MouseWheel += new MouseEventHandler(mouseHook_MouseWheel);
   8: ...
   9: /// <summary>
  10: /// 鼠标钩子。鼠标滚动事件
  11: /// </summary>
  12: /// <param name="sender"></param>
  13: /// <param name="e"></param>
  14: void mouseHook_MouseWheel(object sender, MouseEventArgs e)
  15: {
  16:     IntPtr hWnd = NativeMethods.WindowFromPoint(e.Location);
  17:     if (hWnd == this.GeRenderHWnd)
  18:     {
  19:         Point point = this.Control.PointToClient(e.Location);
  20:         // 如果鼠标位置在控件内部,则说明鼠标在GoogleEarth视图范围内进行了滚动
  21:         if (this.Control.ClientRectangle.Contains(point))
  22:         {
  23:             NativeMethods.PostMessage(GeRenderHWnd, (int)WM_MOUSE.WM_MOUSEWHEEL, e.Delta == 120 ? ZoomIn : ZoomOut, 0);
  24:         }
  25:     }
  26: }

2、读取PlaceMarks

Google Earth COM API中提供了两个读取PlaceMarks的函数。一个是GetTemporaryPlaces(),用来读取临时位置;另一个是GetMyPlaces(),用来读取自定义位置,即GoogleEarth中显示的“我的位置”。呵呵

   1: ...
   2: /// <summary>
   3: /// 显示位置“PlaceMarks”。位置分为两种,一种时TemporaryPlaces,另一种为MyPlaces
   4: /// </summary>
   5: protected void ShowPlaces()
   6: {
   7:     Thread.Sleep(500);
   8:     // 获取MyPlaces
   9:     FeatureGE myPlace = GeApp.GetMyPlaces();
  10:     // 获取临时位置
  11:     FeatureGE temporaryPlace = GeApp.GetTemporaryPlaces();
  12:     // 
  13:     List<FeatureGE> places = new List<FeatureGE>();
  14:     places.Add(myPlace);
  15:     places.Add(temporaryPlace);
  16:  
  17:     // 获取工具面板
  18:     GEToolPad toolPad = GetToolPad();
  19:     // 显示所有位置
  20:     toolPad.ShowPlaces(places);
  21: }
  22: ...
  23: /// <summary>
  24: /// 显示所有PlaceMarks(位置)
  25: /// </summary>
  26: /// <param name="places"></param>
  27: public void ShowPlaces(List<FeatureGE> places)
  28: {
  29:     if (this.InvokeRequired)
  30:     {
  31:         Action method = delegate {
  32:             InternalShowPlaces(places);
  33:         };
  34:  
  35:         try
  36:         {
  37:             this.Invoke(method);
  38:         }
  39:         catch { }
  40:     }
  41:     else
  42:     {
  43:         InternalShowPlaces(places);
  44:     }
  45: }
  46: /// <summary>
  47: /// 显示所有PlaceMarks(位置)。被ShowPlaces函数调用
  48: /// </summary>
  49: /// <param name="places"></param>
  50: protected void InternalShowPlaces(List<FeatureGE> places)
  51: {
  52:     this.tvPlaces.Nodes.Clear();
  53:  
  54:     if (places == null || places.Count <= 0)
  55:         return;
  56:  
  57:     foreach (FeatureGE place in places)
  58:     {
  59:         TreeNode node = new TreeNode(place.Name);
  60:         node.Checked = place.Visibility > 0;
  61:         node.Tag = place;
  62:  
  63:         ShowChildrenPlaces(place, node);
  64:  
  65:         node.Expand();
  66:  
  67:         this.tvPlaces.Nodes.Add(node);
  68:     }
  69: }
  70: /// <summary>
  71: /// 显示指定PlaceMark的子PlaceMark
  72: /// </summary>
  73: /// <param name="place">父PlaceMark</param>
  74: /// <param name="node">父节点</param>
  75: protected void ShowChildrenPlaces(FeatureGE place, TreeNode node)
  76: {
  77:     FeatureCollectionGE places = place.GetChildren();
  78:  
  79:     foreach (FeatureGE child in places)
  80:     {
  81:         TreeNode tn = new TreeNode(child.Name);
  82:         tn.Checked = child.Visibility > 0;
  83:         tn.Tag = child;
  84:  
  85:         ShowChildrenPlaces(child, tn);
  86:  
  87:         node.Nodes.Add(tn);
  88:     }
  89: }

3、读取图层

   1: ...
   2: /// <summary>
   3: /// 显示图层
   4: /// </summary>
   5: protected void ShowLayers()
   6: {
   7:     Thread.Sleep(500);
   8:     // 获取所有图层信息
   9:     FeatureCollectionGE layers = GeApp.GetLayersDatabases();
  10:     // 获取工具面板
  11:     GEToolPad toolPad = GetToolPad();
  12:     // 显示所有图层
  13:     toolPad.ShowLayers(layers);
  14: }
  15: ...
  16: /// <summary>
  17: /// 将给定的图层集合显示在“图层”选项卡的树形控件中
  18: /// </summary>
  19: /// <param name="layers">图层集合</param>
  20: public void ShowLayers(FeatureCollectionGE layers)
  21: {
  22:     if (this.InvokeRequired)
  23:     {
  24:         Action method = delegate {
  25:             InternalShowLayers(layers);
  26:         };
  27:         try
  28:         {
  29:             this.Invoke(method);
  30:         }
  31:         catch { }
  32:     }
  33:     else
  34:     {
  35:         InternalShowLayers(layers);
  36:     }
  37: }
  38: /// <summary>
  39: /// 将给定的图层集合显示在“图层”选项卡的树形控件中.被公共函数ShowLayers调用
  40: /// </summary>
  41: /// <param name="layers"></param>
  42: protected void InternalShowLayers(FeatureCollectionGE layers)
  43: {
  44:     this.tvLayers.Nodes.Clear();
  45:  
  46:     if (layers == null || layers.Count <= 0)
  47:     {
  48:         return;
  49:     }
  50:  
  51:     foreach (FeatureGE layer in layers)
  52:     {
  53:         TreeNode node = new TreeNode(layer.Name);
  54:         node.Checked = layer.Visibility > 0;
  55:         node.Tag = layer;
  56:  
  57:         ShowChidrenLayers(layer, node);
  58:  
  59:         node.Expand();
  60:  
  61:         this.tvLayers.Nodes.Add(node);
  62:     }
  63: }
  64: /// <summary>
  65: /// 显示指定图层的子图层
  66: /// </summary>
  67: /// <param name="layer">当前图层</param>
  68: /// <param name="node">当前节点</param>
  69: protected void ShowChidrenLayers(FeatureGE layer, TreeNode node)
  70: {
  71:     FeatureCollectionGE layers = layer.GetChildren();
  72:  
  73:     foreach (FeatureGE child in layers)
  74:     {
  75:         TreeNode tn = new TreeNode(child.Name);
  76:         tn.Checked = child.Visibility > 0;
  77:         tn.Tag = child;
  78:  
  79:         ShowChidrenLayers(child, tn);
  80:  
  81:         node.Nodes.Add(tn);
  82:     }
  83: }

呵呵,代码很简单。按照此代码修改第三篇的源程序就可以实现本篇的功能了。

GoogleEarthDemo

posted @ 2009-05-25 21:16 温伟鹏 阅读(5654) 评论(30) 编辑 收藏

 回复 引用 查看   
#1楼2009-05-25 22:01 | 姜荣昌      
请问能提供demo吗?谢谢!
 回复 引用 查看   
#2楼[楼主]2009-05-25 22:06 | 温伟鹏      
@姜荣昌
Demo在第三篇文章中提供源代码,第四篇也是在其基础上修改部分代码而成的。

 回复 引用 查看   
#4楼2009-05-26 11:08 | 姜荣昌      
@温伟鹏
3Q,学习中!!

 回复 引用 查看   
#5楼[楼主]2009-05-26 13:10 | 温伟鹏      
@姜荣昌
呵呵,不客气

 回复 引用   
#6楼2009-05-27 15:50 | jlq[未注册用户]
log4net怎么配置呢?还是报错,DEMO无法运行
 回复 引用 查看   
#7楼[楼主]2009-05-29 00:07 | 温伟鹏      
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="log4net" type="System.Configuration.IgnoreSectionHandler" />
</configSections>

<log4net>
<appender name="ColoredConsoleAppender" type="log4net.Appender.ColoredConsoleAppender">
<mapping>
<level value="FATAL" />
<foreColor value="Red, HighIntensity" />
</mapping>
<mapping>
<level value="ERROR" />
<foreColor value="Red" />
</mapping>
<mapping>
<level value="WARN" />
<foreColor value="Yellow" />
</mapping>
<mapping>
<level value="INFO" />
<foreColor value="White" />
</mapping>
<mapping>
<level value="DEBUG" />
<foreColor value="Green" />
</mapping>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level- %message%newline" />
</layout>
</appender>

<appender name="FileAppender" type="log4net.Appender.FileAppender">
<file value="SharpDevelop_UserInterface_Test_Log.txt" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level- %message%newline" />
</layout>
</appender>

<root>
<level value="DEBUG" />
<appender-ref ref="ColoredConsoleAppender" />
</root>
</log4net>
</configuration>

 回复 引用   
#8楼2009-06-07 00:19 | firefly.liu[未注册用户]
090522的源代码例子编译成功
但运行报错
好象是缺少环境(VS2005+GE5.0)
希望博主指点一下呵。

 回复 引用 查看   
#9楼[楼主]2009-06-07 16:01 | 温伟鹏      
@firefly.liu
下载http://files.cnblogs.com/wpwen/GE_DEMO_Bin.rar,覆盖源代码的bin目录,试试

 回复 引用   
#10楼2009-06-07 20:18 | firefly.liu[未注册用户]
环境问题已经搞清楚了,是Log4Net版本的问题,之前提供的是1.1的,换了2.0的就OK了

现在的问题是第四篇发的内容好象少发了部分,运行不起来呵

 回复 引用   
#11楼2009-06-11 14:09 | windFan[未注册用户]
博主你好,有个问题向您请教一下.
对于地图上显示的一些placemark,有没有方法可以动态改变其样式呢,如边线宽度,填充颜色等?
谢谢!

 回复 引用   
#12楼2009-06-11 16:38 | NetFarmer
汗。。原来我还以为我已经精通c#了呢。看来还才入门。啥都不懂、
 回复 引用   
#13楼2009-06-11 21:25 | firefly.liu[未注册用户]
楼主
还是有些问题需要请教呵,希望出来指点一下

GetToolPad();
这个方法应该怎么写呵
对你写的SharpPlatform还不是太熟悉呵,有没有计划啥时候放出源代码或完整的框架呀

Action<FeatureGE> method = delegate
{
InternalShowLayers(layers);
};
不知道加得对不对呵,对泛型还不太了解呵

再就是鼠标点击时得到的经纬度总是与屏幕上显示的不一致呵,有一定的误差,有没有办法解决呀

 回复 引用 查看   
#14楼2009-06-14 09:01 | Sea.Yu      
楼主,我请教个问题,如何在你这个DEMO中装载KML文件,从而在GEVControl控件中显示出对应的地标信息
 回复 引用   
#15楼2009-08-19 13:45 | _-_-_[未注册用户]
[1684] INFO - 正在加载插件 SharpPlatform.GeDemo.dll

然后程序一直卡着,里面只加载了Tab插件,GoogleEarth的视图没被调进去,请问怎么回事???

 回复 引用   
#16楼2009-09-02 17:58 | LouisZhu[未注册用户]
楼主,按照你的方法加载temPlace,当templace非常多时加载很慢
还有什么好办法解决吗?

 回复 引用   
#17楼2009-09-14 19:13 | gis理想[未注册用户]
放大 3: private const long ZoomIn = 0x00780000; 缩小 5: private const long ZoomOut = 0xFF880000;
鼠标滚轮的方法缩小并不能实现啊 为什么呢
还有这里的0x00780000数值是什么意思啊 不明白
请楼主指点迷津啊 其他谁知道的话 也告诉我下呗 谢谢额

 回复 引用   
#18楼2009-09-14 19:14 | gis理想[未注册用户]
对了 我的qq 1006861321 谢谢!
 回复 引用 查看   
#19楼2009-09-22 14:01 | 玻璃珠      
很想知道楼主怎么将坐标是转化成经纬度?
如果可以能不能把本次修改后的源程序发给我一份,不胜感激.
邮箱是zlb0214@126.com

 回复 引用   
#20楼2009-10-28 15:35 | 前进[未注册用户]
如果可以能不能把本次修改后的源程序发给我一份,不胜感激.
邮箱是feng_gongyu@163.com

 回复 引用   
#21楼2009-12-28 22:46 | CCMM[未注册用户]
博主,请问运行时提示未能从插件树找到path:/workspace/tools是什么原因,程序执行不下去。
 回复 引用 查看   
#22楼2009-12-30 17:04 | fei_fei      
我最近也在研究Google Earth 的二次开发 一起讨论下吧
wy83509268@gmail.com

 回复 引用 查看   
#23楼2010-06-17 13:06 | 路清风      
滚轮时间的 zoomin zoomout 是long类型的,在调用时无法转换成int 类型亚,。没有成功。。。。请楼主明示!
 回复 引用 查看   
#24楼2010-07-26 20:34 | GIS开发小兵      
你好,这里的鼠标滚轮事件怎样应用于,比如我重新创建一个windows窗体,要求要把事件写进去,谢谢!
 回复 引用 查看   
#25楼2010-11-17 13:11 | meiwen      
如果可以能不能把本次修改后的源程序发给我一份,不胜感激.
邮箱是zhangmin_wen@163.com
 

 回复 引用 查看   
#26楼2010-11-17 14:48 | lajiao1225      
怎么没有作者解答的信息呢?
我运行第四部分也是有问题,代码不完整,谁愿意给我一份?
lajiao.1225@163.com

 回复 引用 查看   
#27楼2011-03-06 09:33 | samyp1234      
博主好,我按照您的方法,做了如下代码:
//// 设置鼠标钩子
mouseHook = new MouseHook();
mouseHook.MouseWheel += new MouseEventHandler(mouseHook_MouseWheel);
mouseHook.StartHook(HookType.WH_MOUSE_LL, 0);
后面加的有mouseHook_MouseWheel方法,这里略去。

我的问题是:当运行时,出错:对 PInvoke 函数“HookAPI!HookAPI.NativeMethods::SetWindowsHookEx”的调用导致堆栈不对称。原因可能是托管的 PInvoke 签名与非托管的目标签名不匹配。请检查 PInvoke 签名的调用约定和参数与非托管的目标签名是否匹配。

我的环境是.NET2005和GE5,这个错误,我查了资料,可能是在.NET2005和非托管两种情况下,StartHook的第二个参数的类型的长度不一致。

那么,如何才能解决这个问题呢?HookAPI.dll有没有源码呢?修改一下源码,是否可以呢?
非常谢谢您。

 回复 引用 查看   
#28楼2011-07-22 16:59 | 唯伊风格      

你好楼主 我是一个C#新手 呵呵 把第四部分代码运行的时候发生了错误。。。。如图所示:类似的有三个 InvokeRequired;tvLayers;tvPlaces 请楼主指示该怎么修改 谢谢了

 回复 引用 查看   
#29楼2011-07-22 17:01 | 唯伊风格      
或者发到我邮箱也可以 谢谢楼主 382415475@qq.com
 回复 引用 查看   
#30楼2011-12-26 17:45 | tamphoenix      
不知道能不能把源码发一份呢,谢谢,学长,277831894@qq.com,非常感谢,找了好多天了