⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 windowstrayicon.cpp

📁 JAVA程序的系统托盘
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/**
 * WindowsTrayIcon.cpp - a tray icon for Java
 * Best viewed with tab size 8
 *
 * Written by Jan Struyf
 *
 *  jan.struyf@cs.kuleuven.ac.be
 *  http://jeans.studentenweb.org/java/trayicon/trayicon.html
 *
 * Changelog
 *
 * Version pre1.6c (07/16/01)
 *	* Fixed minor compilation warnings reported by the more strict VC++ 6.0
 *
 * Version pre1.6b (12/16/00)
 *	* Fixed memory leak for 'animating icons'
 *      * ReleaseDC -> DeleteDC
 *
 * Version pre1.6 (09/02/00)
 *	* Support for old JDK/JRE 1.1.x
 *	* TrayIcon 1.6 will support Microsoft Visual J++
 *
 * Version 1.5 (07/03/00)
 *	* Tray icon popup menu support
 *	* Added code for sendWindowsMessage()
 *
 * Version 1.4 (06/29/00)
 *	* Added DllMain function to clean init code
 *	* Removed redundant LoadLibrary/FreeLibrary calls
 *	* Added code for isRunning()
 *
 * Version 1.3 (06/09/00)
 *	* Trail bug fix for NT (no public release)
 *		(Patch from 'Daniel Hope <danielh@inform.co.nz>')
 *
 * Version 1.2 (05/03/00)
 *	* Message handler for first icon fixed
 *	* WM_RBUTTONDOWN message handler fixed
 *	* Classes are now unregistered on exit
 *		(Patch from 'Daniel Rejment <daniel@rejment.com>')
 *
 * Version 1.0 (06/29/99)
 *	* Initial release
 *
 * Please mail me if you
 *	- 've found bugs
 *	- like this program
 *	- don't like a particular feature
 *	- would like something to be modified
 *
 * To compile:
 *	- Use the MDP project file in the VC++ IDE
 *	- Use Makefile.vc as in:
 *		VCVARS32
 *		nmake /f makefile.vc
 *
 * I always give it my best shot to make a program useful and solid, but
 * remeber that there is absolutely no warranty for using this program as
 * stated in the following terms:
 *
 * THERE IS NO WARRANTY FOR THIS PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE
 * LAW. THE COPYRIGHT HOLDER AND/OR OTHER PARTIES WHO MAY HAVE MODIFIED THE
 * PROGRAM, PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
 * EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
 * TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
 * PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
 * REPAIR OR CORRECTION.
 *
 * IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL ANY COPYRIGHT HOLDER,
 * OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM,
 * BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
 * CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
 * PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED
 * INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE
 * PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER
 * PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
 *
 * May the Force be with you... Just compile it & use it!
 */

#include <windows.h>
#include <windowsx.h>
#include <process.h>
#include <jni.h>
#include "com_jeans_trayicon_WindowsTrayIcon.h"

#if defined(HAS_JVM_LIB) + defined(HAS_OLD_JVM_LIB) == 0
	#define NO_JVM_LIB
#endif

// Message ID for sendWindowsMessage() function
#define MYWM_APPTALK		(WM_APP+10)
// Message ID for Tray icons
#define MYWM_NOTIFYICON		(WM_APP+100)
// Max number of icons supported by this DLL for each application
#define MY_MAX_ICONS		100
// Max length for the name of the hidden window (used for sendWindowsMessage/isRunning)
#define WNDNAME_MAX         20

// Class for the icon bitmap
class IconData {
private:
	HBITMAP hBitmapXOR;	// Colors
	HBITMAP	hBitmapAND;	// Transparancy info
	int wd, hi;
public:
	IconData();
	~IconData();
	int setData(unsigned long *data, int wd, int hi);
	HICON makeIcon(HINSTANCE hInst);
};

// Class for a popup submenu
class PopupSubMenu {
private:
	HMENU hMenu;
	BOOL bSub;
public:
	PopupSubMenu();
	~PopupSubMenu();
	BOOL isSub();
	void makeSub();
	void reNewMenu();
	HMENU getMenu();
	void TrackPopupMenu(UINT flags, POINT* pos, HWND hWnd);
};

typedef PopupSubMenu* PtrPopupSubMenu;

// Class for a popup menu (the main popup)
class PopupMenu {
private:
	PopupSubMenu **popup;
	int nbLevels;
public:
	PopupMenu(int levels);
	~PopupMenu();
	void TrackPopupMenu(UINT flags, POINT* pos, HWND hWnd);
	HMENU getMenu(int level);
	void initMenu(int level);
	PopupSubMenu *getSubMenu(int level);
};

// Growable array for integers
// Used to store the allocated menu id's
class QSIntArray {
	protected:
		int *m_Array;
		long m_Size, m_Grow, m_ArrSize;
	public:
		QSIntArray();
		QSIntArray(long size, long grow);
		~QSIntArray();
		long getSize();
		int getElementAt(long idx);
		void addElement(int element);
		void setElementAt(long idx, int element);
		void removeElementAt(long idx);
		void removeAll();
	private:
		void shrink();
		void grow();
};

#define JNIProcPtr(name) int (FAR *name) (JNIEnv*, int, int)

// Information for each tray icon
typedef struct {
	BOOL used;		// Is this record in use?
	BOOL visible;		// Icon visible on screen or hidden?
	IconData *icon;		// Icon bitmap data
	char *tooltip;		// Icon tooltip
	PopupMenu *popup;	// Main popup for icon
	jobject globalClass;	// Pointer to Java class for callbacks
} TrayIconData;

// Information for Java callback
typedef struct {
	JNIProcPtr(jni_proc);
	int arg1, arg2;
} ThreadJavaCallback;

// Some error codes
#define TRAY_NOERR		0
#define TRAY_NOTIFYPROCERR	-1
#define TRAY_TOOMANYICONS	-2
#define TRAY_NOTENOUGHMEM	-3
#define TRAY_WRONGICONID	-4
#define TRAY_DLLNOTFOUND	-5
#define TRAY_NOVMS		-6
#define TRAY_ERRTHREAD		-7
#define TRAY_METHODID		-8
#define TRAY_NOLISTENER		-9
#define TRAY_JNIERR		-10
#define TRAY_CALLBACKDLLERR	-11

// Constants for the popup menu system
#define POPUP_TYPE_ITEM       0
#define POPUP_TYPE_SEPARATOR  1
#define POPUP_TYPE_CHECKBOX   2
#define POPUP_TYPE_INIT_LEVEL 3
#define POPUP_TYPE_DONE_LEVEL 4

// Current instance of the TrayIcon DLL
HINSTANCE g_hinst = NULL;
// Handle to the hidden window used to receive the tray icon messages
HWND my_hDlg = NULL;
// App name for the hidden window's registered class
CHAR szAppName[] = "QSJavaTray";
// Title for the hidden window (used for sendWindowsMessage/isRunning)
CHAR szWndName[WNDNAME_MAX+1];
// Number of icons allocated
int nb_tray_icons = 0;
// Record for each icon
TrayIconData tray_icons[MY_MAX_ICONS];
// Contains last error message (see error codes above)
jint last_error = TRAY_NOERR;
// Wait while creating the hidden window
HANDLE wait_event = NULL;
// Wait while destroying hidden window
HANDLE exit_event = NULL;
// Maps menu id's to icon id's
QSIntArray *arrUsedMenuIds = NULL;
// Mouse position
POINT mouse_pos;

#ifdef NO_JVM_LIB
    JavaVM *hJavaVM;
#endif

// Get free menu id (for icon id - see arrUsedMenuIds)
long getFreeMenuId(int id_num);
// Free menu id (when removing menu from icon)
void setFreeMenuId(int id_num);
// Map menu id to icon id
int getMenuItemIdNum(int id);
// Add/Remove/Modify tray icon to system tray
BOOL TrayMessage(HWND hDlg, DWORD dwMessage, UINT uID, HICON hIcon, PSTR pszTip);
// Create the hidden window to receive the icon's mouse messages
HWND MakeHWND(HINSTANCE hInst);
// Remove the hidden window (on app closing)
void RemoveHWND();
// The thread proc that creates the hidden window an listens for messages
void DialogThread( void *dummy );
// Free an icon's menu resources
void freeMenu(int id_num);
// Free an icon's other resources
void freeIcon(JNIEnv *env, int id_num);
// Clean up @ exit of app
void cleanUpExit(JNIEnv *env);
// Call TrayMessage for the specified icon id
void updateIcon(jint id_num);
// Make an icon dissapear from the system tray
void makeInvisible(jint id_num);
// Delete global reference to icon's Java class
int DeleteGlobalCallback(JNIEnv *env, int id_num, int dummy);
// Call a Java method in all available VM's (used for mouse/menu callbacks)
int CallJavaVMS(JNIProcPtr(JNIProc), int arg1, int arg2);
// Call a Java method in a given virtual machine
int CallJavaVM(JavaVM* vm, JNIProcPtr(JNIProc), int arg1, int arg2);

/*
 * Class:     jeans_trayicon_WindowsTrayIcon
 * Method:    getLastError
 * Signature: ()I
 */
JNIEXPORT jint JNICALL Java_com_jeans_trayicon_WindowsTrayIcon_getLastError(JNIEnv *, jclass) {
	int err = last_error;
	last_error = TRAY_NOERR;
	return last_error;		// Return the last error
}

/*
 * Class:     WindowsTrayIcon
 * Method:    getFreeId
 * Signature: ()I
 */
JNIEXPORT jint JNICALL Java_com_jeans_trayicon_WindowsTrayIcon_getFreeId(JNIEnv *env, jclass) {
    #ifdef NO_JVM_LIB
        env->GetJavaVM(&hJavaVM);
    #endif
	// Wait for the hidden window to be created (see initTrayIcon())
	if (wait_event != NULL) {
		WaitForSingleObject(wait_event,10000);
		CloseHandle(wait_event);
		wait_event = NULL;
	}
	// Hidden window handle valid?
	if (my_hDlg == NULL) {
		last_error = TRAY_NOTIFYPROCERR;
		return TRAY_NOTIFYPROCERR;
	}
	// Instance handle valid?
	if (g_hinst == NULL) {
		last_error = TRAY_DLLNOTFOUND;
		return TRAY_DLLNOTFOUND;
	}
	// Find unused icon record and return icon id
	for (int ctr = 0; ctr < MY_MAX_ICONS; ctr++) {
		if (tray_icons[ctr].used == FALSE) {
			// Unused record, initialize fields and return id
			tray_icons[ctr].used = TRUE;
			tray_icons[ctr].visible = FALSE;
			tray_icons[ctr].icon = NULL;
			tray_icons[ctr].tooltip = NULL;
			tray_icons[ctr].popup = NULL;
			return ctr;
		}
	}
	// No empty record left, return error
	last_error = TRAY_NOTIFYPROCERR;
	return TRAY_TOOMANYICONS;
}

/*
 * Class:     WindowsTrayIcon
 * Method:    setIconData
 * Signature: (III[I)V
 */
JNIEXPORT void JNICALL Java_com_jeans_trayicon_WindowsTrayIcon_setIconData(JNIEnv *env, jclass, jint id_num, jint wd, jint hi, jintArray array) {
	// Instance handle valid?
	if (g_hinst == NULL) {
		last_error = TRAY_DLLNOTFOUND;
		return;
	}
	// Icon id valid?
	if (tray_icons[id_num].used == FALSE) {
		last_error = TRAY_WRONGICONID;
		return;
	}
	// Get array length and elements
	jsize len = env->GetArrayLength(array);
	jint *body = env->GetIntArrayElements(array, 0);
	// Allocate data for icon bitmap and store the given pixel array
	IconData *data = new IconData();
	if (data != NULL && data->setData((unsigned long *)body, wd, hi) != -1) {
		IconData *olddata = tray_icons[id_num].icon;
		tray_icons[id_num].icon = data;
		updateIcon(id_num);
		if (olddata != NULL) delete olddata;
	} else {
		delete data;
		last_error = TRAY_NOTENOUGHMEM;
	}
	// Release java array
	env->ReleaseIntArrayElements(array, body, 0);
}

/*
 * Class:     WindowsTrayIcon
 * Method:    showIcon
 * Signature: (IZ)V
 */
JNIEXPORT void JNICALL Java_com_jeans_trayicon_WindowsTrayIcon_showIcon(JNIEnv *, jclass, jint id_num, jboolean show) {
	// Hidden window handle valid?
	if (my_hDlg == NULL) {
		last_error = TRAY_NOTIFYPROCERR;
		return;
	}
	// Instance handle valid?
	if (g_hinst == NULL) {
		last_error = TRAY_DLLNOTFOUND;
		return;
	}
	// Icon id valid?
	if (tray_icons[id_num].used == FALSE) {
		last_error = TRAY_WRONGICONID;
		return;
	}
	if (show) {
		// Show icon in windows system tray
		if (tray_icons[id_num].visible == FALSE && tray_icons[id_num].icon != NULL) {
			HICON icon = tray_icons[id_num].icon->makeIcon(g_hinst);
			if (icon != NULL) {
				TrayMessage(my_hDlg, NIM_ADD, id_num, icon, tray_icons[id_num].tooltip);
				tray_icons[id_num].visible = TRUE;
			} else {
				last_error = TRAY_NOTENOUGHMEM;
			}
		}
	} else {
		// Hide icon (make invisible)
		if (tray_icons[id_num].visible == TRUE) {
			TrayMessage(my_hDlg, NIM_DELETE, id_num, NULL, NULL);
			tray_icons[id_num].visible = FALSE;
		}
	}
}

/*
 * Class:     jeans_trayicon_WindowsTrayIcon
 * Method:    testVisible
 * Signature: (I)I
 */
JNIEXPORT jint JNICALL Java_com_jeans_trayicon_WindowsTrayIcon_testVisible(JNIEnv *, jclass, jint id_num) {
	// Icon id valid?
	if (tray_icons[id_num].used == FALSE) {
		last_error = TRAY_WRONGICONID;
		return TRAY_WRONGICONID;
	}
	// Is the icon visible now?
	if (tray_icons[id_num].visible == TRUE) {
		return 1;
	} else {
		return 0;
	}
}

/*
 * Class:     jeans_trayicon_WindowsTrayIcon
 * Method:    clickEnable
 * Signature: (Ljeans/graph/trayicon/WindowsTrayIcon;IZ)V
 */
JNIEXPORT void JNICALL Java_com_jeans_trayicon_WindowsTrayIcon_clickEnable(JNIEnv *env, jclass, jobject ic_cls, jint id_num, jboolean enable) {
	// Icon id valid?
	if (tray_icons[id_num].used == FALSE) {
		last_error = TRAY_WRONGICONID;
		return;
	}
	if (enable == TRUE) {
		// Make icon clickenable by storing a global reference to it's class
		jobject globalWinTrayClass = env->NewGlobalRef(ic_cls);
		if (globalWinTrayClass != 0) {
			if (tray_icons[id_num].globalClass != 0)
				env->DeleteGlobalRef(tray_icons[id_num].globalClass);
			tray_icons[id_num].globalClass = globalWinTrayClass;
		}
	} else {
		// Remove the icon's global class reference
		if (tray_icons[id_num].globalClass != 0)
			env->DeleteGlobalRef(tray_icons[id_num].globalClass);
		tray_icons[id_num].globalClass = 0;
	}
}

/*
 * Class:     jeans_trayicon_WindowsTrayIcon
 * Method:    setToolTip
 * Signature: (ILjava/lang/String;)V
 */
JNIEXPORT void JNICALL Java_com_jeans_trayicon_WindowsTrayIcon_setToolTip(JNIEnv *env, jclass, jint id_num, jstring tip) {
	// Icon id valid?
	if (tray_icons[id_num].used == FALSE) {
		last_error = TRAY_WRONGICONID;
		return;
	}
	// Get java string for tooltip
	const char *tooltip = env->GetStringUTFChars(tip, 0);
	int len = strlen(tooltip);
	// If already exists delete first..
	if (tray_icons[id_num].tooltip != NULL)	delete tray_icons[id_num].tooltip;
	tray_icons[id_num].tooltip = new char[len+1];
	strcpy(tray_icons[id_num].tooltip, tooltip);
	// Release java string

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -