2008-11-05 30 views
0

我試圖創建一個簡單的Java應用程序,它顯示一個包含JButton的框架。我正在使用JNI爲窗口添加透明度。該窗口是透明的,但按鈕不是。另外,當我移動窗口時,按鈕不隨窗口移動。 JLabel也會發生同樣的情況。如果我使用Button而不是JButton,它就可以工作。使用JNI擺動透明度

本地代碼:

#include <windows.h> 
#include <jawt_md.h> 
#include <jawt.h> 
#include <jni.h> 

// Don't mangle names for the JVM 
extern "C" { 

BOOL APIENTRY DllMain(HMODULE hModule, 
         DWORD ul_reason_for_call, 
         LPVOID lpReserved 
        ) 
{ 
    switch (ul_reason_for_call) 
    { 
    case DLL_PROCESS_ATTACH: 
    case DLL_THREAD_ATTACH: 
    case DLL_THREAD_DETACH: 
    case DLL_PROCESS_DETACH: 
     break; 
    } 
    return TRUE; 
} 

/** 
* Gets the window handle for the Java window. 
* Procedure for obtaining the handle: 
* 1. Get the structure (JAWT) that contains the native methods. 
* 2. Get the drawing surface (JAWT_DrawingSurface). 
* 3. Using the drawing surface, get the drawing surface info (JAWT_DrawingSurfaceInfo). 
* 4. Get the drawing info that's specific to Win32 (JAWT_Win32DrawingSurfaceInfo). 
* 5. Using the drawing surface info, get the hwnd. 
*/ 
/* 
* Class:  test_Transparency 
* Method: getWindowHandle 
* Signature: (Ljava/awt/Component;)J 
*/ 
JNIEXPORT jlong JNICALL Java_test_Transparency_getWindowHandle 
    (JNIEnv * env, jclass cls, jobject component) 
{ 
    JAWT awt; 
    JAWT_DrawingSurface* ds; 
    JAWT_DrawingSurfaceInfo* dsi; 
    JAWT_Win32DrawingSurfaceInfo* dsi_win; 
    jint dsLock; 
    jboolean result = JNI_FALSE; 

    // Get the AWT 
    awt.version = JAWT_VERSION_1_4; 
    result = JAWT_GetAWT(env, &awt); 


    if (result == JNI_FALSE) 
    { 
     printf("%s:%i - JAWT_GetAWT() failed.\n", __FILE__, __LINE__); 
     return 0; 
    } 

    // Get the drawing surface 
    ds = awt.GetDrawingSurface(env, component); 

    if (ds == NULL) 
    { 
     printf("%s:%i - GetDrawingSurface() failed.\n", __FILE__, __LINE__); 
     return 0; 
    } 

    dsLock = ds->Lock(ds); 

    // Get the drawing surface info 
    dsi = ds->GetDrawingSurfaceInfo(ds); 


    // Get the platform-specific drawing info 
    dsi_win = (JAWT_Win32DrawingSurfaceInfo*)dsi->platformInfo; 


    HWND handle = dsi_win->hwnd; 

    ds->FreeDrawingSurfaceInfo(dsi); 
    ds->Unlock(ds); 
    awt.FreeDrawingSurface(ds); 

    return (jlong)handle; 
} 

void printLastError() 
{ 
    LPTSTR pszMessage; 
    DWORD dwLastError = GetLastError(); 

    FormatMessage(
     FORMAT_MESSAGE_ALLOCATE_BUFFER | 
     FORMAT_MESSAGE_FROM_SYSTEM | 
     FORMAT_MESSAGE_IGNORE_INSERTS, 
     NULL, 
     dwLastError, 
     MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 
     (LPTSTR)&pszMessage, 
     0, NULL); 

    // Display the error message 
    wprintf(L"failed with error %d: %s\n", dwLastError, pszMessage); 

    LocalFree(pszMessage); 

} 

/* 
* Class:  test_Transparency 
* Method: setTransparency 
* Signature: (JF)V 
*/ 
JNIEXPORT void JNICALL Java_test_Transparency_setTransparency 
    (JNIEnv * env, jclass cls, jlong windowHandle, jfloat alpha) 
{ 

    HWND hwnd = (HWND)windowHandle; 

    // Get the current window style 
    LONG currentStyle = GetWindowLong(hwnd, GWL_EXSTYLE); 


    if (currentStyle == 0) 
    { 
     printf("Error calling GetWindowLong() "); 
     printLastError(); 

    } 

    if (alpha == 0) 
    { 
     // No transparency. 
     // Remove WS_EX_LAYERED from this window style 
     SetWindowLong(hwnd, GWL_EXSTYLE, currentStyle & ~WS_EX_LAYERED); 
    } 
    else 
    { 
     // Calculate the transparency value. Should be in the range 0-255 
     unsigned char transparency = (unsigned char)(255 * alpha); 

     // Set window style to WS_EX_LAYERED. This is required for windows to be transparent. 
     SetWindowLong(hwnd, GWL_EXSTYLE, currentStyle | WS_EX_LAYERED); 

     // set the transparency level 
     SetLayeredWindowAttributes(hwnd, 0, transparency, LWA_ALPHA); 
    } 
} 


} // extern "C" 

MyFrame.java

package test; 

import javax.swing.*; 
import javax.swing.SwingUtilities; 
import java.awt.event.*; 

public class MyFrame implements ActionListener 
{ 
    private JFrame frame; 
    private Transparency trans; // = new Transparency(); 
    private float t = 1.0f; 

    public MyFrame() 
    { 
     frame = new JFrame("My transparent window"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.setBounds(10, 10, 200, 200); 

     JButton button = new JButton("My button"); 
     button.setBounds(20, 20, 50, 10); 
     button.addActionListener(this); 

     JPanel panel = new JPanel(); 
     panel.add(button); 

     frame.setContentPane(panel); 

     //Display the window. 
     frame.setVisible(true); 

     trans = new Transparency(); 
    } 


    /** 
    * @param args 
    */ 
    public static void main(String[] args) 
    { 
     MyFrame f = new MyFrame(); 
    } 

    public void actionPerformed(ActionEvent e) 
    { 
     t -= 0.05f; 
     trans.setWindowOpacity(frame, t); 
    } 

} 

Transparency.java

package test; 

import java.awt.Window; 
import java.awt.Component; 

public class Transparency 
{ 
    static boolean libLoaded = false; 
    /** 
    * Sets the transparency for a window. 
    * @param hwnd Handle for the window. 
    * @param opacity Transparency level, from 0.0 to 1.0. 
    * 1.0 is completely transparent. 0.0 is completely opaque. 
    */ 
    private static native void setTransparency(long hwnd, float opacity); 

    /** 
    * Get the window handle for the component. 
    * @param component 
    * @return HWND value obtained from the OS. 
    */ 
    private static native long getWindowHandle(Component component); 

    static 
    { 
     try 
     { 
     System.loadLibrary("transJNI"); 
     libLoaded = true; 
     } 
     catch (Exception e) 
     { 
     e.printStackTrace(); 
     libLoaded = false; 
     } 
    } 

    /** 
    * @param window The window whose opacity will be adjusted. 
    * @param opacity The opacity level, from 0.0 (opaque) to 1.0 (completely transparent). 
    */ 
    public void setWindowOpacity(Window window, float opacity) 
    { 
     if (!libLoaded) 
     { 
     return; 
     } 

     if (!window.isVisible()) 
     { 
     return; 
     } 
     long hwnd = getWindowHandle(window); 
     setTransparency(hwnd, opacity); 

    } 

} 

回答

0

你可能有更多的成功與JNA,尤其是其Window utils

+0

謝謝。我看過JNA,但是我不能將它用於這個項目(不幸的是)。我已經看過JNA如何做到這一點,我的解決方案與他們的解決方案非常相似,但我無法實現它。 – SpooneyDinosaur 2008-11-05 16:30:41

0

SwingX有許多透明的功能,我不是100%確定它會適合您的需求,但試試吧! swinglabs.org

2

6u10通過非官方的API支持transparent windows。可以通過java.com下載6u10,以前的JDK版本將盡快更新到它或稍後的更新。