在 C# 应用程序中嵌入 Google Earth






4.78/5 (42投票s)
如何在 C# 应用程序中嵌入 Google Earth 场景。
引言
如果您有兴趣在自定义应用程序中将 Google Earth 查看器用作控件,请继续阅读。互联网上有很多链接提供了关于如何向您的项目添加引用、创建 ApplicationGE
以及控制 Google Earth 应用程序的信息。但是,这些教程大多没有关注在应用程序中嵌入 Google Earth 的细节。 这就是我将在这里关注的内容。 从现在开始,GE 表示 Google Earth。
代码
您可能会像我一样,从以下开始您的嵌入冒险:
EARTHLib.ApplicationGE ge = new ApplicationGEClass();
如果 GE 进程已经存在,我们将获得对它的引用; 如果不存在,将创建一个新进程,并且您会在加载时看到 GE 徽标在屏幕上闪烁。 然后,您将看到带有嵌入式查看器的 Google Earth 主屏幕。 因为我们对嵌入 GE 感兴趣,所以我们不希望主屏幕存在,所以我们将其隐藏!
ShowWindowAsync(ge.GetMainHwnd(), 0);
出于所有实际目的,我们现在有了一个空屏幕。 接下来我们要做的是将 GE 渲染的场景嵌入到我们的应用程序中。 我们通过将渲染 Hwnd 的父级设置为我们想要渲染到的窗口来实现这一点
SetParent(ge.GetRenderHwnd(), this.Handle.ToInt32());
在上面的例子中,'this
' 是一个 Windows 窗体。 如果您执行相同的步骤,最终结果应该类似于下图,但我确实警告说结果可能会有所不同 :-)
您会注意到调整窗口大小对场景没有任何影响。 如果您计划在任何有用的应用程序中嵌入 GE,您很可能需要它对调整大小做出响应。 我花了一些时间研究在调整 GE 主应用程序窗口的大小时传递给场景的事件。 这让我找到了一个特殊的事件 WM_QT_PAINT
,以及一系列其他事件。 花了一点时间进行调整才能使其正确,但这似乎对我有效
SendMessage(ge.GetMainHwnd(), WM_COMMAND, WM_PAINT, 0);
PostMessage(ge.GetMainHwnd(), WM_QT_PAINT, 0, 0);
SetWindowPos( ge.GetMainHwnd(), HWND_TOP, 0, 0, (int)this.Width,
(int)this.Height, SWP_FRAMECHANGED);
SendMessage(ge.GetRenderHwnd(), WM_COMMAND, WM_SIZE, 0);
这应该允许场景根据父窗体的大小进行调整。 我将其捆绑到一个名为 "ResizeGoogleControl
" 的方法中,并在 SetParent
之后和我的 Form_Resize
事件中调用它。 结果如图所示
示例
我拼凑了一个测试应用程序,欢迎您用作参考。 如果您有任何意见或建议,请务必给我发送电子邮件或添加评论。 在 Visual Studio 中创建一个新的 C# 项目,然后用此代码替换 *Form1.cs* 代码
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;
using EARTHLib;
namespace resize_google_earth
{
public partial class Form1 : Form
{
[DllImport("user32.dll")]
private static extern int SetParent(
int hWndChild,
int hWndParent);
[DllImport("user32.dll")]
private static extern bool ShowWindowAsync(
int hWnd,
int nCmdShow);
[DllImport("user32.dll", SetLastError = true)]
private static extern bool PostMessage(
int hWnd,
uint Msg,
int wParam,
int lParam);
[DllImport("user32.dll", EntryPoint = "SetWindowPos")]
private static extern bool SetWindowPos(
int hWnd,
int hWndInsertAfter,
int X,
int Y,
int cx,
int cy,
uint uFlags);
[DllImport("user32.dll")]
private static extern int SendMessage(
int hWnd,
uint Msg,
int wParam,
int lParam);
private const int HWND_TOP = 0x0;
private const int WM_COMMAND = 0x0112;
private const int WM_QT_PAINT = 0xC2DC;
private const int WM_PAINT = 0x000F;
private const int WM_SIZE = 0x0005;
private const int SWP_FRAMECHANGED = 0x0020;
public Form1()
{
InitializeComponent();
ge = new ApplicationGEClass();
ShowWindowAsync(ge.GetMainHwnd(), 0);
SetParent(ge.GetRenderHwnd(), this.Handle.ToInt32());
ResizeGoogleControl();
}
private void Form1_Resize(object sender, EventArgs e)
{
ResizeGoogleControl();
}
private void ResizeGoogleControl()
{
SendMessage(ge.GetMainHwnd(), WM_COMMAND, WM_PAINT, 0);
PostMessage(ge.GetMainHwnd(), WM_QT_PAINT, 0, 0);
SetWindowPos(
ge.GetMainHwnd(),
HWND_TOP,
0,
0,
(int)this.Width,
(int)this.Height,
SWP_FRAMECHANGED);
SendMessage(ge.GetRenderHwnd(), WM_COMMAND, WM_SIZE, 0);
}
private EARTHLib.ApplicationGE ge = null;
}
}