五年前申请的小课题-基于TerraExplorer进行路由成果三维展示,实在拖不下去了,这两天验证一下技术路线。
1、安装与配置
根据上篇的介绍,TerraExplorer5.1.3和TerraBuilder1.7.6不需要修改计算机时间,使用没有问题,但是不能开发,VB、VC和VC#,包括ArcGIS VBA也不行,尝试很多方法都不行,后来,安装了TerraExplorer6.5和TerraBuilder6.5,License文件虽然过期了,但是修改时间以后是可以使用的。不折腾了,还是老老实实使用修改时间的TE/TB吧。
ArcGIS 10.2SDK虽然可以安装到VS2013上,但是仍然不能开发addin,站长的经历是这样的:
错误 2 “ValidateAddInXMLTask”任务意外失败。
System.IO.FileNotFoundException: 未能加载文件或程序集“Microsoft.VisualStudio.Shell.11.0, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a”或它的某一个依赖项。系统找不到指定的文件。
警告: 程序集绑定日志记录被关闭。
要启用程序集绑定失败日志记录,请将注册表值 [HKLM\Software\Microsoft\Fusion!EnableLog] (DWORD)设置为 1。
注意: 会有一些与程序集绑定失败日志记录关联的性能损失。
要关闭此功能,请移除注册表值 [HKLM\Software\Microsoft\Fusion!EnableLog]。GuanluanView
下载了Microsoft.VisualStudio.Shell.11.0安装包,大约227MB解决;
紧接着,又出现了一个问题,就是NO GUI components found in this add-in,尝试了很多办法,觉得可能是ArcGIS 10.2 不能注册addin对应的dll造成的,但是这个就没有招了。
从头捋了捋,发现这个addin方式也有问题,与arcgis耦合度太高,并不适合。这种方式还不如用VBA,VBA的主要的问题是开发能力较弱,但与ArcMap交互较好,如下图:
2、VBA向VC#发送进程消息
VBA发送消息“我爱编程”的代码:
Option Explicit
Private Type COPYDATASTRUCT
dwData As Long
cbData As Long
lpData As Long
End Type
Private Const WM_COPYDATA = &H4A
Private Declare Function FindWindow Lib "user32" Alias _
"FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName _
As String) As Long
Private Declare Function SendMessage Lib "user32" Alias _
"SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal _
wParam As Long, lParam As Any) As Long
'Copies a block of memory from one location to another.
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
(hpvDest As Any, hpvSource As Any, ByVal cbCopy As Long)
Private Sub CommandButton1_Click()
Dim cds As COPYDATASTRUCT
Dim ThWnd As Long
Dim buf(1 To 1024) As Byte
Dim a As String, i As Long, lLen As Long
' Get the hWnd of the target application
ThWnd = FindWindow(vbNullString, "Target")
a$ = "我爱编程" & Format(Now, "yyyy-MM-dd HH:mm:ss") & " !"
' Copy the string into a byte array, converting it to ASCII
lLen = LenB(StrConv(a, vbFromUnicode))
Call CopyMemory(buf(1), ByVal a, lLen)
cds.dwData = 3
cds.cbData = lLen + 1
cds.lpData = VarPtr(buf(1))
i = SendMessage(ThWnd, WM_COPYDATA, ThisDocument.Parent.hwnd, cds)
End Sub
Private Sub UserForm_Initialize()
' This gives you visibility that the target app is running
' and you are pointing to the correct hWnd
Me.Caption = Hex$(FindWindow(vbNullString, "Target"))
End Sub
VC#段接收消息的Form1.cs的代码
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.Text = "Target";
}
protected override void DefWndProc(ref Message m)
{
switch (m.Msg)
{
case WM_COPYDATA:
COPYDATASTRUCT cdata = new COPYDATASTRUCT();
Type mytype = cdata.GetType();
cdata = (COPYDATASTRUCT)m.GetLParam(mytype);
this.textBox1.Text = cdata.lpData;
break;
default:
base.DefWndProc(ref m);
break;
}
}
//WM_COPYDATA消息的主要目的是允许在进程间传递只读数据。
private const int WM_COPYDATA = 0x004A;
//Windows在通过WM_COPYDATA消息传递期间,不提供继承同步方式。
//其中,WM_COPYDATA对应的十六进制数为0x004A
public struct COPYDATASTRUCT
{
public int dwData;
public int cbData;
[MarshalAs(UnmanagedType.LPStr)]
public string lpData;
}
}
}
结果图如下: