| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538 | #include "api__gen_ml.h"#include "main.h"#include "./skinnedmenuwnd.h"#include "./skinnedmenu.h"#include "./skinning.h"#include "./ml_imagelist.h"#include "./colors.h"#include "./resource.h"#include "../winamp/wa_dlg.h"#define MENU_BORDER_WIDTH	3static HMLIMGLST hmlilCheck = NULL;static INT imageCheckMark = -1;static INT imageRadioMark = -1;static INT imageExpandArrow = -1;// menu hit test codes#define MHF_NOWHERE		0xFFFFFFFF#define MHF_SCROLLUP	0xFFFFFFFD#define MHF_SCROLLDOWN	0xFFFFFFFC#define MN_SIZEWINDOW		0x01E2#define MN_SELECTITEM		0x01E5	// wParam - item position or MHF_XXX#define MN_LBUTTONDOWN		0x01ED	// wParam - item position or MHF_XXX#define MN_LBUTTONUP		0x01EF	// wParam - item position or MHF_XXX#define MN_LBUTTONDBLCLK	0x01F1	// ?// menu timer id#define MTID_OPENSUBMENU	0x0000FFFE#define MTID_SCROLLUP		0xFFFFFFFD#define MTID_SCROLLDOWN		0xFFFFFFFC#define MTID_EX_UNBLOCKDRAW	0x0001980extern HMLIMGFLTRMNGR hmlifMngr;	// default gen_ml fitler manager#define SMIF_BLOCKDRAW			0x00000001#define SMIF_REMOVEREFLECTOR	0x00000002static HBRUSH SkinnedMenuWnd_GetBackBrush(HMENU hMenu){	MENUINFO mi = {0};	mi.cbSize = sizeof(MENUINFO);	mi.fMask = MIM_BACKGROUND;	if (NULL == hMenu || !GetMenuInfo(hMenu, &mi))		mi.hbrBack = NULL;	return (NULL != mi.hbrBack) ? mi.hbrBack : GetSysColorBrush(COLOR_MENU);}static INT SkinnedMenuWnd_AddPngResource(HMLIMGLST imageList, INT resourceId){	MLIMAGESOURCE_I src;	ZeroMemory(&src, sizeof(MLIMAGESOURCE_I));	src.type = SRC_TYPE_PNG_I;	src.hInst = plugin.hDllInstance;	src.lpszName = MAKEINTRESOURCEW(resourceId);	return MLImageListI_Add(hmlilCheck, &src, MLIF_FILTER1_UID, 0);}static HBITMAP SkinnedMenuWnd_LoadPngResource(INT resourceId, COLORREF rgbBk, COLORREF rgbFg){	MLIMAGESOURCE_I imageSource;	ZeroMemory(&imageSource, sizeof(MLIMAGESOURCE_I));	imageSource.type = SRC_TYPE_PNG_I;	imageSource.hInst = plugin.hDllInstance;	imageSource.lpszName = MAKEINTRESOURCEW(resourceId);	HBITMAP hbmp = MLImageLoaderI_LoadDib(&imageSource);	if (NULL != hbmp)		MLImageFilterI_Apply(hmlifMngr, &MLIF_FILTER1_UID, hbmp, rgbBk, rgbFg, NULL); 	return hbmp;}SkinnedMenuWnd::SkinnedMenuWnd(UINT menuExStyle, HMLIMGLST hmlil, INT forcedWidth, MENUCUSTOMIZEPROC _customProc, ULONG_PTR customParam) : 	SkinnedWnd(FALSE){	if (FAILED(SkinnedMenuThreadInfo::GetInstance(TRUE, &threadInfo)))		threadInfo = NULL;	hMenu = NULL;	hOwner = NULL;	this->menuExStyle	= menuExStyle;	this->hmlil			= hmlil;	this->lineWidth		= forcedWidth;	bRestoreShadow		= FALSE;	hBoldFont = NULL;	menuFlags = 0;	backBrush = NULL;	borderPen = NULL;	menuOrigBrush	= NULL;	skinnedItems	= NULL;	skinnedItemCount = 0;	skinnedItemCursor = 0;	prevSelectedItem = 0;	shortcutCX = 0;	textCX = 0;	scrollBitmap = NULL;	disabledScrollBitmap = NULL;	this->customProc = _customProc;	this->customParam = customParam;}SkinnedMenuWnd::~SkinnedMenuWnd(void){	SetOwnerWindow(NULL);	if (hMenu)	{		MENUINFO mi = {0};		mi.cbSize = sizeof(MENUINFO);		mi.fMask = MIM_BACKGROUND;		if (GetMenuInfo(hMenu, &mi))		{			mi.fMask = 0;			if (menuOrigBrush != mi.hbrBack)			{				mi.hbrBack = menuOrigBrush;				mi.fMask |= MIM_BACKGROUND;			}			if (0 != mi.fMask)				SetMenuInfo(hMenu, &mi);		}		if (NULL != skinnedItems && skinnedItemCount > 0)		{			MENUITEMINFOW mii = {0};			mii.cbSize = sizeof(MENUITEMINFOW);			for (INT i = 0; i < skinnedItemCount; i++)			{				SkinnedItemRecord *record = &skinnedItems[i];				if(FALSE == record->failed)				{					mii.fMask = MIIM_FTYPE | MIIM_ID | MIIM_BITMAP;					if (FALSE != GetMenuItemInfoW(hMenu, i, TRUE, &mii))					{						mii.fMask = 0;						if (FALSE != record->skinned)						{							mii.fMask |= (MIIM_FTYPE | MIIM_BITMAP);							mii.fType &= ~MFT_OWNERDRAW;							record->skinned = FALSE;						}						if (record->itemId != record->originalId && 							record->itemId == mii.wID)						{							mii.fMask |= MIIM_ID;							mii.wID = record->originalId;						}						if (NULL != threadInfo)						{							threadInfo->ReleaseId(record->itemId);							if (record->itemId != record->originalId)								threadInfo->ReleaseId(record->originalId);						}						if (0 != mii.fMask)						{							if (FALSE == SetMenuItemInfoW(hMenu, i, TRUE, &mii))							{							}						}					}				}			}		}		if (NULL != threadInfo)			threadInfo->UnregisterMenu(hMenu);	}	if (NULL != skinnedItems)		free(skinnedItems);    if (hwnd && bRestoreShadow) 	{		SetClassLongPtrW(hwnd, GCL_STYLE, GetClassLongPtrW(hwnd, GCL_STYLE) | 0x00020000/*CS_DROPSHADOW*/);	}	if (NULL != hBoldFont) 		DeleteObject(hBoldFont);	if (NULL != backBrush)		DeleteObject(backBrush);	if (NULL != borderPen)		DeleteObject(borderPen);	if (NULL != scrollBitmap)		DeleteObject(scrollBitmap);	if (NULL != disabledScrollBitmap)		DeleteObject(disabledScrollBitmap);	if (NULL != threadInfo)	{		threadInfo->RemoveValidationHook(this);		threadInfo->Release();	}}HMENU SkinnedMenuWnd::GetMenuHandle(){	return hMenu;}HWND SkinnedMenuWnd::GetOwnerWindow(){	return hOwner;}HWND SkinnedMenuWnd::SetOwnerWindow(HWND hwndOwner){	if (hOwner == hwndOwner)		return hOwner;	HWND prevOwner = hOwner;	if (NULL != hOwner && 		0 != (SMIF_REMOVEREFLECTOR & menuFlags))	{		RemoveReflector(hOwner);	}	menuFlags &= ~SMIF_REMOVEREFLECTOR;	hOwner = hwndOwner;	if (NULL != hOwner && 		S_OK == InstallReflector(hOwner))	{		menuFlags |= SMIF_REMOVEREFLECTOR;	}	return prevOwner;}BOOL SkinnedMenuWnd::AttachMenu(HMENU hMenuToAttach){	MENUINFO mi = {0};	MENUITEMINFOW mii = {0};	if (NULL != hMenu || 		NULL == hMenuToAttach) 	{		return FALSE;	}	hMenu = hMenuToAttach;	mi.cbSize = sizeof(MENUINFO);	mi.fMask = MIM_BACKGROUND;	if (GetMenuInfo(hMenu, &mi))	{		menuOrigBrush = mi.hbrBack;		mi.fMask = 0;		if (NULL == mi.hbrBack)		{			COLORREF rgb;			if (0 != (SMS_SYSCOLORS & menuExStyle) || 				FAILED(MLGetSkinColor(MLSO_MENU, MP_BACKGROUND, MBS_NORMAL, &rgb)))			{				rgb = GetSysColor(COLOR_MENU);			}			backBrush = CreateSolidBrush(rgb);			mi.hbrBack = backBrush;			mi.fMask |= MIM_BACKGROUND;		}		if (0 != mi.fMask)			SetMenuInfo(hMenu, &mi);	}	if (NULL != threadInfo)		threadInfo->RegisterMenu(hMenu, hwnd);	mii.cbSize = sizeof(MENUITEMINFOW);	INT count = GetMenuItemCount(hMenu);	if (count > 0)	{		skinnedItems = (SkinnedItemRecord*)calloc(count, sizeof(SkinnedItemRecord));		if (NULL != skinnedItems)		{			skinnedItemCount = count;		}	}	if (NULL == skinnedItems)		return FALSE;	skinnedItemCursor = 0;	for (int i = 0; i < count; i++)	{		SkinnedItemRecord *record = &skinnedItems[i];		mii.fMask = MIIM_FTYPE | MIIM_ID | MIIM_BITMAP;  // MIIM_BITMAP - keep it... this forces menu to call WM_MEASUREITEM		if (FALSE != GetMenuItemInfoW(hMenu, i, TRUE, &mii))		{						record->originalId = mii.wID;			record->itemId = record->originalId;			if (NULL != threadInfo)				threadInfo->ClaimId(record->originalId);			if (0 == (MFT_OWNERDRAW & mii.fType))			{				mii.fType |= MFT_OWNERDRAW;				mii.fMask &= ~MIIM_ID;				// copes with separators and popup menus (menu and menuex types)				if (0 == mii.wID || (UINT)-1 == mii.wID || 65535 == mii.wID)				{					if (NULL != threadInfo)					{						mii.wID = threadInfo->GetAvailableId();						if ((unsigned int)-1 != mii.wID)						{							record->itemId = mii.wID;							mii.fMask |= MIIM_ID;						}						else							mii.wID = record->itemId;					}				}				record->skinned = TRUE;				if (FALSE == SetMenuItemInfoW(hMenu, i, TRUE, &mii))				{					record->skinned = FALSE;					record->itemId = record->originalId;				}				else				{					if (record->itemId != record->originalId && 						NULL != threadInfo)					{						threadInfo->ClaimId(record->itemId);					}				}			}		}		else		{			record->failed = TRUE;		}	}	return TRUE;}BOOL SkinnedMenuWnd::Attach(HWND hwndMenu, HWND hwndOwner){			menuFlags &= ~SMIF_BLOCKDRAW;		if(!__super::Attach(hwndMenu)) 		return FALSE;	SetOwnerWindow(hwndOwner);	DWORD windowStyle = GetWindowLongPtrW(hwnd, GWL_STYLE);	DWORD windowStyleEx = GetWindowLongPtrW(hwnd, GWL_EXSTYLE);	DWORD newStyle = windowStyle & ~(WS_BORDER | WS_THICKFRAME | WS_DLGFRAME);	if (newStyle != windowStyle)		SetWindowLongPtr(hwnd, GWL_STYLE, newStyle);	newStyle = windowStyleEx & ~(WS_EX_DLGMODALFRAME | WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE | WS_EX_STATICEDGE);	if (newStyle != windowStyleEx)		SetWindowLongPtr(hwnd, GWL_EXSTYLE, newStyle);	if (0 == (SMS_SYSCOLORS & menuExStyle))	{		SetStyle(SWS_USESKINCOLORS, FALSE);	}	SetType(SKINNEDWND_TYPE_POPUPMENU);	if (!hmlilCheck)		hmlilCheck = MLImageListI_Create(16, 16, MLILC_COLOR24_I, 2, 1, 2, hmlifMngr);	if ((SMS_FORCEWIDTH & menuExStyle) && lineWidth > 0) 	{		lineWidth -= ((GetSystemMetrics(SM_CXMENUCHECK) - 1) + WASABI_API_APP->getScaleX(MENU_BORDER_WIDTH*2));		if (lineWidth < 0) lineWidth = 0;	}	else lineWidth = 0;	lineHeight = GetLineHeight();	if (!hmlil || !MLImageListI_GetImageSize(hmlil, &imageWidth, &imageHeight)) { imageWidth = WASABI_API_APP->getScaleX(24); imageHeight = 0; }	if (hmlilCheck)	{		INT imageCX, imageCY;		if(MLImageListI_GetImageSize(hmlilCheck, &imageCX, &imageCY)) 		{			if (imageWidth < imageCX) imageWidth = imageCX;			if (imageWidth < WASABI_API_APP->getScaleX(25)) imageWidth = WASABI_API_APP->getScaleX(25);	// clamp to a min width to better match the OS			if (imageHeight < imageCY) imageHeight = imageCY;		}	}	if (lineHeight < (imageHeight + WASABI_API_APP->getScaleY(4))) lineHeight = (imageHeight + WASABI_API_APP->getScaleY(4));	if ((SMS_DISABLESHADOW & menuExStyle))	{		UINT cs = GetClassLongPtrW(hwnd, GCL_STYLE);		if (0x00020000/*CS_DROPSHADOW*/ & cs)		{			bRestoreShadow = TRUE;			SetClassLongPtrW(hwnd, GCL_STYLE, cs & ~0x00020000/*CS_DROPSHADOW*/);		}	}	return TRUE;}HPEN SkinnedMenuWnd::GetBorderPen(void){	if (NULL == borderPen)	{		COLORREF rgb;		if (0 != (SMS_SYSCOLORS & menuExStyle))			rgb = GetSysColor(COLOR_GRAYTEXT);		else			MLGetSkinColor(MLSO_MENU, MP_FRAME, 0, &rgb);		borderPen = CreatePen(PS_SOLID, 0, rgb);	}	return borderPen;}INT SkinnedMenuWnd::GetLineHeight(){	INT h = 0;	HDC hdc = GetDCEx(hwnd, NULL, DCX_CACHE);	if (hdc)	{		HFONT hf = GetMenuFont(TRUE);		if (NULL != hf)		{			TEXTMETRICW tm = {0};			HFONT hfo = (HFONT)SelectObject(hdc, hf);			if (GetTextMetricsW(hdc, &tm)) h = tm.tmHeight + WASABI_API_APP->getScaleY(4);			SelectObject(hdc, hfo);		}		ReleaseDC(hwnd, hdc);	}	return h;}HFONT SkinnedMenuWnd::GetMenuFont(BOOL fBold){	HFONT hFont = NULL;	if (SMS_USESKINFONT & menuExStyle) 	{		hFont = (HFONT)MlStockObjects_Get(SKIN_FONT);	}	if (NULL == hFont)		hFont = (HFONT)MlStockObjects_Get(DEFAULT_FONT);		if (FALSE != fBold)	{		if (NULL == hBoldFont)		{			LOGFONTW lf = {0};			if (sizeof(LOGFONTW) == GetObjectW(hFont, sizeof(LOGFONTW), &lf))			{				if (lf.lfWeight < FW_BOLD)					lf.lfWeight = FW_BOLD;				hBoldFont = CreateFontIndirectW(&lf);			}		}		if (NULL != hBoldFont)		{			hFont = hBoldFont;		}	}	return hFont;}INT SkinnedMenuWnd::OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS *pncsp){	DWORD windowStyle = GetWindowLongPtr(hwnd, GWL_STYLE);	DWORD windowStyleEx = GetWindowLongPtr(hwnd, GWL_EXSTYLE);	DWORD newStyle = windowStyle & ~(WS_BORDER | WS_THICKFRAME | WS_DLGFRAME);	if (newStyle != windowStyle)		SetWindowLongPtr(hwnd, GWL_STYLE, newStyle);	newStyle = windowStyleEx & ~(WS_EX_DLGMODALFRAME | WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE | WS_EX_STATICEDGE);	if (newStyle != windowStyleEx)		SetWindowLongPtr(hwnd, GWL_EXSTYLE, newStyle);	LRESULT result = CallPrevWndProc(WM_NCCALCSIZE, (WPARAM)bCalcValidRects, (LPARAM)pncsp);		InflateRect(&pncsp->rgrc[0], WASABI_API_APP->getScaleX(-MENU_BORDER_WIDTH), WASABI_API_APP->getScaleY(-MENU_BORDER_WIDTH)); 	if (bCalcValidRects)	{		InflateRect(&pncsp->rgrc[1], WASABI_API_APP->getScaleX(-MENU_BORDER_WIDTH), WASABI_API_APP->getScaleY(-MENU_BORDER_WIDTH)); 		InflateRect(&pncsp->rgrc[2], WASABI_API_APP->getScaleX(-MENU_BORDER_WIDTH), WASABI_API_APP->getScaleY(-MENU_BORDER_WIDTH)); 	}	return (INT)result;}void SkinnedMenuWnd::PaintScrollButton(HDC hdc, const RECT *prc, UINT scrollButton, BOOL buttonState){	COLORREF rgbBk, rgbFg;	MLGetSkinColor(MLSO_MENU, MP_BACKGROUND, MBS_NORMAL, &rgbBk);	MLGetSkinColor(MLSO_MENU, MP_TEXT, MTS_NORMAL, &rgbFg);	HBITMAP hbmp;	if (0 == (MENU_BUTTON_STATE_DISABLED & buttonState))	{		if (NULL == scrollBitmap)			scrollBitmap = SkinnedMenuWnd_LoadPngResource(IDB_MENU_SCROLLARROW, rgbBk, rgbFg);		hbmp = scrollBitmap;	}	else	{		if (NULL == disabledScrollBitmap)			disabledScrollBitmap = SkinnedMenuWnd_LoadPngResource(IDB_MENU_SCROLLARROW_DISABLED, rgbBk, rgbFg);		hbmp = disabledScrollBitmap;	}	BOOL imageFailed = TRUE;	if (NULL != hbmp)	{		DIBSECTION bitmapInfo;		if (!GetObjectW(hbmp, sizeof(bitmapInfo), &bitmapInfo))			ZeroMemory(&bitmapInfo, sizeof(bitmapInfo));		INT h = abs(bitmapInfo.dsBm.bmHeight);		INT w = bitmapInfo.dsBm.bmWidth;		if (h > 0 && w > 0)		{			INT x, y, nWidth, nHeight;			x = prc->left + ((prc->right - prc->left) - w) / 2;			y = prc->top + ((prc->bottom - prc->top) - h) / 2;			if (MENU_BUTTON_SCROLLDOWN == scrollButton)			{				nWidth = -w;				nHeight = h;				x += w;			}			else			{				nWidth = w;				nHeight = -h;				y += h;			}			SetBkColor(hdc, rgbBk);			ExtTextOut(hdc, 0, 0, ETO_OPAQUE, prc, NULL, 0, NULL);			StretchDIBits(hdc, x, y, nWidth, nHeight, 0, 0, w, h, bitmapInfo.dsBm.bmBits, 							(BITMAPINFO*)&bitmapInfo.dsBmih, DIB_RGB_COLORS, SRCCOPY);			imageFailed = FALSE;		}	}	if (imageFailed)		ExtTextOut(hdc, 0, 0, ETO_OPAQUE, prc, NULL, 0, NULL);}BOOL SkinnedMenuWnd::DrawScrollButton(HDC hdc, UINT scrollButton){	RECT rc, rcWindow, rcPaint;	if (0 == scrollButton || 		0 == GetWindowRect(hwnd, &rcWindow) || 		0 == GetClientRect(hwnd, &rc))	{		return FALSE;	}	MapWindowPoints(hwnd, HWND_DESKTOP, (POINT*)&rc, 2);			HDC hdcOwned = NULL;	if (NULL == hdc)	{		hdcOwned = GetDCEx(hwnd, NULL, DCX_CACHE | DCX_WINDOW | DCX_CLIPSIBLINGS);		hdc = hdcOwned;				if (NULL == hdcOwned)			return FALSE;	}	rcPaint.left = rc.left - rcWindow.left;	rcPaint.right = rc.right - rcWindow.left;	BOOL scrollEnabled;	POINT ptTest;	ptTest.x = rc.left + (rc.right - rc.left) / 2;	if (0 != (MENU_BUTTON_SCROLLUP & scrollButton))	{		rcPaint.top = MENU_BORDER_WIDTH;		rcPaint.bottom = rc.top - rcWindow.top;		if (rcPaint.bottom > rcPaint.top && rcPaint.right > rcPaint.left)		{			ptTest.y = rc.top;			scrollEnabled = (MenuItemFromPoint(hwnd, hMenu, ptTest) > 0);			PaintScrollButton(hdc, &rcPaint, MENU_BUTTON_SCROLLUP, (scrollEnabled) ? 0 : MENU_BUTTON_STATE_DISABLED);		}	}	if (0 != (MENU_BUTTON_SCROLLDOWN & scrollButton))	{		rcPaint.top = rc.bottom - rcWindow.top;		rcPaint.bottom = (rcWindow.bottom - rcWindow.top) - MENU_BORDER_WIDTH;		if (rcPaint.bottom > rcPaint.top && rcPaint.right > rcPaint.left)		{			ptTest.y = rc.bottom - WASABI_API_APP->getScaleY(1);			INT last = MenuItemFromPoint(hwnd, hMenu, ptTest);			scrollEnabled = FALSE;			if (last >= 0)			{				INT count = GetMenuItemCount(hMenu);				if (last != (count - 1))					scrollEnabled = TRUE;			}			PaintScrollButton(hdc, &rcPaint, MENU_BUTTON_SCROLLDOWN, (scrollEnabled) ? 0 : MENU_BUTTON_STATE_DISABLED);		}	}	if (NULL != hdcOwned)		ReleaseDC(hwnd, hdcOwned);	return TRUE;}void SkinnedMenuWnd::DrawBorder(HDC hdc){	RECT rc, rcWindow, rp;	GetClientRect(hwnd, &rc);	GetWindowRect(hwnd, &rcWindow);	MapWindowPoints(hwnd, HWND_DESKTOP, (POINT*)&rc, 2);	OffsetRect(&rc, -rcWindow.left, -rcWindow.top);	OffsetRect(&rcWindow, -rcWindow.left, -rcWindow.top);	SkinnedWnd::DrawBorder(hdc, &rcWindow, BORDER_FLAT, GetBorderPen());	HBRUSH brushBk = SkinnedMenuWnd_GetBackBrush(hMenu);	SetRect(&rp, rcWindow.left + 1, rcWindow.top + 1, rc.left, rcWindow.bottom - 1); 	FillRect(hdc, &rp, brushBk);	SetRect(&rp, rc.left, rcWindow.top + 1, rc.right, rc.top);    FillRect(hdc, &rp, brushBk);	SetRect(&rp, rc.right, rcWindow.top + 1, rcWindow.right - 1, rcWindow.bottom - 1);    FillRect(hdc, &rp, brushBk);	SetRect(&rp, rc.left, rc.bottom, rc.right, rcWindow.bottom - 1);    FillRect(hdc, &rp, brushBk);	if ((rc.top - rcWindow.top) > MENU_BORDER_WIDTH || (rcWindow.bottom - rc.bottom) > MENU_BORDER_WIDTH)		DrawScrollButton(hdc, MENU_BUTTON_SCROLLUP | MENU_BUTTON_SCROLLDOWN);}BOOL SkinnedMenuWnd::IsSkinnedItem(UINT itemId){	if (NULL == skinnedItems)		return TRUE;	if (skinnedItemCursor >= skinnedItemCount)		skinnedItemCursor = 0;	INT start = skinnedItemCursor;	while(itemId != skinnedItems[skinnedItemCursor].itemId)	{		skinnedItemCursor++;		if (skinnedItemCursor == skinnedItemCount)			skinnedItemCursor = 0;		if (skinnedItemCursor == start)		{			skinnedItemCursor = 0;			return FALSE;		}	}	return skinnedItems[skinnedItemCursor].skinned;}static void SkinnedMenuWnd_DrawFrame(HDC hdc, const RECT *prc, INT width, COLORREF rgbFrame){		if (width > 0)	{		COLORREF rgbOld = SetBkColor(hdc, rgbFrame);			RECT rcPart;		SetRect(&rcPart, prc->left, prc->top, prc->right, prc->top + width); 		ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rcPart, NULL, 0, NULL);		SetRect(&rcPart, prc->left, prc->bottom - width, prc->right, prc->bottom); 		ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rcPart, NULL, 0, NULL);		SetRect(&rcPart, prc->left, prc->top + width, 	prc->left + width, prc->bottom - width); 		ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rcPart, NULL, 0, NULL);		SetRect(&rcPart, prc->right - width, prc->top + width, prc->right, prc->bottom - width); 		ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rcPart, NULL, 0, NULL);		if (rgbOld != rgbFrame)			SetBkColor(hdc, rgbOld);	}}BOOL SkinnedMenuWnd::OnReflectedDrawItem(DRAWITEMSTRUCT *pdis){	if (0 != (SMIF_BLOCKDRAW & menuFlags))	{		ExcludeClipRect(pdis->hDC, pdis->rcItem.left, pdis->rcItem.top, pdis->rcItem.right, pdis->rcItem.bottom);	}	if (!IsSkinnedItem(pdis->itemID))		return FALSE;	MENUITEMINFOW mii = {0};	wchar_t szText[256] = {0};	INT imageCX, imageCY, realIndex;	LONG imageTop;	mii.cbSize = sizeof(MENUITEMINFO);	mii.fMask = MIIM_STRING | MIIM_FTYPE | MIIM_STATE | MIIM_SUBMENU;	mii.cch = ARRAYSIZE(szText);	mii.dwTypeData = szText;	if (!GetMenuItemInfoW((HMENU)pdis->hwndItem, pdis->itemID, FALSE, &mii)) 		mii.cch = 0;	COLORREF rgbText, rgbTextBk, rgbTextFrame;	if (0 != (SMS_SYSCOLORS & menuExStyle))	{		INT foreIndex = (0 != (MFS_GRAYED & mii.fState)) ? COLOR_GRAYTEXT : COLOR_MENUTEXT;		INT backIndex = (0 != (ODS_SELECTED & pdis->itemState)) ? COLOR_HIGHLIGHT : COLOR_MENU;		rgbText = GetSysColor(foreIndex);		rgbTextBk = GetSysColor(backIndex);		rgbTextFrame = rgbTextBk;	}	else	{		MLGetSkinColor(MLSO_MENU, MP_BACKGROUND, (0 != (ODS_SELECTED & pdis->itemState)) ? MBS_SELECTED : MBS_NORMAL, &rgbTextBk);		MLGetSkinColor(MLSO_MENU, MP_TEXT, (0 != (MFS_GRAYED & mii.fState)) ? MTS_DISABLED : ((0 != (ODS_SELECTED & pdis->itemState)) ? MBS_SELECTED : MBS_NORMAL), &rgbText);		rgbTextFrame = rgbTextBk;		if (0 != (ODS_SELECTED & pdis->itemState))		{			MLGetSkinColor(MLSO_MENU, MP_BACKGROUND, MBS_SELECTEDFRAME, &rgbTextFrame);		}	}	COLORREF origText = SetTextColor(pdis->hDC, rgbText);	COLORREF origTextBk = SetBkColor(pdis->hDC, rgbTextBk);	if (0 != (MFT_MENUBARBREAK & mii.fType))	{		RECT rect;		if (FALSE != GetClientRect(hwnd, &rect))		{			COLORREF lineColor, prevColor;			HBRUSH brush = SkinnedMenuWnd_GetBackBrush(hMenu);			if(NULL == brush)				brush = GetSysColorBrush(COLOR_WINDOW);			rect.right = pdis->rcItem.left - WASABI_API_APP->getScaleX(1);			rect.left = pdis->rcItem.left - WASABI_API_APP->getScaleX(2);			FillRect(pdis->hDC, &rect, brush);			if (0 != (SMS_SYSCOLORS & menuExStyle) || 				FAILED(MLGetSkinColor(MLSO_MENU, MP_SEPARATOR, 0, &lineColor)))			{				lineColor = GetSysColor(COLOR_3DSHADOW);			}			prevColor = SetBkColor(pdis->hDC, lineColor);			OffsetRect(&rect, -1, 0);			ExtTextOut(pdis->hDC, 0, 0, ETO_OPAQUE, &rect, NULL, 0, NULL);			SetBkColor(pdis->hDC, prevColor);		}	}	if (NULL != customProc)	{		INT customResult  = customProc(MLMENU_ACTION_DRAWITEM, (HMENU)pdis->hwndItem, pdis->hDC, (LPARAM)pdis, customParam);		if (MLMENU_WANT_DRAWPART != customResult && FALSE != customResult)			return TRUE;	}	INT type = ((MFT_STRING | MFT_SEPARATOR) & mii.fType);	switch(type)	{		case MFT_STRING:			if (NULL == customProc ||				FALSE == customProc(MLMENU_ACTION_DRAWBACK, (HMENU)pdis->hwndItem, pdis->hDC, (LPARAM)pdis, customParam))			{				ExtTextOutW(pdis->hDC, 0, 0, ETO_OPAQUE, &pdis->rcItem, NULL, 0, NULL);				if (rgbTextFrame != rgbTextBk)				{					SkinnedMenuWnd_DrawFrame(pdis->hDC, &pdis->rcItem, 1, rgbTextFrame);				}			}			if (NULL == customProc ||				FALSE == customProc(MLMENU_ACTION_DRAWICON, (HMENU)pdis->hwndItem, pdis->hDC, (LPARAM)pdis, customParam))			{				if (hmlil)				{					if (MLImageListI_GetImageSize(hmlil, &imageCX, &imageCY))					{						imageTop = pdis->rcItem.top + (pdis->rcItem.bottom - pdis->rcItem.top - imageCY) / 2;						if (imageTop < pdis->rcItem.top) imageTop = pdis->rcItem.top;															INT index = MLImageListI_GetIndexFromTag(hmlil, pdis->itemID);						if (-1 != index)						{							HIMAGELIST himl = MLImageListI_GetRealList(hmlil);							realIndex = MLImageListI_GetRealIndex(hmlil, index, rgbTextBk, rgbText);							if (-1 != realIndex)							{								ImageList_Draw(himl, realIndex, pdis->hDC, pdis->rcItem.left + WASABI_API_APP->getScaleX(1) + (imageWidth - imageCX) / 2, imageTop, ILD_NORMAL);							}						}					}				}				else if ((MFS_CHECKED & mii.fState) && hmlilCheck)				{					if (0 != (MFT_RADIOCHECK & mii.fType))					{						if (-1 == imageRadioMark)							imageRadioMark = SkinnedMenuWnd_AddPngResource(hmlilCheck, IDB_MENU_RADIOMARK);					}					else					{						if (-1 == imageCheckMark)							imageCheckMark = SkinnedMenuWnd_AddPngResource(hmlilCheck, IDB_MENU_CHECKMARK);					}					if (MLImageListI_GetImageSize(hmlilCheck, &imageCX, &imageCY))					{							imageTop = pdis->rcItem.top + (pdis->rcItem.bottom - pdis->rcItem.top - imageCY) / 2;						if (imageTop < pdis->rcItem.top) imageTop = pdis->rcItem.top;						HIMAGELIST himl = MLImageListI_GetRealList(hmlilCheck);						realIndex = MLImageListI_GetRealIndex(hmlilCheck, (MFT_RADIOCHECK & mii.fType) ? imageRadioMark : imageCheckMark, rgbTextBk, rgbText);						if (-1 != realIndex)						{							ImageList_Draw(himl, realIndex, pdis->hDC, pdis->rcItem.left + WASABI_API_APP->getScaleX(1) + (imageWidth - imageCX) / 2, imageTop, ILD_NORMAL);						}					}				}			}			if (NULL != mii.hSubMenu && hmlilCheck) 			{				if (-1 == imageExpandArrow)					imageExpandArrow = SkinnedMenuWnd_AddPngResource(hmlilCheck, IDB_MENU_EXPANDARROW);				if (MLImageListI_GetImageSize(hmlilCheck, &imageCX, &imageCY))				{						imageTop = pdis->rcItem.top + (pdis->rcItem.bottom - pdis->rcItem.top - imageCY) / 2;					if (imageTop < pdis->rcItem.top) imageTop = pdis->rcItem.top;					HIMAGELIST himl = MLImageListI_GetRealList(hmlilCheck);					realIndex = MLImageListI_GetRealIndex(hmlilCheck, imageExpandArrow, rgbTextBk, rgbText);					if (-1 != realIndex)						ImageList_Draw(himl, realIndex, pdis->hDC, pdis->rcItem.right - imageCX - WASABI_API_APP->getScaleX(1), imageTop, ILD_NORMAL);				}			}			if (NULL == customProc ||				FALSE == customProc(MLMENU_ACTION_DRAWTEXT, (HMENU)pdis->hwndItem, pdis->hDC, (LPARAM)pdis, customParam))			{				if (mii.cch)				{					RECT rt;					CopyRect(&rt, &pdis->rcItem);					if (imageWidth && imageHeight) rt.left += imageWidth + WASABI_API_APP->getScaleX(6);					rt.right -= imageWidth;					HFONT hFont = GetMenuFont(FALSE);					HFONT originalFont = (NULL != hFont) ? (HFONT)SelectObject(pdis->hDC, hFont) : NULL;					INT originalBkMode = SetBkMode(pdis->hDC, TRANSPARENT);					UINT len = mii.cch;					if (len > 0)					{						while(--len > 0 && L'\t' != mii.dwTypeData[len]);						if (0 == len)								len = mii.cch;					}					BOOL showPrefix = FALSE;					if (!SystemParametersInfo(SPI_GETKEYBOARDCUES, 0, &showPrefix, 0))						showPrefix = FALSE;					if (!showPrefix && 0 == (ODS_NOACCEL & pdis->itemState))						showPrefix = TRUE;					UINT drawtextFlags = DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS | DT_NOCLIP;					if (!showPrefix)						drawtextFlags |= 0x000100000; /*DT_HIDEPREFIX*/					if (0 != (MFS_DEFAULT & mii.fState))					{						SetTextColor(pdis->hDC, BlendColors(rgbText, rgbTextBk, 110));						OffsetRect(&rt, 1,0);						DrawTextW(pdis->hDC, mii.dwTypeData, len, &rt, drawtextFlags);						OffsetRect(&rt, -1,0);						SetTextColor(pdis->hDC, rgbText);					}					DrawTextW(pdis->hDC, mii.dwTypeData, len, &rt, drawtextFlags);					if (mii.cch > (len + 1)) 					{						len++;						rt.left = rt.right - shortcutCX;						SetTextColor(pdis->hDC, BlendColors(rgbText, rgbTextBk, 192));						DrawTextW(pdis->hDC, mii.dwTypeData + len, mii.cch - len, &rt, DT_LEFT | DT_VCENTER | 0x000100000/*DT_HIDEPREFIX*/ | DT_SINGLELINE | DT_NOCLIP);					}					SelectObject(pdis->hDC, originalFont);					if (TRANSPARENT != originalBkMode)						SetBkMode(pdis->hDC, originalBkMode);				}			}			ExcludeClipRect(pdis->hDC, pdis->rcItem.left + WASABI_API_APP->getScaleX(23),							pdis->rcItem.top, pdis->rcItem.right, pdis->rcItem.bottom);			break;		case MFT_SEPARATOR:			{				COLORREF rgbSeparator;				HPEN hPen, originalPen;				INT y = (pdis->rcItem.top + (pdis->rcItem.bottom - pdis->rcItem.top) / 2);				if (0 != (SMS_SYSCOLORS & menuExStyle) || 					FAILED(MLGetSkinColor(MLSO_MENU, MP_SEPARATOR, 0, &rgbSeparator)))				{					rgbSeparator = GetSysColor(COLOR_3DSHADOW/*COLOR_GRAYTEXT*/);				}				hPen = CreatePen(PS_SOLID, 0, rgbSeparator);				originalPen = (HPEN)SelectObject(pdis->hDC, hPen);				ExtTextOutW(pdis->hDC, 0, 0, ETO_OPAQUE, &pdis->rcItem, NULL, 0, NULL);				MoveToEx(pdis->hDC, pdis->rcItem.left + WASABI_API_APP->getScaleX(23), y, NULL);				LineTo(pdis->hDC, pdis->rcItem.right, y);				SelectObject(pdis->hDC, originalPen);				DeleteObject(hPen);				// draws a edge on the separator so it looks more like the OS when trying to 'fake it'				if (0 != (SMS_SYSCOLORS & menuExStyle))				{					RECT bottomRect = pdis->rcItem;					HBRUSH brush = GetSysColorBrush(COLOR_3DHIGHLIGHT);										y += WASABI_API_APP->getScaleY(1);					bottomRect.top = y;					bottomRect.bottom = y + WASABI_API_APP->getScaleY(1);					FillRect(pdis->hDC,&bottomRect, brush);				}			}			ExcludeClipRect(pdis->hDC, pdis->rcItem.left + WASABI_API_APP->getScaleX(23),							pdis->rcItem.top, pdis->rcItem.right, pdis->rcItem.bottom);			break;	}	{		COLORREF rgbSeparator;		if (0 != (SMS_SYSCOLORS & menuExStyle) || 			FAILED(MLGetSkinColor(MLSO_MENU, MP_SEPARATOR, 0, &rgbSeparator)))		{			rgbSeparator = GetSysColor(COLOR_3DSHADOW/*COLOR_GRAYTEXT*/);		}		HPEN hPen = CreatePen(PS_SOLID, 0, rgbSeparator);		HPEN originalPen = (HPEN)SelectObject(pdis->hDC, hPen);		MoveToEx(pdis->hDC, pdis->rcItem.left + WASABI_API_APP->getScaleX(22), pdis->rcItem.top, NULL);		LineTo(pdis->hDC, pdis->rcItem.left + WASABI_API_APP->getScaleX(22), pdis->rcItem.top + (pdis->rcItem.bottom - pdis->rcItem.top));		SelectObject(pdis->hDC, originalPen);		DeleteObject(hPen);	}	if (origText != rgbText)		SetTextColor(pdis->hDC, origText);	if (origTextBk != rgbTextBk)		SetBkColor(pdis->hDC, origTextBk);	return TRUE;}BOOL SkinnedMenuWnd::OnReflectedMeasureItem(MEASUREITEMSTRUCT *pmis){	pmis->itemHeight = lineHeight;	pmis->itemWidth = lineWidth;	if (!IsSkinnedItem(pmis->itemID))		return FALSE;	HDC hdc = GetDCEx(hwnd, NULL, DCX_CACHE);	if (NULL == hdc) return FALSE;	MENUITEMINFOW mii = {0};	wchar_t szText[128] = {0};	mii.cbSize = sizeof(MENUITEMINFO);	mii.fMask = MIIM_STRING | MIIM_FTYPE | MIIM_STATE;	mii.cch = ARRAYSIZE(szText);	mii.dwTypeData = szText;	if (!GetMenuItemInfoW(hMenu, pmis->itemID, FALSE, &mii))		mii.cch = 0;	HFONT originalFont = (HFONT)SelectObject(hdc, GetMenuFont(0 != (MFS_DEFAULT & mii.fState)));	if (NULL == customProc ||		FALSE == customProc(MLMENU_ACTION_MEASUREITEM, hMenu, hdc, (LPARAM)pmis, customParam))	{		if (0 == lineWidth || 0 == lineHeight)		{						INT type = ((MFT_STRING | MFT_SEPARATOR) & mii.fType);			switch(type)			{				case MFT_STRING:					if (mii.cch != 0)					{						SIZE sz;						UINT len = mii.cch;						while(--len > 0 && L'\t' != mii.dwTypeData[len]);						if (0 == len) len = mii.cch;						if (len != mii.cch)						{							szText[len] = L' ';							if (GetTextExtentPoint32W(hdc, szText + len, mii.cch - len, &sz) &&								shortcutCX < sz.cx)							{								shortcutCX = sz.cx;							}						}						if (GetTextExtentPoint32W(hdc, szText, len, &sz))						{							if (textCX <= sz.cx) 								textCX = sz.cx;							if (lineHeight < sz.cy) 								pmis->itemHeight = sz.cy + WASABI_API_APP->getScaleY(2);														if (0 == lineWidth)								pmis->itemWidth = textCX + shortcutCX + 8;						}					}					if(imageHeight > (INT)(pmis->itemHeight + WASABI_API_APP->getScaleY(2))) pmis->itemHeight = imageHeight + WASABI_API_APP->getScaleY(2);					if (0 == lineWidth && imageWidth) pmis->itemWidth += imageWidth;					pmis->itemWidth -= (GetSystemMetrics(SM_CXMENUCHECK) - imageWidth - WASABI_API_APP->getScaleX(36));					break;				case MFT_SEPARATOR:					pmis->itemHeight = WASABI_API_APP->getScaleY(7);					break;			}		}	}	SelectObject(hdc, originalFont);	ReleaseDC(hwnd, hdc);	return TRUE;}void SkinnedMenuWnd::OnNcPaint(HRGN rgnUpdate){	if (0 != (SMIF_BLOCKDRAW & menuFlags))		return;	UINT flags = DCX_PARENTCLIP | DCX_WINDOW | DCX_CLIPSIBLINGS |				 DCX_INTERSECTUPDATE | DCX_VALIDATE;	HDC hdc = GetDCEx(hwnd, ((HRGN)NULLREGION != rgnUpdate) ? rgnUpdate : NULL, flags);	if (NULL == hdc) 		return;	DrawBorder(hdc);	ReleaseDC(hwnd, hdc);}LRESULT SkinnedMenuWnd::OnEraseBackground(HDC hdc){	HBRUSH brush;	brush = SkinnedMenuWnd_GetBackBrush(hMenu);	if (NULL != brush)	{		RECT rect;		if (FALSE != GetClientRect(hwnd, &rect) && 			FALSE != FillRect(hdc, &rect, brush))		{			return 1;		}	}	return __super::WindowProc(WM_ERASEBKGND, (WPARAM)hdc, 0L);}void SkinnedMenuWnd::OnPrint(HDC hdc, UINT options){	if (0 != (PRF_CHECKVISIBLE & options))	{		DWORD windowStyle = GetWindowLongPtr(hwnd, GWL_STYLE);		if (0 == (WS_VISIBLE & windowStyle)) 		{			return;		}	}	if (0 != (PRF_NONCLIENT & options))	{		DrawBorder(hdc);	}	if (0 == ((PRF_ERASEBKGND | PRF_CLIENT) & options))	{		return;	}	POINT ptOrig;	RECT rc, rcWindow;	if (GetClientRect(hwnd, &rc) &&		GetWindowRect(hwnd, &rcWindow))	{		MapWindowPoints(hwnd, HWND_DESKTOP, (POINT*)&rc, 2);	}	else	{		SetRectEmpty(&rc);		SetRectEmpty(&rcWindow);	}	INT  clipRegionCode;	HRGN clipRegion = CreateRectRgn(0, 0, 0, 0);	clipRegionCode = (NULL != clipRegion) ? GetClipRgn(hdc, clipRegion) : -1;	OffsetViewportOrgEx(hdc, rc.left - rcWindow.left, rc.top - rcWindow.top, &ptOrig);	if (-1 != clipRegionCode)	{		IntersectClipRect(hdc, 0, 0, rc.right - rc.left, rc.bottom - rc.top);		}	OffsetRect(&rc, -rc.left, -rc.top);	if (0 != (PRF_ERASEBKGND & options))	{		MENUINFO mi = {0};		mi.cbSize = sizeof(MENUINFO);		mi.fMask = MIM_BACKGROUND;		HBRUSH brushBk = NULL; 		if (GetMenuInfo(hMenu, &mi) && mi.hbrBack)			brushBk = mi.hbrBack;		if (NULL == brushBk)			brushBk = GetSysColorBrush(COLOR_WINDOW);		FillRect(hdc, &rc, brushBk);	}	if (0 != (PRF_CLIENT & options))	{		menuFlags &= ~SMIF_BLOCKDRAW;		SendMessage(hwnd, WM_PRINTCLIENT, (WPARAM)hdc, (LPARAM)(~(PRF_NONCLIENT | PRF_ERASEBKGND) & options));		menuFlags |= SMIF_BLOCKDRAW;	}	if (-1 != clipRegionCode)	{		SelectClipRgn(hdc, (0 != clipRegionCode) ? clipRegion : NULL);	}	if (NULL != clipRegion)		DeleteObject(clipRegion);		SetViewportOrgEx(hdc, ptOrig.x, ptOrig.y, NULL);	SetTimer(hwnd, MTID_EX_UNBLOCKDRAW, 250, NULL);}LRESULT SkinnedMenuWnd::OnMenuSelect(UINT selectedItem){	if (((UINT)-1) != selectedItem)		menuFlags &= ~SMIF_BLOCKDRAW;	UINT updateScroll = 0;	if (MHF_SCROLLUP == prevSelectedItem) 		updateScroll |= MENU_BUTTON_SCROLLUP;	else if (MHF_SCROLLDOWN == prevSelectedItem)		updateScroll |= MENU_BUTTON_SCROLLDOWN;	switch(selectedItem)	{		case MHF_SCROLLUP:			updateScroll |= MENU_BUTTON_SCROLLUP;			break;		case MHF_SCROLLDOWN:			updateScroll |= MENU_BUTTON_SCROLLDOWN; 			break;	}	RECT rc;	GetClientRect(hwnd, &rc);	MapWindowPoints(hwnd, HWND_DESKTOP, (POINT*)&rc, 2);	rc.top += WASABI_API_APP->getScaleY(1);	INT item = MenuItemFromPoint(hwnd, hMenu, *((POINT*)&rc));	LRESULT result;	BOOL fInvalidate = FALSE;	if (0 !=  updateScroll)	{		DWORD windowStyle = GetWindowLongPtr(hwnd, GWL_STYLE);		SetWindowLongPtr(hwnd, GWL_STYLE, windowStyle & ~WS_VISIBLE);		result = __super::WindowProc(MN_SELECTITEM, selectedItem, 0L);		SetWindowLongPtr(hwnd, GWL_STYLE, windowStyle);		if (MenuItemFromPoint(hwnd, hMenu, *((POINT*)&rc)) != item)		{			updateScroll = MENU_BUTTON_SCROLLUP | MENU_BUTTON_SCROLLDOWN;			fInvalidate = TRUE;		}	}	else	{		result = __super::WindowProc(MN_SELECTITEM, selectedItem, 0L);	}	prevSelectedItem = selectedItem;	if (0 != updateScroll)	{		DrawScrollButton(NULL, updateScroll);		if (FALSE != fInvalidate)		{			InvalidateRect(hwnd, NULL, FALSE);		}	}	return result;}LRESULT SkinnedMenuWnd::CallHookedWindowProc(UINT uItem, BOOL fByPosition, UINT uMsg, WPARAM wParam, LPARAM lParam){	MENUITEMINFOW mii = {0};	mii.cbSize = sizeof(mii);	mii.fMask = MIIM_SUBMENU;		if (FALSE != GetMenuItemInfoW(hMenu, uItem, fByPosition, &mii) && 		NULL != mii.hSubMenu)	{		SkinnedMenu sm;		sm.InitializeHook(NULL, (menuExStyle & ~SMS_FORCEWIDTH), hmlil, 0, customProc, customParam);		return __super::WindowProc(uMsg, wParam, lParam);	}		return __super::WindowProc(uMsg, wParam, lParam);}INT SkinnedMenuWnd::FindHiliteItem(HMENU hMenu){	MENUITEMINFOW mii = {0};	mii.cbSize = sizeof(MENUITEMINFOW);	mii.fMask = MIIM_STATE;	INT count = GetMenuItemCount(hMenu);	for (INT i = 0; i < count; i++)	{		if (0 != GetMenuItemInfoW(hMenu, i, TRUE, &mii))		{			if (MFS_HILITE == ((MFS_HILITE | MFS_DISABLED | MFS_GRAYED) & mii.fState))				return i;		}	}	return -1;}LRESULT SkinnedMenuWnd::WindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam){	switch(uMsg)	{		case WM_ERASEBKGND:			return OnEraseBackground((HDC)wParam);		case REFLECTED_DRAWITEM: 			if (OnReflectedDrawItem((DRAWITEMSTRUCT*)((REFLECTPARAM*)lParam)->lParam))			{				((REFLECTPARAM*)lParam)->result = TRUE; 				return TRUE;			}			break;		case REFLECTED_MEASUREITEM:			if (OnReflectedMeasureItem((MEASUREITEMSTRUCT*)((REFLECTPARAM*)lParam)->lParam))			{				((REFLECTPARAM*)lParam)->result = TRUE; 				return TRUE;			}			break;		case MN_SIZEWINDOW:			{				BOOL validateOwner = FALSE;				if (NULL == hMenu) 				{					textCX = 0;					shortcutCX = 0;					HMENU menuToAttach = (HMENU)SendMessageW(hwnd, MN_GETHMENU, 0, 0L);					if (FALSE != AttachMenu(menuToAttach))						validateOwner = TRUE;				}				if (NULL != threadInfo)				{					threadInfo->SetActiveMeasureMenu(hMenu);					if (FALSE != validateOwner &&						FALSE == threadInfo->SetValidationHook(this))					{						validateOwner = FALSE;					}				}				LRESULT result = __super::WindowProc(uMsg, wParam, lParam);				if (NULL != threadInfo)				{					threadInfo->SetActiveMeasureMenu(NULL);					if (FALSE != validateOwner)						threadInfo->RemoveValidationHook(this);				}				return result;			}			break;		case MN_SELECTITEM:			return OnMenuSelect((UINT)wParam);		case MN_LBUTTONDBLCLK:		case MN_LBUTTONDOWN:		case MN_LBUTTONUP:			menuFlags &= ~SMIF_BLOCKDRAW;			switch(wParam)			{				case MHF_SCROLLUP:				case MHF_SCROLLDOWN:					{						LRESULT result = __super::WindowProc(uMsg, wParam, lParam);						DrawScrollButton(NULL, MENU_BUTTON_SCROLLDOWN | MENU_BUTTON_SCROLLUP);						return result;					}					break;				default:					if (wParam >= 0)					{						return CallHookedWindowProc((UINT)wParam, TRUE, uMsg, wParam, lParam);					}					break;			}			break;		case WM_TIMER:			switch(wParam)			{				case MTID_OPENSUBMENU:					{												POINT pt;						INT iItem;						if (GetCursorPos(&pt) && 							-1 != (iItem = MenuItemFromPoint(NULL, hMenu, pt)))						{							CallHookedWindowProc(iItem, TRUE, uMsg, wParam, lParam);							return 0;						}					}					break;				case MHF_SCROLLUP:				case MHF_SCROLLDOWN:					__super::WindowProc(uMsg, wParam, lParam);					DrawScrollButton(NULL, MENU_BUTTON_SCROLLDOWN | MENU_BUTTON_SCROLLUP);					return 0;				case MTID_EX_UNBLOCKDRAW:					KillTimer(hwnd, wParam);					menuFlags &= ~SMIF_BLOCKDRAW;					return 0;			}			break;		case WM_KEYDOWN:			menuFlags &= ~SMIF_BLOCKDRAW;			switch(wParam)			{				case VK_RETURN:				case VK_RIGHT:					{						INT iItem = FindHiliteItem(hMenu);						if (-1 != iItem)							return CallHookedWindowProc(iItem, TRUE, uMsg, wParam, lParam);					}					break;				case VK_UP:					{						RECT rc;						GetClientRect(hwnd, &rc);						MapWindowPoints(hwnd, HWND_DESKTOP, (POINT*)&rc, 2);						rc.top += 1;						INT iItem = MenuItemFromPoint(hwnd, hMenu, *((POINT*)&rc));						if (iItem >= 0)						{							MENUITEMINFOW mii = {0};							mii.cbSize = sizeof(MENUITEMINFOW);							mii.fMask = MIIM_STATE;							if (GetMenuItemInfoW(hMenu, iItem, TRUE, &mii) && 								0 != (MFS_HILITE & mii.fState))							{								DWORD windowStyle = GetWindowLongPtr(hwnd, GWL_STYLE);								if (0 != (WS_VISIBLE & windowStyle))									SetWindowLongPtr(hwnd, GWL_STYLE, windowStyle & ~WS_VISIBLE);									__super::WindowProc(uMsg, wParam, lParam);									if (0 != (WS_VISIBLE & windowStyle))								{									windowStyle = GetWindowLongPtr(hwnd, GWL_STYLE);									if (0 == (WS_VISIBLE & windowStyle))									{										windowStyle |= WS_VISIBLE;										SetWindowLongPtr(hwnd, GWL_STYLE, windowStyle);									}									INT iNew = MenuItemFromPoint(hwnd, hMenu, *((POINT*)&rc));									if (iNew != iItem)									{										DrawScrollButton(NULL, MENU_BUTTON_SCROLLUP | MENU_BUTTON_SCROLLDOWN);										InvalidateRect(hwnd, NULL, FALSE);									}									else									{										int iHilite = GetMenuItemCount(hMenu);										while(0 < iHilite--)										{											if (FALSE != GetMenuItemInfoW(hMenu, iHilite, TRUE, &mii) && 												0 != (MFS_HILITE & mii.fState))											{												break;											}										}										if (FALSE != GetMenuItemRect(hwnd, hMenu, iItem, &rc))										{											MapWindowPoints(HWND_DESKTOP, hwnd, (POINT*)&rc, 2);											InvalidateRect(hwnd, &rc, FALSE);										}										if (iHilite != iItem && 											FALSE != GetMenuItemRect(hwnd, hMenu, iHilite, &rc))										{											MapWindowPoints(HWND_DESKTOP, hwnd, (POINT*)&rc, 2);											InvalidateRect(hwnd, &rc, FALSE);										}									}								}								return 0;															}						}					}					break;				case VK_DOWN:					{						RECT rc;						GetClientRect(hwnd, &rc);						MapWindowPoints(hwnd, HWND_DESKTOP, (POINT*)&rc, 2);						rc.top = rc.bottom - 1;						INT item = MenuItemFromPoint(hwnd, hMenu, *((POINT*)&rc));						if (item >= 0)						{							MENUITEMINFOW mii = {0};							mii.cbSize = sizeof(MENUITEMINFOW);							mii.fMask = MIIM_STATE;							if (GetMenuItemInfoW(hMenu, item, TRUE, &mii) && 								MFS_HILITE == ((MFS_HILITE | MFS_DISABLED | MFS_GRAYED) & mii.fState))							{								DWORD windowStyle = GetWindowLongPtr(hwnd, GWL_STYLE);								SetWindowLongPtr(hwnd, GWL_STYLE, windowStyle & ~WS_VISIBLE);								__super::WindowProc(uMsg, wParam, lParam);								SetWindowLongPtr(hwnd, GWL_STYLE, windowStyle);								INT iNew = MenuItemFromPoint(hwnd, hMenu, *((POINT*)&rc));								if (iNew != item)								{									DrawScrollButton(NULL, MENU_BUTTON_SCROLLUP | MENU_BUTTON_SCROLLDOWN);									InvalidateRect(hwnd, NULL, FALSE);								}								return 0;															}						}					}					break;			}			break;	}	return __super::WindowProc(uMsg, wParam, lParam);}
 |