123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468 |
- #include "main.h"
- #include "./skinnedMenuThreadInfo.h"
- #include "./skinnedMenu.h"
- #include "./skinnedMenuWnd.h"
- #ifndef _DEBUG
- #include <new>
- #endif
- static DWORD tlsIndex = TLS_OUT_OF_INDEXES;
- size_t ref;
- HHOOK attachHook;
- SkinnedMenu *attachMenu;
- HHOOK validationHook;
- SkinnedMenuWnd *validationWindow;
- khash_t(intptr_map) *windowMap;
- khash_t(int_set) *claimedIdSet;
- unsigned int lastAssignedId;
- HMENU activeMeasureMenu;
- SkinnedMenuThreadInfo::SkinnedMenuThreadInfo()
- : ref(1), attachHook(NULL), attachMenu(NULL), validationHook(NULL),
- validationWindow(NULL), lastAssignedId((unsigned int)-100),
- activeMeasureMenu(NULL)
- {
- windowMap = kh_init(intptr_map);
- claimedIdSet = kh_init(int_set);
- }
- SkinnedMenuThreadInfo::~SkinnedMenuThreadInfo()
- {
- if (TLS_OUT_OF_INDEXES != tlsIndex)
- TlsSetValue(tlsIndex, NULL);
- if (NULL != attachHook)
- {
- UnhookWindowsHookEx(attachHook);
- attachHook = NULL;
- }
- if (NULL != validationHook)
- {
- UnhookWindowsHookEx(validationHook);
- validationHook = NULL;
- }
- if (NULL != windowMap)
- kh_destroy(intptr_map, windowMap);
- if (NULL != claimedIdSet)
- kh_destroy(int_set, claimedIdSet);
- }
- HRESULT SkinnedMenuThreadInfo::GetInstance(BOOL allowCreate, SkinnedMenuThreadInfo **instance)
- {
- HRESULT hr;
- SkinnedMenuThreadInfo *self;
- if (NULL == instance)
- return E_POINTER;
- *instance = NULL;
- if (TLS_OUT_OF_INDEXES == tlsIndex)
- {
- tlsIndex = TlsAlloc();
- if (TLS_OUT_OF_INDEXES == tlsIndex)
- return E_OUTOFMEMORY;
- self = NULL;
- if (FALSE != TlsSetValue(tlsIndex, NULL))
- SetLastError(ERROR_SUCCESS);
- }
- else
- {
- self = (SkinnedMenuThreadInfo*)TlsGetValue(tlsIndex);
- }
- if (NULL == self)
- {
- unsigned long errorCode;
- errorCode = GetLastError();
- if (ERROR_SUCCESS != errorCode)
- {
- hr = HRESULT_FROM_WIN32(errorCode);
- }
- else
- {
- if (FALSE == allowCreate)
- {
- self = NULL;
- hr = S_FALSE;
- }
- else
- {
- #ifndef _DEBUG
- self = new (std::nothrow) SkinnedMenuThreadInfo();
- #else
- self = new SkinnedMenuThreadInfo();
- #endif
- if (NULL == self)
- hr = E_OUTOFMEMORY;
- else
- {
- if (FALSE == TlsSetValue(tlsIndex, self))
- {
- errorCode = GetLastError();
- hr = HRESULT_FROM_WIN32(errorCode);
- self->Release();
- self = NULL;
- }
- else
- {
- hr = S_OK;
- }
- }
- }
- }
- }
- else
- {
- self->AddRef();
- hr = S_OK;
- }
- *instance = self;
- return hr;
- }
- size_t SkinnedMenuThreadInfo::AddRef()
- {
- return InterlockedIncrement((LONG*)&ref);
- }
- size_t SkinnedMenuThreadInfo::Release()
- {
- if (0 == ref)
- return ref;
-
- LONG r = InterlockedDecrement((LONG*)&ref);
- if (0 == r)
- delete(this);
-
- return r;
- }
- BOOL SkinnedMenuThreadInfo::SetAttachHook(SkinnedMenu *menu)
- {
- if (NULL == menu)
- return FALSE;
- if (NULL != attachHook)
- return FALSE;
- attachMenu = menu;
- attachHook = SetWindowsHookEx(WH_CALLWNDPROC, SkinnedMenuThreadInfo_AttachHookCb, NULL, GetCurrentThreadId());
- if (NULL == attachHook)
- {
- attachMenu = FALSE;
- return FALSE;
- }
- return TRUE;
- }
- BOOL SkinnedMenuThreadInfo::RemoveAttachHook(SkinnedMenu *menu)
- {
- if (NULL == attachHook)
- return FALSE;
- if (menu != attachMenu)
- return FALSE;
- UnhookWindowsHookEx(attachHook);
- attachHook = NULL;
- attachMenu = NULL;
-
- return TRUE;
- }
- BOOL SkinnedMenuThreadInfo::IsAttachHookActive()
- {
- return (NULL != attachHook);
- }
- LRESULT SkinnedMenuThreadInfo::AttachHook(int nCode, WPARAM wParam, LPARAM lParam)
- {
- if (HC_ACTION == nCode)
- {
- CWPSTRUCT *pcwp = (CWPSTRUCT*)lParam;
- if (WM_NCCREATE == pcwp->message)
- {
- wchar_t szName[128] = {0};
- if (GetClassNameW(pcwp->hwnd, szName, ARRAYSIZE(szName)) &&
- CSTR_EQUAL == CompareStringW(CSTR_INVARIANT, NORM_IGNORECASE, szName, -1, L"#32768", -1))
- {
- LRESULT result;
- HHOOK hookCopy;
- SkinnedMenu *menuCopy;
- menuCopy = attachMenu;
- hookCopy = attachHook;
- attachHook = NULL;
- attachMenu = NULL;
- result = CallNextHookEx(hookCopy, nCode, wParam, lParam);
- UnhookWindowsHookEx(hookCopy);
-
- if (NULL != menuCopy)
- menuCopy->AttachToHwnd(pcwp->hwnd);
-
- return result;
- }
- }
- }
- return CallNextHookEx(attachHook, nCode, wParam, lParam);
- }
- BOOL SkinnedMenuThreadInfo::SetValidationHook(SkinnedMenuWnd *window)
- {
- HMENU prevMenu;
- if (NULL == window)
- return FALSE;
- if (NULL != validationHook)
- return FALSE;
- validationWindow = window;
- prevMenu = SetActiveMeasureMenu(window->GetMenuHandle());
- validationHook = SetWindowsHookEx(WH_CALLWNDPROC, SkinnedMenuThreadInfo_ValidationHookCb, NULL, GetCurrentThreadId());
- if (NULL == validationHook)
- {
- validationWindow = FALSE;
- SetActiveMeasureMenu(prevMenu);
- return FALSE;
- }
-
- return TRUE;
- }
- BOOL SkinnedMenuThreadInfo::RemoveValidationHook(SkinnedMenuWnd *window)
- {
- if (NULL == validationHook)
- return FALSE;
- if (window != validationWindow)
- return FALSE;
- UnhookWindowsHookEx(validationHook);
- validationWindow = NULL;
- validationHook = NULL;
-
- return TRUE;
- }
- BOOL SkinnedMenuThreadInfo::IsValidationHookActive()
- {
- return (NULL != validationHook);
- }
- LRESULT SkinnedMenuThreadInfo::ValidationHook(int nCode, WPARAM wParam, LPARAM lParam)
- {
- if (HC_ACTION == nCode)
- {
- CWPSTRUCT *pcwp = (CWPSTRUCT*)lParam;
- if (WM_MEASUREITEM == pcwp->message ||
- WM_DRAWITEM == pcwp->message)
- {
- if (NULL != validationWindow && NULL != pcwp->lParam)
- {
- BOOL validationCompleted(FALSE);
- if (WM_MEASUREITEM == pcwp->message)
- {
- MEASUREITEMSTRUCT *measureItem;
- measureItem = (MEASUREITEMSTRUCT*)pcwp->lParam;
- if (ODT_MENU == measureItem->CtlType &&
- validationWindow->GetMenuHandle() == GetActiveMeasureMenu())
- {
- validationCompleted = TRUE;
- }
- }
- else
- {
- DRAWITEMSTRUCT *drawItem;
- drawItem = (DRAWITEMSTRUCT*)pcwp->lParam;
- if (ODT_MENU == drawItem->CtlType &&
- validationWindow->GetMenuHandle() == (HMENU)drawItem->hwndItem)
- {
- validationCompleted = TRUE;
- }
- }
-
- if (FALSE != validationCompleted)
- {
- LRESULT result;
- HHOOK hookCopy;
- SkinnedMenuWnd *windowCopy;
- windowCopy = validationWindow;
- hookCopy = validationHook;
- validationHook = NULL;
- validationWindow = NULL;
- if (NULL != windowCopy && windowCopy->GetOwnerWindow() != pcwp->hwnd)
- {
- windowCopy->SetOwnerWindow(pcwp->hwnd);
- }
- result = CallNextHookEx(hookCopy, nCode, wParam, lParam);
- UnhookWindowsHookEx(hookCopy);
-
- return result;
- }
- }
- }
- }
- return CallNextHookEx(attachHook, nCode, wParam, lParam);
- }
- BOOL SkinnedMenuThreadInfo::RegisterMenu(HMENU menu, HWND window)
- {
- int code;
- khint_t key;
- if (NULL == menu)
- return FALSE;
- if (NULL == windowMap)
- return FALSE;
- key = kh_put(intptr_map, windowMap, (intptr_t)menu, &code);
- kh_val(windowMap, key) = window;
-
- return TRUE;
- }
- BOOL SkinnedMenuThreadInfo::UnregisterMenu(HMENU menu)
- {
- khint_t key;
- if (NULL == menu)
- return FALSE;
- if (NULL == windowMap)
- return FALSE;
-
- key = kh_get(intptr_map, windowMap, (intptr_t)menu);
- if (kh_end(windowMap) == key)
- return FALSE;
- kh_del(intptr_map, windowMap, key);
- return TRUE;
- }
- HWND SkinnedMenuThreadInfo::FindMenuWindow(HMENU menu)
- {
- khint_t key;
- if (NULL == menu)
- return NULL;
- if (NULL == windowMap)
- return NULL;
-
- key = kh_get(intptr_map, windowMap, (intptr_t)menu);
- if (kh_end(windowMap) == key)
- return NULL;
- return kh_val(windowMap, key);
- }
- void SkinnedMenuThreadInfo::ClaimId(unsigned int id)
- {
- int code;
- kh_put(int_set, claimedIdSet, id, &code);
- }
- void SkinnedMenuThreadInfo::ReleaseId(unsigned int id)
- {
- khint_t key;
- key = kh_get(int_set, claimedIdSet, id);
- if (kh_end(claimedIdSet) != key)
- kh_del(int_set, claimedIdSet, key);
- }
- unsigned int SkinnedMenuThreadInfo::GetAvailableId()
- {
- khint_t key;
- unsigned int originalId;
-
- lastAssignedId--;
- if ((unsigned int)-1 == lastAssignedId)
- lastAssignedId--;
- originalId = lastAssignedId;
- for(;;)
- {
- key = kh_get(int_set, claimedIdSet, lastAssignedId);
- if (kh_end(claimedIdSet) == key)
- return lastAssignedId;
- lastAssignedId--;
- if ((unsigned int)-1 == lastAssignedId)
- lastAssignedId--;
- if (lastAssignedId == originalId)
- break;
- }
- return (unsigned int)-1;
- }
- HMENU SkinnedMenuThreadInfo::SetActiveMeasureMenu(HMENU menu)
- {
- HMENU prevMenu;
- prevMenu = activeMeasureMenu;
- activeMeasureMenu = menu;
- return prevMenu;
- }
- HMENU SkinnedMenuThreadInfo::GetActiveMeasureMenu()
- {
- return activeMeasureMenu;
- }
- static LRESULT CALLBACK SkinnedMenuThreadInfo_AttachHookCb(int nCode, WPARAM wParam, LPARAM lParam)
- {
- LRESULT result;
- SkinnedMenuThreadInfo *self;
- if (S_OK != SkinnedMenuThreadInfo::GetInstance(FALSE, &self))
- return 0;
- result = self->AttachHook(nCode, wParam, lParam);
- self->Release();
- return result;
- }
- static LRESULT CALLBACK SkinnedMenuThreadInfo_ValidationHookCb(int nCode, WPARAM wParam, LPARAM lParam)
- {
- LRESULT result;
- SkinnedMenuThreadInfo *self;
- if (S_OK != SkinnedMenuThreadInfo::GetInstance(FALSE, &self))
- return 0;
- result = self->ValidationHook(nCode, wParam, lParam);
- self->Release();
- return result;
- }
|