2008-11-05 6 views
0

JButton이 포함 된 프레임을 표시하는 간단한 Java 응용 프로그램을 만들려고합니다. JNI를 사용하여 투명도를 창에 추가하고 있습니다. 창은 투명하지만 단추는 투명하지 않습니다. 또한 창을 움직이면 단추가 창과 함께 움직이지 않습니다. 같은 일이 JLabel에서도 발생합니다. JButton 대신 Button을 사용하면 잘 작동합니다.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

0

SwingX에는 많은 투명 기능이 있습니다. 사용자의 요구에 맞을 것이라고 100 % 확신하지는 않지만 시도해보십시오! swinglabs.org

2

6u10은 비공식 API를 통해 transparent windows을 지원합니다. 6u10은 java.com을 통해 다운로드 할 수 있으며 이전 JDK 버전은 곧 업데이트 될 예정입니다.

관련 문제