【问题标题】:JFrame remove taskbar IconJFrame删除任务栏图标
【发布时间】:2013-06-21 06:06:12
【问题描述】:

我有一个 JFrame,我使用以下方法将其最小化到托盘:

这个用于展示:

Frame.this.Minimized = false;
Frame.this.setVisible(true);
systemTray.remove(systemTrayIcon);
Frame.this.setExtendedState(JFrame.NORMAL);

还有这个用于隐藏:

if (SystemTray.isSupported()) {
    systemTray.add(systemTrayIcon);
    Frame.this.setVisible(false);
    Frame.this.Minimized = true;
}
Frame.this.setExtendedState(JFrame.ICONIFIED);

但是,我不想将框架设置为不可见。当我将其设置为不可见时,它会删除我喜欢的任务栏图标。有没有办法在不将可见性设置为 false 的情况下删除框架的任务栏图标?

原因是当我最小化我的应用程序时,我可以向它发送命令并执行它们,但是当我将其可见性设置为 false 时,它​​会停止执行来自外部应用程序的任何命令。我需要做的就是在最小化时从任务栏中删除图标,并在正常时显示图标。

有什么想法吗?

【问题讨论】:

  • 这篇关于如何hide Jframe to SystemTray of Taskbar 的帖子,看起来就像您所指的那样,或者我应该说可能与该线程重复吗? :-)
  • 否,因为它使用 setVisible(false);第二个答案是等价的。我要做的就是随意从任务栏中删除图标并随意添加它。
  • 我放弃了.. 我不敢相信这样的事情在 Java 中如此困难.. 太荒谬了.. 猜猜这就是 C++ 和 Java 之间的区别。 :l

标签: java swing


【解决方案1】:

我知道这已经很晚了,但我花了一个小时试图自己解决这个问题。您所要做的就是将您的 JFrame 更改为 JWindow,然后您就完成了。我有一个相当复杂的 JFrame,我唯一需要删除的是 setUndecorated()setDefaultCloseOperation()。其他一切都很好。

【讨论】:

    【解决方案2】:

    sigh 好久没有回复了。我决定用 C++/JNI 解决它,反射如下:

    在 Java 方面:

    package apptotray;
    
    import java.awt.*;
    import java.io.File;
    import java.nio.file.Paths;
    import javax.swing.*;
    
    public class AppToTray {
    
        public static void main(String[] args) {
            JFrame frame = new JFrame("Some Window");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setLayout(new BorderLayout());
            frame.add(new JPanel(), BorderLayout.CENTER);
            frame.setPreferredSize(new Dimension(500, 500));
            frame.pack();
            frame.setVisible(true);
            
            System.load(new File("JNI.dll").getAbsolutePath());
            try {
                System.out.println("Icon is showing..");
                Thread.sleep(3000);
            } catch (Exception Ex) {
                Ex.printStackTrace();
            }
            
            removeFromTaskBar(getWindowHandle(frame));
            
            try {
                System.out.println("Icon is not showing..");
                Thread.sleep(3000);
            } catch (Exception Ex) {
                Ex.printStackTrace();
            }
            
            addToTaskBar(getWindowHandle(frame));
            System.out.println("Icon is showing again..");
        }
        
        public static native void addToTaskBar(long WindowHandle);
        
        public static native void removeFromTaskBar(long WindowHandle);
    
        public static long getWindowHandle(java.awt.Frame frame) {
            return (Long)invokeMethod(invokeMethod(frame, "getPeer"), "getHWnd");
        }
    
        protected static Object invokeMethod(Object o, String methodName) {
            Class c = o.getClass();
            for (java.lang.reflect.Method m : c.getMethods()) {
                if (m.getName().equals(methodName)) {
                    try {
                        return m.invoke(o);
                    } catch (IllegalAccessException | IllegalArgumentException | java.lang.reflect.InvocationTargetException Ex) {
                        Ex.printStackTrace();
                        break;
                    }
                }
            }
            return null;
        }
    }
    

    在 JNI/C++ 端(Main.cpp):

    #include <windows.h>
    #include <shobjidl.h>
    #include "jni.h"
    
    #if defined _WIN32 || defined _WIN64
    extern "C"
    {
        const GUID CLSID_TaskbarList = {0x56FDF344, 0xFD6D, 0x11D0, {0x95, 0x8A, 0x00, 0x60, 0x97, 0xC9, 0xA0, 0x90}};
    
        const GUID IID_ITaskbarList = {0x56FDF342, 0xFD6D, 0x11D0, {0x95, 0x8A, 0x00, 0x60, 0x97, 0xC9, 0xA0, 0x90}};
    
        const GUID IID_ITaskbarList2 = {0x602D4995, 0xB13A, 0x429b, {0xA6, 0x6E, 0x19, 0x35, 0xE4, 0x4F, 0x43, 0x17}};
    
        const GUID IID_ITaskList3 = {0xEA1AFB91, 0x9E28, 0x4B86, {0x90, 0xE9, 0x9E, 0x9F, 0x8A, 0x5E, 0xEF, 0xAF}};
    }
    #endif
    
    extern "C" JNIEXPORT void JNICALL Java_apptotray_AppToTray_addToTaskBar(JNIEnv *, jclass, jlong WindowHandle)
    {
        #if defined _WIN32 || defined _WIN64
        ITaskbarList* TaskListPtr;
        CoInitialize(nullptr);
        long Result = !CoCreateInstance(CLSID_TaskbarList, nullptr, CLSCTX_SERVER, IID_ITaskbarList, reinterpret_cast<void**>(&TaskListPtr));
        if (Result) TaskListPtr->AddTab(reinterpret_cast<HWND>(WindowHandle));
        TaskListPtr->Release();
        CoUninitialize();
        #endif
    }
    
    extern "C" JNIEXPORT void JNICALL Java_apptotray_AppToTray_removeFromTaskBar(JNIEnv *, jclass, jlong WindowHandle)
    {
        #if defined _WIN32 || defined _WIN64
        ITaskbarList* TaskListPtr;
        CoInitialize(nullptr);
        long Result = !CoCreateInstance(CLSID_TaskbarList, nullptr, CLSCTX_SERVER, IID_ITaskbarList, reinterpret_cast<void**>(&TaskListPtr));
        if (Result) TaskListPtr->DeleteTab(reinterpret_cast<HWND>(WindowHandle));
        TaskListPtr->Release();
        CoUninitialize();
        #endif
    }
    
    extern "C" bool __stdcall DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
    {
        switch (fdwReason)
        {
            case DLL_PROCESS_ATTACH:
                // attach to process
                // return FALSE to fail DLL load
                break;
    
            case DLL_PROCESS_DETACH:
                // detach from process
                break;
    
            case DLL_THREAD_ATTACH:
                // attach to thread
                break;
    
            case DLL_THREAD_DETACH:
                // detach from thread
                break;
        }
        return TRUE; // succesful
    }
    

    使用以下命令编译 DLL:

    x86_64-w64-mingw32-g++.exe -O2 -Wall -DBUILD_DLL -std=c++11 -c C:\Users\Brandon\Desktop\JNI\main.cpp -o obj\Release\main.o

    x86_64-w64-mingw32-g++.exe -shared -Wl,--output-def=bin\Release\libJNI.def -Wl,--out-implib=bin\Release\libJNI.a -Wl,- -dll obj\Release\main.o -o bin\Release\JNI.dll -s -static -static-libgcc -static-libstdc++ -lole32 -lshell32 -luser32

    或者只是使用代码块来做。

    如果其他人有更好的想法,请随时添加它们或发表评论或任何内容。我仍然无法相信我必须使用 C++/JNI 和反射来做到这一点。荒谬。现在是 2013 年, Java需要配合程序。

    【讨论】:

    • 如果它真的不是一堆代码要处理,请您提供一个完整的解决方法,一个小示例程序。双方都为努力+1 :-)
    • 那里.. 添加了一个工作示例。我使用代码块来编译 dll。这是一个文件,又名 main.cpp,java 应用程序也是一个文件。从那里,将其添加到系统托盘与在 OP 中相同,只是您不需要将框架设置为不可见。只需将其最小化,添加托盘图标并调用 removeFromTaskbar。
    猜你喜欢
    • 2013-04-21
    • 2012-01-31
    • 1970-01-01
    • 1970-01-01
    • 2017-08-06
    • 1970-01-01
    • 2012-02-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多