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

📄 windowstrayiconmemoryleak.cpp

📁 JAVA程序的系统托盘
💻 CPP
📖 第 1 页 / 共 3 页
字号:
}

// Handle icon mouse event (left/right button)
void HandleNotifyIcon(WPARAM id_num, LPARAM lParam) {
	switch (lParam)	{
		case WM_LBUTTONDOWN:
			// Callback Java class in new thread using "MousePressedCallback()"
			if (id_num >= 0) CallJavaVMSThread(MousePressedCallback,id_num,0);
			break;
		case WM_RBUTTONDOWN:
			if (id_num >= 0) {
				// If menu defined, then show it
				if (tray_icons[id_num].popup != NULL) {
					POINT pos;
					GetCursorPos(&pos);
					// Display and track the popup menu
					PopupMenu *menu = tray_icons[id_num].popup;
					menu->TrackPopupMenu(TPM_RIGHTALIGN | TPM_RIGHTBUTTON,&pos,my_hDlg);
				} else {
					// Callback Java class in new thread using "MousePressedCallback()"
					CallJavaVMSThread(MousePressedCallback,id_num,1);
				}
			}
			break;
	}
}

// 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 CallJavaVMS(WindowsMessageCallback,0,(int)lParam);
		case WM_COMMAND:
			// Menu command for icon
			HandleMenuCommand(LOWORD(wParam));
			break;
		// Do nothing for other messages
		case WM_CREATE:
		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:
			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 = 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);
}

// 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) {
	// 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);
		        		red   = (unsigned char)((pixel >> 16) & 0x000000ff);
	                		green = (unsigned char)((pixel >>  8) & 0x000000ff);
	                		blue  = (unsigned char)( pixel        & 0x000000ff);
	        		    	if (alpha == 0xFF) {
						// Pixel is not transparent - update xor bitmap
						SetPixel(hdc, col, row, RGB(red, green, blue));
					} else {
						// Pixel is transparent - update and mask
		        			int p = (row*wd) + col;
				        	andMask[p/8] |= 1 << (7-(p%8));
					}
				}
			}
			// Create the monochrome bitmask with transparency info
			hBitmapAND = CreateBitmap(wd, hi, 1, 1, andMask);
			// Free memory
			delete andMask;
			// Release the memory DC
			ReleaseDC(NULL, hdc);
			return 0;
		}
		// Release the memory DC
		ReleaseDC(NULL, hdc);
	}
	// Error on zero size icons
	return -1;
}

// Find free menu id for submenu item (given icon id = owner)
// Each tray icon with a submenu has a number of menu ids, one for each menu item
long getFreeMenuId(int id_num) {
	long size = arrUsedMenuIds->getSize();
	long id = 0;
	BOOL done = FALSE;
	// Find for free id in array that maps menu ids to icon ids
	for (id = 0; id < size && !done; id++)
		if (arrUsedMenuIds->getElementAt(id) == -1) done = TRUE;
	// Found none, create new id
	if (!done) {
		id = size;
		arrUsedMenuIds->addElement(-1);
	}
	// Mark id in array as belonging to icon with id id_num
	arrUsedMenuIds->setElementAt(id, id_num);
	// Return id for new submenu item
	return id;
}

// Free all menu ids for a given icon
void setFreeMenuId(int id_num) {
	long size = arrUsedMenuIds->getSize();
	// Find ids for given icon and free them
	for (long ps = 0; ps < size; ps++) {
		if (arrUsedMenuIds->getElementAt(ps) == id_num)
			arrUsedMenuIds->setElementAt(ps, -1);
	}
	// Shrink array if there are trailing empty places
	long delofs = arrUsedMenuIds->getSize();
	while (delofs > 0 && arrUsedMenuIds->getElementAt(delofs-1) == -1) {
		delofs--;
		arrUsedMenuIds->removeElementAt(delofs);
	}
}

// Map menu id to icon id
int getMenuItemIdNum(int id) {
	long size = arrUsedMenuIds->getSize();
	if (id < size) return arrUsedMenuIds->getElementAt(id);
	else return -1;
}

// Make new popup menu
PopupSubMenu::PopupSubMenu() {
	hMenu = CreatePopupMenu();
	bSub = FALSE;
}

// Make new popup menu (reset all class members)
void PopupSubMenu::reNewMenu() {
	if (!isSub()) DestroyMenu(hMenu);
	hMenu = CreatePopupMenu();
	bSub = FALSE;
}

// Destroy popupmenu
PopupSubMenu::~PopupSubMenu() {
	if (!isSub()) DestroyMenu(hMenu); // Only needed when parent menu, not for submenus
}

// Is this a submenu or a parent popup menu
BOOL PopupSubMenu::isSub() {
	return bSub;
}

// Mark this popup menu as being a submenu
void PopupSubMenu::makeSub() {
	bSub = TRUE;
}

// Get the windows menu handle, used for AppendMenu,..
HMENU PopupSubMenu::getMenu() {
	return hMenu;
}

// Display the popupmenu at given position (in neighbourhood of tray icon)
void PopupSubMenu::TrackPopupMenu(UINT flags, POINT* pos, HWND hWnd) {
	// SetForegroundWindow/PostMessage are hacks because TrackPopupMenu contains bug/feature
	// Otherwise it's not hidden properly when the user clicks on desktop
	SetForegroundWindow(hWnd);
	::TrackPopupMenu(hMenu, flags, (*pos).x, (*pos).y, 0, hWnd, NULL);
	PostMessage(hWnd, WM_NULL, 0, 0);
}

// Make new popup main menu with maximum submenu depth
PopupMenu::PopupMenu(int levels) {
	nbLevels = levels;
	popup = new PtrPopupSubMenu[levels];
	for (int ctr = 0; ctr < levels; ctr++) popup[ctr] = NULL;
}

// Destroy main popup menu
PopupMenu::~PopupMenu() {
	// Destroy all submenu levels
	for (int ctr = 0; ctr < nbLevels; ctr++)
		if (popup[ctr] != NULL) delete popup[ctr];
	delete popup;
}

// Init menu at given level (make new or call reNewMenu())
void PopupMenu::initMenu(int level) {
	if (level >= nbLevels) return;
	if (popup[level] != NULL) popup[level]->reNewMenu();
	else popup[level] = new PopupSubMenu();
}

// Return windows menu handle for given level (should be 0 for main menu)
HMENU PopupMenu::getMenu(int level) {
	PopupSubMenu *menu = getSubMenu(level);
	if (menu == NULL) return NULL;
	else return menu->getMenu();
}

// Return sub menu @ given level (used in getMenu()/TrackPopupMenu())
PopupSubMenu* PopupMenu::getSubMenu(int level) {
	if (level >= nbLevels) return NULL;
	return popup[level];
}

// Display the popupmenu at given position (in neighbourhood of tray icon)
void PopupMenu::TrackPopupMenu(UINT flags, POINT* pos, HWND hWnd) {
	PopupSubMenu *menu = getSubMenu(0);
	if (menu != NULL) menu->TrackPopupMenu(flags, pos, hWnd);
}

// Create new growable integer array
QSIntArray::QSIntArray() {
	m_Array = new int[5];
	m_ArrSize = 5;
	m_Size = 0;
	m_Grow = 10;
}

// Create new growable integer array with initial size and grow term
QSIntArray::QSIntArray(long size, long grow) {
	m_Array = new int[size];
	m_ArrSize = size;
	m_Size = 0;
	m_Grow = grow;
}

// Delete growable integer array
QSIntArray::~QSIntArray() {
	delete m_Array;
}

// Get size
long QSIntArray::getSize() {
	return m_Size;
}

// Get integer @ given position
int QSIntArray::getElementAt(long idx) {
	return m_Array[idx];
}

// Add integer at end of array
void QSIntArray::addElement(int element) {
	m_Size++;
	grow();
	m_Array[m_Size-1] = element;
}

// Set integer @ given position (may be >= getSize() - array grows)
void QSIntArray::setElementAt(long idx, int element) {
	m_Size = max(m_Size, idx+1);
	grow();
	m_Array[idx] = element;
}

// Remove integer at given position
void QSIntArray::removeElementAt(long idx) {
	m_Size--;
	for (long pos = idx; pos < m_Size; pos++)
		m_Array[pos] = m_Array[pos+1];
	shrink();
}

// Empty array
void QSIntArray::removeAll() {
	m_Size = 0;
	shrink();
}

// Shrink array to convenient size
void QSIntArray::shrink() {
	if (m_Size < m_ArrSize - m_Grow) {
		long nSize = m_Size + m_Grow;
		int* nArray = new int[nSize];
		for (long idx = 0; idx < m_Size; idx++)
			nArray[idx] = m_Array[idx];
		delete m_Array;
		m_Array = nArray;
		m_ArrSize = nSize;
	}
}

// Grow array to convenient size
void QSIntArray::grow() {
	if (m_Size > m_ArrSize) {
		long nSize = m_Size + m_Grow;
		int* nArray = new int[nSize];
		for (long idx = 0; idx < m_ArrSize; idx++)
			nArray[idx] = m_Array[idx];
		delete m_Array;
		m_Array = nArray;
		m_ArrSize = nSize;
	}
}







⌨️ 快捷键说明

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