【问题标题】:How to disable the swt Browser clicking sound when used in Eclipse RCP application on windows?在 Windows 上的 Eclipse RCP 应用程序中使用时如何禁用 swt 浏览器单击声音?
【发布时间】:2015-05-29 09:05:29
【问题描述】:

我在我的 Eclipse RCP 应用程序中嵌入了一个 swt 浏览器。我的问题是,在 Windows 上,浏览器的 setUrl()dispose() 方法会导致(烦人的)Internet Explorer 导航声音(“点击”),这是不受欢迎的。

我发现这段代码成功禁用了点击声音

OS.CoInternetSetFeatureEnabled(OS.FEATURE_DISABLE_NAVIGATION_SOUNDS, OS.SET_FEATURE_ON_PROCESS, true);

但由于这是受限制的 API,我无法使用 Maven/Tycho 构建应用程序。

[ERROR] OS.CoInternetSetFeatureEnabled(OS.FEATURE_DISABLE_NAVIGATION_SOUNDS, OS.SET_FEATURE_ON_PROCESS, true);
[ERROR] ^^
[ERROR] OS cannot be resolved to a variable
[ERROR] 4 problems (4 errors)
[ERROR] -> [Help 1]
org.apache.maven.lifecycle.LifecycleExecutionException: Failed to execute goal org.eclipse.tycho:tycho-compiler-plugin:0.22.0:compile (default-compile) on project com.myapp: Compilation failure
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:212)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:153)...

有没有办法让 Maven/Tycho 在使用这个受限 API 时进行编译?

或者还有其他方法可以在 Windows 上禁用 IE 浏览器导航声音吗?

【问题讨论】:

  • 因此您需要将包含OS 类的包或片段放到编译类路径中。哪个包或片段包含该类?
  • oberlies,你是对的,但说起来容易做起来难。我在下面发布了一个答案,说明了如何完成。
  • 非常好的帖子!非常感谢您分享您的见解。

标签: java maven internet-explorer swt tycho


【解决方案1】:

我最终设法破解了这个问题,方法如下。

由于这个限制性 API 存在于特定于平台的插件中,即 SWT 32 位和 SWT 64 位,我创建了两个特定于平台的片段来保存代码。

要让 maven 编译片段,需要在 build.properties 文件中的 32 位片段中添加以下行:

extra.. = platform:/fragment/org.eclipse.swt.win32.win32.x86

以及 64 位片段 build.properties 的以下内容

extra.. = platform:/fragment/org.eclipse.swt.win32.win32.x86_64

maven pom 配置文件也应该是特定于平台的,这可以通过在 32 位片段的 pom.xml 中添加以下部分来完成

<build>
    <plugins>
        <plugin>
            <groupId>org.eclipse.tycho</groupId>
            <artifactId>target-platform-configuration</artifactId>

            <configuration>
                <environments>
                    <environment>
                        <os>win32</os>
                        <ws>win32</ws>
                        <arch>x86</arch>
                    </environment>
                </environments>
            </configuration>
        </plugin>
    </plugins>
</build>

这里是 64 位版本。

<build>
    <plugins>
        <plugin>
            <groupId>org.eclipse.tycho</groupId>
            <artifactId>target-platform-configuration</artifactId>
            <configuration>
                <environments>
                    <environment>
                        <os>win32</os>
                        <ws>win32</ws>
                        <arch>x86_64</arch>
                    </environment>
                </environments>
            </configuration>
        </plugin>
    </plugins>
</build>

也不要忘记在片段清单中设置相应的平台过滤器,如下所示

Eclipse-PlatformFilter: (& (osgi.os=win32) (osgi.arch=x86))
Eclipse-PlatformFilter: (& (osgi.os=win32) (osgi.arch=x86_64))

然后我们将静音代码放在每个片段的一个类中。这个类应该在宿主插件中实现一个接口。 主机插件定义了一个扩展点,该扩展点采用实现主机插件中接口的类。然后片段声明一个扩展并在片段中提供类名。

当宿主代码需要运行静默代码时,它需要检查扩展并实例化并调用静默代码。

例子:

package com.mypackage;

import javax.inject.Inject;

import org.apache.log4j.Logger;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtensionRegistry;
import org.eclipse.core.runtime.ISafeRunnable;
import org.eclipse.core.runtime.SafeRunner;
import org.eclipse.e4.core.di.annotations.Creatable;

import com.mypackage.ISilencer;

@Creatable
public class BrowserSilencer {

    private static final Logger LOGGER = Logger.getLogger(BrowserSilencer.class);

    @Inject
    IExtensionRegistry exReg;

    public void silence=() {
        IConfigurationElement[] config = exReg.getConfigurationElementsFor("com.mypackage.silencer");
        try {
            for (IConfigurationElement e : config) {
                final Object o = e.createExecutableExtension("class");
                if (o instanceof ISilencer) {
                    executeExtension(o);
                }
            }
        } catch (CoreException ex) {
            LOGGER.error("Error finding the com.mypackage.silencer extension");
        }
    }

    private void executeExtension(final Object o) {
        ISafeRunnable runnable = new ISafeRunnable() {
            @Override
            public void handleException(Throwable e) {
                LOGGER.error("Exception while attempting to silence browser");
            }

            @Override
            public void run() throws Exception {
                ((ISilencer) o).silence();
            }
        };
        SafeRunner.run(runnable);
    }
}

主机插件中的接口

package com.mypackage;
public interface ISilencer {
   public void silence();
}

以及 64 位插件中的代码示例。 32位几乎一样

package com.mypackage.fragment.win64;

import org.apache.log4j.Logger;
import org.eclipse.swt.internal.win32.OS;   // yes i DO mean win32 here

import com.mypackage.ISilencer;

@SuppressWarnings("restriction")
public class Silencer implements ISilencer {

    private static final Logger LOGGER = Logger.getLogger(Silencer.class);

    @Override
    public void silence() {
        // removes the annoying browser clicking sound!
        try {
            OS.CoInternetSetFeatureEnabled(OS.FEATURE_DISABLE_NAVIGATION_SOUNDS, OS.SET_FEATURE_ON_PROCESS, true);
        } catch (Throwable e1) {
            // I am just catching any exceptions that may come off this one since it is using restricted API so that if in any case it fail well it will just click.
            LOGGER.error("Caught exception while setting FEATURE_DISABLE_NAVIGATION_SOUNDS.");
        }
    }
}

由于 BrowserSilencer 被标记为 @Creatable,您可以简单地将其注入您的类并调用 silence() 方法

如果不清楚如何创建和扩展点,我可以在后续帖子中说明。

【讨论】:

    【解决方案2】:
    // Silence Windows SWT.browser widget from making awful clicks. 
    // For windows 32 and 64 bit SWT applications. 
    // Uses reflection to call OS.CoInternetSetFeatureEnabled(OS.FEATURE_DISABLE_NAVIGATION_SOUNDS, OS.SET_FEATURE_ON_PROCESS, true);
    // Without importing platform specific 
    // #import org.eclipse.swt.internal.win32.OS  
    private void silenceWindowsExplorer() {
        try {
            Class<?> c = Class.forName("org.eclipse.swt.internal.win32.OS");
            java.lang.reflect.Method method = c.getDeclaredMethod("CoInternetSetFeatureEnabled", Integer.TYPE, Integer.TYPE, Boolean.TYPE);
            method.invoke(null, new Object[] {21, 2, true});
        } catch (Throwable th)
        {
            // Might fail.. but probably will never do harm.
            th.printStackTrace();
        }
    }
    

    【讨论】:

      【解决方案3】:

      在 Windows 中使用 SWT 浏览器(使用 IE)时,我必须修复(可能)相同的导航声音问题,并且我能够找到不需要更改代码的解决方案。

      我发现可以通过将 Windows 控制面板中的特定声音禁用为“无”来改变这一点。我只在 Win 7 中验证过:

      控制面板 => 声音 => 声音 => Windows 资源管理器 => 开始导航
      FROM: Windows Navigation Start.wav
      至:无

      我希望这对正在寻找非代码解决方案的人有所帮助。

      【讨论】:

      • 这是一个无关紧要的答案,因为这不适用于运送到客户机器上的软件
      猜你喜欢
      • 2015-10-11
      • 1970-01-01
      • 2015-10-26
      • 2010-09-05
      • 2023-03-19
      • 1970-01-01
      • 1970-01-01
      • 2011-01-29
      • 1970-01-01
      相关资源
      最近更新 更多