📄 windowstrayicon.cpp
字号:
int m_IDNum, m_Button, m_Mask;
POINT m_Pos;
public:
MouseJavaCallback(int idnum, int button, int mask);
MouseJavaCallback(int idnum, int button, int mask, POINT* pos);
POINT* getPos();
virtual int execute(JNIEnv* env);
};
class BalloonJavaCallback : public ThreadJavaCallback {
protected:
int m_IDNum, m_Mask;
public:
BalloonJavaCallback(int idnum, int mask);
virtual int execute(JNIEnv* env);
};
void doWithHWND(DoWithHWND* hwndProc, JNIEnv* env, jobject window);
void GetJAWTHandle();
void RemoveJAWT();
void RemoveHook();
char* find_in_path(const char* append);
BOOL GetOSName(char* osname, int* version);
int TrayGetWindowsVersion();
int GetShell32VerionHelp(DLLVERSIONINFO* version);
DWORD GetShell32Version();
// Struct size for Win95 compatibility
#define MY_NOTIFYICONDATA_V2_SIZE 88
// New struct (WinXP style)
typedef struct {
DWORD cbSize; // 4
HWND hWnd; // 8
DWORD uID; // 12
DWORD uFlags; // 16
DWORD uCallbackMessage; // 20
HICON hIcon; // 24
char szTip[128]; // 152
DWORD dwState; // 156
DWORD dwStateMask; // 160
char szInfo[256]; // 416
DWORD uTimeOrVersion; // 420
char szInfoTitle[64]; // 484
DWORD dwInfoFlags; // 488
GUID guidItem; // 492
} MY_NOTIFYICONDATA;
// New struct (WinXP style - Unicode Version)
typedef struct {
DWORD cbSize; // 4
HWND hWnd; // 8
DWORD uID; // 12
DWORD uFlags; // 16
DWORD uCallbackMessage; // 20
HICON hIcon; // 24
jchar szTip[128]; // 152
DWORD dwState; // 156
DWORD dwStateMask; // 160
jchar szInfo[256]; // 416
DWORD uTimeOrVersion; // 420
jchar szInfoTitle[64]; // 484
DWORD dwInfoFlags; // 488
GUID guidItem; // 492
} MY_NOTIFYICONDATAW;
// Should be declared by header files
#define NIF_INFO 0x10
#define NIM_SETVERSION 0x04
#define NOTIFYICON_VERSION 3
#define NIIF_NONE 0
#define NIIF_INFO 1
#define NIIF_WARNING 2
#define NIIF_ERROR 3
#define NIIF_NOSOUND 0x10
typedef struct {
UINT cbSize;
HWND hwnd;
DWORD dwFlags;
UINT uCount;
DWORD dwTimeout;
} MY_FLASHWINFO;
#define MY_FLASHW_STOP 0
#define MY_FLASHW_CAPTION 1
#define MY_FLASHW_TRAY 2
#define MY_FLASHW_TIMER 4
#define MY_FLASHW_TIMERNOFG 12
typedef BOOL (*P_FLASHWINDOWEX)(MY_FLASHWINFO*);
void copyJCharMax(const jchar* src, jchar* tar, int size) {
for (int i = 0; i < size-1; i++) {
tar[i] = src[i];
if (src[i] == 0) return;
}
tar[size-1] = 0;
}
int lenJChar(const jchar* src) {
if (src == NULL) return 0;
int len = 0;
while (src[len] != 0) len++;
return len;
}
#define UNICODE_NAME_MAX 8
typedef struct {
char name[UNICODE_NAME_MAX];
jchar value;
} UnicodeMapping;
UnicodeMapping UnicodeMap[] =
{{"lsquo", 8216}, {"rsquo", 8217}, {"ldquo", 8220}, {"rdquo", 8221}, {"dagger", 8224},
{"Dagger", 8225}, {"permil", 8240}, {"larr", 8592}, {"uarr", 8593}, {"rarr", 8594},
{"darr", 8595}, {"trade", 8482}, {"iexcl", 161}, {"cent", 162}, {"pound", 163},
{"curren", 164}, {"yen", 165}, {"sect", 167}, {"copy", 169}, {"not", 172}, {"reg", 174},
{"deg", 176}, {"plusmn", 177}, {"sup2", 178}, {"sup3", 179}, {"micro", 181}, {"para", 182},
{"middot", 183}, {"sup1", 185}, {"frac14", 188}, {"frac12", 189}, {"frac34", 190},
{"iquest", 191}, {"Agrave", 192}, {"Aacute", 193}, {"Acirc", 194}, {"Atilde", 195},
{"Auml", 196}, {"Aring", 197}, {"AElig", 198}, {"Ccedil", 199}, {"Egrave", 200},
{"Eacute", 201}, {"Ecirc", 202}, {"Euml", 203}, {"Igrave", 204}, {"Iacute", 205},
{"Icirc", 206}, {"Iuml", 207}, {"ETH", 208}, {"Ntilde", 209}, {"Ograve", 210},
{"Oacute", 211}, {"Ocirc", 212}, {"Otilde", 213}, {"Ouml", 214}, {"times", 215},
{"Oslash", 216}, {"Ugrave", 217}, {"Uacute", 218}, {"Ucirc", 219}, {"Uuml", 220},
{"Yacute", 221}, {"THORN", 222}, {"szlig", 223}, {"agrave", 224}, {"aacute", 225},
{"acirc", 226}, {"atilde", 227}, {"auml", 228}, {"aring", 229}, {"aelig", 230},
{"ccedil", 231}, {"egrave", 232}, {"eacute", 233}, {"ecirc", 234}, {"euml", 235},
{"igrave", 236}, {"iacute", 237}, {"icirc", 238}, {"iuml", 239}, {"eth", 240},
{"ntilde", 241}, {"ograve", 242}, {"oacute", 243}, {"ocirc", 244}, {"otilde", 245},
{"ouml", 246}, {"divide", 247}, {"oslash", 248}, {"ugrave", 249}, {"uacute", 250},
{"ucirc", 251}, {"uuml", 252}, {"yacute", 253}, {"thorn", 254}, {"yuml", 255},
{"", 0}};
void convertUnicodeString(const jchar* strg, jchar* strgo, int nbMax) {
char buffer[UNICODE_NAME_MAX+1];
int in_buffer = 0, bufpos = 0, pos = 0, opos = 0;
while (strg[pos] != 0) {
if (pos >= nbMax) break;
if (opos >= nbMax) break;
if (in_buffer == 1) {
if (strg[pos] == (jchar)';') {
int mappos = 0, found = 0;
buffer[bufpos] = 0;
while (UnicodeMap[mappos].value != 0) {
if (strcmp(UnicodeMap[mappos].name, buffer) == 0) {
int len = strlen(UnicodeMap[mappos].name);
opos -= len+1;
strgo[opos++] = UnicodeMap[mappos].value;
found = 1;
}
mappos++;
}
if (found == 0) {
strgo[opos++] = (jchar)';';
}
in_buffer = 0;
} else if (strg[pos] == (jchar)'&') {
strgo[opos++] = (jchar)'&';
bufpos = 0;
} else {
if (bufpos < UNICODE_NAME_MAX) {
if (strg[pos] < 255) {
buffer[bufpos++] = (char)strg[pos];
} else {
in_buffer = 0;
}
} else {
in_buffer = 0;
}
strgo[opos++] = strg[pos];
}
} else {
if (strg[pos] == (jchar)'&') {
in_buffer = 1;
bufpos = 0;
}
strgo[opos++] = strg[pos];
}
pos++;
}
strgo[opos] = 0;
}
char* convertUnicodeANSI(jchar* unicode) {
int len = lenJChar(unicode);
int nbmax = nbWideMaxChars*len;
char* result = new char[nbmax+2];
// Convert Unicode string to ANSI string
if (!WideCharToMultiByte(CP_ACP, 0, (const WCHAR*)unicode, len+1, result, nbmax+1, NULL, NULL)) {
// Fall back :-(
for (int i = 0; i < len; i++) {
result[i] = (char)(unicode[i] & 0xFF);
}
}
return result;
}
/*
* Class: com_jeans_trayicon_WindowsTrayIcon
* Method: enableUnicodeConversion
* Signature: (IZ)V
*/
JNIEXPORT void JNICALL Java_com_jeans_trayicon_WindowsTrayIcon_enableUnicodeConversion(JNIEnv *, jclass, jint which, jboolean enable) {
g_UnicodeConversion[which] = enable;
}
/*
* Class: com_jeans_trayicon_WindowsTrayIcon
* Method: hasUnicodeConversion
* Signature: (I)I
*/
JNIEXPORT jboolean JNICALL Java_com_jeans_trayicon_WindowsTrayIcon_hasUnicodeConversion(JNIEnv *, jclass, jint which) {
return g_UnicodeConversion[which];
}
/*
* Class: com_jeans_trayicon_WindowsTrayIcon
* Method: supportsBalloonMessages
* Signature: ()Z
*/
JNIEXPORT jboolean JNICALL Java_com_jeans_trayicon_WindowsTrayIcon_supportsBalloonMessages(JNIEnv *, jclass) {
if (hShell32Version < 5) {
// No balloon messages supported :-(
return FALSE;
} else {
return TRUE;
}
}
/*
* 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) {
// 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_TOOMANYICONS;
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);
}
void showIcon(int id_num) {
// Show icon in windows system tray
if (tray_icons[id_num].icon != NULL) {
HICON icon = tray_icons[id_num].icon->makeIcon(g_hinst);
if (icon != NULL) {
if (bUseUnicode == 0) {
TrayMessage(my_hDlg, NIM_ADD, id_num, icon, tray_icons[id_num].tooltip);
} else {
TrayMessageW(my_hDlg, NIM_ADD, id_num, icon, (jchar*)tray_icons[id_num].tooltip);
}
tray_icons[id_num].visible = TRUE;
} else {
last_error = TRAY_NOTENOUGHMEM;
}
}
}
/*
* 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) {
if (tray_icons[id_num].visible == FALSE) {
showIcon(id_num);
}
} 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;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -