You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
679 lines
16 KiB
679 lines
16 KiB
//
|
|
// lbmenu.cpp
|
|
//
|
|
|
|
#include "private.h"
|
|
#include "candmenu.h"
|
|
#include "cuimenu.h"
|
|
#include "globals.h"
|
|
#include "candutil.h"
|
|
#include "wcand.h"
|
|
|
|
|
|
//
|
|
//
|
|
//
|
|
|
|
#define g_dwMenuStyle UIWINDOW_TOPMOST | UIWINDOW_TOOLWINDOW | UIWINDOW_OFC10MENU | UIWINDOW_HASSHADOW
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CCandMenuItem
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
/* C C A N D M E N U I T E M */
|
|
/*------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
------------------------------------------------------------------------------*/
|
|
CCandMenuItem::CCandMenuItem( CCandMenu *pCandMenu )
|
|
{
|
|
m_pCandMenu = pCandMenu;
|
|
}
|
|
|
|
|
|
/* ~ C C A N D M E N U I T E M */
|
|
/*------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
------------------------------------------------------------------------------*/
|
|
CCandMenuItem::~CCandMenuItem( void )
|
|
{
|
|
}
|
|
|
|
|
|
/* I N S E R T T O U I */
|
|
/*------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
------------------------------------------------------------------------------*/
|
|
BOOL CCandMenuItem::InsertToUI( CUIFMenu *pCuiMenu )
|
|
{
|
|
UINT uFlags = MF_BYPOSITION;
|
|
|
|
if (_dwFlags & TF_LBMENUF_SEPARATOR) {
|
|
uFlags |= MF_SEPARATOR;
|
|
pCuiMenu->InsertSeparator();
|
|
return TRUE;
|
|
}
|
|
|
|
if (_dwFlags & TF_LBMENUF_SUBMENU) {
|
|
Assert(m_pCandMenu);
|
|
CUIFMenu *pCuiMenuSub = ((CCandMenu *)_pSubMenu)->CreateMenuUI( TRUE /* sub menu */ );
|
|
|
|
CUIFMenuItem *pCuiItem = new CUIFMenuItem(pCuiMenu);
|
|
if (!pCuiItem) {
|
|
return FALSE;
|
|
}
|
|
|
|
pCuiItem->Initialize();
|
|
pCuiItem->Init((UINT)-1, _bstr);
|
|
pCuiItem->SetSub(pCuiMenuSub);
|
|
|
|
if (_hbmp) {
|
|
pCuiItem->SetBitmap(_hbmp);
|
|
}
|
|
|
|
if (_hbmpMask) {
|
|
pCuiItem->SetBitmapMask(_hbmpMask);
|
|
}
|
|
|
|
pCuiMenu->InsertItem(pCuiItem);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
CUIFMenuItem *pCuiItem = new CUIFMenuItem(pCuiMenu);
|
|
if (!pCuiItem) {
|
|
return FALSE;
|
|
}
|
|
|
|
pCuiItem->Initialize();
|
|
pCuiItem->Init(_uId, _bstr);
|
|
|
|
if (_dwFlags & TF_LBMENUF_GRAYED) {
|
|
pCuiItem->Gray(TRUE);
|
|
}
|
|
|
|
if (_dwFlags & TF_LBMENUF_CHECKED) {
|
|
pCuiItem->Check(TRUE);
|
|
}
|
|
else if (_dwFlags & TF_LBMENUF_RADIOCHECKED) {
|
|
pCuiItem->RadioCheck(TRUE);
|
|
}
|
|
|
|
if (_hbmp) {
|
|
pCuiItem->SetBitmap(_hbmp);
|
|
}
|
|
|
|
if (_hbmpMask) {
|
|
pCuiItem->SetBitmapMask(_hbmpMask);
|
|
}
|
|
|
|
pCuiMenu->InsertItem(pCuiItem);
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CCandMenu
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
/* C C A N D M E N U */
|
|
/*------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
------------------------------------------------------------------------------*/
|
|
CCandMenu::CCandMenu( HINSTANCE hInst )
|
|
{
|
|
NONCLIENTMETRICS ncm;
|
|
|
|
m_hInst = hInst;
|
|
m_pCUIMenu = NULL;
|
|
memset( &m_lf, 0, sizeof(m_lf) );
|
|
m_pCandWnd = NULL;
|
|
|
|
ncm.cbSize = sizeof(ncm);
|
|
if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &ncm, FALSE)) {
|
|
ConvertLogFontAtoW( &ncm.lfMenuFont, &m_lf );
|
|
}
|
|
}
|
|
|
|
|
|
/* ~ C C A N D M E N U */
|
|
/*------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
------------------------------------------------------------------------------*/
|
|
CCandMenu::~CCandMenu()
|
|
{
|
|
}
|
|
|
|
|
|
/* A D D R E F */
|
|
/*------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
------------------------------------------------------------------------------*/
|
|
STDAPI_(ULONG) CCandMenu::AddRef(void)
|
|
{
|
|
return CCicLibMenu::AddRef();
|
|
}
|
|
|
|
|
|
/* R E L E A S E */
|
|
/*------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
------------------------------------------------------------------------------*/
|
|
STDAPI_(ULONG) CCandMenu::Release(void)
|
|
{
|
|
return CCicLibMenu::Release();
|
|
}
|
|
|
|
|
|
/* Q U E R Y I N T E R F A C E */
|
|
/*------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
------------------------------------------------------------------------------*/
|
|
STDAPI CCandMenu::QueryInterface(REFIID riid, void **ppvObj)
|
|
{
|
|
if (IsEqualIID( riid, IID_ITfCandUIMenuExtension )) {
|
|
if (ppvObj == NULL) {
|
|
return E_POINTER;
|
|
}
|
|
|
|
*ppvObj = SAFECAST( this, ITfCandUIMenuExtension* );
|
|
|
|
AddRef();
|
|
return S_OK;
|
|
}
|
|
|
|
return CCicLibMenu::QueryInterface( riid, ppvObj );
|
|
}
|
|
|
|
|
|
/* S E T F O N T */
|
|
/*------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
------------------------------------------------------------------------------*/
|
|
STDAPI CCandMenu::SetFont( LOGFONTW *plf )
|
|
{
|
|
if (plf == NULL) {
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
m_lf = *plf;
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
/* G E T F O N T */
|
|
/*------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
------------------------------------------------------------------------------*/
|
|
STDAPI CCandMenu::GetFont( LOGFONTW *plf )
|
|
{
|
|
if (plf == NULL) {
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
*plf = m_lf;
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
/* S H O W P O P U P */
|
|
/*------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
------------------------------------------------------------------------------*/
|
|
UINT CCandMenu::ShowPopup( CCandWindowBase *pCandWnd, const POINT pt, const RECT *prcArea )
|
|
{
|
|
if (m_pCUIMenu) {
|
|
return 0;
|
|
}
|
|
|
|
m_pCandWnd = pCandWnd;
|
|
|
|
UINT uRet = 0;
|
|
if (m_pCUIMenu = CreateMenuUI( FALSE /* not sub menu */)) {
|
|
|
|
uRet = m_pCUIMenu->ShowModalPopup( m_pCandWnd, prcArea, TRUE );
|
|
|
|
delete m_pCUIMenu;
|
|
m_pCUIMenu = NULL;
|
|
}
|
|
|
|
m_pCandWnd = NULL;
|
|
|
|
return uRet;
|
|
}
|
|
|
|
|
|
/* C L O S E P O P U P */
|
|
/*------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
------------------------------------------------------------------------------*/
|
|
void CCandMenu::ClosePopup( void )
|
|
{
|
|
if (m_pCUIMenu != NULL) {
|
|
PostThreadMessage( GetCurrentThreadId(), WM_NULL, 0, 0 );
|
|
}
|
|
}
|
|
|
|
|
|
/* C R E A T E M E N U U I */
|
|
/*------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
------------------------------------------------------------------------------*/
|
|
CUIFMenu *CCandMenu::CreateMenuUI( BOOL fSubMenu )
|
|
{
|
|
CUIFCandMenu *pCuiMenu;
|
|
int i;
|
|
|
|
if (fSubMenu) {
|
|
pCuiMenu = new CUIFCandMenu( m_hInst, g_dwMenuStyle, 0 );
|
|
}
|
|
else {
|
|
pCuiMenu = new CUIFCandMenuParent( m_hInst, g_dwMenuStyle, 0, m_pCandWnd );
|
|
}
|
|
|
|
pCuiMenu->Initialize();
|
|
pCuiMenu->ResetMenuFont( &m_lf );
|
|
|
|
for (i = 0; i < _rgItem.Count(); i++) {
|
|
CCandMenuItem *pItem = (CCandMenuItem *)_rgItem.Get(i);
|
|
pItem->InsertToUI( pCuiMenu );
|
|
}
|
|
|
|
return pCuiMenu;
|
|
}
|
|
|
|
|
|
/* G E T M E N U U I */
|
|
/*------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
------------------------------------------------------------------------------*/
|
|
CUIFMenu *CCandMenu::GetMenuUI( void )
|
|
{
|
|
return m_pCUIMenu;
|
|
}
|
|
|
|
|
|
//
|
|
//
|
|
//
|
|
|
|
/* C U I F C A N D M E N U */
|
|
/*------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
------------------------------------------------------------------------------*/
|
|
CUIFCandMenu::CUIFCandMenu( HINSTANCE hInst, DWORD dwWndStyle, DWORD dwMenuStyle ) : CUIFMenu( hInst, dwWndStyle, dwMenuStyle )
|
|
{
|
|
}
|
|
|
|
|
|
/* ~ C U I F C A N D M E N U */
|
|
/*------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
------------------------------------------------------------------------------*/
|
|
CUIFCandMenu::~CUIFCandMenu( void )
|
|
{
|
|
}
|
|
|
|
|
|
/* R E S E T M E N U F O N T */
|
|
/*------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
------------------------------------------------------------------------------*/
|
|
void CUIFCandMenu::ResetMenuFont( LOGFONTW *plf )
|
|
{
|
|
ClearMenuFont();
|
|
SetFont( OurCreateFontIndirectW( plf ) );
|
|
}
|
|
|
|
|
|
//
|
|
//
|
|
//
|
|
|
|
/* C U I F C A N D M E N U P A R E N T */
|
|
/*------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
------------------------------------------------------------------------------*/
|
|
CUIFCandMenuParent::CUIFCandMenuParent( HINSTANCE hInst, DWORD dwWndStyle, DWORD dwMenuStyle, CCandWindowBase *pCandWnd ) : CUIFCandMenu( hInst, dwWndStyle, dwMenuStyle )
|
|
{
|
|
m_pCandWnd = pCandWnd;
|
|
}
|
|
|
|
|
|
/* ~ C U I F C A N D M E N U P A R E N T */
|
|
/*------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
------------------------------------------------------------------------------*/
|
|
CUIFCandMenuParent::~CUIFCandMenuParent( void )
|
|
{
|
|
UninstallHook();
|
|
}
|
|
|
|
|
|
/* I N I T S H O W */
|
|
/*------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
------------------------------------------------------------------------------*/
|
|
BOOL CUIFCandMenuParent::InitShow( CUIFWindow *pcuiWndParent, const RECT *prc, BOOL fVertical, BOOL fAnimate )
|
|
{
|
|
BOOL fSucceed = TRUE;
|
|
|
|
if (!CUIFMenu::InitShow( pcuiWndParent, prc, fVertical, fAnimate )) {
|
|
fSucceed = FALSE;
|
|
}
|
|
|
|
if (!InstallHook()) {
|
|
fSucceed = FALSE;
|
|
}
|
|
|
|
if (m_pCandWnd != NULL) {
|
|
m_pCandWnd->OnMenuOpened();
|
|
}
|
|
|
|
return fSucceed;
|
|
}
|
|
|
|
|
|
/* U N I N I T S H O W */
|
|
/*------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
------------------------------------------------------------------------------*/
|
|
BOOL CUIFCandMenuParent::UninitShow()
|
|
{
|
|
BOOL fSucceed = TRUE;
|
|
|
|
if (!CUIFMenu::UninitShow()) {
|
|
fSucceed = FALSE;
|
|
}
|
|
|
|
if (!UninstallHook()) {
|
|
fSucceed = FALSE;
|
|
}
|
|
|
|
if (m_pCandWnd != NULL) {
|
|
m_pCandWnd->OnMenuClosed();
|
|
}
|
|
|
|
return fSucceed;
|
|
}
|
|
|
|
|
|
/* M O D A L M E S S A G E L O O P */
|
|
/*------------------------------------------------------------------------------
|
|
|
|
NOTE: we need to use PeekMessage to cancel candidate menu
|
|
in unknown mouse message (w/o eating...)
|
|
|
|
------------------------------------------------------------------------------*/
|
|
void CUIFCandMenuParent::ModalMessageLoop( void )
|
|
{
|
|
MSG msg;
|
|
|
|
while (TRUE) {
|
|
while (!PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE )) {
|
|
WaitMessage();
|
|
}
|
|
|
|
if (PeekMessage( &msg, NULL, 0, 0, PM_REMOVE )) {
|
|
if (msg.message == WM_NULL) {
|
|
break;
|
|
}
|
|
|
|
else if (msg.message == WM_QUIT) {
|
|
PostQuitMessage( (int)msg.wParam );
|
|
break;
|
|
}
|
|
|
|
// check hooked mouse message (messages sent to another window)
|
|
|
|
else if (msg.message == g_msgHookedMouse) {
|
|
if (((msg.wParam != WM_MOUSEMOVE) && (msg.wParam != WM_NCMOUSEMOVE))) {
|
|
CancelMenu();
|
|
break;
|
|
}
|
|
|
|
msg.hwnd = GetWnd();
|
|
msg.message = (UINT)msg.wParam;
|
|
msg.wParam = 0;
|
|
}
|
|
|
|
// check hooked keyboard messages (all keyboard messages)
|
|
|
|
else if (msg.message == g_msgHookedKey) {
|
|
UINT message;
|
|
CUIFMenu *pMenuObj = GetTopSubMenu();
|
|
|
|
if (HIWORD(msg.lParam) & KF_ALTDOWN) {
|
|
message = (HIWORD(msg.lParam) & KF_UP) ? WM_SYSKEYUP : WM_SYSKEYDOWN;
|
|
}
|
|
else {
|
|
message = (HIWORD(msg.lParam) & KF_UP) ? WM_KEYUP : WM_KEYDOWN;
|
|
}
|
|
|
|
if (message == WM_SYSKEYDOWN) {
|
|
CancelMenu();
|
|
}
|
|
|
|
msg.hwnd = (pMenuObj != NULL) ? pMenuObj->GetWnd() : NULL;
|
|
msg.message = message;
|
|
}
|
|
|
|
TranslateMessage(&msg);
|
|
DispatchMessage(&msg);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/* I N S T A L L H O O K */
|
|
/*------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
------------------------------------------------------------------------------*/
|
|
BOOL CUIFCandMenuParent::InstallHook( void )
|
|
{
|
|
HHOOK hHookKeyboard;
|
|
HHOOK hHookMouse;
|
|
|
|
if (!g_ShareMem.Create()) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (!g_ShareMem.LockData()) {
|
|
return FALSE;
|
|
}
|
|
|
|
hHookKeyboard = SetWindowsHookEx( WH_KEYBOARD, KeyboardProc, m_hInstance, NULL );
|
|
hHookMouse = SetWindowsHookEx( WH_MOUSE, MouseProc, m_hInstance, NULL );
|
|
|
|
g_ShareMem.GetData()->dwThreadId = GetCurrentThreadId();
|
|
g_ShareMem.GetData()->hHookKeyboard = hHookKeyboard;
|
|
g_ShareMem.GetData()->hHookMouse = hHookMouse;
|
|
g_ShareMem.GetData()->hWndMenu = GetWnd();
|
|
|
|
g_ShareMem.UnlockData();
|
|
|
|
return (hHookKeyboard != NULL) && (hHookMouse != NULL);
|
|
}
|
|
|
|
|
|
/* U N I N S T A L L H O O K */
|
|
/*------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
------------------------------------------------------------------------------*/
|
|
BOOL CUIFCandMenuParent::UninstallHook( void )
|
|
{
|
|
HHOOK hHook;
|
|
|
|
if (!g_ShareMem.LockData()) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (g_ShareMem.GetData()->dwThreadId != GetCurrentThreadId()) {
|
|
g_ShareMem.UnlockData();
|
|
return FALSE;
|
|
}
|
|
|
|
hHook = g_ShareMem.GetData()->hHookKeyboard;
|
|
if (hHook != NULL) {
|
|
UnhookWindowsHookEx( hHook );
|
|
}
|
|
|
|
hHook = g_ShareMem.GetData()->hHookMouse;
|
|
if (hHook != NULL) {
|
|
UnhookWindowsHookEx( hHook );
|
|
}
|
|
|
|
g_ShareMem.GetData()->dwThreadId = 0;
|
|
g_ShareMem.GetData()->hHookKeyboard = NULL;
|
|
g_ShareMem.GetData()->hHookMouse = NULL;
|
|
g_ShareMem.GetData()->hWndMenu = NULL;
|
|
|
|
g_ShareMem.UnlockData();
|
|
|
|
g_ShareMem.Close();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/* K E Y B O A R D P R O C */
|
|
/*------------------------------------------------------------------------------
|
|
|
|
Hook function for keyboard message
|
|
Forward all keyboard message as g_msgHookedKey to the manu window thread
|
|
|
|
------------------------------------------------------------------------------*/
|
|
LRESULT CALLBACK CUIFCandMenuParent::KeyboardProc( int code, WPARAM wParam, LPARAM lParam )
|
|
{
|
|
LRESULT lResult = 0;
|
|
BOOL fEatMessage = FALSE;
|
|
|
|
if (!g_ShareMem.LockData()) {
|
|
return 0;
|
|
}
|
|
|
|
if (code == HC_ACTION || code == HC_NOREMOVE) {
|
|
PostThreadMessage( g_ShareMem.GetData()->dwThreadId, g_msgHookedKey, wParam, lParam );
|
|
fEatMessage = TRUE;
|
|
}
|
|
|
|
if ((code < 0) || !fEatMessage) {
|
|
lResult = CallNextHookEx( g_ShareMem.GetData()->hHookKeyboard, code, wParam, lParam );
|
|
}
|
|
else {
|
|
lResult = (LRESULT)TRUE;
|
|
}
|
|
|
|
g_ShareMem.UnlockData();
|
|
|
|
return lResult;
|
|
}
|
|
|
|
|
|
/* M O U S E P R O C */
|
|
/*------------------------------------------------------------------------------
|
|
|
|
Hook function for mouse message
|
|
Forward mouse message sent to non-menu window (excluding mouse movement)
|
|
as g_msgHookedMouse to the manu window thread
|
|
|
|
------------------------------------------------------------------------------*/
|
|
LRESULT CALLBACK CUIFCandMenuParent::MouseProc( int code, WPARAM wParam, LPARAM lParam )
|
|
{
|
|
LRESULT lResult = 0;
|
|
BOOL fEatMessage = FALSE;
|
|
|
|
if (!g_ShareMem.LockData()) {
|
|
return 0;
|
|
}
|
|
|
|
if (code == HC_ACTION || code == HC_NOREMOVE) {
|
|
MOUSEHOOKSTRUCT *pmhs = (MOUSEHOOKSTRUCT *)lParam;
|
|
UINT message = (UINT)wParam;
|
|
|
|
if (GetCurrentThreadId() == g_ShareMem.GetData()->dwThreadId) {
|
|
HWND hWndTemp = pmhs->hwnd;
|
|
HWND hWndMenu = g_ShareMem.GetData()->hWndMenu;
|
|
|
|
while ((hWndTemp != NULL) && (hWndTemp != hWndMenu)) {
|
|
hWndTemp = GetParent( hWndTemp );
|
|
}
|
|
|
|
if (hWndTemp == NULL /* not menu window */) {
|
|
if ((message != WM_NCMOUSEMOVE) && (message != WM_MOUSEMOVE)) {
|
|
PostThreadMessage( g_ShareMem.GetData()->dwThreadId, g_msgHookedMouse, wParam, MAKELPARAM(pmhs->pt.x, pmhs->pt.y) );
|
|
}
|
|
else {
|
|
fEatMessage = (message == WM_NCMOUSEMOVE);
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
if ((message != WM_NCMOUSEMOVE) && (message != WM_MOUSEMOVE)) {
|
|
PostThreadMessage( g_ShareMem.GetData()->dwThreadId, g_msgHookedMouse, wParam, MAKELPARAM(pmhs->pt.x, pmhs->pt.y) );
|
|
}
|
|
}
|
|
}
|
|
|
|
if ((code < 0) || !fEatMessage) {
|
|
lResult = CallNextHookEx( g_ShareMem.GetData()->hHookMouse, code, wParam, lParam );
|
|
}
|
|
else {
|
|
lResult = (LRESULT)TRUE;
|
|
}
|
|
|
|
g_ShareMem.UnlockData();
|
|
|
|
return lResult;
|
|
}
|
|
|