alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (awt_TrayIcon.cpp)

This example Java source code file (awt_TrayIcon.cpp) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

awtcomponent\:\:getjavamodifiers, awttrayicon, catch_bad_alloc, dassert, jni_version_1_2, jnicall, jnienv, jniexport, jnu_getenv, lpctstr, msgrouting, null, timehelper\:\:windowstoutc, try

The awt_TrayIcon.cpp Java example source code

/*
 * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

#include "awt.h"
#include <windowsx.h>
#include <shellapi.h>
#include <shlwapi.h>

#include "awt_Toolkit.h"
#include "awt_TrayIcon.h"
#include "awt_AWTEvent.h"

#include <java_awt_event_InputEvent.h>

/***********************************************************************/
// Struct for _SetToolTip() method
struct SetToolTipStruct {
    jobject trayIcon;
    jstring tooltip;
};
// Struct for _SetIcon() method
struct SetIconStruct {
    jobject trayIcon;
    HICON hIcon;
};
// Struct for _UpdateIcon() method
struct UpdateIconStruct {
    jobject trayIcon;
    jboolean update;
};
// Struct for _DisplayMessage() method
struct DisplayMessageStruct {
    jobject trayIcon;
    jstring caption;
    jstring text;
    jstring msgType;
};

typedef struct tagBitmapheader  {
    BITMAPV5HEADER bmiHeader;
    DWORD            dwMasks[256];
} Bitmapheader, *LPBITMAPHEADER;


/************************************************************************
 * AwtTrayIcon fields
 */

jfieldID AwtTrayIcon::idID;
jfieldID AwtTrayIcon::actionCommandID;

HWND AwtTrayIcon::sm_msgWindow = NULL;
AwtTrayIcon::TrayIconListItem* AwtTrayIcon::sm_trayIconList = NULL;
int AwtTrayIcon::sm_instCount = 0;

/************************************************************************
 * AwtTrayIcon methods
 */

AwtTrayIcon::AwtTrayIcon() {
    ::ZeroMemory(&m_nid, sizeof(m_nid));

    if (sm_instCount++ == 0 && AwtTrayIcon::sm_msgWindow == NULL) {
        sm_msgWindow = AwtTrayIcon::CreateMessageWindow();
    }
    m_mouseButtonClickAllowed = 0;
}

AwtTrayIcon::~AwtTrayIcon() {
}

void AwtTrayIcon::Dispose() {
    SendTrayMessage(NIM_DELETE);
    UnlinkObjects();

    if (--sm_instCount == 0) {
        AwtTrayIcon::DestroyMessageWindow();
    }

    AwtObject::Dispose();
}

LPCTSTR AwtTrayIcon::GetClassName() {
    return TEXT("SunAwtTrayIcon");
}

void AwtTrayIcon::FillClassInfo(WNDCLASS *lpwc)
{
    lpwc->style         = 0L;
    lpwc->lpfnWndProc   = (WNDPROC)TrayWindowProc;
    lpwc->cbClsExtra    = 0;
    lpwc->cbWndExtra    = 0;
    lpwc->hInstance     = AwtToolkit::GetInstance().GetModuleHandle(),
    lpwc->hIcon         = AwtToolkit::GetInstance().GetAwtIcon();
    lpwc->hCursor       = NULL;
    lpwc->hbrBackground = NULL;
    lpwc->lpszMenuName  = NULL;
    lpwc->lpszClassName = AwtTrayIcon::GetClassName();
}

void AwtTrayIcon::RegisterClass()
{
    WNDCLASS  wc;

    ::ZeroMemory(&wc, sizeof(wc));

    if (!::GetClassInfo(AwtToolkit::GetInstance().GetModuleHandle(),
                        AwtTrayIcon::GetClassName(), &wc))
    {
        AwtTrayIcon::FillClassInfo(&wc);
        ATOM atom = ::RegisterClass(&wc);
        DASSERT(atom != 0);
    }
}

void AwtTrayIcon::UnregisterClass()
{
    ::UnregisterClass(AwtTrayIcon::GetClassName(), AwtToolkit::GetInstance().GetModuleHandle());
}

HWND AwtTrayIcon::CreateMessageWindow()
{
    AwtTrayIcon::RegisterClass();

    HWND hWnd = ::CreateWindow(AwtTrayIcon::GetClassName(), TEXT("TrayMessageWindow"),
                               0, 0, 0, 0, 0, NULL, NULL,
                               AwtToolkit::GetInstance().GetModuleHandle(), NULL);
    return hWnd;
}

void AwtTrayIcon::DestroyMessageWindow()
{
    ::DestroyWindow(AwtTrayIcon::sm_msgWindow);
    AwtTrayIcon::sm_msgWindow = NULL;
    AwtTrayIcon::UnregisterClass();
}

AwtTrayIcon* AwtTrayIcon::Create(jobject self, jobject parent)
{
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
    jobject target = NULL;
    AwtTrayIcon* awtTrayIcon = NULL;

    target  = env->GetObjectField(self, AwtObject::targetID);
    DASSERT(target);

    awtTrayIcon = new AwtTrayIcon();
    awtTrayIcon->LinkObjects(env, self);
    awtTrayIcon->InitNID(env->GetIntField(target, AwtTrayIcon::idID));
    awtTrayIcon->AddTrayIconItem(awtTrayIcon->GetID());

    env->DeleteLocalRef(target);
    return awtTrayIcon;
}

void AwtTrayIcon::InitNID(UINT uID)
{
    // fix for 6271589: we MUST set the size of the structure to match
    // the shell version, otherwise some errors may occur (like missing
    // balloon messages on win2k)
    DLLVERSIONINFO dllVersionInfo;
    dllVersionInfo.cbSize = sizeof(DLLVERSIONINFO);
    int shellVersion = 5; // WIN_2000
    // MSDN: DllGetVersion should not be implicitly called, but rather
    // loaded using GetProcAddress
    HMODULE hShell = JDK_LoadSystemLibrary("Shell32.dll");
    if (hShell != NULL) {
        DLLGETVERSIONPROC proc = (DLLGETVERSIONPROC)GetProcAddress(hShell, "DllGetVersion");
        if (proc != NULL) {
            if (proc(&dllVersionInfo) == NOERROR) {
                shellVersion = dllVersionInfo.dwMajorVersion;
            }
        }
    }
    FreeLibrary(hShell);
    switch (shellVersion) {
        case 5: // WIN_2000
            m_nid.cbSize = (BYTE *)(&m_nid.guidItem) - (BYTE *)(&m_nid.cbSize);
            break;
        case 6: // WIN_XP
            m_nid.cbSize = (BYTE *)(&m_nid.hBalloonIcon) - (BYTE *)(&m_nid.cbSize);
            break;
        default: // WIN_VISTA
            m_nid.cbSize = sizeof(m_nid);
            break;
    }
    m_nid.hWnd = AwtTrayIcon::sm_msgWindow;
    m_nid.uID = uID;
    m_nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
    m_nid.uCallbackMessage = WM_AWT_TRAY_NOTIFY;
    m_nid.hIcon = AwtToolkit::GetInstance().GetAwtIcon();
    m_nid.szTip[0] = '\0';
    m_nid.uVersion = NOTIFYICON_VERSION;
}

BOOL AwtTrayIcon::SendTrayMessage(DWORD dwMessage)
{
    return Shell_NotifyIcon(dwMessage, (PNOTIFYICONDATA)&m_nid);
}

static UINT lastMessage = WM_NULL;

LRESULT CALLBACK AwtTrayIcon::TrayWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    LRESULT retValue = 0;
    MsgRouting mr = mrDoDefault;
    static UINT s_msgTaskbarCreated;

    switch(uMsg)
    {
        case WM_CREATE:
            // Fix for CR#6369062
            s_msgTaskbarCreated = ::RegisterWindowMessage(TEXT("TaskbarCreated"));
            break;
        case WM_AWT_TRAY_NOTIFY:
            if (hwnd == AwtTrayIcon::sm_msgWindow) {
                AwtTrayIcon* trayIcon = AwtTrayIcon::SearchTrayIconItem((UINT)wParam);
                if (trayIcon != NULL) {
                    mr = trayIcon->WmAwtTrayNotify(wParam, lParam);
                }
            }
            break;
        default:
            if(uMsg == s_msgTaskbarCreated) {
                if (hwnd == AwtTrayIcon::sm_msgWindow) {
                    mr = WmTaskbarCreated();
                }
            }
            break;
    }

    if (mr != mrConsume) {
        retValue = ::DefWindowProc(hwnd, uMsg, wParam, lParam);
    }
    return retValue;
}

/*
 * This function processes callback messages for taskbar icons.
 */
MsgRouting AwtTrayIcon::WmAwtTrayNotify(WPARAM wParam, LPARAM lParam)
{
    MsgRouting mr = mrDoDefault;

    POINT pos = {0, 0};
    ::GetCursorPos(&pos);

    lastMessage = (UINT)lParam;
    UINT flags = AwtToolkit::GetInstance().GetMouseKeyState();

    switch((UINT)lParam)
    {
        case WM_MOUSEMOVE:
            mr = WmMouseMove(flags, pos.x, pos.y);
            break;
        case WM_LBUTTONDBLCLK:
        case WM_LBUTTONDOWN:
            mr = WmMouseDown(flags, pos.x, pos.y, LEFT_BUTTON);
            break;
        case WM_LBUTTONUP:
            mr = WmMouseUp(flags, pos.x, pos.y, LEFT_BUTTON);
            break;
        case WM_RBUTTONDBLCLK:
        case WM_RBUTTONDOWN:
            mr = WmMouseDown(flags, pos.x, pos.y, RIGHT_BUTTON);
            break;
        case WM_RBUTTONUP:
            mr = WmMouseUp(flags, pos.x, pos.y, RIGHT_BUTTON);
            break;
        case WM_MBUTTONDBLCLK:
        case WM_MBUTTONDOWN:
            mr = WmMouseDown(flags, pos.x, pos.y, MIDDLE_BUTTON);
            break;
        case WM_MBUTTONUP:
            mr = WmMouseUp(flags, pos.x, pos.y, MIDDLE_BUTTON);
            break;
        case WM_CONTEXTMENU:
            mr = WmContextMenu(0, pos.x, pos.y);
            break;
        case NIN_KEYSELECT:
            mr = WmKeySelect(0, pos.x, pos.y);
            break;
        case NIN_SELECT:
            mr = WmSelect(0, pos.x, pos.y);
            break;
        case NIN_BALLOONUSERCLICK:
            mr = WmBalloonUserClick(0, pos.x, pos.y);
            break;
    }
    return mr;
}

/* Double-click variables. */
static jlong multiClickTime = ::GetDoubleClickTime();
static int multiClickMaxX = ::GetSystemMetrics(SM_CXDOUBLECLK);
static int multiClickMaxY = ::GetSystemMetrics(SM_CYDOUBLECLK);
static AwtTrayIcon* lastClickTrIc = NULL;
static jlong lastTime = 0;
static int lastClickX = 0;
static int lastClickY = 0;
static int lastButton = 0;
static int clickCount = 0;

MsgRouting AwtTrayIcon::WmMouseDown(UINT flags, int x, int y, int button)
{
    jlong now = TimeHelper::windowsToUTC(::GetTickCount());
    jint javaModif = AwtComponent::GetJavaModifiers();

    if (lastClickTrIc == this &&
        lastButton == button &&
        (now - lastTime) <= multiClickTime &&
        abs(x - lastClickX) <= multiClickMaxX &&
        abs(y - lastClickY) <= multiClickMaxY)
    {
        clickCount++;
    } else {
        clickCount = 1;
        lastClickTrIc = this;
        lastButton = button;
        lastClickX = x;
        lastClickY = y;
    }
    lastTime = now;
    // it's needed only if WM_LBUTTONUP doesn't come for some reason
    m_mouseButtonClickAllowed |= AwtComponent::GetButtonMK(button);

    MSG msg;
    AwtComponent::InitMessage(&msg, lastMessage, flags, MAKELPARAM(x, y), x, y);

    SendMouseEvent(java_awt_event_MouseEvent_MOUSE_PRESSED, now, x, y,
                   javaModif, clickCount, JNI_FALSE,
                   AwtComponent::GetButton(button), &msg);

    return mrConsume;
}

MsgRouting AwtTrayIcon::WmMouseUp(UINT flags, int x, int y, int button)
{
    MSG msg;
    AwtComponent::InitMessage(&msg, lastMessage, flags, MAKELPARAM(x, y), x, y);

    SendMouseEvent(java_awt_event_MouseEvent_MOUSE_RELEASED, TimeHelper::windowsToUTC(::GetTickCount()),
                   x, y, AwtComponent::GetJavaModifiers(), clickCount,
                   (AwtComponent::GetButton(button) == java_awt_event_MouseEvent_BUTTON3 ?
                    TRUE : FALSE), AwtComponent::GetButton(button), &msg);

    if ((m_mouseButtonClickAllowed & AwtComponent::GetButtonMK(button)) != 0) { // No up-button in the drag-state
        SendMouseEvent(java_awt_event_MouseEvent_MOUSE_CLICKED,
                       TimeHelper::windowsToUTC(::GetTickCount()), x, y, AwtComponent::GetJavaModifiers(),
                       clickCount, JNI_FALSE, AwtComponent::GetButton(button));
    }
    m_mouseButtonClickAllowed &= ~AwtComponent::GetButtonMK(button); // Exclude the up-button from the drag-state

    return mrConsume;
}

MsgRouting AwtTrayIcon::WmMouseMove(UINT flags, int x, int y)
{
    MSG msg;
    static AwtTrayIcon* lastComp = NULL;
    static int lastX = 0;
    static int lastY = 0;

    /*
     * Workaround for CR#6267980
     * Windows sends WM_MOUSEMOVE if mouse is motionless
     */
    if (lastComp != this || x != lastX || y != lastY) {
        lastComp = this;
        lastX = x;
        lastY = y;
        AwtComponent::InitMessage(&msg, lastMessage, flags, MAKELPARAM(x, y), x, y);
        if ((flags & ALL_MK_BUTTONS) != 0) {
            m_mouseButtonClickAllowed = 0;
        } else {
            SendMouseEvent(java_awt_event_MouseEvent_MOUSE_MOVED, TimeHelper::windowsToUTC(::GetTickCount()), x, y,
                           AwtComponent::GetJavaModifiers(), 0, JNI_FALSE,
                           java_awt_event_MouseEvent_NOBUTTON, &msg);
        }
    }
    return mrConsume;
}

MsgRouting AwtTrayIcon::WmBalloonUserClick(UINT flags, int x, int y)
{
    if (AwtComponent::GetJavaModifiers() & java_awt_event_InputEvent_BUTTON1_DOWN_MASK) {
        MSG msg;
        AwtComponent::InitMessage(&msg, lastMessage, flags, MAKELPARAM(x, y), x, y);
        SendActionEvent(java_awt_event_ActionEvent_ACTION_PERFORMED, TimeHelper::windowsToUTC(::GetTickCount()),
                        AwtComponent::GetJavaModifiers(), &msg);
    }
    return mrConsume;
}

MsgRouting AwtTrayIcon::WmKeySelect(UINT flags, int x, int y)
{
    static jlong lastKeySelectTime = 0;
    jlong now = TimeHelper::windowsToUTC(::GetTickCount());

    // If a user selects a notify icon with the ENTER key,
    // Shell 5.0 sends double NIN_KEYSELECT notification.
    if (lastKeySelectTime != now) {
        MSG msg;
        AwtComponent::InitMessage(&msg, lastMessage, flags, MAKELPARAM(x, y), x, y);
        SendActionEvent(java_awt_event_ActionEvent_ACTION_PERFORMED, TimeHelper::windowsToUTC(::GetTickCount()),
                        AwtComponent::GetJavaModifiers(), &msg);
    }
    lastKeySelectTime = now;

    return mrConsume;
}

MsgRouting AwtTrayIcon::WmSelect(UINT flags, int x, int y)
{

    // If a user click on a notify icon with the mouse,
    // Shell 5.0 sends NIN_SELECT notification on every click.
    // To be compatible with JDK6.0 only second click is important.
    if (clickCount == 2) {
        MSG msg;
        AwtComponent::InitMessage(&msg, lastMessage, flags, MAKELPARAM(x, y), x, y);
        SendActionEvent(java_awt_event_ActionEvent_ACTION_PERFORMED, TimeHelper::windowsToUTC(::GetTickCount()),
                        AwtComponent::GetJavaModifiers(), &msg);
    }
    return mrConsume;
}

MsgRouting AwtTrayIcon::WmContextMenu(UINT flags, int x, int y)
{
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
    jobject peer = GetPeer(env);
    if (peer != NULL) {
        JNU_CallMethodByName(env, NULL, peer, "showPopupMenu",
                             "(II)V", x, y);
    }
    return mrConsume;
}

/*
 * Adds all icons we already have to taskbar.
 * We use this method on taskbar recreation (see 6369062).
 */
MsgRouting AwtTrayIcon::WmTaskbarCreated() {
    TrayIconListItem* item;
    for (item = sm_trayIconList; item != NULL; item = item->m_next) {
        BOOL result = item->m_trayIcon->SendTrayMessage(NIM_ADD);
        // 6270114: Instructs the taskbar to behave according to the Shell version 5.0
        if (result) {
            item->m_trayIcon->SendTrayMessage(NIM_SETVERSION);
        }
    }
    return mrDoDefault;
}

void AwtTrayIcon::SendMouseEvent(jint id, jlong when, jint x, jint y,
                                 jint modifiers, jint clickCount,
                                 jboolean popupTrigger, jint button,
                                 MSG *pMsg)
{
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
    if (GetPeer(env) == NULL) {
        /* event received during termination. */
        return;
    }

    static jclass mouseEventCls;
    if (mouseEventCls == NULL) {
        jclass mouseEventClsLocal =
            env->FindClass("java/awt/event/MouseEvent");
        if (!mouseEventClsLocal) {
            /* exception already thrown */
            return;
        }
        mouseEventCls = (jclass)env->NewGlobalRef(mouseEventClsLocal);
        env->DeleteLocalRef(mouseEventClsLocal);
    }

    static jmethodID mouseEventConst;
    if (mouseEventConst == NULL) {
        mouseEventConst =
            env->GetMethodID(mouseEventCls, "<init>",
                             "(Ljava/awt/Component;IJIIIIIIZI)V");
        DASSERT(mouseEventConst);
    }
    if (env->EnsureLocalCapacity(2) < 0) {
        return;
    }
    jobject target = GetTarget(env);
    jobject mouseEvent = env->NewObject(mouseEventCls, mouseEventConst,
                                        target,
                                        id, when, modifiers,
                                        x, y, // no client area coordinates
                                        x, y,
                                        clickCount, popupTrigger, button);

    if (safe_ExceptionOccurred(env)) {
        env->ExceptionDescribe();
        env->ExceptionClear();
    }

    DASSERT(mouseEvent != NULL);
    if (pMsg != 0) {
        AwtAWTEvent::saveMSG(env, pMsg, mouseEvent);
    }
    SendEvent(mouseEvent);

    env->DeleteLocalRef(mouseEvent);
    env->DeleteLocalRef(target);
}

void AwtTrayIcon::SendActionEvent(jint id, jlong when, jint modifiers, MSG *pMsg)
{
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
    if (GetPeer(env) == NULL) {
        /* event received during termination. */
        return;
    }

    static jclass actionEventCls;
    if (actionEventCls == NULL) {
        jclass actionEventClsLocal =
            env->FindClass("java/awt/event/ActionEvent");
        if (!actionEventClsLocal) {
            /* exception already thrown */
            return;
        }
        actionEventCls = (jclass)env->NewGlobalRef(actionEventClsLocal);
        env->DeleteLocalRef(actionEventClsLocal);
    }

    static jmethodID actionEventConst;
    if (actionEventConst == NULL) {
        actionEventConst =
            env->GetMethodID(actionEventCls, "<init>",
                             "(Ljava/lang/Object;ILjava/lang/String;JI)V");
        DASSERT(actionEventConst);
    }
    if (env->EnsureLocalCapacity(2) < 0) {
        return;
    }
    jobject target = GetTarget(env);
    jstring actionCommand = (jstring)env->GetObjectField(target, AwtTrayIcon::actionCommandID);
    jobject actionEvent = env->NewObject(actionEventCls, actionEventConst,
                                         target, id, actionCommand, when, modifiers);

    if (safe_ExceptionOccurred(env)) {
        env->ExceptionDescribe();
        env->ExceptionClear();
    }

    DASSERT(actionEvent != NULL);
    if (pMsg != 0) {
        AwtAWTEvent::saveMSG(env, pMsg, actionEvent);
    }
    SendEvent(actionEvent);

    env->DeleteLocalRef(actionEvent);
    env->DeleteLocalRef(target);
    env->DeleteLocalRef(actionCommand);
}

AwtTrayIcon* AwtTrayIcon::SearchTrayIconItem(UINT id) {
    TrayIconListItem* item;
    for (item = sm_trayIconList; item != NULL; item = item->m_next) {
        if (item->m_ID == id) {
            return item->m_trayIcon;
        }
    }
    /*
     * DASSERT(FALSE);
     * This should not be happend if all tray icons are recorded
     */
    return NULL;
}

void AwtTrayIcon::RemoveTrayIconItem(UINT id) {
    TrayIconListItem* item = sm_trayIconList;
    TrayIconListItem* lastItem = NULL;
    while (item != NULL) {
        if (item->m_ID == id) {
            if (lastItem == NULL) {
                sm_trayIconList = item->m_next;
            } else {
                lastItem->m_next = item->m_next;
            }
            item->m_next = NULL;
            DASSERT(item != NULL);
            delete item;
            return;
        }
        lastItem = item;
        item = item->m_next;
    }
}

void AwtTrayIcon::LinkObjects(JNIEnv *env, jobject peer)
{
    if (m_peerObject == NULL) {
        m_peerObject = env->NewGlobalRef(peer);
    }

    /* Bind JavaPeer -> C++*/
    JNI_SET_PDATA(peer, this);
}

void AwtTrayIcon::UnlinkObjects()
{
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
    if (m_peerObject) {
        JNI_SET_PDATA(m_peerObject, static_cast<PDATA>(NULL));
        env->DeleteGlobalRef(m_peerObject);
        m_peerObject = NULL;
    }
}

HBITMAP AwtTrayIcon::CreateBMP(HWND hW,int* imageData,int nSS, int nW, int nH)
{
    Bitmapheader    bmhHeader = {0};
    HDC             hDC;
    char            *ptrImageData;
    HBITMAP         hbmpBitmap;
    HBITMAP         hBitmap;
    int             nNumChannels    = 4;

    if (!hW) {
        hW = ::GetDesktopWindow();
    }
    hDC = ::GetDC(hW);
    if (!hDC) {
        return NULL;
    }

    bmhHeader.bmiHeader.bV5Size              = sizeof(BITMAPV5HEADER);
    bmhHeader.bmiHeader.bV5Width             = nW;
    bmhHeader.bmiHeader.bV5Height            = -nH;
    bmhHeader.bmiHeader.bV5Planes            = 1;

    bmhHeader.bmiHeader.bV5BitCount          = 32;
    bmhHeader.bmiHeader.bV5Compression       = BI_BITFIELDS;

    // The following mask specification specifies a supported 32 BPP
    // alpha format for Windows XP.
    bmhHeader.bmiHeader.bV5RedMask   =  0x00FF0000;
    bmhHeader.bmiHeader.bV5GreenMask =  0x0000FF00;
    bmhHeader.bmiHeader.bV5BlueMask  =  0x000000FF;
    bmhHeader.bmiHeader.bV5AlphaMask =  0xFF000000;

    hbmpBitmap = ::CreateDIBSection(hDC, (BITMAPINFO*)&(bmhHeader),
                                    DIB_RGB_COLORS,
                                    (void**)&(ptrImageData),
                                    NULL, 0);
    int  *srcPtr = imageData;
    char *dstPtr = ptrImageData;
    if (!dstPtr) {
        ReleaseDC(hW, hDC);
        return NULL;
    }
    for (int nOutern = 0; nOutern < nH; nOutern++) {
        for (int nInner = 0; nInner < nSS; nInner++) {
            dstPtr[3] = (*srcPtr >> 0x18) & 0xFF;
            dstPtr[2] = (*srcPtr >> 0x10) & 0xFF;
            dstPtr[1] = (*srcPtr >> 0x08) & 0xFF;
            dstPtr[0] = *srcPtr & 0xFF;

            srcPtr++;
            dstPtr += nNumChannels;
        }
    }

    // convert it into DDB to make CustomCursor work on WIN95
    hBitmap = CreateDIBitmap(hDC,
                             (BITMAPINFOHEADER*)&bmhHeader,
                             CBM_INIT,
                             (void *)ptrImageData,
                             (BITMAPINFO*)&bmhHeader,
                             DIB_RGB_COLORS);

    ::DeleteObject(hbmpBitmap);
    ::ReleaseDC(hW, hDC);
//  ::GdiFlush();
    return hBitmap;
}

void AwtTrayIcon::SetToolTip(LPCTSTR tooltip)
{
    if (tooltip == NULL) {
        m_nid.szTip[0] = '\0';
    } else if (lstrlen(tooltip) > TRAY_ICON_TOOLTIP_MAX_SIZE) {
        _tcsncpy(m_nid.szTip, tooltip, TRAY_ICON_TOOLTIP_MAX_SIZE);
        m_nid.szTip[TRAY_ICON_TOOLTIP_MAX_SIZE - 1] = '\0';
    } else {
        _tcscpy_s(m_nid.szTip, TRAY_ICON_TOOLTIP_MAX_SIZE, tooltip);
    }

    SendTrayMessage(NIM_MODIFY);
}

void AwtTrayIcon::_SetToolTip(void *param)
{
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
    SetToolTipStruct *sts = (SetToolTipStruct *)param;
    jobject self = sts->trayIcon;
    jstring jtooltip = sts->tooltip;
    AwtTrayIcon *trayIcon = NULL;
    LPCTSTR tooltipStr = NULL;

    PDATA pData;
    JNI_CHECK_PEER_GOTO(self, ret);
    trayIcon = (AwtTrayIcon *)pData;

    if (jtooltip == NULL) {
        trayIcon->SetToolTip(NULL);
        goto ret;
    }

    tooltipStr = JNU_GetStringPlatformChars(env, jtooltip, (jboolean *)NULL);
    trayIcon->SetToolTip(tooltipStr);
    JNU_ReleaseStringPlatformChars(env, jtooltip, tooltipStr);
ret:
    env->DeleteGlobalRef(self);
    env->DeleteGlobalRef(jtooltip);
    delete sts;
}

void AwtTrayIcon::SetIcon(HICON hIcon)
{
    ::DestroyIcon(m_nid.hIcon);
    m_nid.hIcon = hIcon;
}

void AwtTrayIcon::_SetIcon(void *param)
{
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
    SetIconStruct *sis = (SetIconStruct *)param;
    jobject self = sis->trayIcon;
    HICON hIcon = sis->hIcon;
    AwtTrayIcon *trayIcon = NULL;

    PDATA pData;
    JNI_CHECK_PEER_GOTO(self, ret);
    trayIcon = (AwtTrayIcon *)pData;

    trayIcon->SetIcon(hIcon);

ret:
    env->DeleteGlobalRef(self);
    delete sis;
}

void AwtTrayIcon::_UpdateIcon(void *param)
{
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
    UpdateIconStruct *uis = (UpdateIconStruct *)param;
    jobject self = uis->trayIcon;
    jboolean jupdate = uis->update;
    AwtTrayIcon *trayIcon = NULL;

    PDATA pData;
    JNI_CHECK_PEER_GOTO(self, ret);
    trayIcon = (AwtTrayIcon *)pData;

    BOOL result = trayIcon->SendTrayMessage(jupdate == JNI_TRUE ? NIM_MODIFY : NIM_ADD);
    // 6270114: Instructs the taskbar to behave according to the Shell version 5.0
    if (result && jupdate == JNI_FALSE) {
        trayIcon->SendTrayMessage(NIM_SETVERSION);
    }
ret:
    env->DeleteGlobalRef(self);
    delete uis;
}

void AwtTrayIcon::DisplayMessage(LPCTSTR caption, LPCTSTR text, LPCTSTR msgType)
{
    m_nid.uFlags |= NIF_INFO;
    m_nid.uTimeout = 10000;

    if (lstrcmp(msgType, TEXT("ERROR")) == 0) {
        m_nid.dwInfoFlags = NIIF_ERROR;
    } else if (lstrcmp(msgType, TEXT("WARNING")) == 0) {
        m_nid.dwInfoFlags = NIIF_WARNING;
    } else if (lstrcmp(msgType, TEXT("INFO")) == 0) {
        m_nid.dwInfoFlags = NIIF_INFO;
    } else if (lstrcmp(msgType, TEXT("NONE")) == 0) {
        m_nid.dwInfoFlags = NIIF_NONE;
    } else {
        m_nid.dwInfoFlags = NIIF_NONE;
    }

    if (caption[0] == '\0') {
        m_nid.szInfoTitle[0] = '\0';

    } else if (lstrlen(caption) > TRAY_ICON_BALLOON_TITLE_MAX_SIZE) {

        _tcsncpy(m_nid.szInfoTitle, caption, TRAY_ICON_BALLOON_TITLE_MAX_SIZE);
        m_nid.szInfoTitle[TRAY_ICON_BALLOON_TITLE_MAX_SIZE - 1] = '\0';

    } else {
        _tcscpy_s(m_nid.szInfoTitle, TRAY_ICON_BALLOON_TITLE_MAX_SIZE, caption);
    }

    if (text[0] == '\0') {
        m_nid.szInfo[0] = ' ';
        m_nid.szInfo[1] = '\0';

    } else if (lstrlen(text) > TRAY_ICON_BALLOON_INFO_MAX_SIZE) {

        _tcsncpy(m_nid.szInfo, text, TRAY_ICON_BALLOON_INFO_MAX_SIZE);
        m_nid.szInfo[TRAY_ICON_BALLOON_INFO_MAX_SIZE - 1] = '\0';

    } else {
        _tcscpy_s(m_nid.szInfo, TRAY_ICON_BALLOON_INFO_MAX_SIZE, text);
    }

    SendTrayMessage(NIM_MODIFY);
    m_nid.uFlags &= ~NIF_INFO;
}

void AwtTrayIcon::_DisplayMessage(void *param)
{
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
    DisplayMessageStruct *dms = (DisplayMessageStruct *)param;
    jobject self = dms->trayIcon;
    jstring jcaption = dms->caption;
    jstring jtext = dms-> text;
    jstring jmsgType = dms->msgType;
    AwtTrayIcon *trayIcon = NULL;
    LPCTSTR captionStr = NULL;
    LPCTSTR textStr = NULL;
    LPCTSTR msgTypeStr = NULL;

    PDATA pData;
    JNI_CHECK_PEER_GOTO(self, ret);
    trayIcon = (AwtTrayIcon *)pData;

    captionStr = JNU_GetStringPlatformChars(env, jcaption, (jboolean *)NULL);
    textStr = JNU_GetStringPlatformChars(env, jtext, (jboolean *)NULL);
    msgTypeStr = JNU_GetStringPlatformChars(env, jmsgType, (jboolean *)NULL);

    trayIcon->DisplayMessage(captionStr, textStr, msgTypeStr);

    JNU_ReleaseStringPlatformChars(env, jcaption, captionStr);
    JNU_ReleaseStringPlatformChars(env, jtext, textStr);
    JNU_ReleaseStringPlatformChars(env, jmsgType, msgTypeStr);
ret:
    env->DeleteGlobalRef(self);
    env->DeleteGlobalRef(jcaption);
    env->DeleteGlobalRef(jtext);
    env->DeleteGlobalRef(jmsgType);
    delete dms;
}

/************************************************************************
 * TrayIcon native methods
 */

extern "C" {

/*
 * Class:     java_awt_TrayIcon
 * Method:    initIDs
 * Signature: ()V
 */
JNIEXPORT void JNICALL
Java_java_awt_TrayIcon_initIDs(JNIEnv *env, jclass cls)
{
    TRY;

    /* init field ids */
    AwtTrayIcon::idID = env->GetFieldID(cls, "id", "I");
    AwtTrayIcon::actionCommandID = env->GetFieldID(cls, "actionCommand", "Ljava/lang/String;");

    DASSERT(AwtTrayIcon::idID != NULL);
    DASSERT(AwtTrayIcon::actionCommandID != NULL);

    CATCH_BAD_ALLOC;
}

/*
 * Class:     sun_awt_windows_WTrayIconPeer
 * Method:    create
 * Signature: ()V
 */
JNIEXPORT void JNICALL
Java_sun_awt_windows_WTrayIconPeer_create(JNIEnv *env, jobject self)
{
    TRY;

    AwtToolkit::CreateComponent(self, NULL,
                                (AwtToolkit::ComponentFactory)
                                AwtTrayIcon::Create);
    PDATA pData;
    JNI_CHECK_PEER_CREATION_RETURN(self);

    CATCH_BAD_ALLOC;
}

/*
 * Class:     sun_awt_windows_WTrayIconPeer
 * Method:    _dispose
 * Signature: ()V
 */
JNIEXPORT void JNICALL
Java_sun_awt_windows_WTrayIconPeer__1dispose(JNIEnv *env, jobject self)
{
    TRY;

    AwtObject::_Dispose(self);

    CATCH_BAD_ALLOC;
}

/*
 * Class:     sun_awt_windows_WTrayIconPeer
 * Method:    _setToolTip
 * Signature: ()V
 */
JNIEXPORT void JNICALL
Java_sun_awt_windows_WTrayIconPeer_setToolTip(JNIEnv *env, jobject self,
                                              jstring tooltip)
{
    TRY;

    SetToolTipStruct *sts = new SetToolTipStruct;
    sts->trayIcon = env->NewGlobalRef(self);
    if (tooltip != NULL) {
        sts->tooltip = (jstring)env->NewGlobalRef(tooltip);
    } else {
        sts->tooltip = NULL;
    }

    AwtToolkit::GetInstance().SyncCall(AwtTrayIcon::_SetToolTip, sts);
    // global ref and sts are deleted in _SetToolTip

    CATCH_BAD_ALLOC;
}

/*
 * Class:     sun_awt_windows_WTrayIconPeer
 * Method:    setNativeIcon
 * Signature: (I[B[IIIII)V
 */
JNIEXPORT void JNICALL
Java_sun_awt_windows_WTrayIconPeer_setNativeIcon(JNIEnv *env, jobject self,
                                                 jintArray intRasterData, jbyteArray andMask,
                                                 jint nSS, jint nW, jint nH)
{
    TRY;

    int length = env->GetArrayLength(andMask);
    jbyte *andMaskPtr = new jbyte[length];

    env->GetByteArrayRegion(andMask, 0, length, andMaskPtr);

    HBITMAP hMask = ::CreateBitmap(nW, nH, 1, 1, (BYTE *)andMaskPtr);
//    ::GdiFlush();

    delete[] andMaskPtr;

    jint *intRasterDataPtr = NULL;
    HBITMAP hColor = NULL;
    try {
        intRasterDataPtr =
            (jint *)env->GetPrimitiveArrayCritical(intRasterData, 0);
        hColor = AwtTrayIcon::CreateBMP(NULL, (int *)intRasterDataPtr, nSS, nW, nH);
    } catch (...) {
        if (intRasterDataPtr != NULL) {
            env->ReleasePrimitiveArrayCritical(intRasterData, intRasterDataPtr, 0);
        }
        ::DeleteObject(hMask);
        throw;
    }

    env->ReleasePrimitiveArrayCritical(intRasterData, intRasterDataPtr, 0);
    intRasterDataPtr = NULL;

    HICON hIcon = NULL;

    if (hMask && hColor) {
        ICONINFO icnInfo;
        memset(&icnInfo, 0, sizeof(ICONINFO));
        icnInfo.hbmMask = hMask;
        icnInfo.hbmColor = hColor;
        icnInfo.fIcon = TRUE;
        icnInfo.xHotspot = TRAY_ICON_X_HOTSPOT;
        icnInfo.yHotspot = TRAY_ICON_Y_HOTSPOT;

        hIcon = ::CreateIconIndirect(&icnInfo);
    }
    ::DeleteObject(hColor);
    ::DeleteObject(hMask);

    //////////////////////////////////////////

    SetIconStruct *sis = new SetIconStruct;
    sis->trayIcon = env->NewGlobalRef(self);
    sis->hIcon = hIcon;

    AwtToolkit::GetInstance().SyncCall(AwtTrayIcon::_SetIcon, sis);
    // global ref is deleted in _SetIcon

    CATCH_BAD_ALLOC;
}

/*
 * Class:     sun_awt_windows_WTrayIconPeer
 * Method:    updateNativeIcon
 * Signature: (Z)V
 */
JNIEXPORT void JNICALL
Java_sun_awt_windows_WTrayIconPeer_updateNativeIcon(JNIEnv *env, jobject self,
                                                    jboolean doUpdate)
{
    TRY;

    UpdateIconStruct *uis = new UpdateIconStruct;
    uis->trayIcon = env->NewGlobalRef(self);
    uis->update = doUpdate;

    AwtToolkit::GetInstance().SyncCall(AwtTrayIcon::_UpdateIcon, uis);
    // global ref is deleted in _UpdateIcon

    CATCH_BAD_ALLOC;
}

/*
 * Class:     sun_awt_windows_WTrayIconPeer
 * Method:    displayMessage
 * Signature: ()V;
 */
JNIEXPORT void JNICALL
Java_sun_awt_windows_WTrayIconPeer__1displayMessage(JNIEnv *env, jobject self,
    jstring caption, jstring text, jstring msgType)
{
    TRY;

    DisplayMessageStruct *dms = new DisplayMessageStruct;
    dms->trayIcon = env->NewGlobalRef(self);
    dms->caption = (jstring)env->NewGlobalRef(caption);
    dms->text = (jstring)env->NewGlobalRef(text);
    dms->msgType = (jstring)env->NewGlobalRef(msgType);

    AwtToolkit::GetInstance().SyncCall(AwtTrayIcon::_DisplayMessage, dms);
    // global ref is deleted in _DisplayMessage

    CATCH_BAD_ALLOC(NULL);
}

} /* extern "C" */

Other Java examples (source code examples)

Here is a short list of links related to this Java awt_TrayIcon.cpp source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.