Leaked source code of windows server 2003
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

//
// 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;
}