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

📄 windowstrayicon.cpp

📁 本组件可以定制各种最小化图标,为应用程序添加图标,就是系统托盘图标
💻 CPP
📖 第 1 页 / 共 5 页
字号:
	if (tray_icons[m_IDNum].used == FALSE) return TRAY_WRONGICONID;
	jobject obj = tray_icons[m_IDNum].globalClass;
	if (obj == 0) return TRAY_NOLISTENER;
	jclass winTrayClass = env->GetObjectClass(obj);
	if (winTrayClass == 0) return TRAY_NOTENOUGHMEM;
	// Get callback method id
	jmethodID mid = env->GetMethodID(winTrayClass, "notifyMouseListeners", "(IIII)V");
	if (mid == 0) return TRAY_METHODID;
	// Call method "notifyMouseListeners"
	env->CallVoidMethod(obj, mid, m_Button, m_Mask, m_Pos.x, m_Pos.y);
	return TRAY_NOERR;
}

BalloonJavaCallback::BalloonJavaCallback(int idnum, int mask) {
    m_Mask = mask;
    m_IDNum = idnum; 
}

int BalloonJavaCallback::execute(JNIEnv* env) {
	// Valid icon id and valid global reference to icon's Java class?
	if (tray_icons[m_IDNum].used == FALSE) return TRAY_WRONGICONID;
	jobject obj = tray_icons[m_IDNum].globalClass;
	if (obj == 0) return TRAY_NOLISTENER;
	jclass winTrayClass = env->GetObjectClass(obj);
	if (winTrayClass == 0) return TRAY_NOTENOUGHMEM;
	// Get callback method id
	jmethodID mid = env->GetMethodID(winTrayClass, "notifyBalloonListeners", "(I)V");
	if (mid == 0) return TRAY_METHODID;
	// Call method "notifyMouseListeners"
	env->CallVoidMethod(obj, mid, m_Mask);
	return TRAY_NOERR;
}

// Call a Java method in a given virtual machine
int CallJavaVM(JavaVM* vm, ThreadJavaCallback* call) {
	int result = TRAY_NOERR;
	JNIEnv* env;
	// Attach current thread to given Java VM
	if (vm->AttachCurrentThread((void**) &env, NULL) < 0) return TRAY_ERRTHREAD;
	// Call method (MousePressedCallback/MenuItemCallback/WindowsMessageCallback/..)
	result = call->execute(env);
	// Check for exception detach thread and exit
	if (env->ExceptionOccurred()) env->ExceptionDescribe();
	vm->DetachCurrentThread();
	return result;
}

// Thread proc to call Java method (calls CallJavaVMS but with wrapped params)
void CallJavaThread(void *arg) {
	ThreadJavaCallback *tjc = (ThreadJavaCallback*)arg;
	int result = CallJavaVM(hJavaVM, tjc);
	if (result != TRAY_NOERR) last_error = result;
	delete tjc;
}

// Call a Java method in a new thread
void CallJavaVMSThread(ThreadJavaCallback* tjc) {
	if (_beginthread(CallJavaThread, 0, tjc) == -1) delete tjc;
}

SimpleJavaCallback::SimpleJavaCallback(JNIProcPtr(jniproc), int arg1, int arg2) {
    m_JNIProc = jniproc;
    m_Arg1 = arg1;
    m_Arg2 = arg2;
}

int SimpleJavaCallback::execute(JNIEnv* env) {
    return m_JNIProc(env, m_Arg1, m_Arg2);
}

// Handle popup menu command
void HandleMenuCommand(WPARAM menuId) {
	// Get icon id given menu id
	int id_num = getMenuItemIdNum(menuId);
	// Callback to Java class in new thread, using method "MenuItemCallback()"
	SimpleJavaCallback* call = new SimpleJavaCallback(MenuItemCallback, id_num, menuId);
	CallJavaVMSThread(call);
}

// Handle icon mouse event (left/right button)
void HandleNotifyIcon(WPARAM id_num, LPARAM lParam) {	
    if (lParam == WM_RBUTTONDOWN || lParam == NIN_KEYSELECT || lParam == NIN_SELECT || lParam == WM_CONTEXTMENU) {
		if (id_num >= 0) {
		    POINT mouse_pos;
			GetCursorPos(&mouse_pos);				
			// If menu defined, then show it
			if (tray_icons[id_num].popup != NULL) {
				// Display and track the popup menu
				PopupMenu *menu = tray_icons[id_num].popup;
				menu->TrackPopupMenu(TPM_RIGHTALIGN | TPM_RIGHTBUTTON,&mouse_pos,my_hDlg);
			} else {
				// Callback Java class in new thread using "MousePressedCallback()"
		                MouseJavaCallback* call = new MouseJavaCallback(id_num, 1, 0, &mouse_pos);
				CallJavaVMSThread(call);					
			}
		}
    } else {
		int button = -1;
        	int mask = 0;
	        switch (lParam)	{
		    case WM_LBUTTONDOWN:
		        button = 0; break;
		    case WM_MBUTTONDOWN:
		        button = 2; break;
		    case WM_LBUTTONUP:
		        button = 0; mask |= MOUSE_BTN_UP; break;
		    case WM_MBUTTONUP:
		        button = 2; mask |= MOUSE_BTN_UP; break;
		    case NIN_KEYSELECT:
		    case NIN_SELECT:
		    case WM_CONTEXTMENU:
	            case WM_RBUTTONUP:
		        button = 1; mask |= MOUSE_BTN_UP; break;
	            case WM_LBUTTONDBLCLK:
        	        button = 0; mask |= MOUSE_BTN_DOUBLE; break;
	            case WM_RBUTTONDBLCLK:
	                button = 1; mask |= MOUSE_BTN_DOUBLE; break;
        	    case WM_MBUTTONDBLCLK:
	                button = 2; mask |= MOUSE_BTN_DOUBLE; break;
	            case NIN_BALLOONSHOW:
	            	button = 3; mask |= BALLOON_MSG_SHOW; break;
	            case NIN_BALLOONHIDE:
			button = 3; mask |= BALLOON_MSG_HIDE; break;
	            case NIN_BALLOONTIMEOUT:
			button = 3; mask |= BALLOON_MSG_TIMEOUT; break;	            
	            case NIN_BALLOONUSERCLICK:
			button = 3; mask |= BALLOON_MSG_CLICK; break;	                
        	}
		if (id_num >= 0 && button != -1) {
			if (button == 3) {
				BalloonJavaCallback* call = new BalloonJavaCallback(id_num, mask);
				CallJavaVMSThread(call);				
			} else {
				MouseJavaCallback* call = new MouseJavaCallback(id_num, button, mask);
				GetCursorPos(call->getPos());
				CallJavaVMSThread(call);
			}
		}        
    }	
}

void ReAddAllIcons() {
	for (int id_num = 0; id_num < MY_MAX_ICONS; id_num++) {
		if (tray_icons[id_num].visible == TRUE) {
			showIcon(id_num);
		}
	}
}

int HandleAppTalk(int value) {
	SimpleJavaCallback call(WindowsMessageCallback, 0, value);
	return CallJavaVM(hJavaVM, &call);
}

int HandleAppMouse(int xp, int yp) {
	SimpleJavaCallback call(MouseHookCallback, xp, yp);
	return CallJavaVM(hJavaVM, &call);
}

// Windows message proc for hidden window
// Receives mouse/menu events for the apps tray icons
LONG APIENTRY WndProc(HWND hWnd, UINT iMessage, UINT wParam, LONG lParam) {
	switch (iMessage) {
		case WM_DESTROY:
			// Exit message thread
			PostQuitMessage(0) ;
			break;
		case MYWM_NOTIFYICON:
			// Mouse event for icon (left/right button)
			HandleNotifyIcon(wParam, lParam);
			break;
		case MYWM_APPTALK:
			// ID used for sendWindowsMessage()
			// Callback Java class using "WindowsMessageCallback()"
			return HandleAppTalk((int)lParam);
		case MYWM_APPMOUSE:
			// Handle mouse message (from global hook)
			return HandleAppMouse((int)wParam, (int)lParam);
		case WM_COMMAND:
			// Menu command for icon
			HandleMenuCommand(LOWORD(wParam));
			break;		
			// Get notified if task bar restarts
		case WM_CREATE:
            		g_TaskbarRestart = RegisterWindowMessage(TEXT("TaskbarCreated"));
			break;
		// Do nothing for other messages		    
		case WM_GETMINMAXINFO:
		case WM_PAINT:
		case WM_MOUSEMOVE:
		case WM_RBUTTONDOWN:
		case WM_RBUTTONUP:
		case WM_MOVE:
		case WM_SIZE:
		case WM_LBUTTONDOWN:
		case WM_KEYDOWN:
			break;
		    // Or use default handler
		default:
			if (iMessage == g_TaskbarRestart) ReAddAllIcons();
			else return DefWindowProc (hWnd, iMessage, wParam, lParam) ;
	}
	return 0L ;
}

// Create the hidden window to receive the icon's mouse messages
HWND MakeHWND(HINSTANCE hInst) {
	HWND hWnd;
	// Create window class
	WNDCLASS wndclass;
	wndclass.style         = CS_HREDRAW | CS_VREDRAW;
	wndclass.lpfnWndProc   = (WNDPROC) WndProc;
	wndclass.cbClsExtra    = 0;
	wndclass.cbWndExtra    = 0;
	wndclass.hInstance     = hInst;
	wndclass.hIcon         = LoadIcon(hInst, IDI_APPLICATION);
	wndclass.hCursor       = LoadCursor(NULL, IDC_ARROW);
	wndclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
	wndclass.lpszMenuName  = NULL;
	wndclass.lpszClassName = szAppName;
	if (!RegisterClass(&wndclass)) return NULL;
	// Create window
	hWnd = CreateWindow(szAppName, szWndName, WS_OVERLAPPEDWINDOW,
                          0,0,100,100,
                          NULL, NULL, hInst, NULL);
	return hWnd;
}

// Remove the hidden window (on app closing)
void RemoveHWND() {
	// Close dial
	if (my_hDlg != NULL) {
		// Create wait event
		exit_event = CreateEvent(NULL,FALSE,FALSE,NULL);
		// Send destroy messages
		PostMessage(my_hDlg, WM_NCDESTROY, 0, 0);
		PostMessage(my_hDlg, WM_DESTROY, 0, 0);
		// Wait for window to destroy
		WaitForSingleObject(exit_event,10000);
		CloseHandle(exit_event);
		exit_event = NULL;
	}
	// Free handle
	if (wait_event != NULL) {
		CloseHandle(wait_event);
		wait_event = NULL;
	}
}

// The thread proc that creates the hidden window an listens for messages
void DialogThread(void *dummy) {
	MSG msg;
	// Create window
	my_hDlg = MakeHWND(g_hinst);
	// Signal wait event
	if (wait_event != NULL) SetEvent(wait_event);
	// Hide window
	ShowWindow(my_hDlg, SW_HIDE);
	UpdateWindow(my_hDlg);
	// Process messages
	while (GetMessage(&msg, NULL, 0, 0)){
		TranslateMessage(&msg) ;
		DispatchMessage(&msg) ;
	}
	// Unregister window class
	UnregisterClass(szAppName, g_hinst);
	// Signal exit event (so app knows hidden window is destroyed)
	if (exit_event != NULL) SetEvent(exit_event);
}

JNIEXPORT void JNICALL Java_com_jeans_trayicon_WindowsTrayIcon_setAlwaysOnTop(JNIEnv *env, jclass cls, jobject win, jboolean onTop) {
    DoAlwaysOnTop top;
    doWithHWND(&top, env, win);
}

int DoAlwaysOnTop::execute(HWND hwnd) {
    SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
    return 0;
}

void doWithHWND(DoWithHWND* hwndProc, JNIEnv* env, jobject window) {    
    if (hJAWT == NULL) {
        last_error = TRAY_NO_JAWT;
        return;
    }
    PJAWT_GETAWT JAWT_GetAWT = (PJAWT_GETAWT)GetProcAddress(hJAWT, "_JAWT_GetAWT@8");
    if (JAWT_GetAWT == NULL) {
        last_error = TRAY_NO_GET_JAWT;
        return;
    }
    JAWT awt;
    awt.version = JAWT_VERSION_1_3;
    jboolean result = JAWT_GetAWT(env, &awt);
    if (result == JNI_FALSE) {
        last_error = TRAY_GET_JAWT_FAILS;
        return;
    }    
    JAWT_DrawingSurface* ds = awt.GetDrawingSurface(env, window);
    if (ds == NULL) {
        last_error = TRAY_JAWT_DS_FAILS;
        return;
    }    
    jint lock = ds->Lock(ds);
    if ((lock & JAWT_LOCK_ERROR) == 0) {                                                                                     
        JAWT_DrawingSurfaceInfo* dsi = ds->GetDrawingSurfaceInfo(ds);
        JAWT_Win32DrawingSurfaceInfo* dsi_win = (JAWT_Win32DrawingSurfaceInfo*)dsi->platformInfo;
        hwndProc->execute(dsi_win->hwnd);
        ds->FreeDrawingSurfaceInfo(dsi);
        ds->Unlock(ds);                                                            
    } else {
        last_error = TRAY_JAWT_LOCK_FAILS;
    }
    awt.FreeDrawingSurface(ds);                                                      
}  

void RemoveJAWT() {
    if (hJAWT != NULL) {
        FreeLibrary(hJAWT);
        hJAWT = NULL;
    }
}

void RemoveHook() {
	if (hMouseClickHook != NULL) {
		UnhookWindowsHookEx(hMouseClickHook);
		hMouseClickHook = NULL;
	}
}

void GetJAWTHandle() {
	if (hJAWTTried == 0 && hJAWT == NULL) {
		hJAWTTried = 1;
		hJAWT = LoadLibrary("jawt.dll");
		if (hJAWT == NULL) {
			char* jawt_path = find_in_path("../jre/bin/jawt.dll");
			if (jawt_path != NULL) hJAWT = LoadLibrary(jawt_path);
		}
		if (hJAWT == NULL) {
			last_error = TRAY_NO_JAWT;
		}
	}
}

// New icon resource with no bitmap and zero size
IconData::IconData() {
	wd = hi = 0;
	hBitmapAND = hBitmapXOR = NULL;
}

// Destroy icon resources (and and xor bitmap)
IconData::~IconData() {
	if (hBitmapAND != NULL) DeleteObject(hBitmapAND);
	if (hBitmapXOR != NULL) DeleteObject(hBitmapXOR);
}

// Make icon using and and xor bitmaps (returns handle to new icon)
HICON IconData::makeIcon(HINSTANCE hInst) {
        ICONINFO ii;
        ii.fIcon    = TRUE;
        ii.xHotspot = 0;
        ii.yHotspot = 0;
        ii.hbmMask  = hBitmapAND;
        ii.hbmColor = hBitmapXOR;
        return CreateIconIndirect(&ii);
}

// Set icon's image data (pixel array, width, height)
int IconData::setData(unsigned long *data, int wd, int hi) {
	int res = -1;
	// Set size
	this->wd = wd;
	this->hi = hi;
	// Clean up if setData was called before
	if (hBitmapAND != NULL) DeleteObject(hBitmapAND);
	if (hBitmapXOR != NULL) DeleteObject(hBitmapXOR);
	// To protect against java sending a dud image
	if (wd > 0 && hi > 0) {
		    // Set up the header for creating our 24 bit colour bitmap
	    	BITMAPINFOHEADER bih;
		    bih.biSize          = sizeof(BITMAPINFOHEADER);
	    	bih.biWidth         = wd;
		    bih.biHeight        = hi;
		    bih.biPlanes        = 1;
	    	bih.biBitCount      = 24;
	    	bih.biCompression   = BI_RGB;
	    	bih.biSizeImage     = 0;
	    	bih.biXPelsPerMeter = 0;
	    	bih.biYPelsPerMeter = 0;
	    	bih.biClrUsed       = 0;
	    	bih.biClrImportant  = 0;
	    	// Create memory DC
	    	HDC hdc = CreateCompatibleDC(NULL);
	    	// Make the 24-bit DIB
	    	hBitmapXOR = CreateDIBSection(hdc, (LPBITMAPINFO)&bih, DIB_RGB_COLORS, (LPVOID *)NULL, NULL, 0);
	    	// Select it into the DC so we can draw onto it
	    	SelectObject(hdc, hBitmapXOR);
	    	// Calloc memory to be used to create a monochrome bitmask
		long size = (wd*hi/8)+1;
	    	unsigned char *andMask = new unsigned char[size];
		if (andMask != NULL) {
			    for (int i = 0; i < size; i++) andMask[i] = 0;
				// Loop through the given pixels and draw onto the colour and mono bitmaps
				unsigned long pixel;
		        	unsigned char red, green, blue, alpha;
		        	for (int row = 0; row < hi; row++) {
    			    	for (int col = 0; col < wd; col++) {
	            			pixel = data[(row*wd)+col];
		            		alpha = (unsigned char)((pixel >> 24) & 0x000000ff);
		          

⌨️ 快捷键说明

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