65.9K
CodeProject 正在变化。 阅读更多。
Home

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

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.78/5 (42投票s)

2008 年 12 月 8 日

LGPL3

2分钟阅读

viewsIcon

367067

如何在 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 窗体。 如果您执行相同的步骤,最终结果应该类似于下图,但我确实警告说结果可能会有所不同 :-)

google_earth_embedded.jpg

您会注意到调整窗口大小对场景没有任何影响。 如果您计划在任何有用的应用程序中嵌入 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 事件中调用它。 结果如图所示

google_earth_embedded_good.jpg

示例

我拼凑了一个测试应用程序,欢迎您用作参考。 如果您有任何意见或建议,请务必给我发送电子邮件或添加评论。 在 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;
}
}
© . All rights reserved.