Click here to Skip to main content
13,042,691 members (76,036 online)
Click here to Skip to main content

Stats

1.2M views
21.8K downloads
634 bookmarked
Posted 29 May 2002

Professional User Interface Suite

MFC extension library enabling software to be provided with a professional UI
Prof-UIS
Bin_600
Bin_700
Bin_710
Include
profuisdll
idd_ext_color_dlg.ico
profuisdll.def
profuisdll_600.dsp
profuisdll_600.dsw
res
black_arrow_bottom.cur
black_arrow_left.cur
black_arrow_right.cur
black_arrow_top.cur
cmd00001.cur
cmd00002.cur
cmd00003.cur
cur_arrow_invert.cur
cur_black_finger.cur
cur_black_hand.cur
cur_hand_like.cur
cur_pan_all.cur
cur_pan_bottom.cur
cur_pan_bottom_left.cur
cur_pan_bottom_right.cur
cur_pan_horz.cur
cur_pan_left.cur
cur_pan_right.cur
cur_pan_top.cur
cur_pan_top_left.cur
cur_pan_top_right.cur
cur_pan_vert.cur
cur_resize_h1.cur
cur_resize_h2.cur
cur_resize_v1.cur
cur_resize_v2.cur
cur00001.cur
cur00002.cur
cur00003.cur
cur00004.cur
hollow_cross_normal.cur
hollow_cross_small.cur
ico00001.ico
id_view_.bmp
idd_ext_.ico
idd_icon.ico
ied_cp.cur
ied_el.cur
ied_fill.cur
ied_line.cur
ied_pen.cur
ied_rect.cur
ied_tool.cur
suppress.cur
suppress_arrow.cur
toolbar_.bmp
zoom_hollow.cur
zoom_minus.cur
zoom_plus.cur
profuislib
profuislib_600.dsp
profuislib_600.dsw
Samples
AviFrames
AviFrames_600.dsp
res
AviFrames.ico
CINEAPK.AVI
IDR_TOOLBAR_PLAYER.bmp
IDR_TOOLBAR_UISTYLE.bmp
Toolbar.bmp
toolbar2.bmp
xptheme.bin
DRAWCLI
DRAWCLI_600.dsp
L.JPN
RES
res
DRAWCLI.ICO
DRAWDOC.ICO
ico00001.ico
ico00002.ico
ico00003.ico
ico00004.ico
ico00005.ico
ico00006.ico
ico00007.ico
ico00008.ico
icon1.ico
id_objec.ico
id_scppv.ico
idr_abou.ico
PENCIL.CUR
TOOLBAR_1_16bit.bmp
TOOLBAR_1_4bit.bmp
TOOLBAR_2_16bit.bmp
TOOLBAR_2_4bit.bmp
FixedSizePanels
FixedSizePanels_600.dsp
res
bitmap_t.bmp
FixedSizePanels.ico
Toolbar.bmp
toolbar2.bmp
FullScreenState
FullScreenState_600.dsp
res
FullScreenState.ico
idr_mdit.ico
Toolbar.bmp
toolbar1.bmp
toolbar2.bmp
toolbar4.bmp
FunnyBars
FunnyBars_600.dsp
res
FunnyBars.ico
Toolbar.bmp
toolbar_16_16_8.bmp
toolbar_44_40_32.bmp
winXP.manifest
GLViews
GLViews_600.dsp
res
bitmap_i.bmp
bitmap_s.bmp
bitmap_t.bmp
bmp00001.bmp
btpnlane.bmp
CINEAPK.AVI
cur00001.cur
cur00002.cur
cursor_g.cur
earth.bmp
GLViews.ico
moon.bmp
ProfUisCubeSideOrange.bmp
ProfUisCubeSideWhite.bmp
ring.bmp
Toolbar.bmp
toolbar_.bmp
toolbar2.bmp
wndavipl.bmp
wndmirror.bmp
res_html
bodytop.gif
book_close.gif
book_open.gif
MDI
MDI_600.dsp
res
idr_mdit.ico
MDI.ico
Toolbar.bmp
toolbar2.bmp
MDI_InnerOuterBars
MDI_InnerOuterBars_600.dsp
res
bmp00001.bmp
idr_mdit.ico
MDI_InnerOuterBars.ico
Toolbar.bmp
toolbar_.bmp
toolbar2.bmp
MDIDOCVIEW
MDIDOCVIEW_600.dsp
res
MDIDOCVIEW.ico
MDIDOCVIEWDoc.ico
Toolbar.bmp
MthOutput
MthOutput_600.dsp
res
idr_mdit.ico
MthOutput.ico
Toolbar.bmp
toolbar1.bmp
toolbar2.bmp
ProfUIS_Controls
ProfUIS_Controls_600.dsp
res
bitmap1.bmp
bitmap2.bmp
icon1.ico
ProfUIS_Controls.ico
tab_imag.bmp
toolbar1.bmp
ResizableChildSheet
res
idr_chil.ico
ResizableChildSheet.ico
Toolbar.bmp
ResizableChildSheet_600.dsp
ResizablePropertySheet
res
bitmap1.bmp
bitmap2.bmp
ResizablePropertySheet.ico
ResizablePropertySheet_600.dsp
SDI
res
SDI.ico
Toolbar.bmp
toolbar2.bmp
SDI_600.dsp
SDIDOCVIEW
res
SDIDOCVIEW.ico
SDIDOCVIEWDoc.ico
Toolbar.bmp
SDIDOCVIEW_600.dsp
StateInFile
res
StateInFile.ico
Toolbar.bmp
StateInFile_600.dsp
StatusPanes
res
download.avi
StatusPanes.ico
Toolbar.bmp
toolbar2.bmp
StatusPanes_600.dsp
Src
Workspace
ProfUIS_600.dsw
Include
profuisdll
idd_ext_color_dlg.ico
profuisdll.def
profuisdll.dsp
res
profuislib
profuislib.dsp
Samples
DRAWCLI
MDI
MDIDOCVIEW
MDI_InnerOuterBars
ProfUIS_Controls
ResizablePropertySheet
SDI
SDIDOCVIEW
StateInFile
DRAWCLI.dsp
L.JPN
res
RES
DRAWCLI.ICO
DRAWDOC.ICO
ico00001.ico
ico00002.ico
icon1.ico
id_objec.ico
PENCIL.CUR
TOOLBAR.BMP
MDI.dsp
res
idr_mdit.ico
MDI.ico
Toolbar.bmp
toolbar2.bmp
MDIDOCVIEW.dsp
res
MDIDOCVIEW.ico
MDIDOCVIEWDoc.ico
Toolbar.bmp
MDI_InnerOuterBars.dsp
res
bmp00001.bmp
idr_mdit.ico
MDI_InnerOuterBars.ico
Toolbar.bmp
toolbar2.bmp
toolbar_.bmp
ProfUIS_Controls.dsp
res
bitmap1.bmp
bitmap2.bmp
icon1.ico
ProfUIS_Controls.ico
tab_imag.bmp
toolbar1.bmp
res
ResizablePropertySheet.dsp
ResizablePropertySheet.ico
res
SDI.dsp
SDI.ico
Toolbar.bmp
toolbar2.bmp
res
SDIDOCVIEW.dsp
SDIDOCVIEW.ico
SDIDOCVIEWDoc.ico
Toolbar.bmp
res
StateInFile.dsp
StateInFile.ico
Toolbar.bmp
Src
Workspace
ProfUIS.dsw
ProfUIS.suo
Bin
MDI.exe
ProfUIS21.dll
ProfUIS_Controls.exe
SDI.exe
StateInFile.exe
idd_ext_color_dlg.ico
profuisdll.aps
profuisdll.clw
profuisdll.def
profuisdll.dep
profuisdll.dsp
profuisdll.mak
profuisdll.plg
MDI.APS
MDI.clw
MDI.dep
MDI.dsp
MDI.mak
MDI.plg
idr_mdit.ico
MDI.ico
Toolbar.bmp
toolbar2.bmp
ProfUIS_Controls.aps
ProfUIS_Controls.clw
ProfUIS_Controls.dep
ProfUIS_Controls.dsp
ProfUIS_Controls.mak
ProfUIS_Controls.ico
toolbar1.bmp
SDI.APS
SDI.clw
SDI.dep
SDI.dsp
SDI.mak
SDI.plg
SDI.ico
Toolbar.bmp
toolbar2.bmp
StateInFile.aps
StateInFile.clw
StateInFile.dep
StateInFile.dsp
StateInFile.mak
StateInFile.plg
StateInFile.ico
Toolbar.bmp
ProfUIS.dsw
ProfUIS.ncb
ProfUIS.opt
// This is part of the Professional User Interface Suite library.
// Copyright (C) 2001-2004 FOSS Software, Inc.
// All rights reserved.
//
// http://www.prof-uis.com
// http://www.fossware.com
// mailto:foss@fossware.com
//
// This source code can be used, modified and redistributed
// under the terms of the license agreement that is included
// in the Professional User Interface Suite package.
//
// Warranties and Disclaimers:
// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND
// INCLUDING, BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
// IN NO EVENT WILL FOSS SOFTWARE INC. BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES,
// INCLUDING DAMAGES FOR LOSS OF PROFITS, LOSS OR INACCURACY OF DATA,
// INCURRED BY ANY PERSON FROM SUCH PERSON'S USAGE OF THIS SOFTWARE
// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.

// ExtPopupMenuWnd.cpp : implementation file
//

#include "stdafx.h"

#define _AFX_NO_OLE_SUPPORT

#ifndef __AFXPRIV_H__
	#include <AfxPriv.h>
#endif

#if _MFC_VER < 0x700
	#include <../src/AfxImpl.h>
#else
	#include <../src/mfc/AfxImpl.h>
#endif

#include <math.h>

#if (!defined __EXT_POPUP_MENU_WND_H)
	#include <ExtPopupMenuWnd.h>
#endif

#if (!defined __EXT_MFC_NO_BUILTIN_TEXTFIELD)
	#if (!defined __EXT_POPUP_CTRL_MENU_H)
		#include <ExtPopupCtrlMenu.h>
	#endif
#endif // (!defined __EXT_MFC_NO_BUILTIN_TEXTFIELD)

#if (!defined __EXT_TOOLCONTROLBAR_H)
	#include <ExtToolControlBar.h>
#endif

#if (!defined __EXT_PAINT_MANAGER_H)
	#include <ExtPaintManager.h>
#endif

#if (!defined __EXT_MEMORY_DC_H)
	#include <../Src/ExtMemoryDC.h>
#endif

#if (!defined __EXT_LOCALIZATION_H)
	#include <../Src/ExtLocalization.h>
#endif

#include <../profuisdll/resource.h>

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

#if (!defined __EXT_MFC_WINMMDLL_ALREADY_DYN_LIKNED)
	#define __EXT_MFC_WINMMDLL_ALREADY_DYN_LIKNED
	#pragma message("   Prof-UIS is automatically linking with WinMM library")
	#pragma message("      (Windows Multimedia System)")
	#pragma comment( lib, "winmm.lib" ) 
#endif

#ifdef _DEBUG
	static int g_nPopupCount = 0;
	//#define __VPC_VERIFY_0 ASSERT( g_nPopupCount == 0 )
	#define __VPC_VERIFY_0 { }
	#define __VPC_INC g_nPopupCount++
	#define __VPC_DEC g_nPopupCount--
#else // _DEBUG
	#define __VPC_VERIFY_0 { }
	#define __VPC_INC { }
	#define __VPC_DEC { }
#endif // _DEBUG

#define ID_TIMER_ANIMATION 666
#define ID_PERIOD_ANIMATION 30 // 20

#define ID_TIMER_ITEM_FOCUS_DELAY 667
#define ID_PERIOD_ITEM_FOCUS_DELAY 500

#define ID_TIMER_SCROLLING 668
#define ID_PERIOD_SCROLLING 15

#define ID_TIMER_DELAY_SHOW 669
#define ID_PERIOD_DELAY_SHOW 1000

#define ID_TIMER_DELAY_EXPAND 670
#define ID_FREQ_DELAY_EXPAND 50
#define ID_TOTAL_DELAY_EXPAND 1500

#define __SCROLLING_PIXEL_STEP 5

static const int g_nAnimStepMetric = 20;
static clock_t g_nLastAnimTime = 0;

#define __ANIM_CY 15

#define __EXCLUDE_AREA_GAP_DX 3
#define __EXCLUDE_AREA_GAP_DY __EXCLUDE_AREA_GAP_DX

#define __MI_HORZ_GAP_TO_BORDER 1

#define __BOX_ANIM_METRIC 32 // for __AT_BOXES,__AT_CIRCLES animation

CExtPopupMenuSite CExtPopupMenuSite::g_DefPopupMenuSite;

bool CExtPopupMenuWnd::g_bMenuWithShadows = true; // allow shadows
bool CExtPopupMenuWnd::g_bMenuExpanding = true; // allow hide rarely used
bool CExtPopupMenuWnd::g_bMenuDelayExpanding = true;  // show full menu after short delay
bool CExtPopupMenuWnd::g_bMenuHighlightRarely = true; // display rarely used in different style
bool CExtPopupMenuWnd::g_bMenuShowCoolTips = true; // allow display cool tooltips
bool CExtPopupMenuWnd::g_bMenuExpandAnimation = true; // allow animation when show rarely used
bool CExtPopupMenuWnd::g_bUseStretchOnExpandAnimation = false; // use StretchBlt() instead of BitBlt() for painting menu expand amimation
bool CExtPopupMenuWnd::g_bMenuLargeIcons = false; // use large icons

bool CExtPopupBaseWnd::g_bUseDesktopWorkArea = true; // align to desktop work area (false - to screen area)

bool CExtPopupBaseWnd::g_bEnableOnIdleCalls = false;

CExtPopupBaseWnd::e_animation_type_t
	CExtPopupBaseWnd::g_DefAnimationType =
		CExtPopupBaseWnd::__AT_FADE; // __AT_RANDOM

UINT CExtPopupBaseWnd::g_nMsgPrepareMenu =
	::RegisterWindowMessage(
		_T("CExtPopupMenuWnd::g_nMsgPrepareMenu")
		);
UINT CExtPopupBaseWnd::g_nMsgPopupNext =
	::RegisterWindowMessage(
		_T("CExtPopupMenuWnd::g_nMsgPopupNext")
		);
UINT CExtPopupBaseWnd::g_nMsgPopupPrev =
	::RegisterWindowMessage(
		_T("CExtPopupMenuWnd::g_nMsgPopupPrev")
		);
UINT CExtPopupBaseWnd::g_nMsgNotifyMenuExpanded =
	::RegisterWindowMessage(
		_T("CExtPopupMenuWnd::g_nMsgNotifyMenuExpanded")
		);
UINT CExtPopupBaseWnd::g_nMsgNotifyMenuClosed =
	::RegisterWindowMessage(
		_T("CExtPopupMenuWnd::g_nMsgNotifyMenuClosed")
		);
UINT CExtPopupBaseWnd::g_nMsgPopupDrawItem =
	::RegisterWindowMessage(
		_T("CExtPopupMenuWnd::g_nMsgPopupDrawItem")
		);
UINT CExtPopupBaseWnd::g_nMsgPopupDrawLeftArea =
	::RegisterWindowMessage(
		_T("CExtPopupMenuWnd::g_nMsgPopupDrawLeftArea")
		);
UINT CExtPopupBaseWnd::g_nMsgCreateInplaceEdit =
	::RegisterWindowMessage(
		_T("CExtPopupMenuWnd::g_nMsgCreateInplaceEdit")
		);

#define __POPUP_WNDCLASS_STYLES__ \
	( CS_SAVEBITS )
//	( CS_SAVEBITS \
//		|CS_HREDRAW \
//		|CS_VREDRAW \
//		|CS_NOCLOSE \
//	)

/////////////////////////////////////////////////////////////////////////////
// CExtSoundPlayer

CExtSoundPlayer::CExtSoundPlayerAutoPtr g_SoundPlayer;

IMPLEMENT_DYNCREATE( CExtSoundPlayer, CObject );

CExtSoundPlayer::InternalSoundEventInitDone_t::InternalSoundEventInitDone_t()
	: CEvent( FALSE, TRUE )
{
}

void CExtSoundPlayer::InternalSoundEventInitDone_t::SetInitDone()
{
	SetEvent();
}

void CExtSoundPlayer::InternalSoundEventInitDone_t::WaitInitDone()
{
HANDLE hEvent = *this;
	ASSERT( hEvent != NULL );
	::WaitForSingleObject( hEvent, INFINITE );
}

CExtSoundPlayer::InternalSoundThredadParms_t::InternalSoundThredadParms_t(
	__EXT_MFC_SAFE_LPCTSTR sSoundSpecBuffer,
	HANDLE hModule,
	DWORD dwPlayerFlags
	)
	: m_hModule( hModule )
	, m_dwPlayerFlags( dwPlayerFlags )
	, m_hThread( NULL )
	, m_dwThreadID( 0 )
	, m_pEventInitDone( NULL )
{
	::memset( m_sSoundSpecBuffer, 0, sizeof(m_sSoundSpecBuffer) );
	ASSERT( sSoundSpecBuffer != NULL );
	ASSERT( _tclen(sSoundSpecBuffer) > 0 );
	_tcsncpy(
		m_sSoundSpecBuffer,
		sSoundSpecBuffer,
		sizeof(m_sSoundSpecBuffer) / sizeof(m_sSoundSpecBuffer[0]) - 1
		);
}

CEvent CExtSoundPlayer::InternalSoundThredadParms_t::g_EventPlaySnd(
	TRUE,
	FALSE,
	_T("CExtSoundPlayer__InternalSoundThredadParms_t")
	);

CCriticalSection CExtSoundPlayer::InternalSoundThredadParms_t::g_CsPlaySnd;

DWORD WINAPI CExtSoundPlayer::InternalSoundThredadParms_t::stat_ParallelPlayerProc(
	CExtSoundPlayer::InternalSoundThredadParms_t * pParms
	)
{
	ASSERT( pParms != NULL );
	pParms->PlaySound();
	g_EventPlaySnd.SetEvent();
	return 0;
}

//#define __TRACE_SOUND_PLAYER_THREAD

void CExtSoundPlayer::InternalSoundThredadParms_t::PlaySound()
{
TCHAR sSoundSpecBuffer[ sizeof(m_sSoundSpecBuffer) / sizeof(m_sSoundSpecBuffer[0]) ];
	_tcscpy(
		sSoundSpecBuffer,
		m_sSoundSpecBuffer
		);
HANDLE hModule = m_hModule;
DWORD dwPlayerFlags = m_dwPlayerFlags;
	if( m_pEventInitDone != NULL )
		m_pEventInitDone->SetInitDone();
#ifdef __TRACE_SOUND_PLAYER_THREAD
	TRACE1("CExtSoundPlayer::InternalSoundThredadParms_t::PlaySound(\"%s\") - START\n",sSoundSpecBuffer);
#endif // __TRACE_SOUND_PLAYER_THREAD
	if( (m_dwPlayerFlags & SND_ASYNC) != 0 )
		::PlaySound( NULL, NULL, SND_PURGE );
	::PlaySound(
		sSoundSpecBuffer,
		(HMODULE)hModule,
		dwPlayerFlags
		);
	if( (m_dwPlayerFlags & SND_SYNC) != 0 )
		::PlaySound( NULL, NULL, SND_PURGE );
#ifdef __TRACE_SOUND_PLAYER_THREAD
	TRACE1("CExtSoundPlayer::InternalSoundThredadParms_t::PlaySound(\"%s\") - STOP\n",sSoundSpecBuffer);
#endif // __TRACE_SOUND_PLAYER_THREAD
}

void CExtSoundPlayer::InternalSoundThredadParms_t::PlaySoundParallel()
{
	ASSERT( m_hThread == NULL );
CSingleLock slCs( &g_CsPlaySnd );
	slCs.Lock();
HANDLE hEvent = (HANDLE)g_EventPlaySnd;
	ASSERT( hEvent != NULL );
	if( ::WaitForSingleObject(hEvent,0) == WAIT_OBJECT_0 )
	{
		ASSERT( m_pEventInitDone == NULL );
		InternalSoundEventInitDone_t EventInitDone;
		m_pEventInitDone = &EventInitDone;
		m_hThread =
			::CreateThread(
				NULL,
				0,
				*this,
				this,
				CREATE_SUSPENDED,
				&m_dwThreadID
				);
		ASSERT( m_hThread != NULL );
		if( m_hThread != NULL )
		{
			VERIFY(
				::SetThreadPriority(
					m_hThread,
					THREAD_PRIORITY_BELOW_NORMAL
					)
				);
			::ResumeThread( m_hThread );
			EventInitDone.WaitInitDone();
		} // if( m_hThread != NULL )
		else
			g_EventPlaySnd.SetEvent();
	} // if( ::WaitForSingleObject(hEvent,0) == WAIT_OBJECT_0 )
	if( m_hThread != NULL )
		::CloseHandle( m_hThread );
	slCs.Unlock();
}

CExtSoundPlayer::CExtSoundPlayerAutoPtr::CExtSoundPlayerAutoPtr()
{
	m_pPlayer = new CExtSoundPlayer;
}

CExtSoundPlayer::CExtSoundPlayerAutoPtr::~CExtSoundPlayerAutoPtr()
{
	if( m_pPlayer != NULL )
		delete m_pPlayer;
}

void CExtSoundPlayer::CExtSoundPlayerAutoPtr::InstallSoundPlayer(
	CExtSoundPlayer * pPlayer
	)
{
	ASSERT( pPlayer != NULL );
	ASSERT_VALID( pPlayer );
	ASSERT_KINDOF( CExtSoundPlayer, m_pPlayer );
	if( m_pPlayer != NULL )
		delete m_pPlayer;
	m_pPlayer = pPlayer;
}

CExtSoundPlayer::CExtSoundPlayer()
{
}

CExtSoundPlayer::~CExtSoundPlayer()
{
}

void CExtSoundPlayer::PlaySound(
	CExtSoundPlayer::e_ui_sounds_t eSoundID
	)
{
	ASSERT_VALID( this );
	switch( eSoundID )
	{
	case __NO_SOUND:
		return;
	case __ON_MENU_EXPAND_CLICKED:
	case __ON_MENU_POPUP_DISPLAYED:
		{
			InternalSoundThredadParms_t _istp(
				_T("MenuPopup"),
				NULL,
				SND_ALIAS|SND_NODEFAULT|SND_NOWAIT|SND_ASYNC
				);
			_istp.PlaySoundParallel();
			return;
		}
	case __ON_MENU_CMD_CLICKED:
		{
			InternalSoundThredadParms_t _istp(
				_T("MenuCommand"),
				NULL,
				SND_ALIAS|SND_NODEFAULT|SND_NOWAIT|SND_SYNC
				);
			_istp.PlaySoundParallel();
			return;
		}
	} // switch( eSoundID )
}

/////////////////////////////////////////////////////////////////////////////
// CExtPopupMenuSite

CExtPopupMenuSite::CExtPopupMenuSite()
	: m_pTopMenu( NULL )
	, m_pWndCapture( NULL )
	, m_pWndAnimation( NULL )
	, m_bShutdownMode( false )
	, m_hMouseHook( NULL )
	, m_hKeyboardHook( NULL )
	, m_lpnResultCmdID( NULL )
{
}

CExtPopupMenuSite::~CExtPopupMenuSite()
{
	_Done();
}

CExtPopupMenuWnd * CExtPopupMenuSite::GetCapture()
{
	ASSERT( !IsEmpty() );
	ASSERT( !IsShutdownMode() );
	return m_pWndCapture;
}

void CExtPopupMenuSite::SetCapture(
	CExtPopupMenuWnd * pNewPopup // = NULL
	)
{
	ASSERT( !IsEmpty() );
	ASSERT( !IsShutdownMode() );

#ifdef _DEBUG
	if( pNewPopup != NULL )
	{
		ASSERT_VALID( pNewPopup );
	}
#endif // _DEBUG
	m_pWndCapture = pNewPopup;
}

void CExtPopupMenuSite::SetInstance(
	CExtPopupMenuWnd * pTopMenu // = NULL
	)
{
	ASSERT( !IsShutdownMode() );
	if( !IsEmpty() )
	{
		ASSERT( m_pTopMenu != NULL );
		ASSERT_VALID( m_pTopMenu );
		ASSERT( m_pTopMenu->m_bTopLevel );
		if( m_pTopMenu == pTopMenu )
			return;
		if( m_pTopMenu != pTopMenu )
			_Done();
	}
	ASSERT( m_pTopMenu == NULL );
	if( pTopMenu != NULL )
	{
		ASSERT_VALID( pTopMenu );
		ASSERT( pTopMenu->m_bTopLevel );
		m_pTopMenu = pTopMenu;
		_Hook( true );
	}
}

CExtPopupMenuWnd * CExtPopupMenuSite::GetAnimated()
{
	ASSERT( !IsEmpty() );
	ASSERT( !IsShutdownMode() );
	return m_pWndAnimation;
}

void CExtPopupMenuSite::SetAnimated(
	CExtPopupMenuWnd * pNewPopup // = NULL
	)
{
	ASSERT( !IsEmpty() );
	ASSERT( !IsShutdownMode() );
	m_pWndAnimation = pNewPopup;
}

CExtPopupMenuWnd * CExtPopupMenuSite::GetInstance()
{
	return m_pTopMenu;
}

void CExtPopupMenuSite::SetTargetCmdIdPtr(
	UINT * lpnResultCmdID // = NULL
	)
{
	m_lpnResultCmdID = lpnResultCmdID;
}

UINT * CExtPopupMenuSite::GetTargetCmdIdPtr()
{
	return m_lpnResultCmdID;
}

void CExtPopupMenuSite::DoneInstance()
{
	_Done();
}

bool CExtPopupMenuSite::IsTopPupup(
	CExtPopupMenuWnd * pTopMenu
	) const
{
	ASSERT( !IsEmpty() );
	ASSERT( !IsShutdownMode() );
	ASSERT_VALID( pTopMenu );
	return (pTopMenu==m_pTopMenu) ? true : false;
}

void CExtPopupMenuSite::_Done()
{
	ASSERT( !m_bShutdownMode );
	m_bShutdownMode = true;
	m_pWndCapture = NULL;
	m_pWndAnimation = NULL;
	m_lpnResultCmdID = NULL;
	if( m_pTopMenu != NULL )
	{
		ASSERT( m_pTopMenu->m_bTopLevel );
		VERIFY( m_pTopMenu->_BuildItems( NULL, true ) );
		if( m_pTopMenu->GetSafeHwnd() != NULL
			&& ::IsWindow( m_pTopMenu->GetSafeHwnd() )
			)
		{
			CExtControlBar::stat_SetMessageString(
				m_pTopMenu->GetOwner()
				);
			m_pTopMenu->DestroyWindow();
			CExtPopupMenuWnd::PassMsgLoop( CExtPopupBaseWnd::g_bEnableOnIdleCalls );
		}
		ASSERT( m_pTopMenu->GetSafeHwnd() == NULL );
		delete m_pTopMenu;
		m_pTopMenu = NULL;
	}
	_Hook( false );
	__VPC_VERIFY_0;
	m_bShutdownMode = false;
}

LRESULT CALLBACK CExtPopupMenuSite::_HookMouseProc(
	int nCode,      // hook code
	WPARAM wParam,  // message identifier
	LPARAM lParam   // mouse coordinates
	)
{

MOUSEHOOKSTRUCT* lpMS = (MOUSEHOOKSTRUCT*)lParam;
	ASSERT( lpMS != NULL );

	if( !g_DefPopupMenuSite.IsEmpty() && !g_DefPopupMenuSite.IsShutdownMode() )
	{
		CExtPopupMenuWnd * pWndCapture =
			g_DefPopupMenuSite.GetCapture();
		if( pWndCapture != NULL
			&& ::IsWindow( pWndCapture->GetSafeHwnd() )
			)
		{
			ASSERT_VALID( pWndCapture );
			switch( wParam )
			{
			//case WM_MOUSEACTIVATE:
			//	if( lpMS->hwnd != pWndCapture->GetSafeHwnd() )
			//		return 1;
			//break;

			case WM_MOUSEMOVE:
			{
				CPoint pt( lpMS->pt );
				pWndCapture->ScreenToClient( &pt );
				bool bNoEat = false;
				if(	pWndCapture->
						_OnMouseMove(
							wParam,
							pt,
							bNoEat
							)
					)
					return 1; // eat!
				if( bNoEat )
					return
						::CallNextHookEx(
							g_DefPopupMenuSite.m_hMouseHook,
							nCode,
							wParam,
							lParam
							);
			}
			break;

			case WM_MOUSEWHEEL:
			{
				bool bNoEat = false;
				if(	pWndCapture->
						_OnMouseWheel(
							wParam,
							lParam,
							bNoEat
							)
					)
					return 1; // eat!
				if( bNoEat )
					return
						::CallNextHookEx(
							g_DefPopupMenuSite.m_hMouseHook,
							nCode,
							wParam,
							lParam
							);
				return 1; // eat!
			}
			break;

			case WM_NCLBUTTONDOWN:
			case WM_NCRBUTTONDOWN:
			case WM_NCMBUTTONDOWN:
			case WM_LBUTTONDOWN:
			case WM_RBUTTONDOWN:
			case WM_MBUTTONDOWN:

			case WM_NCLBUTTONUP:
			case WM_NCRBUTTONUP:
			case WM_NCMBUTTONUP:
			case WM_LBUTTONUP:
			case WM_RBUTTONUP:
			case WM_MBUTTONUP:
			{
				//CRect rcWndCapture;
				//_pWndCapture->GetWindowRect( &rcWndCapture );
				//if( !rcWndCapture.PtInRect(lpMS->pt) )
				//	break;
				CPoint ptSrc( lpMS->pt );
				pWndCapture->ScreenToClient( &ptSrc );

				bool bNoEat = false;
				if(	pWndCapture->_OnMouseClick(
						wParam,
						ptSrc,
						bNoEat
						)
					)
					return 1; // eat!
				if( bNoEat )
					return
						::CallNextHookEx(
							g_DefPopupMenuSite.m_hMouseHook,
							nCode,
							wParam,
							lParam
							);
			
				// post processing			
				CPoint pt( lpMS->pt );
				for(	CExtPopupMenuWnd * pPopup = pWndCapture;
						pPopup != NULL;
						pPopup = pPopup->m_pWndParentMenu
						)
				{
					CPoint ptClient( pt );
					pPopup->ScreenToClient( &ptClient );
					if( pPopup->_PtInWndArea(ptClient) )
						return 1; // eat!
					HWND hWndTest = pPopup->m_wndToolTip.GetSafeHwnd();
					if(		hWndTest != NULL
						&&	hWndTest == (::WindowFromPoint(pt))
						)
						return 1; // eat!
				}

				pPopup = CExtPopupMenuSite::g_DefPopupMenuSite.GetInstance();
				ASSERT_VALID( pPopup );
				ASSERT( ::IsWindow(pPopup->GetSafeHwnd()) );
				pPopup->_OnCancelMode();
				
				if(		wParam != WM_LBUTTONDOWN
					&&	wParam != WM_RBUTTONDOWN
					&&	wParam != WM_MBUTTONDOWN
					)
					// currently NC areas are not safe on MDI apps
					return 1; // eat!
			}
			break;

			//default:
			//	return 1; // eat!
			} // switch( wParam )
		} // if( pWndCapture != NULL ....
		else
			return 1; // eat
	} // if( !g_DefPopupMenuSite.IsEmpty() && !g_DefPopupMenuSite.IsShutdownMode() )
	return
		::CallNextHookEx(
			g_DefPopupMenuSite.m_hMouseHook,
			nCode,
			wParam,
			lParam
			);
}

LRESULT CALLBACK CExtPopupMenuSite::_HookKeyboardProc(
	int nCode,      // hook code
	WPARAM wParam,  // virtual-key code
	LPARAM lParam   // keystroke-message information
	)
{

	if( !g_DefPopupMenuSite.IsEmpty() && !g_DefPopupMenuSite.IsShutdownMode() )
	{
		CExtPopupMenuWnd * pWndCapture =
			g_DefPopupMenuSite.GetCapture();
		if(	pWndCapture->GetSafeHwnd() != NULL
			&& ::IsWindow( pWndCapture->GetSafeHwnd() )
			)
		{
			ASSERT_VALID( pWndCapture );
			if( (lParam & (1<<31)) == 0 )
			{
				// clocks allows to fix problem with
				// duplicated fast key hook calls
				static clock_t _clock_step =
					CLOCKS_PER_SEC / 50; // 1/50 of second
				static clock_t _clock_last =
					0; //clock();
				clock_t _clock_curr =
					clock();
				//ASSERT( _clock_curr >= _clock_last );
				clock_t _clock_diff =
					abs(_clock_curr - _clock_last);
				if( _clock_diff >= _clock_step )
				{
					_clock_last = _clock_curr;
					bool bNoEat = false;
					if(	pWndCapture->
							_OnKeyDown(
								wParam,
								LOWORD(lParam),
								HIWORD(lParam),
								bNoEat
								)
						)
						return 1; // eat!
					if( bNoEat )
						return
							::CallNextHookEx(
								g_DefPopupMenuSite.m_hKeyboardHook,
								nCode,
								wParam,
								lParam
								);
					if( pWndCapture != NULL )
						return 1; // eat!
				}
			} // if( (lParam & (1<<31)) == 0 )
			else
			{
				// 2.21 fix for dlg sys menu
				return 1; // eat!
			}
		}
//		if( !CExtToolControlBar::g_bMenuTracking )
//			return 1; // eat!
	} // if( !g_DefPopupMenuSite.IsEmpty() && !g_DefPopupMenuSite.IsShutdownMode() )

	if(		(!CExtToolControlBar::g_bMenuTracking)
		&&	CExtPopupMenuWnd::IsCmdKeyActivation( lParam )
		&&	( lParam & (1<<31) ) != 0
		)
	{
		CExtPopupMenuWnd::CancelMenuTracking();
		return
			::CallNextHookEx(
				g_DefPopupMenuSite.m_hKeyboardHook,
				nCode,
				wParam,
				lParam
				);
	}

	return
		::CallNextHookEx(
			g_DefPopupMenuSite.m_hKeyboardHook,
			nCode,
			wParam,
			lParam
			);
}

void CExtPopupMenuSite::_Hook(
	bool bHook // = true
	)
{
	if( bHook )
	{
		if( m_hMouseHook == NULL )
		{
			m_hMouseHook =
				::SetWindowsHookEx(
					WH_MOUSE,
					_HookMouseProc, 
					0,
					::GetCurrentThreadId()
					);
			ASSERT( m_hMouseHook != NULL );
		}
		if( m_hKeyboardHook == NULL )
		{
			m_hKeyboardHook =
				::SetWindowsHookEx(
					WH_KEYBOARD,
					_HookKeyboardProc, 
					0,
					::GetCurrentThreadId()
					);
			ASSERT( m_hKeyboardHook != NULL );
		}
	} // if( bHook )
	else
	{
		if( m_hMouseHook != NULL )
		{
			::UnhookWindowsHookEx( m_hMouseHook );
			m_hMouseHook = NULL;
		}
		if( m_hKeyboardHook != NULL )
		{
			::UnhookWindowsHookEx( m_hKeyboardHook );
			m_hKeyboardHook = NULL;
		}
	} // else from if( bHook )
}

/////////////////////////////////////////////////////////////////////////////
// CExtWndShadow

CExtWndShadow::CExtWndShadow()
{
	Destroy();
}

CExtWndShadow::~CExtWndShadow()
{
	Destroy();
}

void CExtWndShadow::_DoPixelOvershadow(
	int nMakeSpec,
	int nPosX,
	int nPosY,
	COLORREF clrShadowAdjust
	)
{
	ASSERT( nMakeSpec >= 0 && nMakeSpec <= 100 );
	ASSERT( !m_rcWndArea.IsRectEmpty() );
	ASSERT( nPosX < m_rcWndArea.Width() + INT(m_nShadowSize) );
	ASSERT( nPosY < m_rcWndArea.Height() + INT(m_nShadowSize) );
	ASSERT( m_pHelperDibSurface != NULL );
int nTotalWidth = m_rcWndArea.Width()+m_nShadowSize;
int nTotalHeight = m_rcWndArea.Height()+m_nShadowSize;
COLORREF * ptr =
		m_pHelperDibSurface
		+ nPosX
		+ (nTotalHeight-nPosY)*nTotalWidth;
COLORREF clrAdj = *ptr;
	if( clrShadowAdjust != ((COLORREF)(-1)) )
	{
		int nMakeSpecR = nMakeSpec + ::MulDiv( (100-nMakeSpec), GetBValue(clrShadowAdjust), 255 );
		int nMakeSpecG = nMakeSpec + ::MulDiv( (100-nMakeSpec), GetGValue(clrShadowAdjust), 255 );
		int nMakeSpecB = nMakeSpec + ::MulDiv( (100-nMakeSpec), GetRValue(clrShadowAdjust), 255 );
		if( nMakeSpecR > 100 )
			nMakeSpecR = 100;
		if( nMakeSpecG > 100 )
			nMakeSpecG = 100;
		if( nMakeSpecB > 100 )
			nMakeSpecB = 100;
		clrAdj = 
			RGB(
				(( nMakeSpecR * int(GetRValue(clrAdj)) ) / 100),
				(( nMakeSpecG * int(GetGValue(clrAdj)) ) / 100),
				(( nMakeSpecB * int(GetBValue(clrAdj)) ) / 100)
				);
	} // if( clrShadowAdjust != ((COLORREF)(-1)) )
	else
	{
		clrAdj = 
			RGB(
				(( nMakeSpec * int(GetRValue(clrAdj)) ) / 100),
				(( nMakeSpec * int(GetGValue(clrAdj)) ) / 100),
				(( nMakeSpec * int(GetBValue(clrAdj)) ) / 100)
				);
	} // else from if( clrShadowAdjust != ((COLORREF)(-1)) )
	*ptr = clrAdj;
}

bool CExtWndShadow::Restore( CDC & dc )
{
	ASSERT( m_nShadowSize >= 0 );
	if( m_nShadowSize == 0 || m_rcWndArea.IsRectEmpty () )
		return true;
	if(		m_bmp0.GetSafeHandle() == NULL
		||	m_bmp1.GetSafeHandle() == NULL
		)
		return false;

INT nWndAreaDX = m_rcWndArea.Width ();
INT nWndAreaDY = m_rcWndArea.Height ();
	ASSERT( nWndAreaDX > 0 && nWndAreaDY > 0 );
CDC dcmm;
	if( !dcmm.CreateCompatibleDC(&dc) )
	{
		ASSERT( FALSE );
		return false;
	}
CBitmap * pbmpold = dcmm.SelectObject( &m_bmp0 );
	ASSERT( pbmpold != NULL );
	dc.BitBlt(
		m_rcWndArea.right, m_rcWndArea.top,
		m_nShadowSize, nWndAreaDY+m_nShadowSize,
		&dcmm,
		0, 0,
		SRCCOPY
		);
	dcmm.SelectObject( &m_bmp1 );
	dc.BitBlt(
		m_rcWndArea.left, m_rcWndArea.bottom,
		nWndAreaDX+m_nShadowSize, m_nShadowSize,
		&dcmm,
		0, 0,
		SRCCOPY
		);
	dcmm.SelectObject( pbmpold );
	return true;
}

bool CExtWndShadow::Paint(
	CDC & dc,
	const CRect & rcWndArea,
	const CRect & rc1stArea, // = CRect(0,0,0,0)
	const CRect & rc2ndArea, // = CRect(0,0,0,0)
	UINT nShadowSize, // = DEF_SHADOW_SIZE
	UINT nBr0, // = DEF_BRIGHTNESS_MIN
	UINT nBr1, // = DEF_BRIGHTNESS_MAX
	bool bEnablePhotos, // = true
	bool bEnablePaingMgrColor // = true
	)
{
	m_rcWndArea = rcWndArea;
	m_rc1stArea = rc1stArea;
	m_rc2ndArea = rc2ndArea;
	m_nShadowSize = nShadowSize;
	m_nBr0 = nBr0;
	m_nBr1 = nBr1;
	m_bEnablePhotos = bEnablePhotos;
	m_bEnablePaingMgrColor = bEnablePaingMgrColor;
	return Paint( dc );
}

bool CExtWndShadow::Paint( CDC & dc )
{
	ASSERT( m_nShadowSize >= 0 );
	ASSERT( !m_rcWndArea.IsRectEmpty() );
	if( m_nShadowSize == 0 || m_rcWndArea.IsRectEmpty() )
		return true;

	if( Restore( dc ) )
		return true;

	if( CExtPaintManager::stat_GetBPP() > 8 )
		return _PaintHi( dc );
	return _PaintLo( dc );
}

bool CExtWndShadow::_PaintLo( CDC & dc )
{
INT nWndAreaDX = m_rcWndArea.Width();
INT nWndAreaDY = m_rcWndArea.Height();
	ASSERT(
			m_bmp0.GetSafeHandle() == NULL
		&&	m_bmp1.GetSafeHandle() == NULL
		);
static int _Pattern[] =
{
	~0xAA,
	~0x55,
	~0xAA,
	~0x55,
	~0xAA,
	~0x55,
	~0xAA,
	~0x55
};
CBitmap bmpsh;
CBrush brsh;
	if(		!bmpsh.CreateBitmap(8, 8, 1, 1, _Pattern)
		||	!brsh.CreatePatternBrush( &bmpsh )
		)
		return false;
CExtMemoryDC dcmm(
		&dc,
		NULL,
		CExtMemoryDC::MDCOPT_TO_MEMORY
		);
	ASSERT( dcmm.GetSafeHdc() != NULL );
	if( dcmm.GetSafeHdc() == NULL )
		return false;
CPalette * pOldPalette = NULL;
    if( dcmm.GetDeviceCaps(RASTERCAPS) & RC_PALETTE )
	{
        pOldPalette =
			dcmm.SelectPalette( &g_PaintManager->m_PaletteWide, FALSE );
        dcmm.RealizePalette();
    }
	dcmm.BitBlt(
		m_rcWndArea.left, m_rcWndArea.top,
		nWndAreaDX+m_nShadowSize, nWndAreaDY+m_nShadowSize,
		&dc,
		m_rcWndArea.left, m_rcWndArea.top,
		SRCCOPY
		);
UINT nPaintShadowSize =
		( m_nShadowSize > 4 )
			? 4
			: m_nShadowSize;
CRect rV(
		 m_rcWndArea.right,
		 m_rcWndArea.top+nPaintShadowSize,
		 m_rcWndArea.right+nPaintShadowSize,
		 m_rcWndArea.bottom
		 );
CRect rH(
		 m_rcWndArea.left+nPaintShadowSize,
		 m_rcWndArea.bottom,
		 m_rcWndArea.right+nPaintShadowSize,
		 m_rcWndArea.bottom+nPaintShadowSize
		 );
CBrush * pbrold = dcmm.SelectObject( &brsh );
	dcmm.PatBlt( rH.left, rH.top, rH.Width(), rH.Height(), 0xA000C9 );
	dcmm.PatBlt( rV.left, rV.top, rV.Width(), rV.Height(), 0xA000C9 );
	dcmm.SelectObject( pbrold );
	dc.BitBlt(
		m_rcWndArea.left, m_rcWndArea.top,
		nWndAreaDX+m_nShadowSize, nWndAreaDY+m_nShadowSize, 
		&dcmm,
		m_rcWndArea.left, m_rcWndArea.top,
		SRCCOPY
		);
	if( m_bEnablePhotos )
	{
		if( !_MakePhotos(dc,dcmm) )
		{
			ASSERT( FALSE );
			return false;
		}
	}
	if( pOldPalette != NULL )
		dcmm.SelectPalette( pOldPalette, FALSE );
	dcmm.__Flush( FALSE );
	return true;
}

bool CExtWndShadow::_PaintHi( CDC & dc )
{
INT nWndAreaDX = m_rcWndArea.Width();
INT nWndAreaDY = m_rcWndArea.Height();
	ASSERT(
			m_bmp0.GetSafeHandle() == NULL
		&&	m_bmp1.GetSafeHandle() == NULL
		);
CDC dcmm;
	if( !dcmm.CreateCompatibleDC( &dc ) )
	{
		ASSERT( FALSE );
		return false;
	}

COLORREF clrShadowAdjust = ((COLORREF)(-1));
	if( m_bEnablePaingMgrColor )
		clrShadowAdjust = g_PaintManager->GetShadowAdjustColor();

BITMAPINFOHEADER bih;
	bih.biSize = sizeof(BITMAPINFOHEADER);
	bih.biWidth = nWndAreaDX+m_nShadowSize;
	bih.biHeight = nWndAreaDY+m_nShadowSize;
	bih.biPlanes = 1;
	bih.biBitCount = 32;
	bih.biCompression = BI_RGB;
	bih.biSizeImage = (nWndAreaDX+m_nShadowSize) * (nWndAreaDY+m_nShadowSize);
	bih.biXPelsPerMeter = 0;
	bih.biYPelsPerMeter = 0;
	bih.biClrUsed = 0;
	bih.biClrImportant = 0;

	ASSERT( m_pHelperDibSurface == NULL );
HBITMAP hDIB =
		::CreateDIBSection(
			dcmm.GetSafeHdc(),
			(LPBITMAPINFO)&bih,
			DIB_RGB_COLORS,
			(void **)&m_pHelperDibSurface,
			NULL,
			NULL
			);
	if( hDIB == NULL || m_pHelperDibSurface == NULL )
	{
		ASSERT( FALSE );
		return false;
	}

	dcmm.SelectObject( hDIB );
	dcmm.BitBlt(
		0, 0,
		nWndAreaDX+m_nShadowSize, nWndAreaDY+m_nShadowSize,
		&dc,
		m_rcWndArea.left, m_rcWndArea.top,
		SRCCOPY
		);

UINT nBrDiff = m_nBr1-m_nBr0;
LONG n2nd, nStep, nDist, nDist1;
LONG nDist2 = m_nShadowSize*m_nShadowSize;
INT nMakeSpec;
bool	bCmbaV = false, bCmbaH = false,
		bCmbaVrt = false, bCmbaVrb = false,
		bCmbaHrb = false, bCmbaHlb = false,
		bCmbaLA = false;
INT		nX0 = 0, nX1 = nWndAreaDX,
		nY0 = 0, nY1 = nWndAreaDY,
		nLa0 = 0, nLa1 = 0;
	if( !( m_rc1stArea.IsRectEmpty() || m_rc2ndArea.IsRectEmpty() ) )
	{
		bool bCmbaDetected = false;
		if( m_rc1stArea.right == m_rc2ndArea.right )
		{ // vertical-right combining
			bCmbaDetected = true;
			if( m_rc1stArea.top < m_rc2ndArea.top )
				bCmbaVrb = true;
			else
				bCmbaVrt = true;
		} // vertical-right combining
		if( (!bCmbaDetected) &&
			m_rc1stArea.left == m_rc2ndArea.left )
		{ // vertical-left combining
			if( m_rc2ndArea.bottom >= m_rc1stArea.top-1
				&& m_rc2ndArea.top < m_rc1stArea.top
				)
			{
				if( m_rc2ndArea.right >= m_rc1stArea.right )
				{
					bCmbaDetected = true;
					bCmbaV = true;
				}
			}
			if(	(!bCmbaDetected)
				&& m_rc1stArea.bottom >= m_rc2ndArea.top-1 
				&& m_rc1stArea.top < m_rc2ndArea.top
				)
			{
				if( m_rc1stArea.right >= m_rc2ndArea.right )
				{
					bCmbaDetected = true;
					bCmbaH = true;
					nX0 =
						m_rcWndArea.right  -
						(m_rc1stArea.right - m_rc2ndArea.right);
				}
			}
		} // vertical-left combining
		if( (!bCmbaDetected) &&
			m_rc1stArea.bottom == m_rc2ndArea.bottom
			)
		{ // horizontal-bottom combining
			bCmbaDetected = true;
			if( m_rc1stArea.left < m_rc2ndArea.left )
				bCmbaHrb = true;
			else
				bCmbaHlb = true;
		} // horizontal-bottom combining
		if( (!bCmbaDetected) &&
			m_rc1stArea.right == m_rc2ndArea.left+1
			)
		{
			bCmbaDetected = true;
			bCmbaLA = true;
			nLa0 = m_rcWndArea.top
				+ m_rc2ndArea.bottom - m_rc1stArea.top;
			nLa1 = nLa0 + m_nShadowSize;
		}
		if( (!bCmbaDetected) &&
			m_rc1stArea.left == m_rc2ndArea.right-1
			)
		{
			bCmbaDetected = true;
			bCmbaH = true;
		}
		bCmbaDetected;
	} // if( !( m_rc1stArea.IsRectEmpty() || m_rc2ndArea.IsRectEmpty() ) )
	for( nStep = 0; ULONG(nStep) < m_nShadowSize; nStep++ )
	{
		nMakeSpec = m_nBr0+(nStep*nBrDiff)/m_nShadowSize;
		for(	n2nd = nX0
					+ m_nShadowSize*2+1
					- ( bCmbaH ? (m_nShadowSize*2-nStep) : 0 )
					- ( bCmbaHlb ? m_nShadowSize : 0 )
					;
				n2nd < LONG(nX1) + (bCmbaHrb ? LONG(m_nShadowSize) : 0);
				n2nd++
				)
			_DoPixelOvershadow(
				nMakeSpec,
				n2nd,
				nY1 + nStep,
				clrShadowAdjust
				);
		for(	n2nd = nY0
					+ m_nShadowSize*2+1
					- ( bCmbaV ? (m_nShadowSize*2-nStep) : 0 )
					- ( bCmbaVrt ? m_nShadowSize : 0 )
					;
				n2nd < LONG(nY1) + (bCmbaVrb ? LONG(m_nShadowSize) : 0);
				n2nd++
				)
		{
			if( bCmbaLA
				&& n2nd >= nLa0
				&& n2nd < LONG(nLa1) - (LONG(m_nShadowSize) - nStep)
				)
			{
				continue;
			}
			_DoPixelOvershadow(
				nMakeSpec,
				nX1 + nStep,
				n2nd,
				clrShadowAdjust
				);
		}
		nDist1 = nStep*nStep;
		for( n2nd = 0; ULONG(n2nd) < m_nShadowSize; n2nd++ )
		{
			nDist = nDist1 + n2nd*n2nd;
			if( nDist > nDist2 )
				continue;
			nDist = (LONG)::sqrt( double(nDist) );
			nMakeSpec = m_nBr0+(nDist*nBrDiff)/m_nShadowSize;
			if( !(bCmbaVrb || bCmbaHrb) )
				_DoPixelOvershadow(
					nMakeSpec,
					nX1+nStep,
					nY1+n2nd,
					clrShadowAdjust
					);
			if( !(bCmbaH || bCmbaHlb) )
				_DoPixelOvershadow(
					nMakeSpec,
					m_nShadowSize+(m_nShadowSize-nStep),
					nY1 + n2nd,
					clrShadowAdjust
					);
			if( !(bCmbaV || bCmbaVrt) )
				_DoPixelOvershadow(
					nMakeSpec,
					nX1 + nStep,
					m_nShadowSize+(m_nShadowSize-n2nd),
					clrShadowAdjust
					);
		} // for( n2nd = 0; ULONG(n2nd) < m_nShadowSize; n2nd++ )
	} // for( nStep = 0; ULONG(nStep) < m_nShadowSize; nStep++ )
	dc.BitBlt(
		m_rcWndArea.left, m_rcWndArea.top,
		nWndAreaDX+m_nShadowSize, nWndAreaDY+m_nShadowSize, 
		&dcmm,
		0, 0,
		SRCCOPY
		);

	if( m_bEnablePhotos )
	{
		if( !_MakePhotos(dc,dcmm) )
		{
			ASSERT( FALSE );
			return false;
		}
	}

	::DeleteObject( hDIB );
	m_pHelperDibSurface = NULL;

	return true;
}

bool CExtWndShadow::_MakePhotos( CDC & dc, CDC & dcmm )
{
	ASSERT( m_nShadowSize >= 0 );
	ASSERT( !m_rcWndArea.IsRectEmpty() );
INT nWndAreaDX = m_rcWndArea.Width();
INT nWndAreaDY = m_rcWndArea.Height();
	ASSERT(
			m_bmp0.GetSafeHandle() == NULL
		&&	m_bmp1.GetSafeHandle() == NULL
		);
	if(	!m_bmp0.CreateCompatibleBitmap(
			&dc, m_nShadowSize, nWndAreaDY+m_nShadowSize
			)
		)
	{
		ASSERT( FALSE );
		return false;
	}
	dcmm.SelectObject( &m_bmp0 );
	if(	!dcmm.BitBlt(
			0, 0, m_nShadowSize, nWndAreaDY+m_nShadowSize,
			&dc,
			m_rcWndArea.right, m_rcWndArea.top,
			SRCCOPY
			)
		)
	{
		ASSERT( FALSE );
		return false;
	}
	if(	!m_bmp1.CreateCompatibleBitmap(
			&dc, nWndAreaDX+m_nShadowSize, m_nShadowSize
			)
		)
	{
		ASSERT( FALSE );
		return false;
	}
	dcmm.SelectObject( &m_bmp1 );
	if(	!dcmm.BitBlt(
			0, 0, nWndAreaDX+m_nShadowSize, m_nShadowSize,
			&dc,
			m_rcWndArea.left, m_rcWndArea.bottom,
			SRCCOPY
			)
		)
	{
		ASSERT( FALSE );
		return false;
	}
	return true;
}

void CExtWndShadow::_FreeWinObjects()
{
	if( m_bmp0.GetSafeHandle() != NULL )
		m_bmp0.DeleteObject();
	if( m_bmp1.GetSafeHandle() != NULL )
		m_bmp1.DeleteObject();
	m_pHelperDibSurface = NULL;
}

void CExtWndShadow::Destroy()
{
	_FreeWinObjects();
	m_rcWndArea.SetRectEmpty();
	m_bEnablePhotos = false;
	m_bEnablePaingMgrColor = false;
}

/////////////////////////////////////////////////////////////////////////////
// CExtPopupMenuWnd::MENUITEMDATA

CExtPopupMenuWnd::MENUITEMDATA::MENUITEMDATA()
	: m_cAccelChar( _T('\0') )
{
	// self constant type assertion
	ASSERT( TYPE_SEPARATOR==ID_SEPARATOR );
	m_pWndChild = NULL;
	m_nItemIndex = -100;
	m_nCmdID = TYPE_SEPARATOR;
#if (!defined __EXT_MFC_NO_CUSTOMIZE)
	m_pCmdNode = NULL;
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)
	m_sItemText = m_sAccelText = _T("");
	m_sizeItem.cx = m_sizeItem.cy = 0;
	m_nIconAreaWidth = 0;
	m_bSelected
		= m_bDisplayed
		= m_bForceDisplayed
		= m_bChildCombine
		= m_bToolButton
		= m_bForceEnabled
		= m_bForceNoLeftGradient
		= m_bCheck
		= m_bRadio
		= m_bIndeterminate
		= m_bXtraChecked
		= m_bNoCmdUI
		= false;
	m_pCbCmdDeliver = NULL;
	m_pCbXtraMarkState = NULL;
	m_bEnabled = true;
	m_hWndSpecCmdReciever = NULL;
	m_pHelperInplaceEditWnd = NULL;
	m_pInplaceEditStr = NULL;
	m_pCbVerifyTextInput = NULL;
	m_pCbPutTextInputResult = NULL;
	m_pInplaceEditCbWndProc = NULL;
	m_pInplaceEditCbCoockie = NULL;
	m_nInplaceEditWidth = 0;
	m_bAllowInplaceEditActivation = true;
	m_nLParam = 0L;
	m_bTempSelTextValid = false;
	m_sTempSelText.Empty();
}

CExtPopupMenuWnd::MENUITEMDATA::MENUITEMDATA(
	const CExtPopupMenuWnd::MENUITEMDATA & other
	)
	: m_cAccelChar( _T('\0') )
{
	// self constant type assertion
	ASSERT( TYPE_SEPARATOR==ID_SEPARATOR );
	m_pWndChild = NULL;
	m_nItemIndex = -100;
	m_nCmdID = TYPE_SEPARATOR;
#if (!defined __EXT_MFC_NO_CUSTOMIZE)
	m_pCmdNode = NULL;
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)
	m_sItemText = m_sAccelText = _T("");
	m_sizeItem.cx = m_sizeItem.cy = 0;
	m_nIconAreaWidth = 0;
	m_bSelected
		= m_bDisplayed
		= m_bForceDisplayed
		= m_bChildCombine
		= m_bToolButton
		= m_bForceEnabled
		= m_bForceNoLeftGradient
		= m_bCheck
		= m_bRadio
		= m_bIndeterminate
		= m_bXtraChecked
		= m_bNoCmdUI
		= false;
	m_pCbCmdDeliver = NULL;
	m_pCbXtraMarkState = NULL;
	m_bEnabled = true;
	m_hWndSpecCmdReciever = NULL;
	m_pHelperInplaceEditWnd = NULL;
	m_pInplaceEditStr = NULL;
	m_pCbVerifyTextInput = NULL;
	m_pCbPutTextInputResult = NULL;
	m_pInplaceEditCbWndProc = NULL;
	m_pInplaceEditCbCoockie = NULL;
	m_nInplaceEditWidth = 0;
	m_bAllowInplaceEditActivation = true;
	m_nLParam = 0L;
	m_bTempSelTextValid = false;
	m_sTempSelText.Empty();
	AssignFromOther( other );
}

CExtPopupMenuWnd::MENUITEMDATA::~MENUITEMDATA()
{
	// DestroyPopup();
}

CExtPopupMenuWnd::MENUITEMDATA &
	CExtPopupMenuWnd::MENUITEMDATA::operator=(
		const CExtPopupMenuWnd::MENUITEMDATA & other
		)
{
	AssignFromOther( other );
	return (*this);
}

void CExtPopupMenuWnd::MENUITEMDATA::AssignFromOther(
	const CExtPopupMenuWnd::MENUITEMDATA & other
	)
{
	// self constant type assertion
	ASSERT( TYPE_SEPARATOR==ID_SEPARATOR );

LPVOID lpvThis = (LPVOID)this;
LPVOID lpvOther = (LPVOID)(&other);
	if( lpvThis == lpvOther )
		return;
	
	m_pWndChild = other.m_pWndChild;
	m_nItemIndex = other.m_nItemIndex;
	m_nCmdID = other.m_nCmdID;
#if (!defined __EXT_MFC_NO_CUSTOMIZE)
	m_pCmdNode = other.m_pCmdNode;
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)
	m_sItemText = other.m_sItemText;
	m_sAccelText = other.m_sAccelText;
	m_iconPopup = other.m_iconPopup;
	m_sizeItem = other.m_sizeItem;
	m_nIconAreaWidth = other.m_nIconAreaWidth;
	m_bSelected = other.m_bSelected;
	m_bDisplayed = other.m_bDisplayed;
	m_bForceDisplayed = other.m_bForceDisplayed;
	m_bChildCombine = other.m_bChildCombine;
	m_bToolButton = other.m_bToolButton;
	m_bForceEnabled = other.m_bForceEnabled;
	m_bForceNoLeftGradient = other.m_bForceNoLeftGradient;
	m_cAccelChar = other.m_cAccelChar;
	m_hWndSpecCmdReciever = other.m_hWndSpecCmdReciever;
	m_bCheck = other.m_bCheck;
	m_bRadio = other.m_bRadio;
	m_pCbCmdDeliver = other.m_pCbCmdDeliver;
	m_pCbXtraMarkState = other.m_pCbXtraMarkState;
	m_bXtraChecked = other.m_bXtraChecked;
	m_bNoCmdUI = other.m_bNoCmdUI;
	m_bEnabled = other.m_bEnabled;
	m_bIndeterminate = other.m_bIndeterminate;
	m_pHelperInplaceEditWnd = other.m_pHelperInplaceEditWnd;
	m_pInplaceEditStr = other.m_pInplaceEditStr;
	m_pCbVerifyTextInput = other.m_pCbVerifyTextInput;
	m_pCbPutTextInputResult = other.m_pCbPutTextInputResult;
	m_pInplaceEditCbWndProc = other.m_pInplaceEditCbWndProc;
	m_pInplaceEditCbCoockie = other.m_pInplaceEditCbCoockie;
	m_nInplaceEditWidth = other.m_nInplaceEditWidth;
	m_bAllowInplaceEditActivation = other.m_bAllowInplaceEditActivation;
	m_nLParam = other.m_nLParam;
	m_bTempSelTextValid = other.m_bTempSelTextValid;
	m_sTempSelText = other.m_sTempSelText;
}

CRect CExtPopupMenuWnd::MENUITEMDATA::AdjustInplaceEditRect( const RECT & rcItem ) const
{
CRect rcInplaceEdit( rcItem );
int nInplaceEditWidth = GetInplaceEditWidth();
	ASSERT( nInplaceEditWidth > 0 );
	rcInplaceEdit.DeflateRect(
		1,
		2,
		1,
		2 + __EXT_MENU_VERT_DISTANCE_NORM
		);
	rcInplaceEdit.left = rcInplaceEdit.right - nInplaceEditWidth;
	if( IsPopup() )
//		rcInplaceEdit.OffsetRect(
//			- ::GetSystemMetrics(SM_CXHTHUMB),
//			0
//			);
		rcInplaceEdit.right -= ::GetSystemMetrics(SM_CXHTHUMB);
	return rcInplaceEdit;
}

UINT CExtPopupMenuWnd::MENUITEMDATA::GetCmdID() const
{
	if( IsSeparator() || IsPopup() )
		return ( (UINT) (IDC_STATIC) );
	return m_nCmdID;
}

UINT CExtPopupMenuWnd::MENUITEMDATA::SetCmdID( UINT nCmdID )
{
	// should be used only without references to command manager
	ASSERT( ! IsPopup() ); // should not be applied for popups
UINT nOldCmdID = m_nCmdID;
	m_nCmdID = nCmdID;
	return nOldCmdID;
}

bool CExtPopupMenuWnd::MENUITEMDATA::SetPopupText( __EXT_MFC_SAFE_LPCTSTR strText )
{
	SetText( strText );
	int nPos = m_sItemText.Find(_T('\t'));
	if( nPos >= 0 )
	{
		CExtSafeString sLeft = m_sItemText.Left(nPos);
		CExtSafeString sRight = m_sItemText.Right(m_sItemText.GetLength()-nPos-1);
		m_sItemText = sLeft;
		m_sAccelText = sRight;
	}
	return true;
}

bool CExtPopupMenuWnd::MENUITEMDATA::SetPopupAccelText( __EXT_MFC_SAFE_LPCTSTR strText ) // NULL if empty
{
	m_sAccelText =
		(strText == NULL) ? _T("") : strText;
	return true;
}

__EXT_MFC_SAFE_LPCTSTR CExtPopupMenuWnd::MENUITEMDATA::GetText() const
{
	if( IsSeparator() )
		return _T("");
	return m_sItemText;
}

void CExtPopupMenuWnd::MENUITEMDATA::SetText( __EXT_MFC_SAFE_LPCTSTR strText )
{
	if( IsSeparator() )
		return;
	m_sItemText = (strText != NULL) ? strText : _T("");
}

__EXT_MFC_SAFE_LPCTSTR CExtPopupMenuWnd::MENUITEMDATA::GetAccelText() const
{
	if( IsSeparator() )
		return _T("");
	return m_sAccelText;
}

void CExtPopupMenuWnd::MENUITEMDATA::SetAccelText( __EXT_MFC_SAFE_LPCTSTR strText )
{
	if( IsSeparator() )
		return;
	m_sAccelText = (strText != NULL) ? strText : _T("");
}

void CExtPopupMenuWnd::MENUITEMDATA::AccelCharInit()
{
	m_cAccelChar = _T('\0');
CExtSafeString sDisplayText( GetText() );
	if( sDisplayText.IsEmpty() )
		return;
int nIndex = sDisplayText.Find( _T('&') );
	if( nIndex + 1 == sDisplayText.GetLength() )
	{
		TRACE(_T("warning : & is bad position, access key is invalid.\n"));
		return;
	}
	if( nIndex < 0 )
	{
		if( !CExtPopupMenuWnd::g_bAllowNonAccelPositioning )
			return;
		m_cAccelChar = sDisplayText[0];
	}
	else
		m_cAccelChar = sDisplayText[nIndex + 1]; // -1 + 1 = 0; it's ok
	TCHAR szChar[2] = { m_cAccelChar, _T('\0') };
	::CharUpper( szChar );
	m_cAccelChar = szChar[0];
}

__EXT_MFC_SAFE_TCHAR CExtPopupMenuWnd::MENUITEMDATA::AccelCharGet() const
{
	return __EXT_MFC_SAFE_TCHAR( m_cAccelChar );
}

bool CExtPopupMenuWnd::MENUITEMDATA::AccelCharIsSet() const
{
	return (m_cAccelChar == _T('\0') ) ? false : true;
}

bool CExtPopupMenuWnd::MENUITEMDATA::UpdateCmdManagerCommand(
	CExtCmdItem * pCmdItem,
	int nItemIndex
	)
{
	ASSERT( pCmdItem != NULL );
	ASSERT( !IsPopup() );
	ASSERT( m_pWndChild == NULL );
	m_sItemText.Empty();
	m_sAccelText.Empty();
	m_nCmdID = pCmdItem->m_nCmdID;
	if( !CExtCmdManager::IsCommand(m_nCmdID) )
	{
		m_nCmdID = TYPE_SEPARATOR;
		m_nItemIndex = -100;
		ASSERT( FALSE );
		return false;
	}
	if( nItemIndex >= 0 )
		m_nItemIndex = nItemIndex;
	SetText( pCmdItem->m_sMenuText );
	SetAccelText( pCmdItem->m_sAccelText );
	AccelCharInit();
	MeasureItem();
	return true;
}

CExtCmdItem * CExtPopupMenuWnd::MENUITEMDATA::GetCmd() const
{
	if( IsSeparator() || IsNoCmdUI() )
		return NULL;
#if (!defined __EXT_MFC_NO_CUSTOMIZE)
	CExtCustomizeCmdTreeNode * pNode = ((MENUITEMDATA*)this)->GetCmdNode();
	if(		pNode != NULL
		&&	(	(pNode->GetFlags() & __ECTN_TBB_COLOR) != NULL
			||	IsInplaceEdit()
			)
		)
	{
		CExtCmdItem * pCmdItem =
			g_CmdManager->CmdGetPtr(
				g_CmdManager->ProfileNameFromWnd( GetCmdReciever() ),
				pNode->GetCmdID( false )
				);
		ASSERT( pCmdItem != NULL );
		return pCmdItem;
	} // if( pNode != NULL ...
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)
	if( IsPopup() )
		return NULL;
CExtCmdItem * pCmdItem =
		g_CmdManager->CmdGetPtr(
			g_CmdManager->ProfileNameFromWnd( GetCmdReciever() ),
			m_nCmdID
			);
	//ASSERT( pCmdItem != NULL );
	return pCmdItem;
}

#if (!defined __EXT_MFC_NO_CUSTOMIZE)
CExtCustomizeCmdTreeNode * CExtPopupMenuWnd::MENUITEMDATA::GetCmdNode()
{
#ifdef _DEBUG
	if( m_pCmdNode != NULL )
	{
		ASSERT_VALID( m_pCmdNode );
	}
#endif // _DEBUG
	return m_pCmdNode;
}
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)

void CExtPopupMenuWnd::MENUITEMDATA::MeasureItem()
{
	AccelCharInit();
	m_nIconAreaWidth = __EXT_MENU_ICON_CX;
	if( IsSeparator() )
	{
		m_sizeItem.cx = 0;
		m_sizeItem.cy = __EXT_MENU_SEPARATOR_HEIGHT;
		return;
	}
CExtSafeString sMeasureText( GetText() );
	if( !IsInplaceEdit() )
		sMeasureText += (LPCTSTR)GetAccelText();
	sMeasureText.Replace( _T("&"), _T("") );
CWindowDC dc(NULL);
CFont * pOldFont =
		dc.SelectObject( &(g_PaintManager->m_FontNormal) );
	ASSERT( pOldFont != NULL );
CRect rect( 0, 0, 0, 0 );
	::DrawText(
		dc.GetSafeHdc(),
		sMeasureText,
		sMeasureText.GetLength(),
		&rect,
		DT_CALCRECT|DT_SINGLELINE|DT_LEFT
		);
	m_sizeItem.cx = rect.Width();
	m_sizeItem.cy = rect.Height() + __EXT_MENU_IMG_RECT_OUT_GAP*2;
	dc.SelectObject( pOldFont );

CSize sizeIcon( 0, 0 );
int nIconHeightMetric = 0;
	if( !IsToolButton() )
	{
		CExtCmdIcon * pIcon = GetIconPtr();
		if( pIcon != NULL )
		{
			sizeIcon = pIcon->GetSize();
			if( g_bMenuLargeIcons )
			{
				sizeIcon.cx *= 2;
				sizeIcon.cy *= 2;
			} // if( g_bMenuLargeIcons )
			if( sizeIcon.cx < __EXT_MENU_ICON_CX )
				sizeIcon.cx = __EXT_MENU_ICON_CX;
			if( sizeIcon.cy < __EXT_MENU_ICON_CY )
				sizeIcon.cy = __EXT_MENU_ICON_CY;
			if(	sizeIcon.cx <= 18 && sizeIcon.cy < sizeIcon.cx )
				sizeIcon.cy = sizeIcon.cx;
			m_nIconAreaWidth =
				max( m_nIconAreaWidth, sizeIcon.cx );
			nIconHeightMetric = sizeIcon.cy + __EXT_MENU_IMG_RECT_OUT_GAP*2;
		} // if( pIcon != NULL )
	} // if( !IsToolButton() )

	m_sizeItem.cy = max( m_sizeItem.cy, nIconHeightMetric );
	if( m_sizeItem.cy < __EXT_MENU_MIN_HEIGHT )
		m_sizeItem.cy = __EXT_MENU_MIN_HEIGHT;
	if( IsToolButton() && sizeIcon.cy == 0 )
		m_sizeItem.cy -= 2;
	m_nIconAreaWidth = max( sizeIcon.cx, m_sizeItem.cy );

	if( IsExtraMark() )
	{
		m_nIconAreaWidth *= 2;
		m_nIconAreaWidth += 4;
	} // if( IsExtraMark() )
	
	m_sizeItem.cx +=
		__EXT_MENU_GAP * 7;
	if( IsInplaceEdit() )
	{
		m_sizeItem.cx += m_nInplaceEditWidth + 2 + 10;
//		if( IsPopup() )
//			m_sizeItem.cx += ::GetSystemMetrics(SM_CXHTHUMB);
	} // if( IsInplaceEdit() )
	else if( IsToolButton() )
	{
		m_sizeItem.cx +=
			__DROPDOWN_ARROW_GAP * 2
			+ __EXT_MENU_TOOLBTN_GAP * 2;
		m_sizeItem.cy += __EXT_MENU_VERT_DISTANCE_NORM;
	} // if( IsToolButton() )
	else
	{
		m_sizeItem.cx +=
			m_nIconAreaWidth // sizeIcon.cx
			+ __EXT_MENU_POPUP_ARROW_AREA_DX;
		m_sizeItem.cy += __EXT_MENU_VERT_DISTANCE_TOOL;
	} // else from if( IsToolButton() )

}

bool CExtPopupMenuWnd::MENUITEMDATA::UpdateFromMenu(
	HWND hWndCmdProfileInfo,
	CMenu * pTrackMenu,
	int nItemIndex
	)
{
	ASSERT( pTrackMenu != NULL );
	ASSERT( pTrackMenu->GetSafeHmenu() != NULL );
	
#ifdef _DEBUG
	int	nMenuItemCount = pTrackMenu->GetMenuItemCount();
	ASSERT( nMenuItemCount > 0 );
	ASSERT( nItemIndex >= 0 && nItemIndex<nMenuItemCount );
#endif // _DEBUG

MENUITEMINFO _mii;
	::memset( &_mii, 0, sizeof(MENUITEMINFO) );
	_mii.cbSize = sizeof(MENUITEMINFO);
	_mii.fMask =
		MIIM_CHECKMARKS
		|MIIM_DATA
		|MIIM_ID
		|MIIM_STATE
		|MIIM_SUBMENU
		|MIIM_TYPE
		;
	_mii.cch = __MAX_UI_ITEM_TEXT;
CExtSafeString _sItemText;
	_mii.dwTypeData =
		_sItemText.GetBuffer(__MAX_UI_ITEM_TEXT);
	ASSERT( _mii.dwTypeData != NULL );
	if( _mii.dwTypeData == NULL )
	{
		ASSERT( FALSE );
		return false;
	}
	if( !pTrackMenu->GetMenuItemInfo(
			nItemIndex,
			&_mii,
			TRUE
			)
		)
	{
		_sItemText.ReleaseBuffer();
		ASSERT( FALSE );
		return false;
	}
	_sItemText.ReleaseBuffer();

	m_nItemIndex = nItemIndex;
	if( (_mii.fType&MFT_SEPARATOR) != 0 )
	{
		m_sItemText.Empty();
		m_nCmdID = TYPE_SEPARATOR;
		MeasureItem();
		return true;
	}

	if( _mii.hSubMenu != NULL )
	{
		if( !ConstructPopup() )
		{
			ASSERT( FALSE );
			return false;
		}
		m_nCmdID = (UINT)TYPE_POPUP;
		SetPopupText( _sItemText );
		MeasureItem();
		return true;
	}

//	m_sItemText.Empty();
	if( !CExtCmdManager::IsCommand(_mii.wID) )
	{
		ASSERT( FALSE );
		return false;
	}
	m_nCmdID = _mii.wID;
	CExtCmdItem * pCmdItem =
		g_CmdManager->CmdGetPtr(
			g_CmdManager->ProfileNameFromWnd( hWndCmdProfileInfo ),
			m_nCmdID
			);
	ASSERT( pCmdItem != NULL );
	if( pCmdItem == NULL )
		return false;

	if( _sItemText.IsEmpty() )
		_sItemText = pCmdItem->m_sMenuText;
	if( _sItemText.IsEmpty() )
		_sItemText = pCmdItem->m_sToolbarText;
	SetPopupText( _sItemText );
	MeasureItem();
	return true;
}

#if (!defined __EXT_MFC_NO_CUSTOMIZE)

#if (!defined __EXT_MFC_NO_BUILTIN_TEXTFIELD)

bool CExtPopupMenuWnd::MENUITEMDATA::stat_CbVerifyTextInput(
	CInPlaceEditWnd & wndEdit,
	CExtCustomizeCmdTreeNode * pNode,
	__EXT_MFC_SAFE_LPCTSTR sTextOld,
	__EXT_MFC_SAFE_LPCTSTR sTextNew
	)
{
	ASSERT_VALID( pNode );
	ASSERT( sTextOld != NULL );
	ASSERT( sTextNew != NULL );
	ASSERT(
			wndEdit.GetSafeHwnd() != NULL
		&&	::IsWindow( wndEdit.GetSafeHwnd() )
		);
CExtCustomizeSite * pSite =
		CExtCustomizeSite::GetCustomizeSite( wndEdit.GetSafeHwnd() );
	if( pSite == NULL )
		return true;
	return
		pSite->OnTextFieldVerify(
			NULL,
			pNode,
			sTextOld,
			sTextNew
			);
}

void CExtPopupMenuWnd::MENUITEMDATA::stat_CbPutTextInputResult(
	CInPlaceEditWnd & wndEdit,
	CExtCustomizeCmdTreeNode * pNode,
	__EXT_MFC_SAFE_LPCTSTR sTextNew
	)
{
	ASSERT_VALID( pNode );
	ASSERT( sTextNew != NULL );
	ASSERT(
			wndEdit.GetSafeHwnd() != NULL
		&&	::IsWindow( wndEdit.GetSafeHwnd() )
		);
CExtCustomizeSite * pSite =
		CExtCustomizeSite::GetCustomizeSite( wndEdit.GetSafeHwnd() );
	if( pSite == NULL )
		return;
	pSite->OnTextFieldInplaceTextSet(
		NULL,
		pNode,
		pNode->m_sDefInplaceEditBuffer,
		sTextNew
		);
}

bool CExtPopupMenuWnd::MENUITEMDATA::stat_CbInplaceEditWndProc(
	LRESULT & lResult,
	UINT message,
	WPARAM wParam,
	LPARAM lParam,
	CEdit & wndEdit,
	CExtCustomizeCmdTreeNode * pNode
	)
{
	if( message == CExtCustomizeSite::g_nMsgQueryCustomizeSite )
		return false;
	if( (wndEdit.GetStyle() & WS_VISIBLE) == 0 )
		return false;
	ASSERT_VALID( pNode );
	ASSERT(
			wndEdit.GetSafeHwnd() != NULL
		&&	::IsWindow( wndEdit.GetSafeHwnd() )
		);
CExtCustomizeSite * pSite =
		CExtCustomizeSite::GetCustomizeSite( wndEdit.GetSafeHwnd() );
	if( pSite == NULL )
		return false;
	return
		pSite->OnTextFieldWndProcHook(
			lResult,
			message,
			wParam,
			lParam,
			wndEdit,
			NULL,
			pNode
			);
}

bool CExtPopupMenuWnd::MENUITEMDATA::stat_CbInitListBoxContent(
	CExtPopupInplaceListBox & wndListBox,
	CExtCustomizeCmdTreeNode * pNode
	)
{
	ASSERT_VALID( pNode );
	ASSERT(
			wndListBox.GetSafeHwnd() != NULL
		&&	::IsWindow( wndListBox.GetSafeHwnd() )
		);
CExtCustomizeSite * pSite =
		CExtCustomizeSite::GetCustomizeSite( wndListBox.GetSafeHwnd() );
	if( pSite == NULL )
		return false;
	return
		pSite->OnPopupListBoxInitContent(
			NULL,
			pNode,
			wndListBox
			);
}

bool CExtPopupMenuWnd::MENUITEMDATA::stat_CbListBoxSelection(
	CExtPopupInplaceListBox & wndListBox,
	CExtCustomizeCmdTreeNode * pNode,
	int eSAT // CExtPopupInplaceListBox::e_sel_action_t
	)
{
	ASSERT_VALID( pNode );
	ASSERT(
			wndListBox.GetSafeHwnd() != NULL
		&&	::IsWindow( wndListBox.GetSafeHwnd() )
		);
CExtCustomizeSite * pSite =
		CExtCustomizeSite::GetCustomizeSite( wndListBox.GetSafeHwnd() );
	if( pSite == NULL )
		return false;
	switch( ((CExtPopupInplaceListBox::e_sel_action_t)eSAT) )
	{
	case CExtPopupInplaceListBox::e_sel_action_t::__SAT_SELCHANGE:
		return
			pSite->OnPopupListBoxSelChange(
				NULL,
				pNode,
				wndListBox
				);
	case CExtPopupInplaceListBox::e_sel_action_t::__SAT_SELENDOK:
		return
			pSite->OnPopupListBoxSelEndOK(
				NULL,
				pNode,
				wndListBox
				);
	case CExtPopupInplaceListBox::e_sel_action_t::__SAT_SELENDCANCEL:
		return
			pSite->OnPopupListBoxSelEndCancel(
				NULL,
				pNode,
				wndListBox
				);
#ifdef _DEBUG
	default:
		ASSERT( FALSE );
	break;
#endif // _DEBUG
	} // switch( ((CExtPopupInplaceListBox::e_sel_action_t)eSAT) )
	return false;
}

bool CExtPopupMenuWnd::MENUITEMDATA::stat_CbListBoxItemDraw(
	CExtPopupInplaceListBox & wndListBox,
	CExtCustomizeCmdTreeNode * pNode,
	LPDRAWITEMSTRUCT pDIS
	)
{
	ASSERT_VALID( pNode );
	ASSERT( pDIS != NULL && pDIS->hDC != NULL );
	ASSERT(
			wndListBox.GetSafeHwnd() != NULL
		&&	::IsWindow( wndListBox.GetSafeHwnd() )
		);
CExtCustomizeSite * pSite =
		CExtCustomizeSite::GetCustomizeSite( wndListBox.GetSafeHwnd() );
	if( pSite == NULL )
		return false;
	if(	pSite->OnPopupListBoxItemDraw(
			NULL,
			pNode,
			wndListBox,
			pDIS
			)
		)
		return true;

	if( (wndListBox.GetStyle() & LBS_HASSTRINGS) == 0 )
		return false;
	if( ((INT)pDIS->itemID) < 0 || ((INT)pDIS->itemID) >= wndListBox.GetCount() )
		return true;
CDC dc;
	dc.Attach( pDIS->hDC );

	dc.FillSolidRect(
		&pDIS->rcItem,
		g_PaintManager->GetColor(
			( pDIS->itemState & ODS_SELECTED )
				? COLOR_HIGHLIGHT
				: COLOR_WINDOW
			)
		);

CString sText;
	wndListBox.GetText( (INT)pDIS->itemID, sText );
	if( !sText.IsEmpty() )
	{
		COLORREF clrTextOld =
			dc.SetTextColor(
				g_PaintManager->GetColor(
					( pDIS->itemState & ODS_SELECTED )
						? COLOR_HIGHLIGHTTEXT
						: COLOR_BTNTEXT
					)
				);
		int nOldBkMode = dc.SetBkMode( TRANSPARENT );
		CRect rcText( pDIS->rcItem );
		rcText.DeflateRect(
			pSite->OnPopupListBoxCalcItemExtraSizes(
				NULL,
				pNode
				)
			);
		dc.DrawText(
			sText,
			&rcText,
			DT_SINGLELINE|DT_LEFT|DT_VCENTER|DT_NOPREFIX
			);
		dc.SetBkMode( nOldBkMode );
		dc.SetTextColor( clrTextOld );
	} // if( !sText.IsEmpty() )

	if( pDIS->itemState & ODS_SELECTED )
		dc.DrawFocusRect( &pDIS->rcItem );

	dc.Detach();
	return true;
}

bool CExtPopupMenuWnd::MENUITEMDATA::stat_CbListBoxItemMeasure(
	CExtPopupInplaceListBox & wndListBox,
	CExtCustomizeCmdTreeNode * pNode,
	LPMEASUREITEMSTRUCT pMIS
	)
{
	ASSERT_VALID( pNode );
	ASSERT( pMIS != NULL );
	ASSERT(
			wndListBox.GetSafeHwnd() != NULL
		&&	::IsWindow( wndListBox.GetSafeHwnd() )
		);
CExtCustomizeSite * pSite =
		CExtCustomizeSite::GetCustomizeSite( wndListBox.GetSafeHwnd() );
	if( pSite == NULL )
		return false;
	if(	pSite->OnPopupListBoxItemMeasure(
			NULL,
			pNode,
			wndListBox,
			pMIS
			)
		)
		return true;

	if( (wndListBox.GetStyle() & LBS_HASSTRINGS) == 0 )
		return false;
	pMIS->itemWidth = pMIS->itemHeight = 10;
	if( ((INT)pMIS->itemID) < 0 || ((INT)pMIS->itemID) >= wndListBox.GetCount() )
		return true;
CExtSafeString sMeasure;
	wndListBox.GetText( (INT)pMIS->itemID, *((CString*)&sMeasure) );
	if( sMeasure.IsEmpty() )
		return true;
CWindowDC dc( NULL );
CRect rcMeasure =
		CExtPaintManager::stat_CalcTextDimension(
			dc,
			g_PaintManager->m_FontNormal,
			sMeasure
			);
	rcMeasure.InflateRect(
		pSite->OnPopupListBoxCalcItemExtraSizes(
			NULL,
			pNode
			)
		);
	pMIS->itemWidth = rcMeasure.Width();
	pMIS->itemHeight = rcMeasure.Height();
	return true;
}
#endif // (!defined __EXT_MFC_NO_BUILTIN_TEXTFIELD)

bool CExtPopupMenuWnd::MENUITEMDATA::UpdateFromCmdTree(
	HWND hWndCmdRecv,
	CExtCustomizeCmdTreeNode * pNode,
	int nItemIndex
	)
{
	ASSERT_VALID( pNode );
	m_nItemIndex = nItemIndex;

CExtCustomizeSite * pSite = NULL;
#if (!defined __EXT_MFC_NO_BUILTIN_TEXTFIELD)
	if( (pNode->GetFlags() & __ECTN_TBB_TEXT_FIELD) != 0 )
	{
		ASSERT( m_hWndSpecCmdReciever != NULL );
		ASSERT( ::IsWindow(m_hWndSpecCmdReciever) );
		pSite =
			CExtCustomizeSite::GetCustomizeSite(
				m_hWndSpecCmdReciever
				);
		if( pSite == NULL )
		{
			ASSERT( FALSE );
			return false;
		}
		bool bComboField =
			( (pNode->GetFlags() & __ECTN_TBB_COMBO) != 0 )
				? true : false;
		m_nCmdID =
			bComboField
				? ((UINT)TYPE_POPUP)
				: pNode->GetCmdID( false )
				;
		m_pCmdNode = pNode;
		if( bComboField )
		{
			// construct a popup
			ASSERT( m_iconPopup.IsEmpty() );
			ASSERT( m_pWndChild == NULL );
			
			CExtPopupControlMenuWnd * pExtCrtPopup =
				pSite->OnTextFieldCreateDropPopup(
					NULL,
					pNode,
					m_hWndSpecCmdReciever,
					false
					);
			if( pExtCrtPopup != NULL )
			{
				m_pWndChild = pExtCrtPopup;
			} // if( pExtCrtPopup != NULL )
			else
			{
				CExtPopupListBoxMenuWnd * pPopup = new CExtPopupListBoxMenuWnd;
				pPopup->m_lParamListCookie = pNode->GetLParam();
				pPopup->m_pCbListBoxSelection = 
					(CExtPopupInplaceListBox::pCbListBoxSelection)
						stat_CbListBoxSelection;
				pPopup->m_pSelectionCoockie = (LPVOID)pNode;
				pPopup->m_pCbInitListBoxContent =
					(CExtPopupInplaceListBox::pCbInitListBoxContent)
						stat_CbInitListBoxContent;
				pPopup->m_pInitListBoxCoockie = (LPVOID)pNode;
				pPopup->m_pCbListBoxItemDraw =
					(CExtPopupInplaceListBox::pCbListBoxItemDraw)
						stat_CbListBoxItemDraw;
				pPopup->m_pCbListBoxItemMeasure =
					(CExtPopupInplaceListBox::pCbListBoxItemMeasure)
						stat_CbListBoxItemMeasure;
				pPopup->m_pListBoxItemCoockie = (LPVOID)pNode;
				pSite->OnPopupListBoxGetStyles(
					NULL,
					pNode,
					pPopup->m_dwListBoxStyles
					);
				CSize sizeMeasure =
					pSite->OnPopupListBoxMeasureTrackSize(
						NULL,
						pNode
						);
				if( sizeMeasure.cx == 0 && sizeMeasure.cy == 0 )
				{
					pPopup->m_sizeChildControl.cx =
						pNode->TextFieldWidthGet()
						//+ ::GetSystemMetrics( SM_CXHTHUMB )
						;
					pPopup->m_sizeChildControl.cy = pNode->DropDownHeightMaxGet();
				} // if( sizeMeasure.cx == 0 && sizeMeasure.cy == 0 )
				else
					pPopup->m_sizeChildControl = sizeMeasure;
				m_pWndChild = pPopup;
			} // else from if( pExtCrtPopup != NULL )
			m_pWndChild->m_hWndCmdReciever = m_hWndSpecCmdReciever;
			//
			m_sItemText = _T("");
			m_sAccelText = _T("");
			SetPopupText( pNode->GetTextInMenu( NULL ) );
		} // if( bComboField )
		else
			m_sItemText = pNode->GetTextInMenu( NULL );
		pSite->OnTextFieldInplaceTextGet(
			NULL,
			pNode,
			pNode->m_sDefInplaceEditBuffer
			);
		SetInplaceEdit(
			&pNode->m_sDefInplaceEditBuffer,
			(CExtPopupMenuWnd::pCbVerifyTextInput)stat_CbVerifyTextInput,
			(CExtPopupMenuWnd::pCbPutTextInputResult)stat_CbPutTextInputResult,
			(CExtPopupMenuWnd::pCbInplaceEditWndProc)stat_CbInplaceEditWndProc,
			(LPVOID)pNode,
			pNode->TextFieldWidthGet()
			);
		SetDisplayed( true );
		MeasureItem();
		return true;
	} // if( (pNode->GetFlags() & __ECTN_TBB_TEXT_FIELD) != 0 )
#endif // (!defined __EXT_MFC_NO_BUILTIN_TEXTFIELD)

	if( pNode->GetFlags() & __ECTN_TBB_COLOR )
	{
		ASSERT( m_iconPopup.IsEmpty() );
		ASSERT( m_pWndChild == NULL );
		 CExtPopupColorMenuWnd * pColorPopup= new CExtPopupColorMenuWnd;
		 m_pWndChild = pColorPopup;
		
		ASSERT( m_hWndSpecCmdReciever != NULL );
		ASSERT( ::IsWindow(m_hWndSpecCmdReciever) );
		m_pWndChild->m_hWndCmdReciever = m_hWndSpecCmdReciever;

		m_nCmdID = (UINT)TYPE_POPUP;
		m_sItemText = pNode->GetTextInMenu( NULL );
		m_pCmdNode = pNode;
		ASSERT( m_pWndChild != NULL );
		m_pWndChild->m_pNode = pNode;

		pColorPopup->m_lParamCookie = pNode->GetLParam();
		pColorPopup->m_bEnableBtnColorDefault =
			( (pNode->GetFlags() & __ECTN_TBB_MCB_DEFAULT) != 0 ) ? true : false;
		pColorPopup->m_bEnableBtnColorCustom =
			( (pNode->GetFlags() & __ECTN_TBB_MCB_CUSTOM) != 0 ) ? true : false;
		if( pSite == NULL )
			pSite =
				CExtCustomizeSite::GetCustomizeSite(
					m_hWndSpecCmdReciever
					);
		if( pSite == NULL )
		{
			ASSERT( FALSE );
			return false;
		}
		pSite->OnColorItemValueGet(
			NULL,
			pNode,
			pColorPopup->m_clrDefault,
			false
			);
		pSite->OnColorItemValueGet(
			NULL,
			pNode,
			pColorPopup->m_clrInitial,
			true
			);
		CExtSafeString sBtnText;
		if(	pSite->OnColorItemGetBtnTextDefault(
				NULL,
				pNode,
				sBtnText
				)
			)
			pColorPopup->m_sBtnTextColorDefault = sBtnText;
		sBtnText.Empty();
		if(	pSite->OnColorItemGetBtnTextCustom(
				NULL,
				pNode,
				sBtnText
				)
			)
			pColorPopup->m_sBtnTextColorCustom = sBtnText;
		HICON hIconColorItem =
			pSite->OnColorItemGenerateIcon(
				NULL,
				pNode,
				pColorPopup->m_clrInitial
				);
		if( hIconColorItem != NULL )
			m_iconPopup.AssignFromHICON( hIconColorItem, false );
		
		MeasureItem();
		return true;
	} // if( pNode->GetFlags() & __ECTN_TBB_COLOR )

	if(		(pNode->GetFlags() & __ECTN_AUTO_POPUP) != 0
		||	pNode->GetNodeCount() > 0
		)
	{
		if( !ConstructPopup() )
		{
			ASSERT( FALSE );
			return false;
		}
		m_nCmdID = (UINT)TYPE_POPUP;
		m_sItemText = pNode->GetTextInMenu( NULL );
		m_pCmdNode = pNode;
		ASSERT( m_pWndChild != NULL );
		m_pWndChild->m_pNode = pNode;
		MeasureItem();
		return true;
	}

//	m_sItemText.Empty();
	if( !CExtCmdManager::IsCommand(pNode->GetCmdID()) )
	{
		ASSERT( FALSE );
		return false;
	}
#if (!defined __EXT_MFC_NO_BUILTIN_TEXTFIELD)
	if( (pNode->GetFlags() & (__ECTN_TBB_COMBO|__ECTN_TBB_TEXT_FIELD) ) == 0 )
#endif // (!defined __EXT_MFC_NO_BUILTIN_TEXTFIELD)
		m_nCmdID = pNode->GetCmdID();
CExtCmdItem * pCmdItem =
		g_CmdManager->CmdGetPtr(
			g_CmdManager->ProfileNameFromWnd( hWndCmdRecv ),
			pNode->GetCmdID()
			);
	ASSERT( pCmdItem != NULL );
	if( pCmdItem == NULL )
		return false;
	m_sItemText = pNode->GetTextInMenu( pCmdItem );
	m_pCmdNode = pNode;
	MeasureItem();
	return true;
}

#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)

/////////////////////////////////////////////////////////////////////////////
// CExtPopupBaseWnd

IMPLEMENT_DYNCREATE(CExtPopupBaseWnd, __BaseClassOfCExtPopupBaseWnd)

CExtPopupBaseWnd::CExtPopupBaseWnd()
{
	m_clrFadeBitsSrc
		= m_clrFadeBitsDst
		= m_clrFadeBitsTmp
		= NULL;
	m_AnimationType = g_DefAnimationType;
	_InitAnimation();
	m_ePlaySoundOnAnimationFinished =
		CExtSoundPlayer::__NO_SOUND;

	m_sizeFullItems.cx = m_sizeFullItems.cy = 1;

	m_bExcludeAreaSpec
		= m_bCombineWithEA
		= false;
	m_rcExcludeArea.SetRectEmpty();
	m_ptTrack.x = m_ptTrack.y;
}

CExtPopupBaseWnd::~CExtPopupBaseWnd()
{
}

void CExtPopupBaseWnd::_AdjustAnimation(
	CExtPopupBaseWnd::e_animation_type_t & eAT
	)
{
	ASSERT_VALID( this );
	eAT;
}

void CExtPopupBaseWnd::_InitAnimation()
{
	ASSERT_VALID( this );

	m_nAnimPercent = m_nAnimPercentOld = 0;
	//m_AnimationType = g_DefAnimationType;

	_AdjustAnimation( m_AnimationType );

	if( (m_AnimationType < 0
			|| m_AnimationType > __AT_MAX_VALID_VALUE)
		&&
		m_AnimationType != __AT_CONTENT_DISPLAY
		&&
		m_AnimationType != __AT_CONTENT_EXPAND
		)
		m_AnimationType = __AT_NONE;

	if( m_AnimationType == __AT_RANDOM )
	{
		int nRand = rand() % (__AT_MAX_VALID_VALUE+1);
		ASSERT( nRand >= 0 && nRand <= __AT_MAX_VALID_VALUE );
		if( nRand == __AT_NONE || nRand == __AT_RANDOM )
			nRand = __AT_FADE; // most cool of all effects
		m_AnimationType = (e_animation_type_t)nRand;
	}

int nBitsPerPixel = CExtPaintManager::stat_GetBPP();
	if( nBitsPerPixel <= 8
		&&
		m_AnimationType != __AT_CONTENT_EXPAND
		&&
		m_AnimationType != __AT_CONTENT_DISPLAY
		)
	{
		m_AnimationType = __AT_NONE;
		m_bAnimFinished = true;
	}

	else
	{
		m_bAnimFinished =
			(m_AnimationType == __AT_NONE) ? true : false;
	}

	ASSERT(
			m_bmpScreenDst.GetSafeHandle() == NULL
		&&	m_bmpScreenSrc.GetSafeHandle() == NULL
		&&	m_bmpScreenTmp.GetSafeHandle() == NULL
		&&	m_clrFadeBitsSrc == NULL
		&&	m_clrFadeBitsDst == NULL
		&&	m_clrFadeBitsTmp == NULL
		);
}

void CExtPopupBaseWnd::_StartAnimation()
{
	ASSERT_VALID( this );
	_InitAnimation();
	if( m_AnimationType != __AT_NONE )
	{
		SetTimer( ID_TIMER_ANIMATION, ID_PERIOD_ANIMATION, NULL );
		g_nLastAnimTime = clock();
	}
}

void CExtPopupMenuWnd::_StartAnimation()
{
	ASSERT_VALID( this );
	if( _FindCustomizeMode() )
		return;
	_ItemFocusDelay();
	_CoolTipHide( false );
	CExtPopupBaseWnd::_StartAnimation();
	GetSite().SetAnimated(
		m_bAnimFinished ? NULL : this
		);
}

BEGIN_MESSAGE_MAP(CExtPopupBaseWnd, __BaseClassOfCExtPopupBaseWnd)
	//{{AFX_MSG_MAP(CExtPopupBaseWnd)
	ON_WM_MOUSEACTIVATE()
	ON_WM_ERASEBKGND()
	ON_WM_PAINT()
	ON_WM_NCPAINT()
	ON_WM_NCCALCSIZE()
	ON_WM_SIZE()
	ON_WM_ACTIVATEAPP()
	ON_WM_CANCELMODE()
	ON_WM_SETCURSOR()
	ON_WM_TIMER()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

void CExtPopupBaseWnd::OnPaint() 
{
	ASSERT_VALID( this );

	if( !(::IsWindow(GetSafeHwnd())) )
		return;
	if( !(::IsWindowVisible(GetSafeHwnd())) )
		return;
CPaintDC dc(this); // device context for painting
	CExtPaintManager::stat_ExcludeChildAreas(
		dc.GetSafeHdc(),
		m_hWnd
		);
	if( !m_bAnimFinished )
		_DrawAnimatedState( dc );
	else
		_DoPaint( dc );
}

void CExtPopupBaseWnd::_DrawAnimatedState( CDC & dc )
{
	ASSERT_VALID( this );
	_DoPaint( dc );
}

void CExtPopupMenuWnd::_DrawAnimatedState( CDC & dc )
{
	ASSERT_VALID( this );

	if( !(::IsWindow(GetSafeHwnd())) )
		return;
CRect rcClient;
	GetClientRect( &rcClient );

int cx = rcClient.Width();
int cy = rcClient.Height();

CDC * pPaintDC = &dc;

CPalette * pOldPalette = NULL;
    if( pPaintDC->GetDeviceCaps(RASTERCAPS) & RC_PALETTE )
    {
        pOldPalette =
			pPaintDC->SelectPalette( &g_PaintManager->m_PaletteWide, FALSE );
        pPaintDC->RealizePalette();
    }

CDC dcmm;
	VERIFY( dcmm.CreateCompatibleDC(pPaintDC) );
bool bFail = false;
	if( m_bmpScreenDst.GetSafeHandle() == NULL )
	{
		ASSERT( m_bmpScreenSrc.GetSafeHandle() == NULL );
		ASSERT( m_bmpScreenTmp.GetSafeHandle() == NULL );
		
		int nBitsPerPixel = CExtPaintManager::stat_GetBPP();
		CBitmap * pBmpOld = NULL;
		if(	(m_AnimationType == __AT_FADE
				&& nBitsPerPixel > 8 )
			|| m_AnimationType == __AT_CONTENT_EXPAND
			|| m_AnimationType == __AT_CONTENT_DISPLAY
			|| m_AnimationType == __AT_ROLL
			|| m_AnimationType == __AT_SLIDE
			|| m_AnimationType == __AT_ROLL_AND_STRETCH
			|| m_AnimationType == __AT_SLIDE_AND_STRETCH
			|| m_AnimationType == __AT_NOISE
			|| m_AnimationType == __AT_BOXES
			|| m_AnimationType == __AT_CIRCLES
			|| m_AnimationType == __AT_HOLES
			)
		{
			BITMAPINFOHEADER bih;
			bih.biSize = sizeof(BITMAPINFOHEADER);
			bih.biWidth = cx;
			bih.biHeight = cy;
			bih.biPlanes = 1;
			bih.biBitCount = 32;
			bih.biCompression = BI_RGB;
			bih.biSizeImage = cx * cy;
			bih.biXPelsPerMeter = 0;
			bih.biYPelsPerMeter = 0;
			bih.biClrUsed = 0;
			bih.biClrImportant = 0;

			HBITMAP hDIB =
				::CreateDIBSection(
					dcmm.GetSafeHdc(),
					(LPBITMAPINFO)&bih,
					DIB_RGB_COLORS,
					(void **)&m_clrFadeBitsSrc,
					NULL,
					NULL
					);
			if( hDIB != NULL && m_clrFadeBitsSrc != NULL )
			{
				m_bmpScreenSrc.Attach( hDIB );

				hDIB =
					::CreateDIBSection(
						dcmm.GetSafeHdc(),
						(LPBITMAPINFO)&bih,
						DIB_RGB_COLORS,
						(void **)&m_clrFadeBitsDst,
						NULL,
						NULL
						);
				if( hDIB != NULL && m_clrFadeBitsDst != NULL )
				{
					m_bmpScreenDst.Attach( hDIB );

					hDIB =
						::CreateDIBSection(
							dcmm.GetSafeHdc(),
							(LPBITMAPINFO)&bih,
							DIB_RGB_COLORS,
							(void **)&m_clrFadeBitsTmp,
							NULL,
							NULL
							);
					if( hDIB != NULL && m_clrFadeBitsTmp != NULL )
					{
						m_bmpScreenTmp.Attach( hDIB );

						pBmpOld =
							dcmm.SelectObject( &m_bmpScreenSrc );
						dcmm.BitBlt(
							0, 0, cx, cy, pPaintDC,
							rcClient.left,
							rcClient.top,
							SRCCOPY
							);

						::memcpy(
							m_clrFadeBitsDst,
							m_clrFadeBitsSrc,
							sizeof(COLORREF)*cx*cy
							);
						dcmm.SelectObject( &m_bmpScreenDst );
					} // if( hDIB != NULL && m_clrFadeBitsTmp != NULL )
					else
					{
						m_bmpScreenSrc.DeleteObject();
						m_bmpScreenDst.DeleteObject();
						//return;
						bFail = true;
					} // else from if( hDIB != NULL && m_clrFadeBitsTmp != NULL )
				} // if( hDIB != NULL && m_clrFadeBitsDst != NULL )
				else
				{
					m_bmpScreenSrc.DeleteObject();
					//return;
					bFail = true;
				} // else from if( hDIB != NULL && m_clrFadeBitsDst != NULL )
			} // if( hDIB != NULL && m_clrFadeBitsSrc != NULL )
		}
		else
		{
			m_bmpScreenDst.CreateCompatibleBitmap(
				pPaintDC,
				cx,
				cy
				);
			pBmpOld =
				dcmm.SelectObject( &m_bmpScreenDst );
		}

		if( !bFail )
			_DoPaint( dcmm, false );
		dcmm.SetViewportOrg( CPoint(0,0) );
		dcmm.SelectObject( pBmpOld );
	} // if( m_bmpScreenDst.GetSafeHandle() == NULL )

CBitmap * pBmpOld = NULL;
	if( !bFail )
	{
		COLORREF * src = m_clrFadeBitsSrc;
		COLORREF * dst = m_clrFadeBitsDst;
		COLORREF * tmp = m_clrFadeBitsTmp;

		switch( m_AnimationType )
		{
		case __AT_BOXES:
		case __AT_CIRCLES:
		case __AT_HOLES:
			if( tmp!= NULL && src!=NULL && dst != NULL )
			{
				ASSERT(
					m_nAnimPercent >= 0 && m_nAnimPercent <= 100
					&&
					m_nAnimPercentOld >= 0 && m_nAnimPercentOld <= 100
					&&
					m_nAnimPercentOld <= m_nAnimPercent
					);
				ASSERT( __BOX_ANIM_METRIC > 0 ); // self assert
				if( m_nAnimPercentOld != m_nAnimPercent )
				{
					pBmpOld = dcmm.SelectObject( &m_bmpScreenTmp );
					if( m_AnimationType == __AT_BOXES )
					{ // do boxes animation
						for( int y=0; y<cy; y++ )
						{
							int _y0 = y % __BOX_ANIM_METRIC;
							int _yPercent = 100 -
								(_y0 * 100) / __BOX_ANIM_METRIC;
							if( _yPercent < m_nAnimPercent )
							{
								::memcpy(
									tmp,
									src,
									cx*sizeof(COLORREF)
									);
								tmp += cx;
								src += cx;
								dst += cx;
								continue;
							}
							for( int x=0; x<cx; x++ )
							{
								int _x0 = x % __BOX_ANIM_METRIC;
								int _xPercent =
									(_x0 * 100) / __BOX_ANIM_METRIC;
								if( _xPercent < m_nAnimPercent )
									*tmp = *dst;
								else
									*tmp = *src;
								tmp++; src++; dst++;
							}
						} // for( int y=0; y<cy; y++ )
					} // do boxes animation
					else
					{ // do circles/holes animation
						double radius = 0;
						if( m_AnimationType == __AT_HOLES )
							radius = 
								((((double)(__BOX_ANIM_METRIC)) / 2) * (100-m_nAnimPercent))
								/ 100;
						else
							radius = 
								((((double)(__BOX_ANIM_METRIC)) / 2) * m_nAnimPercent)
								/ 100;
						if( radius > 0 )
						{
							for( int y=0; y<cy; y++ )
							{
								int _y0 = y % __BOX_ANIM_METRIC;
								int _y1 = y - _y0;
								//int _y2 = _y1 + __BOX_ANIM_METRIC;
								int _yCenter = _y1 + __BOX_ANIM_METRIC/2;
								int _yDist = abs( y - _yCenter );
								double _yDist2 = (double)_yDist*_yDist;
								for( int x=0; x<cx; x++ )
								{
									int _x0 = x % __BOX_ANIM_METRIC;
									int _x1 = x - _x0;
									//int _x2 = _x1 + __BOX_ANIM_METRIC;
									int _xCenter = _x1 + __BOX_ANIM_METRIC/2;
									int _xDist = abs( x - _xCenter );
									double _xDist2 = (double)_xDist*_xDist;

									double nDispance =
										::sqrt(_yDist2+_xDist2);
									if( m_AnimationType == __AT_HOLES )
									{ // holes
										if( nDispance >= radius )
											*tmp = *dst;
										else
											*tmp = *src;
									} // holes
									else
									{ // circles
										if( nDispance < radius )
											*tmp = *dst;
										else
											*tmp = *src;
									} // circles
									tmp++; src++; dst++;
								}
							} // for( int y=0; y<cy; y++ )
						} // if( radius > 0 )
					} // do circles/holes animation

					int nMenuShadowSize = _GetPopupShadowSize();
					if( m_bCombineWithEA )
					{ // paint combined area AS IS
						ASSERT( !m_rcExcludeArea.IsRectEmpty() );
						CRect rcExcludeArea( m_rcExcludeArea );
						ScreenToClient( &rcExcludeArea );
						pBmpOld = dcmm.SelectObject( &m_bmpScreenDst );
						pPaintDC->BitBlt(
							rcExcludeArea.left, rcExcludeArea.top,
							rcExcludeArea.Width(), rcExcludeArea.Height(), 
							&dcmm,
							rcExcludeArea.left, rcExcludeArea.top,
							SRCCOPY
							);
						dcmm.SelectObject( pBmpOld );
						pBmpOld = NULL;
						if( m_eCombineAlign != __CMBA_NONE )
						{
//							int nMenuShadowSize = _GetPopupShadowSize();
							rcExcludeArea.InflateRect(
								(m_eCombineAlign == __CMBA_RIGHT) ?
									0 : nMenuShadowSize,
								(m_eCombineAlign == __CMBA_BOTTOM) ?
									0 : nMenuShadowSize,
								(m_eCombineAlign == __CMBA_LEFT) ?
									0 : nMenuShadowSize,
								(m_eCombineAlign == __CMBA_TOP) ?
									0 : nMenuShadowSize
								);
						} // if( m_eCombineAlign != __CMBA_NONE )
						pPaintDC->ExcludeClipRect(
							&rcExcludeArea
							);
					} // paint combined area AS IS
					if( nMenuShadowSize > 0 )
					{
						CRect rcExcludeArea( rcClient );
						rcExcludeArea.left =
							rcExcludeArea.right
							- nMenuShadowSize;
						pPaintDC->ExcludeClipRect(
							&rcExcludeArea
							);
						rcExcludeArea = rcClient ;
						rcExcludeArea.top =
							rcExcludeArea.bottom
							- nMenuShadowSize;
						pPaintDC->ExcludeClipRect(
							&rcExcludeArea
							);
					}
					
					pPaintDC->BitBlt(
						rcClient.left, rcClient.top, cx, cy, 
						&dcmm,
						0,
						0,
						SRCCOPY
						);

					if( nMenuShadowSize > 0 || m_bCombineWithEA )
						pPaintDC->SelectClipRgn( NULL );
				} // if( m_nAnimPercentOld != m_nAnimPercent )
			}
		break; // cases __AT_BOXES,__AT_CIRCLES,__AT_HOLES
		case __AT_NOISE:
			if( tmp!= NULL && src!=NULL && dst != NULL )
			{
				ASSERT(
					m_nAnimPercent >= 0 && m_nAnimPercent <= 100
					&&
					m_nAnimPercentOld >= 0 && m_nAnimPercentOld <= 100
					&&
					m_nAnimPercentOld <= m_nAnimPercent
					);
				if( m_nAnimPercentOld != m_nAnimPercent )
				{
					int nDiff =
						m_nAnimPercent - m_nAnimPercentOld;
					ASSERT( nDiff > 0 );
					int nRandHalf = nDiff / 2 + 1;
					ASSERT( nRandHalf > 0 );
					pBmpOld = dcmm.SelectObject( &m_bmpScreenTmp );
					for( int pixel = 0; pixel < cx * cy; pixel++ )
					{
						int nRandValue = 
							rand() % nDiff;
						if( nRandValue > nRandHalf )
							*tmp = *dst;
//						else
//							*tmp = *src;
						tmp++; src++; dst++;
					} // for( int pixel = 0; pixel < cx * cy; pixel++ )

					int nMenuShadowSize = _GetPopupShadowSize();
					if( m_bCombineWithEA )
					{ // paint combined area AS IS
						ASSERT( !m_rcExcludeArea.IsRectEmpty() );
						CRect rcExcludeArea( m_rcExcludeArea );
						ScreenToClient( &rcExcludeArea );
						pBmpOld = dcmm.SelectObject( &m_bmpScreenDst );
						pPaintDC->BitBlt(
							rcExcludeArea.left, rcExcludeArea.top,
							rcExcludeArea.Width(), rcExcludeArea.Height(), 
							&dcmm,
							rcExcludeArea.left, rcExcludeArea.top,
							SRCCOPY
							);
						dcmm.SelectObject( pBmpOld );
						pBmpOld = NULL;
						if( m_eCombineAlign != __CMBA_NONE )
						{
//							int nMenuShadowSize = _GetPopupShadowSize();
							rcExcludeArea.InflateRect(
								(m_eCombineAlign == __CMBA_RIGHT) ?
									0 : nMenuShadowSize,
								(m_eCombineAlign == __CMBA_BOTTOM) ?
									0 : nMenuShadowSize,
								(m_eCombineAlign == __CMBA_LEFT) ?
									0 : nMenuShadowSize,
								(m_eCombineAlign == __CMBA_TOP) ?
									0 : nMenuShadowSize
								);
						} // if( m_eCombineAlign != __CMBA_NONE )
						pPaintDC->ExcludeClipRect(
							&rcExcludeArea
							);
					} // paint combined area AS IS
					if( nMenuShadowSize > 0 )
					{
						CRect rcExcludeArea( rcClient );
						rcExcludeArea.left =
							rcExcludeArea.right
							- nMenuShadowSize;
						pPaintDC->ExcludeClipRect(
							&rcExcludeArea
							);
						rcExcludeArea = rcClient ;
						rcExcludeArea.top =
							rcExcludeArea.bottom
							- nMenuShadowSize;
						pPaintDC->ExcludeClipRect(
							&rcExcludeArea
							);
					}
					
					pPaintDC->BitBlt(
						rcClient.left, rcClient.top, cx, cy, 
						&dcmm,
						0,
						0,
						SRCCOPY
						);

					if( nMenuShadowSize > 0 || m_bCombineWithEA )
						pPaintDC->SelectClipRgn( NULL );
				} // if( m_nAnimPercentOld != m_nAnimPercent )
			}
		break; // case __AT_NOISE
		case __AT_SLIDE:
		case __AT_ROLL:
		case __AT_ROLL_AND_STRETCH:
		case __AT_SLIDE_AND_STRETCH:
			if( tmp!= NULL && src!=NULL && dst != NULL )
			{
				ASSERT(
					m_nAnimPercent >= 0 && m_nAnimPercent <= 100
					&&
					m_nAnimPercentOld >= 0 && m_nAnimPercentOld <= 100
					&&
					m_nAnimPercentOld <= m_nAnimPercent
					);

				CRect _rcClient;
				_GetClientRect( &_rcClient );

				if( m_bCombineWithEA )
				{ // paint combined area AS IS
					ASSERT( !m_rcExcludeArea.IsRectEmpty() );
					CRect rcExcludeArea( m_rcExcludeArea );
					ScreenToClient( &rcExcludeArea );
					pBmpOld = dcmm.SelectObject( &m_bmpScreenDst );
					pPaintDC->BitBlt(
						rcExcludeArea.left, rcExcludeArea.top,
						rcExcludeArea.Width(), rcExcludeArea.Height(), 
						&dcmm,
						rcExcludeArea.left, rcExcludeArea.top,
						SRCCOPY
						);
					dcmm.SelectObject( pBmpOld );
					pBmpOld = NULL;
					if( m_eCombineAlign != __CMBA_NONE )
					{
						int nMenuShadowSize = _GetPopupShadowSize();
						rcExcludeArea.InflateRect(
							(m_eCombineAlign == __CMBA_RIGHT) ?
								0 : nMenuShadowSize,
							(m_eCombineAlign == __CMBA_BOTTOM) ?
								0 : nMenuShadowSize,
							(m_eCombineAlign == __CMBA_LEFT) ?
								0 : nMenuShadowSize,
							(m_eCombineAlign == __CMBA_TOP) ?
								0 : nMenuShadowSize
							);
					} // if( m_eCombineAlign != __CMBA_NONE )
					pPaintDC->ExcludeClipRect(
						&rcExcludeArea
						);
				} // paint combined area AS IS

				pBmpOld = dcmm.SelectObject( &m_bmpScreenDst );
				int cx =
					_rcClient.Width();
				int cy =
					_rcClient.Height();
				if( m_AnimationType == __AT_ROLL
					||
					m_AnimationType == __AT_SLIDE
					)
				{ // non-stratchable variants
					int _cx = 0;
					if( m_AnimationType == __AT_ROLL )
						_cx = (cx * (100-m_nAnimPercent)) / 100;
					int _cy =
						(cy * (100-m_nAnimPercent)) / 100;
					if( m_eCombineAlign == __CMBA_RIGHT )
					{
						CRgn rgnClip;
						if( rgnClip.CreateRectRgnIndirect( &_rcClient ) )
							pPaintDC->SelectClipRgn( &rgnClip );
						pPaintDC->BitBlt(
							_rcClient.left+_cx, _rcClient.top-_cy, cx, cy, 
							&dcmm,
							_rcClient.left, _rcClient.top,
							SRCCOPY
							);
						pPaintDC->SelectClipRgn( NULL );
					} // if m_eCombineAlign is __CMBA_RIGHT
					else if( m_eCombineAlign == __CMBA_BOTTOM )
					{
						CRgn rgnClip;
						if( rgnClip.CreateRectRgnIndirect( &_rcClient ) )
							pPaintDC->SelectClipRgn( &rgnClip );
						pPaintDC->BitBlt(
							_rcClient.left-_cx, _rcClient.top+_cy, cx, cy,
							&dcmm,
							_rcClient.left, _rcClient.top,
							SRCCOPY
							);
						pPaintDC->SelectClipRgn( NULL );
					} // if m_eCombineAlign is __CMBA_BOTTOM
					else
					{ // if m_eCombineAlign is __CMBA_TOP or __CMBA_LEFT
						pPaintDC->BitBlt(
							_rcClient.left-_cx, _rcClient.top-_cy, cx, cy,
							&dcmm,
							_rcClient.left, _rcClient.top,
							SRCCOPY
							);
					} // if m_eCombineAlign is __CMBA_TOP or __CMBA_LEFT
				} // non-stratchable variants
				else
				{ // stratchable variants
					int _cx = cx;
					if( m_AnimationType == __AT_ROLL_AND_STRETCH )
						_cx = (cx * m_nAnimPercent) / 100;
					int _cy =
						(cy * m_nAnimPercent) / 100;
					int nOldStretchBltMode =
						pPaintDC->SetStretchBltMode(
							g_PaintManager.m_bIsWinNT ? HALFTONE : COLORONCOLOR
							);
					if(		m_eCombineAlign == __CMBA_RIGHT
						&&	m_AnimationType == __AT_ROLL_AND_STRETCH
						)
					{
						CRgn rgnClip;
						if( rgnClip.CreateRectRgnIndirect( &_rcClient ) )
							pPaintDC->SelectClipRgn( &rgnClip );
						pPaintDC->StretchBlt(
							_rcClient.left+cx-_cx, _rcClient.top, _cx, _cy,
							&dcmm,
							_rcClient.left, _rcClient.top, cx, cy, 
							SRCCOPY
							);
						pPaintDC->SelectClipRgn( NULL );
					} // if m_eCombineAlign is __CMBA_RIGHT with __AT_ROLL_AND_STRETCH animation
					else if( m_eCombineAlign == __CMBA_BOTTOM )
					{
						CRgn rgnClip;
						if( rgnClip.CreateRectRgnIndirect( &_rcClient ) )
							pPaintDC->SelectClipRgn( &rgnClip );
						pPaintDC->StretchBlt(
							_rcClient.left-cx+_cx, _rcClient.top+cy-_cy, _cx, _cy,
							&dcmm,
							_rcClient.left, _rcClient.top, cx, cy, 
							SRCCOPY
							);
						pPaintDC->SelectClipRgn( NULL );
					} // if m_eCombineAlign is __CMBA_BOTTOM
					else
					{ // if m_eCombineAlign is __CMBA_TOP or __CMBA_LEFT
						pPaintDC->StretchBlt(
							_rcClient.left, _rcClient.top, _cx, _cy,
							&dcmm,
							_rcClient.left, _rcClient.top, cx, cy, 
							SRCCOPY
							);
					} // if m_eCombineAlign is __CMBA_TOP or __CMBA_LEFT
					pPaintDC->SetStretchBltMode( nOldStretchBltMode );
				} // stratchable variants

				if( m_bCombineWithEA )
					pPaintDC->SelectClipRgn( NULL );
			}
		break; // cases __AT_ROLL, __AT_SLIDE, __AT_ROLL_AND_STRETCH, __AT_ROLL_AND_STRETCH

		case __AT_CONTENT_EXPAND:
			if( tmp!= NULL && src!=NULL && dst != NULL )
			{
				ASSERT(
					m_nAnimPercent >= 0 && m_nAnimPercent <= 100
					&&
					m_nAnimPercentOld >= 0 && m_nAnimPercentOld <= 100
					&&
					m_nAnimPercentOld <= m_nAnimPercent
					);

				CRect _rcClient;
				_GetClientRect( &_rcClient );

				if( m_bCombineWithEA )
				{ // paint combined area AS IS
					ASSERT( !m_rcExcludeArea.IsRectEmpty() );
					CRect rcExcludeArea( m_rcExcludeArea );
					ScreenToClient( &rcExcludeArea );
					pBmpOld = dcmm.SelectObject( &m_bmpScreenDst );
					pPaintDC->BitBlt(
						rcExcludeArea.left, rcExcludeArea.top,
						rcExcludeArea.Width(), rcExcludeArea.Height(), 
						&dcmm,
						rcExcludeArea.left, rcExcludeArea.top,
						SRCCOPY
						);
					dcmm.SelectObject( pBmpOld );
					pBmpOld = NULL;
				} // paint combined area AS IS

				pBmpOld = dcmm.SelectObject( &m_bmpScreenDst );
				int cx =
					_rcClient.Width();
				int cy =
					_rcClient.Height();
				int _cx = cx;
				int _cy =
					(cy * m_nAnimPercent) / 100;

				visible_items_t v;
					_GetVisibleItems(
						dcmm.GetSafeHdc(), // dc.GetSafeHdc()
						v
						);
				if( v.GetSize() == 0 )
				{ // if menu is empty
					int nOldStretchBltMode =
						pPaintDC->SetStretchBltMode(
							g_PaintManager.m_bIsWinNT ? HALFTONE : COLORONCOLOR
							);
					pPaintDC->StretchBlt(
						_rcClient.left, _rcClient.top, _cx, _cy, 
						&dcmm,
						_rcClient.left, _rcClient.top, cx, cy,
						SRCCOPY
						);
					pPaintDC->SetStretchBltMode( nOldStretchBltMode );
				} // if menu is empty
				else
				{ // if menu is NOT empty
					int y_pos_src = _rcClient.top;
					int y_pos_dst = _rcClient.top;
					INT vis_iter = 0;
					int nItemIndex = 0;
					int nItemCount = v.GetSize();
					ASSERT( nItemCount > 0 );
					expand_effect_rects_container_t vRects;
					
					for( ; vis_iter < v.GetSize(); ++vis_iter, ++nItemIndex )
					{ // calc rects for visible items
						VisibleItemDefinition_t & vi = v[vis_iter];
#ifdef _DEBUG
						ASSERT(
							vi.m_nIndex >= 0
							&&
							vi.m_nIndex < m_items_all.GetSize()
							);
//						ASSERT( !vi.m_rcItem.IsRectEmpty() );
//						ASSERT( dc.RectVisible(&vi.m_rcItem) );
						MENUITEMDATA & mi =
							m_items_all[vi.m_nIndex];
						ASSERT( mi.IsDisplayed() );
						ASSERT( mi.GetCmdID() == vi.m_nHelperCmdID );
#endif // _DEBUG

						CRect rcItemSrc( vi.m_rcItem );
						rcItemSrc.left = _rcClient.left;
						rcItemSrc.right = _rcClient.right;
						if( nItemIndex == 0 )
							rcItemSrc.top = _rcClient.top;
						else if( nItemIndex == (nItemCount-1) )
							rcItemSrc.bottom = _rcClient.bottom;

						int y_pos_src_next = 
							y_pos_src + rcItemSrc.Height();
						CRect rcItemDst( rcItemSrc );
						rcItemDst.OffsetRect(
							0,
							y_pos_dst - rcItemDst.top
							);
						if( vi.m_bRarelyUsed )
							rcItemDst.bottom =
								rcItemDst.top
								+
								(rcItemDst.Height() * m_nAnimPercent)
									/ 100;
						int y_pos_dst_next = 
							y_pos_dst + rcItemDst.Height();
						
						ExpandEffectRects_t _eert(
							rcItemSrc,
							rcItemDst
							);
						vRects.Add( _eert );
						y_pos_dst = y_pos_dst_next;
						y_pos_src = y_pos_src_next;
					} // calc rects for visible items

					// y_pos_dst is now equal to size of
					// all compressed itsms
					ASSERT( y_pos_dst <= y_pos_src );
					if( m_bCombineWithEA
						&&
						m_eCombineAlign == __CMBA_BOTTOM
						&&
						y_pos_dst != y_pos_src
						)
					{ // expand from bottom to top
						INT iter_rects = 0;
						int nDstOffset =
							y_pos_src - y_pos_dst;
						for( ; iter_rects < vRects.GetSize(); ++iter_rects )
						{ // adjust destination rects
							ExpandEffectRects_t & eerc =
								vRects[ iter_rects ];
							eerc.m_rcDst.OffsetRect(
								0,
								nDstOffset
								);
						} // adjust destination rects
					} // expand from bottom to top

					INT iter_rects = 0;
					for( ; iter_rects < vRects.GetSize(); ++iter_rects )
					{ // paint visible items
						ExpandEffectRects_t & eerc =
							vRects[ iter_rects ];
						if( eerc.m_rcDst.IsRectEmpty() )
							continue;
						if( g_bUseStretchOnExpandAnimation )
						{
							int nOldStretchBltMode =
								pPaintDC->SetStretchBltMode(
									g_PaintManager.m_bIsWinNT ? HALFTONE : COLORONCOLOR
									);
							// something better then Office XP
							pPaintDC->StretchBlt(
								eerc.m_rcDst.left, eerc.m_rcDst.top,
								eerc.m_rcDst.Width(), eerc.m_rcDst.Height(), 
								&dcmm,
								eerc.m_rcSrc.left, eerc.m_rcSrc.top,
								eerc.m_rcSrc.Width(), eerc.m_rcSrc.Height(), 
								SRCCOPY
								);
							pPaintDC->SetStretchBltMode( nOldStretchBltMode );
						} // if( g_bUseStretchOnExpandAnimation )
						else
							// somthing really like Office XP
							pPaintDC->BitBlt(
								eerc.m_rcDst.left, eerc.m_rcDst.top,
								eerc.m_rcDst.Width(), eerc.m_rcDst.Height(), 
								&dcmm,
								eerc.m_rcSrc.left, eerc.m_rcSrc.top,
								SRCCOPY
								);
					} // paint visible items
				} // if menu is NOT empty

			}
		break; // case __AT_CONTENT_EXPAND

		case __AT_CONTENT_DISPLAY:
			if( tmp!= NULL && src!=NULL && dst != NULL )
			{
				pBmpOld = dcmm.SelectObject( &m_bmpScreenDst );
				pPaintDC->BitBlt(
					rcClient.left, rcClient.top, cx, cy, 
					&dcmm,
					0,
					0,
					SRCCOPY
					);
			}
		break; // case __AT_CONTENT_DISPLAY

		case __AT_FADE:
			if( tmp!= NULL && src!=NULL && dst != NULL )
			{
				ASSERT(
					m_nAnimPercent >= 0 && m_nAnimPercent <= 100
					&&
					m_nAnimPercentOld >= 0 && m_nAnimPercentOld <= 100
					&&
					m_nAnimPercentOld <= m_nAnimPercent
					);
				pBmpOld = dcmm.SelectObject( &m_bmpScreenTmp );
				for( int pixel = 0; pixel < cx * cy; pixel++ )
				{
					COLORREF c0 = *dst++;
					COLORREF c1 = *src++;
					*tmp++ =
						RGB(
							(m_nAnimPercent*long(GetRValue(c0)) + (100L-m_nAnimPercent)*long(GetRValue(c1)) ) / 100L,
							(m_nAnimPercent*long(GetGValue(c0)) + (100L-m_nAnimPercent)*long(GetGValue(c1)) ) / 100L,
							(m_nAnimPercent*long(GetBValue(c0)) + (100L-m_nAnimPercent)*long(GetBValue(c1)) ) / 100L
							);
				} // for( int pixel = 0; pixel < cx * cy; pixel++ )
				pPaintDC->BitBlt(
					rcClient.left, rcClient.top, cx, cy, 
					&dcmm,
					0,
					0,
					SRCCOPY
					);
			}
		break; // case __AT_FADE

#ifdef _DEBUG
		default:
			ASSERT( FALSE );
		break; // default
#endif // _DEBUG
		} // switch( m_AnimationType )
	} // if( !bFail )

	if( pBmpOld != NULL )
		dcmm.SelectObject( pBmpOld );

	if( pOldPalette != NULL )
		pPaintDC->SelectPalette( pOldPalette, FALSE );
}

void CExtPopupBaseWnd::_DoPaint( CDC & dcPaint, bool bUseBackBuffer /*= true*/ )
{
	ASSERT_VALID( this );

	dcPaint;
	bUseBackBuffer;
}

void CExtPopupBaseWnd::OnTimer(UINT nIDEvent) 
{
	ASSERT_VALID( this );

	switch( nIDEvent )
	{
	case ID_TIMER_DELAY_SHOW:
	{
		VERIFY( KillTimer(ID_TIMER_DELAY_SHOW) );
		ShowWindow( SW_SHOWNA );
		Invalidate( FALSE );
		UpdateWindow();
		return;
	}
	// case ID_TIMER_DELAY_SHOW

	case ID_TIMER_ANIMATION:
		if( !m_bAnimFinished )
		{
			clock_t nCurrAnimTime = clock();
			int nDuration =
				nCurrAnimTime - g_nLastAnimTime;
			int nSteps = (int)
				(0.5 + (float) nDuration / ID_PERIOD_ANIMATION);
			switch( m_AnimationType )
			{
			case __AT_CONTENT_DISPLAY:
				m_bAnimFinished = true;
			break;
			case __AT_FADE:
			case __AT_CONTENT_EXPAND:
			case __AT_ROLL:
			case __AT_SLIDE:
			case __AT_ROLL_AND_STRETCH:
			case __AT_SLIDE_AND_STRETCH:
			case __AT_NOISE:
			case __AT_BOXES:
			case __AT_CIRCLES:
			case __AT_HOLES:
				m_nAnimPercentOld = m_nAnimPercent;
				m_nAnimPercent += g_nAnimStepMetric;
				if( m_nAnimPercent >
						100 + nSteps * g_nAnimStepMetric
					)
					m_nAnimPercent = 101;
				if( m_nAnimPercent > 100 )
					m_bAnimFinished = true;
			break;
#ifdef _DEBUG
			default:
				ASSERT( FALSE );
			break;
#endif // _DEBUG
			} // switch( m_AnimationType )

			if( m_bAnimFinished )
			{
				if( !_FindCustomizeMode() )
				{
					g_SoundPlayer->PlaySound(
						m_ePlaySoundOnAnimationFinished
						);
					m_ePlaySoundOnAnimationFinished =
						CExtSoundPlayer::__NO_SOUND;
				} // if( !_FindCustomizeMode() )
				KillTimer(ID_TIMER_ANIMATION);
				m_AnimationType = g_DefAnimationType;
			} // if( m_bAnimFinished )

			if( GetSafeHwnd() != NULL )
			{
				if( m_bAnimFinished )
					_EndAnimation();
				else
					Invalidate( FALSE );
				g_nLastAnimTime = nCurrAnimTime;
			}
		} // if( !m_bAnimFinished )
		
		if( m_bAnimFinished )
			if( IsKindOf(RUNTIME_CLASS(CExtPopupMenuWnd)) )
				((CExtPopupMenuWnd *)this)->
					GetSite().SetAnimated( NULL );

		return;
	// case ID_TIMER_ANIMATION
	default:
		__BaseClassOfCExtPopupBaseWnd::OnTimer(nIDEvent);
	break; // default
	} // switch( nIDEvent )
}

int CExtPopupBaseWnd::OnMouseActivate(CWnd* pDesktopWnd, UINT nHitTest, UINT message) 
{
	ASSERT_VALID( this );

	pDesktopWnd;
	nHitTest;
	message;
	if( _FindCustomizeMode() )
	{
		if( IsKindOf(RUNTIME_CLASS(CExtPopupMenuWnd)) )
		{
///			((CExtPopupMenuWnd*)this)->_ItemFocusCancel( FALSE );
			((CExtPopupMenuWnd*)this)->_DoResetChainPositions();
		} // if( IsKindOf(RUNTIME_CLASS(CExtPopupMenuWnd)) )
		else
			SetWindowPos(
				&CWnd::wndTopMost,
				-1, -1, -1, -1,
				SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE
				);
		return MA_NOACTIVATE;
	}

HWND hWndInPlace = ::GetWindow( m_hWnd, GW_CHILD );
	if( hWndInPlace != NULL )
	{
		CPoint ptScreenClick;
		if( ! ::GetCursorPos(&ptScreenClick) )
			return MA_NOACTIVATEANDEAT;
		HWND hWndFromPoint = ::WindowFromPoint( ptScreenClick );
		if(		hWndFromPoint != NULL
			&&	(::GetWindowLong(hWndFromPoint,GWL_STYLE)&WS_CHILD) != 0
			&&	::GetParent(hWndFromPoint) == m_hWnd
			)
		return MA_ACTIVATE;
	} // if( hWndInPlace != NULL )

	return MA_NOACTIVATEANDEAT;
	//return CExtPopupBaseWnd::OnMouseActivate(pDesktopWnd, nHitTest, message);
}

void CExtPopupMenuWnd::_DoShowChain(
	int nCmdShow // = SW_SHOWNA
	)
{
	ASSERT_VALID( this );
	if( m_hWnd == NULL || (! ::IsWindow(m_hWnd) ) )
		return;
	ShowWindow( nCmdShow );
	if( m_nCurIndex < 0 )
		return;
MENUITEMDATA & mi = _GetItemRef( m_nCurIndex );
	if( !mi.IsPopup() )
		return;
	mi.GetPopup()->_DoShowChain( nCmdShow );
}

void CExtPopupMenuWnd::_DoResetChainPositions()
{
	ASSERT_VALID( this );
CExtPopupMenuWnd * pChild = NULL;
	if( m_nCurIndex >= 0 )
	{
		MENUITEMDATA & mi = _GetItemRef( m_nCurIndex );
		if( mi.IsPopup() )
		{
			pChild = mi.GetPopup();
			if(		pChild->GetSafeHwnd() == NULL
				||	(! pChild->IsWindowVisible() )
				)
				pChild = NULL;
		} // if( mi.IsPopup() )
	} // if( m_nCurIndex >= 0 )
	if( pChild != NULL )
		pChild->_DoResetChainPositions();
	_DoResetChainPositionsImpl( NULL );
}

void CExtPopupMenuWnd::_DoResetChainPositionsImpl(
	CExtPopupMenuWnd * pPrev
	)
{
	SetWindowPos(
		( pPrev == NULL ) ? (&CWnd::wndTopMost) : pPrev,
		0, 0, 0, 0,
		SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE
			|SWP_NOREDRAW
		);
	{ // BLOCK : DC painting
		CClientDC dc( this );
		_DoPaint( dc );
	} // BLOCK : DC painting
	if( m_pWndParentMenu != NULL )
		m_pWndParentMenu->_DoResetChainPositionsImpl( this );
}

BOOL CExtPopupBaseWnd::OnEraseBkgnd(CDC* pDC) 
{
	ASSERT_VALID( this );

	pDC;
	return TRUE;
}

void CExtPopupBaseWnd::OnNcPaint() 
{
	ASSERT_VALID( this );
}

void CExtPopupBaseWnd::OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS FAR* lpncsp) 
{
	ASSERT_VALID( this );

	bCalcValidRects;
	lpncsp;
///	__BaseClassOfCExtPopupBaseWnd::OnNcCalcSize(bCalcValidRects, lpncsp);
}

void CExtPopupBaseWnd::OnSize(UINT nType, int cx, int cy) 
{
	ASSERT_VALID( this );

	__BaseClassOfCExtPopupBaseWnd::OnSize(nType, cx, cy);
	Invalidate(FALSE);
}

BOOL CExtPopupBaseWnd::DestroyWindow()
{
	ASSERT_VALID( this );
	if( !(::IsWindow(GetSafeHwnd())) )
		return TRUE;
	return __BaseClassOfCExtPopupBaseWnd::DestroyWindow();
}

void CExtPopupBaseWnd::PostNcDestroy() 
{
	ASSERT_VALID( this );
}

void CExtPopupMenuWnd::PostNcDestroy() 
{
	ASSERT_VALID( this );
	if( _FindCustomizeMode() )
		return;
	if( m_bTopLevel )
	{
		ASSERT( m_hWndCmdReciever != NULL );
		if( ::IsWindow(m_hWndCmdReciever) )
			::SendMessage(
				m_hWndCmdReciever,
				g_nMsgNotifyMenuClosed,
				0,
				LPARAM( this )
				);
		CExtPopupMenuSite & _site = GetSite();
		ASSERT( !_site.IsEmpty() );
		if( //!_site.IsEmpty() &&
			!_site.IsShutdownMode()
			)
		{
			_site.DoneInstance();
			ASSERT( _site.IsEmpty() );
			ASSERT( !_site.IsShutdownMode() );
		}
	} // if( m_bTopLevel )
}

bool CExtPopupBaseWnd::_FindHelpMode() const
{
//	if( ::AfxGetApp()->m_bHelpMode )
//		return true;
	return false;
}

bool CExtPopupMenuWnd::_FindHelpMode() const
{
	if( (m_dwTrackFlags&TPMX_HELP_CTX_MODE) != 0 )
		return true;
	if( m_pWndParentMenu != NULL )
		return m_pWndParentMenu->_FindHelpMode();
	return CExtPopupBaseWnd::_FindHelpMode();
}

#if (!defined __EXT_MFC_NO_CUSTOMIZE)
CExtCustomizeSite * CExtPopupMenuWnd::_FindCustomizeSite() const
{
	if( m_pCustomizeSite != NULL )
		return (CExtCustomizeSite *)m_pCustomizeSite;
	if( m_pWndParentMenu != NULL )
		return m_pWndParentMenu->_FindCustomizeSite();
	return NULL;
}
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)

bool CExtPopupBaseWnd::_FindCustomizeMode() const
{
	return false;
}

bool CExtPopupMenuWnd::_FindCustomizeMode() const
{
	if( (m_dwTrackFlags&TPMX_CUSTOMIZE_MODE) != 0 )
		return true;
	if( m_pWndParentMenu != NULL )
		return m_pWndParentMenu->_FindCustomizeMode();
	return false;
}

BOOL CExtPopupBaseWnd::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) 
{
	ASSERT_VALID( this );
	if( _FindHelpMode() )
	{
		SetCursor( afxData.hcurHelp );
		return TRUE;
	}
	return __BaseClassOfCExtPopupBaseWnd::OnSetCursor(pWnd, nHitTest, message);
}

/////////////////////////////////////////////////////////////////////////////
// CExtPopupMenuTipWnd

IMPLEMENT_DYNCREATE(CExtPopupMenuTipWnd, CExtPopupBaseWnd)

CExtPopupMenuTipWnd::CExtPopupMenuTipWnd()
{
	m_hIcon = NULL;
	m_IconSize.cx = m_IconSize.cy = 0;
	m_sText = _T("");
	m_bFlipHorz = false;
	m_bFlipVert = false;

	m_hIcon = ::LoadIcon( NULL, IDI_INFORMATION );
	m_IconSize.cx = m_IconSize.cy = 16;

	m_bAnimFinished = true;
	m_AnimationType = __AT_NONE;
}

CExtPopupMenuTipWnd::~CExtPopupMenuTipWnd()
{
	if( m_hIcon != NULL )
	{
		::DestroyIcon( m_hIcon );
		m_hIcon = NULL;
	}
}

BEGIN_MESSAGE_MAP(CExtPopupMenuTipWnd, CExtPopupBaseWnd)
	//{{AFX_MSG_MAP(CExtPopupMenuTipWnd)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

#define CX_ROUNDED				12		// Tip horizontal roundness
#define CY_ROUNDED				10		// Tip vertical roundness
#define CX_LEADER				25		// Width of tip lead
#define CY_LEADER				25		// Height of tip lead
#define CX_ICON_MARGIN			5		// Width of margin between icon and tip text

#define __TIP_OVER_METRIC 12

bool CExtPopupMenuTipWnd::GetWindowRegion(
	CDC* pDC,
	HRGN* hRegion,
	CSize *Size /* = NULL */
	)
{
	ASSERT_VALID( this );

CRect	rcWnd(0,0,0,0);
POINT	ptLeader[3];
CRgn	LeaderRegion;
CRgn	CaptionRegion;
CFont	*pSysFont;
	
	ASSERT( pDC != NULL );
	ASSERT( hRegion != NULL );

	// Calculate the are for the tip text
	pSysFont =
		(CFont *)pDC->SelectObject(
			&(g_PaintManager->m_FontNormal)
			);
	pDC->DrawText(
		m_sText,
		m_sText.GetLength(),
		&rcWnd,
		DT_CALCRECT
		);
	pDC->SelectObject( pSysFont );

	// Adjust for the rounded corners
	rcWnd.InflateRect(CX_ROUNDED, CY_ROUNDED);

	// Adjust for icon
	if( m_hIcon != NULL )
		rcWnd.right = rcWnd.right + m_IconSize.cx + CX_ICON_MARGIN;
	if( rcWnd.Height() < m_IconSize.cy )
		rcWnd.bottom = rcWnd.top + m_IconSize.cy;

	// Calculate the leader triangle coordinates

	ptLeader[0].x = rcWnd.Width() - CX_ROUNDED;
	ptLeader[0].y = rcWnd.Height() - CY_ROUNDED;

	ptLeader[1].x = ptLeader[0].x;
	ptLeader[1].y = ptLeader[0].y + CY_LEADER;

	ptLeader[2].x = ptLeader[0].x - CX_LEADER;
	ptLeader[2].y = rcWnd.Height() - CY_ROUNDED;

CRect rcRoundRectRgn(CPoint(0,0),rcWnd.Size());
CRect rcRectRgn( 0, 0, rcWnd.Width(), rcWnd.Height() + CY_LEADER );
	m_bFlipHorz = false;
	m_bFlipVert = false;

CWnd * pWndSearchMon = GetParent();
	ASSERT_VALID( pWndSearchMon );
	ASSERT( pWndSearchMon->GetSafeHwnd() != NULL );
	ASSERT( ::IsWindow( pWndSearchMon->GetSafeHwnd() ) );
CExtPaintManager::monitor_parms_t _mp;
	CExtPaintManager::stat_GetMonitorParms( _mp, pWndSearchMon );
CRect rcDesktop = g_bUseDesktopWorkArea
		? _mp.m_rcWorkArea
		: _mp.m_rcMonitor
		;

	if( m_ptTrack.x - rcWnd.Width() < rcDesktop.left )
	{
		m_bFlipHorz = true;
		ptLeader[0].x = CX_ROUNDED;
		ptLeader[0].y = rcWnd.Height() - CY_ROUNDED;
		ptLeader[1].x = ptLeader[0].x;
		ptLeader[1].y = ptLeader[0].y + CY_LEADER;
		ptLeader[2].x = ptLeader[0].x + CX_LEADER;
		ptLeader[2].y = ptLeader[0].y;
	}

	if( m_ptTrack.y - rcWnd.Height() - CY_ROUNDED*2 < rcDesktop.top )
	{
		m_bFlipVert = true;
		ptLeader[0].y -= rcWnd.Height() - CY_ROUNDED*2;
		ptLeader[1].y = ptLeader[0].y - CY_LEADER;
		ptLeader[2].y -= ptLeader[0].y;
	}

	// Create the caption region
	CaptionRegion.CreateRoundRectRgn(
		rcRoundRectRgn.left,rcRoundRectRgn.top,rcRoundRectRgn.right,rcRoundRectRgn.bottom,
		CX_ROUNDED, CY_ROUNDED
		);
	// Create the leader region
	LeaderRegion.CreatePolygonRgn(ptLeader, 3, ALTERNATE);
	// Create window region
	*hRegion =  ::CreateRectRgn(
		rcRectRgn.left,rcRectRgn.top,rcRectRgn.right,rcRectRgn.bottom
		);
	// Combine the regions
	CombineRgn(*hRegion, CaptionRegion.operator HRGN(), LeaderRegion.operator HRGN(), RGN_OR);

	if( m_bFlipVert )
		OffsetRgn(*hRegion,0,CY_LEADER);

	// Set the window size
	if (Size != NULL)
	{
		Size->cx	= rcWnd.Width();
		Size->cy	= rcWnd.Height() + CY_LEADER;
	}

	return true;
}

void CExtPopupMenuTipWnd::_DoPaint( CDC & dcPaint, bool bUseBackBuffer /*= true*/ )
{
	ASSERT_VALID( this );

	bUseBackBuffer;
CDC & dc = dcPaint;

CRect	rc;
CBrush	WindowBrush;
CBrush	FrameBrush;
CBrush	InnerFrameBrush;
HRGN	hRegion;
CRgn	*pRegion;
CFont	*pSysFont;

	// Get the client rectangle
	GetClientRect(rc);

	// Create the brushes
	InnerFrameBrush.CreateSolidBrush(
		g_PaintManager->GetColor(COLOR_3DFACE)
		);
	FrameBrush.CreateSolidBrush(
		g_PaintManager->GetColor(COLOR_3DDKSHADOW)
		);
	WindowBrush.CreateSolidBrush(
		g_PaintManager->GetColor(COLOR_INFOBK)
		);

	// Get the window region
	hRegion = CreateRectRgnIndirect(&rc);
	GetWindowRgn(hRegion);
	pRegion = CRgn::FromHandle(hRegion);

	// Draw the frame
	dc.FillRgn(pRegion, &WindowBrush);
	dc.FrameRgn(pRegion, &InnerFrameBrush, 3, 3);
	dc.FrameRgn(pRegion, &FrameBrush, 1, 1);

	// Adjust the area for the icon
	rc.DeflateRect(CX_ROUNDED, CY_ROUNDED, 0, 0);
	if( m_hIcon != NULL )
		rc.left += m_IconSize.cx + CX_ICON_MARGIN;
	
	// Set the font
	pSysFont = (CFont *)dc.SelectObject(
		&(g_PaintManager->m_FontNormal)
		);
	// Draw the tip text	
	dc.SetBkMode( TRANSPARENT );

int nIconVertPos = CY_ROUNDED;
	if( m_bFlipVert )
	{
		rc.OffsetRect(0,CY_LEADER);
		nIconVertPos += CY_LEADER;
	}

COLORREF clrOltTextColor =
		dc.SetTextColor(
			g_PaintManager->GetColor(COLOR_INFOTEXT)
			);
	dc.DrawText( m_sText, m_sText.GetLength(), &rc, DT_TOP | DT_LEFT );
	dc.SetTextColor( clrOltTextColor );

	// Draw the icon
	if( m_hIcon != NULL )
		DrawIconEx(
			dc.GetSafeHdc(),
			CX_ROUNDED,
			nIconVertPos,
			m_hIcon,
			m_IconSize.cx,
			m_IconSize.cy,
			0,
			NULL,
			DI_NORMAL
			);

	// Clean up GDI
	::DeleteObject(hRegion);
	//if( pSysFont != NULL )
		dc.SelectObject(pSysFont);
}

void CExtPopupMenuTipWnd::SetText(__EXT_MFC_SAFE_LPCTSTR lpszText)
{
	ASSERT_VALID( this );

	m_sText = (lpszText==NULL) ? _T("") : lpszText;
	m_sText.TrimLeft();
	m_sText.TrimRight();
}

void CExtPopupMenuTipWnd::SetIcon(HICON hIcon) 
{
	ASSERT_VALID( this );

	if( m_hIcon != NULL )
	{
		::DestroyIcon( m_hIcon );
		m_hIcon = NULL;
	}
	if( hIcon == NULL )
	{
		m_IconSize = CSize( 0, 0 );
		return;
	}
ICONINFO IconInfo;
	m_hIcon = hIcon; 
	
	// Get the icon sizes	
	ZeroMemory( &IconInfo, sizeof(ICONINFO) );
	::GetIconInfo( m_hIcon, &IconInfo );
	ASSERT( IconInfo.hbmColor != NULL || IconInfo.hbmMask != NULL );

	m_IconSize.cx = (BYTE)(IconInfo.xHotspot * 2);
	m_IconSize.cy = (BYTE)(IconInfo.yHotspot * 2);
	if( m_IconSize.cx == 0 || m_IconSize.cy == 0 )
	{
		ASSERT( IconInfo.hbmColor != NULL || IconInfo.hbmMask != NULL );
		BITMAP bi;
		::memset( &bi, 0, sizeof(BITMAP) );
		::GetObject(
			(IconInfo.hbmColor != NULL) ? IconInfo.hbmColor : IconInfo.hbmMask,
			sizeof(BITMAP),
			&bi
			);
		ASSERT( bi.bmWidth > 0 && bi.bmHeight > 0 );
		m_IconSize.cx = bi.bmWidth;
		m_IconSize.cy = bi.bmHeight;
	} // if( m_IconSize.cx == 0 || m_IconSize.cy == 0 )
	ASSERT( m_IconSize.cx > 0 && m_IconSize.cy > 0 );

	::DeleteObject( IconInfo.hbmMask );
	::DeleteObject( IconInfo.hbmColor );

	if( ::IsWindow(m_hWnd) )
		RedrawWindow();
}

bool CExtPopupMenuTipWnd::Show(
	CWnd * pWndParent,
	const RECT & rcExcludeArea // = CExtPopupMenuTipWnd::rcNoExcludeArea
	)
{
	ASSERT_VALID( this );

	ASSERT_VALID( pWndParent );
	ASSERT( pWndParent->GetSafeHwnd() != NULL );

HCURSOR hCursor = ::LoadCursor(NULL, IDC_ARROW);
	ASSERT( hCursor != NULL );

	if( GetSafeHwnd() == NULL )
	{
		CExtSafeString strClassName =
			::AfxRegisterWndClass (
				__POPUP_WNDCLASS_STYLES__,
				hCursor,
				(HBRUSH)(COLOR_BTNFACE + 1),
				NULL
				);
		BOOL bCreateResult =
			CWnd::CreateEx(
				WS_EX_TOPMOST,
				strClassName,
				NULL,
				WS_POPUP,
				0, 0, 0, 0,
				pWndParent->GetSafeHwnd(),
				NULL,
				NULL
				);
		ASSERT( bCreateResult );
		if( !bCreateResult )
			return false;
	} // if( GetSafeHwnd() == NULL )
#ifdef _DEBUG
	else
	{
		ASSERT_VALID( pWndParent );
		ASSERT( ::IsWindow( pWndParent->GetSafeHwnd() ) );
//		CWnd * pExistingParent = GetParent();
//		ASSERT( pWndParent == pExistingParent );
	} // else from if( GetSafeHwnd() == NULL )
#endif // _DEBUG

	ASSERT_VALID( this );

	m_rcExcludeArea = rcExcludeArea;
	m_rcExcludeArea.NormalizeRect();
CPoint ptTipTarget( m_rcExcludeArea.TopLeft() );
	ptTipTarget += CSize( __TIP_OVER_METRIC/2, __TIP_OVER_METRIC/2 );
	m_ptTrack = ptTipTarget;

CDC * pDC = GetDC();
	ASSERT_VALID( pDC );
HRGN	hRegion;
CSize WindowSize;
	VERIFY( GetWindowRegion(pDC, &hRegion, &WindowSize) );
	ReleaseDC(pDC);
	VERIFY(
		::SetWindowRgn(
			m_hWnd,
			hRegion,
			TRUE
			)
		);

	if( m_bFlipHorz )
		m_ptTrack.x +=
			m_rcExcludeArea.Width() - __TIP_OVER_METRIC
			+ WindowSize.cx - CX_ROUNDED*2
			;
	if( m_bFlipVert )
		m_ptTrack.y += 
			m_rcExcludeArea.Height() - __TIP_OVER_METRIC
			+ WindowSize.cy - CX_ROUNDED*2
			;

CPoint ptWndPos(
		m_ptTrack.x - WindowSize.cx + CX_ROUNDED,
		m_ptTrack.y - WindowSize.cy + CY_ROUNDED
		);
	SetWindowPos(
		&CWnd::wndTopMost,
		ptWndPos.x,
		ptWndPos.y,
		WindowSize.cx,
		WindowSize.cy,
		SWP_NOACTIVATE //| SWP_SHOWWINDOW
		);
CRect rcWnd(ptWndPos,WindowSize);
	MoveWindow(&rcWnd);
//	ASSERT( IsWindowVisible() );
	::SetCursor(hCursor);

//	Invalidate( FALSE );
//	UpdateWindow();
	SetTimer( ID_TIMER_DELAY_SHOW, ID_PERIOD_DELAY_SHOW, NULL );

	return true;
}

void CExtPopupMenuTipWnd::Hide()
{
	ASSERT_VALID( this );

	if( GetSafeHwnd() != NULL )
	{
		KillTimer( ID_TIMER_DELAY_SHOW );
		ShowWindow( SW_HIDE );
	}
	m_rcExcludeArea.SetRectEmpty();
}

/////////////////////////////////////////////////////////////////////////////
// CExtPopupMenuWnd

// is allowed menu item positioning without
// using only & - marked text
bool CExtPopupMenuWnd::g_bAllowNonAccelPositioning = false;

IMPLEMENT_DYNCREATE(CExtPopupMenuWnd, CExtPopupBaseWnd)

CExtPopupMenuWnd::CExtPopupMenuWnd()
	: m_pWndParentMenu( NULL )
	, m_hWndCmdReciever( m_hWndCmdReciever )
	, m_nLeftAreaWidth( 0 )
#if (!defined __EXT_MFC_NO_CUSTOMIZE)
	, m_pNode( NULL )
	, m_pDragSrcNode( NULL )
	, m_nDragSrcIdx( -1 )
	, m_bHelperNoRemoveSrc( false )
	, m_bHelperDragOverPassed( false )
	, m_pCustomizeSite( NULL )
	, m_nHelperDropIndexBefore( -1 )
	, m_bHelperNoHideChild( false )
	, m_ptHelperDragStart( 0, 0 )
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)
{
	__VPC_INC;
	_Init();
}

CExtPopupMenuWnd::~CExtPopupMenuWnd()
{
	_OnCancelMode( true );
	if( m_bTopLevel )
	{
		VERIFY( _BuildItems( NULL, true ) );
	}
	__VPC_DEC;
#ifdef _DEBUG
	if( m_bTopLevel )
	{
		__VPC_VERIFY_0;
	}
#endif // _DEBUG
}

bool CExtPopupMenuWnd::TestHoverEnabledFromActiveHWND(
	HWND hWndTestFrom,
	HWND hWndActive, // = ::GetActiveWindow(),
	bool bCheckEnabled, // = true,
	bool bCheckVisible, // = true,
	bool bCheckExtPopupMenuTracking // = true
	)
{
	if( bCheckExtPopupMenuTracking )
	{
		if( CExtPopupMenuWnd::IsMenuTracking() )
			return false;
	} // if( bCheckExtPopupMenuTracking )
	
	if(		hWndTestFrom == NULL
		||	( ! ::IsWindow( hWndTestFrom ) )
		)
		return false;
	if(		hWndActive == NULL
		||	( ! ::IsWindow( hWndActive ) )
		)
		return false;

	if( bCheckEnabled )
	{
		if( ! ::IsWindowEnabled( hWndTestFrom ) )
			return false;
		if( ! ::IsWindowEnabled( hWndActive ) )
			return false;
	} // if( bCheckEnabled )

DWORD dwWndStyle;
	if( bCheckVisible )
	{
		dwWndStyle =
			(DWORD) ::GetWindowLong(
				hWndTestFrom,
				GWL_STYLE
				);
		if( (dwWndStyle & WS_VISIBLE) == 0 )
			return false;

		dwWndStyle =
			(DWORD) ::GetWindowLong(
				hWndActive,
				GWL_STYLE
				);
		if( (dwWndStyle & WS_VISIBLE) == 0 )
			return false;
	} // if( bCheckVisible )

const DWORD dwTestStyles = (WS_VISIBLE|WS_POPUP);

	for(	HWND hWndParentOfTest = ::GetParent( hWndTestFrom );
			hWndParentOfTest != NULL;
			hWndParentOfTest = ::GetParent( hWndParentOfTest )
			)
	{ // walk parent popup windows of hWndTestFrom
		ASSERT( ::IsWindow( hWndParentOfTest ) );
		dwWndStyle =
			(DWORD) ::GetWindowLong(
				hWndParentOfTest,
				GWL_STYLE
				);
		if( (dwWndStyle&dwTestStyles) == 0L )
			continue;
		if( hWndParentOfTest == hWndActive )
			return true;

		for(	HWND hWndParentOfActive = hWndActive;
				hWndParentOfActive != NULL;
				hWndParentOfActive = ::GetParent( hWndParentOfActive )
				)
		{ // walk parent popup windows of hWndActive
			ASSERT( ::IsWindow( hWndParentOfActive ) );
			dwWndStyle =
				(DWORD) ::GetWindowLong(
					hWndParentOfActive,
					GWL_STYLE
					);
			if( (dwWndStyle&dwTestStyles) == 0L )
				continue;
			if( hWndParentOfActive == hWndParentOfTest )
				return true;
		} // walk parent popup windows of hWndActive

	} // walk parent popup windows of hWndTestFrom

	return false;
}

void CExtPopupMenuWnd::_Init()
{
	ASSERT_VALID( this );

	_InitAnimation();

	m_nDyScrollOffset = 0;
	m_bTopLevel
		= m_bScrollingAvailable
		= m_bExpandAvailable
		= m_bExpandWasPressed
		= m_bCombineWithEA 
		= false;
	m_dwTrackFlags = 0;
	m_nWaitingExpandTickCount = 0;
	m_nCurIndex
		= m_nDelayedFocusItemIndex
		= IDX_NOTHING;

	m_nScrollingDirection = 0;
	m_rcScrollTop.SetRectEmpty();
	m_rcScrollBottom.SetRectEmpty();
	m_rcExpandBtn.SetRectEmpty();

	m_eCombineAlign = __CMBA_NONE;

	m_pCbPaintCombinedCookie = NULL;
	m_pCbPaintCombinedContent = NULL;
	m_bCookieIsObject = false;
}

CObject * CExtPopupBaseWnd::GetCoockieAsObject()
{
	if(		(!m_bCookieIsObject)
		||	m_pCbPaintCombinedCookie == NULL
		)
		return NULL;
CObject * pObj = (CObject*)m_pCbPaintCombinedCookie;
	ASSERT_VALID( pObj );
	return pObj;
}

bool CExtPopupBaseWnd::IsToolBtnCombinedArea() const
{
	if( !IsKindOf( RUNTIME_CLASS(CExtPopupMenuWnd) ) )
		return false;
CExtPopupMenuWnd * pPopup = (CExtPopupMenuWnd*)(this);
//	pPopup = pPopup->GetParentMenuWnd();
//	if( pPopup == NULL )
//		return false;
	if(		(LPVOID)(CExtPopupMenuWnd::stat_paint_combined_menu_toolbtn)
		!=	(LPVOID)(pPopup->GetCbPaintCombinedContent())
		)
		return false;
	return true;
}

int CExtPopupMenuWnd::_GetCurIndex() const
{
	ASSERT_VALID( this );

	return m_nCurIndex;
}

int CExtPopupMenuWnd::_GetSpecBtnHeight()
{
int nHeight = g_PaintManager->GetMenuExpandButtonHeight();
	ASSERT( nHeight > 0 );
	return nHeight;
}

void CExtPopupMenuWnd::_RecalcLayoutImpl()
{
	ASSERT_VALID( this );

CRect rcClient;
	_GetClientRect( &rcClient );
int nScrollBtnDy =
		_GetSpecBtnHeight();
int nMenuBorderSize =
		g_PaintManager->GetMenuBorderSize();
int nMenuShadowSize = 0;
//		_GetPopupShadowSize();

int nScrollBottomOffsetDy = 0;
	if( m_bExpandAvailable )
	{
		m_rcExpandBtn.left =
			rcClient.left + nMenuBorderSize;
		m_rcExpandBtn.right =
			rcClient.right - (nMenuBorderSize + nMenuShadowSize);
		m_rcExpandBtn.bottom =
			rcClient.bottom - (nMenuBorderSize + nMenuShadowSize);
		m_rcExpandBtn.top =
			m_rcExpandBtn.bottom - nScrollBtnDy;
		nScrollBottomOffsetDy =
			- m_rcExpandBtn.Height();
		m_rcExpandBtn.DeflateRect(
			__MI_HORZ_GAP_TO_BORDER,
			0
			);
		m_rcExpandBtn.left += m_nLeftAreaWidth;
	} // if( m_bExpandAvailable )

	if( m_bScrollingAvailable )
	{
		m_rcScrollTop.left = m_rcScrollBottom.left =
			rcClient.left + nMenuBorderSize;
		m_rcScrollTop.right = m_rcScrollBottom.right =
			rcClient.right - (nMenuBorderSize + nMenuShadowSize);

		m_rcScrollTop.top =
			rcClient.top + nMenuBorderSize;
		m_rcScrollTop.bottom =
			m_rcScrollTop.top + nScrollBtnDy;
		
		m_rcScrollBottom.bottom =
			rcClient.bottom - (nMenuBorderSize + nMenuShadowSize);
		m_rcScrollBottom.top =
			m_rcScrollBottom.bottom - nScrollBtnDy;

		m_rcScrollBottom.OffsetRect(0,nScrollBottomOffsetDy);
		m_rcScrollTop.DeflateRect(
			__MI_HORZ_GAP_TO_BORDER,
			0
			);
		m_rcScrollBottom.DeflateRect(
			__MI_HORZ_GAP_TO_BORDER,
			0
			);
		m_rcScrollTop.left += m_nLeftAreaWidth;
		m_rcScrollBottom.left += m_nLeftAreaWidth;
	} // if( m_bScrollingAvailable )
}

class CExtPopupMenuWnd::CExtPopupMenuCmdUI : public CCmdUI
{
public: // re-implementations only
	HWND m_hWndCmdReciever;
	CExtPopupMenuWnd * m_pPopup;
	CExtPopupMenuWnd::MENUITEMDATA * m_pItemDataActive;
	CExtPopupMenuCmdUI(
		HWND hWndCmdReciever,
		CExtPopupMenuWnd * pPopup
		)
		: m_hWndCmdReciever( hWndCmdReciever )
		, m_pPopup( pPopup )
		, m_pItemDataActive( NULL )
	{
		ASSERT( m_hWndCmdReciever != NULL && ::IsWindow(m_hWndCmdReciever) );
		ASSERT_VALID( m_pPopup );
		CCmdUI::m_pOther = NULL; // menu
		CCmdUI::m_nIndexMax = (UINT)m_pPopup->ItemGetCount();
		CCmdUI::m_nIndex = 0;
	}
	void SetActiveIndex( int nIndex )
	{
		ASSERT( m_hWndCmdReciever != NULL && ::IsWindow(m_hWndCmdReciever) );
		ASSERT_VALID( m_pPopup );
		CCmdUI::m_nIndex = (UINT)nIndex;
		ASSERT( CCmdUI::m_nIndex >= 0 && CCmdUI::m_nIndex < CCmdUI::m_nIndexMax );
		m_pItemDataActive = &m_pPopup->_GetItemRef(nIndex);
		ASSERT( m_pItemDataActive != NULL );
		CCmdUI::m_nID = m_pItemDataActive->GetCmdID();
		if(		m_pItemDataActive->IsPopup()
			||	m_pItemDataActive->IsSeparator()
			||	CExtCmdManager::IsSystemCommand( CCmdUI::m_nID )
			)
			return;
		CExtCmdItem * pCmdItem =
			g_CmdManager->CmdGetPtr(
				g_CmdManager->ProfileNameFromWnd(m_hWndCmdReciever),
				CCmdUI::m_nID
				);
		if( pCmdItem == NULL )
			return;
//		m_pItemDataActive->SetText( pCmdItem->m_sMenuText );
		m_pItemDataActive->SetAccelText( pCmdItem->m_sAccelText );
		m_pItemDataActive->AccelCharInit();
		m_pItemDataActive->MeasureItem();
	}
	virtual void Enable(BOOL bOn)
	{
		CCmdUI::m_bEnableChanged = TRUE;
		ASSERT( m_hWndCmdReciever != NULL && ::IsWindow(m_hWndCmdReciever) );
		ASSERT_VALID( m_pPopup );
		ASSERT( m_pItemDataActive != NULL );
/*
		if( m_pItemDataActive->IsPopup() )
		{
#if (!defined __EXT_MFC_NO_CUSTOMIZE)
			CExtCustomizeSite * pSite =
				CExtCustomizeSite::GetCustomizeSite(m_hWndCmdReciever);
			if(	!(		m_pItemDataActive->IsInplaceEdit()
					&&	pSite != NULL
					&&	m_pItemDataActive->GetCmdNode() != NULL
					)
				)
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)
				return;
		}
*/
		if( m_pItemDataActive->IsPopup() && m_pItemDataActive->GetCmd() == NULL )
			return;

		if( m_pItemDataActive->IsForceEnabled() )
			bOn = TRUE;
		m_pItemDataActive->Enable( bOn ? true : false );
//		m_pItemDataActive->MeasureItem();
	}
	virtual void SetRadio(BOOL bOn)
	{
		ASSERT( m_hWndCmdReciever != NULL && ::IsWindow(m_hWndCmdReciever) );
		ASSERT_VALID( m_pPopup );
		ASSERT( m_pItemDataActive != NULL );
		if( m_pItemDataActive->IsPopup() )
			return;
		m_pItemDataActive->Radio( bOn ? true : false );
//		m_pItemDataActive->MeasureItem();
	}
	virtual void SetCheck(int nCheck)
	{
		ASSERT_VALID( m_pPopup );
		ASSERT( m_pItemDataActive != NULL );
		if( m_pItemDataActive->IsPopup() )
			return;
		m_pItemDataActive->Check( nCheck ? true : false );
//		m_pItemDataActive->MeasureItem();
	}
	virtual void SetText( LPCTSTR lpszText )
	{
		ASSERT( m_hWndCmdReciever != NULL && ::IsWindow(m_hWndCmdReciever) );
		ASSERT_VALID( m_pPopup );
		ASSERT( m_pItemDataActive != NULL );
		if( lpszText == NULL )
			return;
		if( m_pItemDataActive->IsPopup() )
			return;
		m_pItemDataActive->SetText( lpszText );
		m_pItemDataActive->MeasureItem();
	}
}; // class CExtPopupMenuWnd::CExtPopupMenuCmdUI

void CExtPopupMenuWnd::_UpdateCmdUI()
{
	ASSERT_VALID( this );

	if( m_bTopLevel )
		if( (m_dwTrackFlags&TPMX_NO_CMD_UI) != 0 )
			return;

	ASSERT( m_hWndCmdReciever != NULL );

#if (!defined __EXT_MFC_NO_CUSTOMIZE)
__EXT_MFC_SAFE_LPCTSTR strProfileName = g_CmdManager->ProfileNameFromWnd(m_hWndCmdReciever);
CExtCustomizeSite * pSite = CExtCustomizeSite::GetCustomizeSite(m_hWndCmdReciever);
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)

BOOL bDisableIfNoHndler = TRUE;
CExtPopupMenuCmdUI _state( m_hWndCmdReciever, this );

bool bResyncItems = false;
	for(	INT _iter = 0;
			_iter < m_items_all.GetSize();
			_iter++
			)
	{ // walk all items
		_state.SetActiveIndex( _iter );
		ASSERT( _state.m_pItemDataActive != NULL );
		if( _state.m_pItemDataActive->IsSeparator() )
			continue;
		if( _state.m_pItemDataActive->IsPopup() )
		{
#if (!defined __EXT_MFC_NO_CUSTOMIZE)
			if(	/*	_state.m_pItemDataActive->IsInplaceEdit()
				&&*/	pSite != NULL
				&&	_state.m_pItemDataActive->GetCmdNode() != NULL
				)
			{
				UINT _nCmdIdSaved = _state.m_pItemDataActive->m_nCmdID;
				_state.m_nID =
					_state.m_pItemDataActive ->
						GetCmdNode() ->
							GetCmdID( false );
				ASSERT( CExtCmdManager::IsCommand( _state.m_nID ) );
				HWND hWndCmdReciever =
					_state.m_pItemDataActive->GetCmdReciever();
				ASSERT( hWndCmdReciever != NULL );
				ASSERT( ::IsWindow(hWndCmdReciever) );
				CWnd * pWndCmdReciever =
					CWnd::FromHandle( hWndCmdReciever );
				ASSERT_VALID( pWndCmdReciever );
				_state.DoUpdate( pWndCmdReciever, bDisableIfNoHndler );
#if (!defined __EXT_MFC_NO_CUSTOMIZE)
				if(		pSite != NULL
					&&	pSite->IsCustomizeMode()
					)
					_state.m_pItemDataActive->SetForceEnabled( true );
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)
				_state.m_pItemDataActive->m_nCmdID = _nCmdIdSaved;

				_state.m_pItemDataActive->GetPopup()->_UpdateCmdUI();
				
				continue;
			}
			else
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)
			{
				_state.m_pItemDataActive->GetPopup()->_UpdateCmdUI();
				continue;
			}
		}
		if( _state.m_pItemDataActive->IsExtraMark() )
		{
			bResyncItems = true;
			continue;
		}
#if (!defined __EXT_MFC_NO_CUSTOMIZE)
		if(		pSite != NULL
			&&	pSite->IsUserBarCommand(
					_state.m_pItemDataActive->GetCmdID()
					)
			&&	strProfileName != NULL
			)
		{
			_state.m_pItemDataActive->SetForceEnabled( true );
			CExtCmdItem * pCmdItem =
				g_CmdManager->CmdGetPtr(
					strProfileName,
					_state.m_pItemDataActive->GetCmdID()
					);
			ASSERT( pCmdItem != NULL );
			CExtToolControlBar * pUserBar =
				pSite->GetUserBar( _state.m_pItemDataActive->GetCmdID() );
			ASSERT_VALID( pUserBar );
			bool bCheck = pUserBar->IsVisible() ? true : false;
			pCmdItem->StateSetCheck( bCheck );
			_state.SetCheck( bCheck );
			continue;
		}
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)
		if(		CExtCmdManager::IsCommandNeedsSpecUpdate(
					_state.m_pItemDataActive->GetCmdID()
					)
			||	CExtCmdManager::IsSystemCommand(
					_state.m_pItemDataActive->GetCmdID()
					)
			)
			continue;

		HWND hWndCmdReciever =
			_state.m_pItemDataActive->GetCmdReciever();
		ASSERT( hWndCmdReciever != NULL );
		ASSERT( ::IsWindow(hWndCmdReciever) );
		CWnd * pWndCmdReciever =
			CWnd::FromHandle( hWndCmdReciever );
		ASSERT_VALID( pWndCmdReciever );
		_state.DoUpdate( pWndCmdReciever, bDisableIfNoHndler );
#if (!defined __EXT_MFC_NO_CUSTOMIZE)
		if(		pSite != NULL
			&&	pSite->IsCustomizeMode()
			)
			_state.m_pItemDataActive->SetForceEnabled( true );
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)
	}  // walk all items

	if( bResyncItems )
		_SyncItems();
}

bool CExtPopupMenuWnd::MENUITEMDATA::ConstructPopup()
{
	ASSERT( m_iconPopup.IsEmpty() );
	ASSERT( m_pWndChild == NULL );
	m_pWndChild = new CExtPopupMenuWnd;
	
	ASSERT( m_hWndSpecCmdReciever != NULL );
	ASSERT( ::IsWindow(m_hWndSpecCmdReciever) );
	m_pWndChild->m_hWndCmdReciever = m_hWndSpecCmdReciever;
	
	return true;
}

void CExtPopupMenuWnd::MENUITEMDATA::DestroyPopup()
{
	VERIFY( SetPopupIcon(NULL) );
	if( m_pWndChild == NULL )
		return;
	if( m_pWndChild->GetSafeHwnd() != NULL
		&& ::IsWindow( m_pWndChild->GetSafeHwnd() )
		)
		m_pWndChild->DestroyWindow();
//	else
//		delete m_pWndChild;
	delete m_pWndChild;
	m_pWndChild = NULL;
}

bool CExtPopupMenuWnd::_BuildItems(
	CMenu * pBuildMenu,
	bool bTopLevel
	)
{
	ASSERT_VALID( this );
#ifdef _DEBUG
	if( pBuildMenu != NULL )
	{
		ASSERT( m_hWndCmdReciever != NULL );
		ASSERT( ::IsWindow(m_hWndCmdReciever) );
	}
#endif // _DEBUG
INT iter = 0;
	for( ; iter < m_items_all.GetSize(); iter++)
	{
		MENUITEMDATA & mi = m_items_all[ iter ];
		if( mi.IsPopup() )
		{
			mi.GetPopup()->m_hWndCmdReciever = m_hWndCmdReciever;
			mi.GetPopup()->_OnCancelMode();
			VERIFY( mi.GetPopup()->_BuildItems( NULL, false ) );
			mi.DestroyPopup();
		}
	} // for( ; iter < m_items_all.GetSize(); iter++)
	m_items_all.RemoveAll();

	if( pBuildMenu == NULL )
		return true;
	ASSERT( pBuildMenu->GetSafeHmenu() != NULL );

	m_bTopLevel = bTopLevel;
	if( m_bTopLevel )
		m_pWndParentMenu = NULL;

	// build items loop
bool bPrevWasSeparator = false;
int nMruUpdateIndex = -1, nInsertedIndex = 0;
int	nMenuItemCount = pBuildMenu->GetMenuItemCount();
	ASSERT( nMenuItemCount > 0 );
	m_items_all.RemoveAll();
	for( int nItemIndex=0; nItemIndex<nMenuItemCount; nItemIndex++ )
	{
		UINT nMenuItemID =
			pBuildMenu->GetMenuItemID( nItemIndex );
		if( ID_FILE_MRU_FIRST <= nMenuItemID
			&&
			nMenuItemID <= ID_FILE_MRU_LAST
			)
		{
			if( nMruUpdateIndex < 0 )
				nMruUpdateIndex = nInsertedIndex;
			continue;
		}
		MENUITEMDATA mi;
		mi.SetCmdReciever( m_hWndCmdReciever );
		VERIFY(
			mi.UpdateFromMenu(
				m_hWndCmdReciever,
				pBuildMenu,
				nItemIndex
				)
			);
		bool bIsSeparator = mi.IsSeparator();
		if( bPrevWasSeparator && bIsSeparator )
				continue;
		bPrevWasSeparator = bIsSeparator;
		
		if( mi.IsPopup() )
		{
			CMenu * pSubMenu =
					pBuildMenu->GetSubMenu(nItemIndex);
			ASSERT( pSubMenu != NULL );
			ASSERT( pSubMenu->GetSafeHmenu() != NULL );
			mi.GetPopup()->m_hWndCmdReciever = m_hWndCmdReciever;
			mi.GetPopup()->_BuildItems( pSubMenu, false );
			mi.GetPopup()->m_pWndParentMenu = this;
		}
		_InsertItem( -1, mi );
		nInsertedIndex++;
	} // for( int nItemIndex=0; nItemIndex<nMenuItemCount; nItemIndex++ )
	ASSERT( m_items_all.GetSize() <= nMenuItemCount );

int nMruInsertCount = 0;
	if( nMruUpdateIndex >= 0 )
	{ // insert recently opened file items
		ASSERT( nMruUpdateIndex < nMenuItemCount );
		CRecentFileList * pRecentFileList =
			InternalFriendlyWinApp::_GetFriendlyApp()->
				_GetRecentFileList();
		if( pRecentFileList != NULL )
		{ // can be null !?
			int nRecentCount =
				pRecentFileList->GetSize();
			TCHAR sCurrDir[_MAX_PATH+1];
			::memset(sCurrDir,0,sizeof(sCurrDir));
			::GetCurrentDirectory(_MAX_PATH,sCurrDir);
			int nLenCurDir = _tcslen(sCurrDir);
			for( nItemIndex=0; nItemIndex<nRecentCount; nItemIndex++ )
			{
				CExtSafeString sDisplayName( _T("") );
				if(	!pRecentFileList->GetDisplayName(
						*((CString *)&sDisplayName),
						nItemIndex,
						sCurrDir,
						nLenCurDir,
						TRUE
						)
					)
					continue;
				ASSERT( !sDisplayName.IsEmpty() );
				UINT nCmdID = ID_FILE_MRU_FIRST + nItemIndex;
				ASSERT( nCmdID <= ID_FILE_MRU_LAST );
				CExtCmdItem * pCmdItem =
					g_CmdManager->CmdGetPtr(
						g_CmdManager->ProfileNameFromWnd( m_hWndCmdReciever ),
						nCmdID
						);
				if( pCmdItem == NULL )
					pCmdItem =
						g_CmdManager->CmdAllocPtr(
							g_CmdManager->ProfileNameFromWnd( m_hWndCmdReciever ),
							nCmdID
							);
				ASSERT( pCmdItem != NULL );
				if( pCmdItem == NULL )
					return false;
				int nDisplayIndex = nItemIndex+1;
				if( nDisplayIndex < 10 )
					pCmdItem->m_sMenuText.Format(
						_T("&%d %s"),
						nDisplayIndex,
						sDisplayName
						);
				else
					pCmdItem->m_sMenuText.Format(
						_T("%d&%d %s"),
						nDisplayIndex/10,
						nDisplayIndex%10,
						sDisplayName
						);
				
#if (defined _AFXDLL && !defined __STATPROFUIS_WITH_DLLMFC__)
				CExtLocalResourceHelper _LRH;
#endif // #if (defined _AFXDLL && !defined __STATPROFUIS_WITH_DLLMFC__)
				
				CExtSafeString sRecentFileFmt1,sRecentFileFmt2;
				if( !sRecentFileFmt1.LoadString(IDS_RECENT_FILE_FMT_1) )
				{
#if (defined _AFXDLL && !defined __STATPROFUIS_WITH_DLLMFC__)
					ASSERT( FALSE );
#endif // #if (defined _AFXDLL && !defined __STATPROFUIS_WITH_DLLMFC__)
					sRecentFileFmt1 = _T("Recent file %d");
				}
				if( !sRecentFileFmt2.LoadString(IDS_RECENT_FILE_FMT_2) )
				{
#if (defined _AFXDLL && !defined __STATPROFUIS_WITH_DLLMFC__)
					ASSERT( FALSE );
#endif // #if (defined _AFXDLL && !defined __STATPROFUIS_WITH_DLLMFC__)
					sRecentFileFmt2 = _T("Recent file %d (\"%s\")");
				}
				pCmdItem->m_sToolbarText.Format(
					(LPCTSTR)sRecentFileFmt1,
					nItemIndex + 1
					);
				pCmdItem->m_sTipTool.Format(
					(LPCTSTR)sRecentFileFmt2,
					nItemIndex + 1,
					sDisplayName
					);
				pCmdItem->m_sTipStatus = pCmdItem->m_sTipTool;

				BOOL bInsRetVal =
					ItemInsert(
						nCmdID,
						nMruUpdateIndex + nItemIndex
						);
				
				if( !bInsRetVal )
				{
					ASSERT( FALSE );
					return false;
				}
				nMruInsertCount++;
			} // for( nItemIndex=0; nItemIndex<nRecentCount; nItemIndex++ )
		} // can be null !?
		if( nMruInsertCount > 0 )
		{
			if( !ItemInsert(
					ID_SEPARATOR,
					nMruUpdateIndex + nMruInsertCount
					)
				)
			{
				ASSERT( FALSE );
				return false;
			}
			nMruInsertCount++;
		} // if( nMruInsertCount > 0 )
	} // insert recently opened file items

	_SyncItems();
	return true;
}

void CExtPopupMenuWnd::_GetClientRect(RECT * pRectClient)
{
	ASSERT_VALID( this );

	ASSERT( pRectClient != NULL );
	ASSERT( GetSafeHwnd() != NULL );

	*pRectClient = m_rcClient;

	ASSERT( pRectClient->top <= pRectClient->bottom );
	ASSERT( pRectClient->left <= pRectClient->right );
}

BOOL CExtPopupMenuWnd::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) 
{
	ASSERT_VALID( this );
	if( _FindHelpMode() )
	{
		SetCursor( afxData.hcurHelp );
		return TRUE;
	}
CPoint ptCursor;
	if( ItemGetCount() > 0 && ::GetCursorPos(&ptCursor) )
	{
		ScreenToClient( &ptCursor );
		int nIndex = _HitTest( ptCursor );
		if( nIndex >= 0 )
		{
			MENUITEMDATA & mi = _GetItemRef( nIndex );
			if(		(! mi.IsExtraMark() )
				&&	mi.IsInplaceEdit()
				&&	mi.IsAllowInplaceEditActivation()
				&&	(! _FindHelpMode() )
				)
			{
				CRect rcItem;
				_GetItemRect( nIndex, rcItem );
#if (!defined __EXT_MFC_NO_CUSTOMIZE)
#if (!defined __EXT_MFC_NO_BUILTIN_TEXTFIELD)
				if( _FindCustomizeMode() )
				{
					ASSERT_VALID( mi.GetCmdNode() );
					if(		mi.IsSelected()
						&&	(mi.GetCmdNode()->GetFlags() & __ECTN_TBB_RESIZABLE) != 0
						)
					{ // if button can be resized
						int nDdWidth = g_PaintManager->GetDropDividerMerics().cx / 2;
						if( nDdWidth < 2 )
							nDdWidth = 2;
						CRect rcH( rcItem );
						rcH.right = rcH.left + nDdWidth;
						bool bSetCursor = false;
						if( rcH.PtInRect(ptCursor) )
							bSetCursor = true;
						else
						{
							rcH = rcItem;
							rcH.left = rcH.right - nDdWidth;
							if( rcH.PtInRect(ptCursor) )
								bSetCursor = true;
						} // else from if( rcH.PtInRect(ptCursor) )
						if( bSetCursor )
						{
#if (defined _AFXDLL && !defined __STATPROFUIS_WITH_DLLMFC__)
							CExtLocalResourceHelper _LRH;
							CWinApp * pApp = ::AfxGetApp();
							ASSERT_VALID( pApp );
							HCURSOR hCursor =
								pApp->LoadCursor(
									MAKEINTRESOURCE( IDC_EXT_RESIZE_H1 )
									);
							if( hCursor == NULL )
							{
								ASSERT( FALSE );
								hCursor = ::LoadCursor( NULL, IDC_SIZEWE );
							} // if( hCursor == NULL )
#else // if - (defined _AFXDLL && !defined __STATPROFUIS_WITH_DLLMFC__)
							HCURSOR hCursor = ::LoadCursor( NULL, IDC_SIZEWE );
#endif // if NOT - (defined _AFXDLL && !defined __STATPROFUIS_WITH_DLLMFC__)
							ASSERT( hCursor != NULL );
							::SetCursor( hCursor );
							return TRUE;
						} // if( bSetCursor )
					} // if button can be resized
				} // if( _FindCustomizeMode() )
				else
#endif // (!defined __EXT_MFC_NO_BUILTIN_TEXTFIELD)
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)
				{
					CRect rcInplaceCtrl = mi.AdjustInplaceEditRect( rcItem );
					if( rcInplaceCtrl.PtInRect(ptCursor) )
					{
						HCURSOR hCursor = ::LoadCursor( NULL, IDC_IBEAM );
						SetCursor( hCursor );
						return TRUE;
					} // if( rcInplaceCtrl.PtInRect(ptCursor) )
				} // else from if( _FindCustomizeMode() )
			}
		} // if( nIndex >= 0 )
	} // if( ItemGetCount() > 0 && ::GetCursorPos(&ptCursor) )
	return CExtPopupBaseWnd::OnSetCursor(pWnd, nHitTest, message);
}

int CExtPopupMenuWnd::_HitTest(
	const CPoint & point,
	bool * p_bInplaceControlArea, // = NULL
	bool * p_bInplaceDropDownArea // = NULL
	)
{
	ASSERT_VALID( this );

	if( p_bInplaceControlArea != NULL )
		*p_bInplaceControlArea = false;
	if( p_bInplaceDropDownArea != NULL )
		*p_bInplaceDropDownArea = false;

	if( GetSafeHwnd() == NULL )
		return IDX_NOTHING;

CRect rcClient;
	_GetClientRect( &rcClient );
	if( !rcClient.PtInRect(point) )
		return IDX_NOTHING;

	if( m_bScrollingAvailable )
	{
		CRect rcItem;
		if( m_nDyScrollOffset != 0 )
		{
			_GetItemRect(IDX_SCROLL_TOP,rcItem);
			if( rcItem.PtInRect(point) )
				return IDX_SCROLL_TOP;
		}
		int nMaxScrollPos = _GetMaxScrollPos();
		if( m_nDyScrollOffset != nMaxScrollPos )
		{
			_GetItemRect(IDX_SCROLL_BOTTOM,rcItem);
			if( rcItem.PtInRect(point) )
				return IDX_SCROLL_BOTTOM;
		}
	}
	if( m_bExpandAvailable )
	{
		CRect rcExpand;
		_GetItemRect(IDX_EXPAND,rcExpand);
		if( rcExpand.PtInRect(point) )
			return IDX_EXPAND;
	}

//int nMenuBorderSize =
//		g_PaintManager->GetMenuBorderSize();

//int y = m_nDyScrollOffset + nMenuBorderSize;

INT iter = 0;
int nIndex = 0;
	for( ; iter < m_items_all.GetSize(); iter++,nIndex++ )
	{
		MENUITEMDATA & mi = m_items_all[ iter ];
		if( !mi.IsDisplayed() )
			continue;

		CRect rcItem;
		_GetItemRect( nIndex, rcItem );
		if( rcItem.PtInRect(point) )
		{
			int nRetIndex = mi.GetIndex();
			ASSERT(
					nRetIndex >= 0
				&&	nRetIndex < m_items_all.GetSize()
				);
			if(		(	p_bInplaceControlArea != NULL
					||	p_bInplaceDropDownArea != NULL
					)
				&&	mi.IsInplaceEdit()
				)
			{
				CRect rcInplaceCtrl = mi.AdjustInplaceEditRect( rcItem );
				if( p_bInplaceControlArea != NULL )
				{
					if( rcInplaceCtrl.PtInRect(point) )
						*p_bInplaceControlArea = true;
				}
				if(		p_bInplaceDropDownArea != NULL
					&&	mi.IsPopup()
					)
				{
					rcInplaceCtrl.left = rcInplaceCtrl.right;
					rcInplaceCtrl.right += ::GetSystemMetrics(SM_CXHTHUMB);
					if( rcInplaceCtrl.PtInRect(point) )
						*p_bInplaceDropDownArea = true;
				}
			}
			return nRetIndex;
		}
	} // for( ; iter < m_items_all.GetSize(); iter++,nIndex++ )
	return IDX_NOTHING;
};


BEGIN_MESSAGE_MAP(CExtPopupMenuWnd, CExtPopupBaseWnd)
	//{{AFX_MSG_MAP(CExtPopupMenuWnd)
	ON_WM_CANCELMODE()
	ON_WM_TIMER()
	ON_WM_ACTIVATEAPP()
	ON_WM_SHOWWINDOW()
	ON_WM_SETCURSOR()
	//}}AFX_MSG_MAP
	ON_WM_MOUSEMOVE()
	ON_WM_LBUTTONDOWN()
	ON_WM_LBUTTONUP()
	ON_WM_LBUTTONDBLCLK()
	ON_WM_MBUTTONDOWN()
	ON_WM_MBUTTONUP()
	ON_WM_MBUTTONDBLCLK()
	ON_WM_RBUTTONDOWN()
	ON_WM_RBUTTONUP()
	ON_WM_RBUTTONDBLCLK()
	ON_WM_KEYDOWN()
	ON_WM_KEYUP()
	ON_WM_SYSKEYDOWN()
	ON_WM_SYSKEYUP()
	ON_WM_SYSDEADCHAR()
	ON_WM_CHAR()
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CExtPopupMenuWnd message handlers

BOOL CExtPopupMenuWnd::LoadMenu( 
	HWND hWndCmdRecv,
	UINT nIDResource,
	bool bPopupMenu // = true
	)
{
	ASSERT_VALID( this );

CMenu menu;
	if( !menu.LoadMenu(nIDResource) )
	{
		ASSERT( FALSE );
		return FALSE;
	}
	return
		UpdateFromMenu(
			hWndCmdRecv,
			&menu,
			bPopupMenu
			);
}

BOOL CExtPopupMenuWnd::UpdateMdiWindowsMenu(
	CWnd * pWndStartSearchMdiFrameWnd // = NULL
	)
{
	ASSERT_VALID( this );

	ASSERT( m_hWndCmdReciever != NULL );
	ASSERT( ::IsWindow(m_hWndCmdReciever) );
CMDIFrameWnd * pFrame = NULL;
CWnd * pWnd =
		(pWndStartSearchMdiFrameWnd != NULL)
			? pWndStartSearchMdiFrameWnd
			: FromHandle(m_hWndCmdReciever) // ::AfxGetMainWnd()
			;
	while( true )
	{
		ASSERT( pWnd != NULL );
		ASSERT_VALID( pWnd );
		pFrame =
			DYNAMIC_DOWNCAST(
				CMDIFrameWnd,
				pWnd
				);
		if( pFrame != NULL )
			break;
		pWnd = pWnd->GetParentFrame();
		if( pWnd == NULL )
			return FALSE;
	} // while( true )
	if( pFrame == NULL )
		return FALSE;
int nItemIndex = ItemGetCount();
	if( nItemIndex > 0 )
	{
		MENUITEMDATA & mi = _GetItemRef(nItemIndex-1);
		if( !mi.IsSeparator() )
		{
			ItemInsert(ID_SEPARATOR);
			nItemIndex++;
			ASSERT( nItemIndex == ItemGetCount() );
		}
	}

HWND m_hWndMDIClient = pFrame->m_hWndMDIClient;
	ASSERT( m_hWndMDIClient != NULL );
	ASSERT( ::IsWindow(m_hWndMDIClient) );
HWND hWndActiveChildFrame =
		(HWND)::SendMessage(
			m_hWndMDIClient,
			WM_MDIGETACTIVE,
			0,
			NULL
			);
int nCmdID = __ID_MDIWNDLIST_FIRST;
	for( int iWin=1; true; iWin++,nCmdID++ )
	{
		HWND hWndChildFrame =
			::GetDlgItem(m_hWndMDIClient, nCmdID);
		if( hWndChildFrame == NULL )
			break;

		if( iWin <= __ID_MDIWNDLIST_COUNT )
		{ // if head of MDI windows list
			ASSERT( ::IsWindow(hWndChildFrame) );
			CString sWinName( _T("") );
			CWnd::FromHandle( hWndChildFrame )-> GetWindowText( sWinName );
			CExtCmdItem * pCmdItem =
				g_CmdManager->CmdGetPtr(
					g_CmdManager->ProfileNameFromWnd( pWndStartSearchMdiFrameWnd->GetSafeHwnd() ),
					nCmdID
					);
			if( pCmdItem == NULL )
				pCmdItem =
				g_CmdManager->CmdAllocPtr(
					g_CmdManager->ProfileNameFromWnd( pWndStartSearchMdiFrameWnd->GetSafeHwnd() ),
					nCmdID
					);
			ASSERT( pCmdItem != NULL );
			if( pCmdItem == NULL )
				return FALSE;
			pCmdItem->m_sMenuText.Format(
				_T("&%d %s"),
				iWin,
				sWinName
				);
			pCmdItem->m_sToolbarText = pCmdItem->m_sMenuText;
			
#if (defined _AFXDLL && !defined __STATPROFUIS_WITH_DLLMFC__)
			CExtLocalResourceHelper _LRH;
#endif // #if (defined _AFXDLL && !defined __STATPROFUIS_WITH_DLLMFC__)
			
			CExtSafeString sDocumentNameFmt;
			if( !sDocumentNameFmt.LoadString(IDS_DOCUMENT_NAME_FMT) )
			{
#if (defined _AFXDLL && !defined __STATPROFUIS_WITH_DLLMFC__)
				ASSERT( FALSE );
#endif // #if (defined _AFXDLL && !defined __STATPROFUIS_WITH_DLLMFC__)
				sDocumentNameFmt = _T("Document \"%s\"");
			}
			pCmdItem->m_sTipTool.Format(
				(LPCTSTR)sDocumentNameFmt,
				sWinName
				);
			pCmdItem->m_sTipStatus = pCmdItem->m_sTipTool;
			bool bRadio =
				(hWndChildFrame == hWndActiveChildFrame)
					? true : false;
			pCmdItem->StateSetRadio( bRadio );
			if( !ItemInsert(nCmdID) )
			{
				ASSERT( FALSE );
				return FALSE;
			}
			MENUITEMDATA & mi = ItemGetInfo( ItemGetCount()-1 );
			mi.Radio( bRadio );
		} // if head of MDI windows list
		else
		{ // MDI windows list enough long, trim it
			if( !ItemInsert(TYPE_SEPARATOR) )
			{
				ASSERT( FALSE );
				return FALSE;
			}
			HWND hWndSearch = pWndStartSearchMdiFrameWnd->GetSafeHwnd();
			ASSERT( hWndSearch != NULL );
			ASSERT( ::IsWindow(hWndSearch) );
			CExtCmdItem * pCmdItem =
				g_CmdManager->CmdGetPtr(
					g_CmdManager->ProfileNameFromWnd( hWndSearch ),
					__ID_MDIWND_DLGWINDOWS
					);
			if( pCmdItem == NULL )
				pCmdItem =
				g_CmdManager->CmdAllocPtr(
					g_CmdManager->ProfileNameFromWnd( hWndSearch ),
					__ID_MDIWND_DLGWINDOWS
					);
			ASSERT( pCmdItem != NULL );
			if( pCmdItem == NULL )
				return FALSE;
			
#if (defined _AFXDLL && !defined __STATPROFUIS_WITH_DLLMFC__)
			CExtLocalResourceHelper _LRH;
#endif // #if (defined _AFXDLL && !defined __STATPROFUIS_WITH_DLLMFC__)
			
			CExtSafeString sMoreWindows,sManageWindows;
			if( !sMoreWindows.LoadString(IDS_MDI_MORE_WINDOWS) )
			{
#if (defined _AFXDLL && !defined __STATPROFUIS_WITH_DLLMFC__)
				ASSERT( FALSE );
#endif // #if (defined _AFXDLL && !defined __STATPROFUIS_WITH_DLLMFC__)
				sMoreWindows = _T("More Windows");
			}
			if( !sManageWindows.LoadString(IDS_MDI_MANAGE_OPENED_WINDOWS) )
			{
#if (defined _AFXDLL && !defined __STATPROFUIS_WITH_DLLMFC__)
				ASSERT( FALSE );
#endif // #if (defined _AFXDLL && !defined __STATPROFUIS_WITH_DLLMFC__)
				sManageWindows = _T("Manage opened document windows");
			}
			pCmdItem->m_sMenuText = sMoreWindows;
			pCmdItem->m_sToolbarText = pCmdItem->m_sMenuText;
			pCmdItem->m_sTipTool = sManageWindows;
			pCmdItem->m_sTipStatus = pCmdItem->m_sTipTool;
			if( !ItemInsert(nCmdID) )
			{
				ASSERT( FALSE );
				return FALSE;
			}
			break;
		} // MDI windows list enough long, trim it
	} // for( int iWin=1; true; iWin++,nCmdID++ )
	
	_SyncItems();
	return TRUE;
}

HMENU CExtPopupMenuWnd::ExportToMenu(
	BOOL bDeep // = TRUE
	) const
{
	ASSERT_VALID( this );

CMenu menu;
	if( !menu.CreatePopupMenu() )
	{
		ASSERT( FALSE );
		return NULL;
	}

OSVERSIONINFO ov;
    ov.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
	VERIFY( ::GetVersionEx( &ov ) );
bool bStupidNT4XX =
		(
		( ov.dwPlatformId == VER_PLATFORM_WIN32_NT )
		&&
		( ov.dwMajorVersion < 5 )
		);

int nCount = ItemGetCount();
	for( int nItem = 0; nItem < nCount; nItem++ )
	{
		const MENUITEMDATA & mi =
			_GetItemRef( nItem );

		if( mi.IsPopup() )
		{
			CExtSafeString sMiText( mi.GetText() );
			CExtSafeString sMiAccelText( mi.GetAccelText() );
			if( !sMiAccelText.IsEmpty() )
			{
				sMiText += _T("\t");
				sMiText += sMiAccelText;
			}
			const CExtPopupMenuWnd * pPopup = mi.GetPopup();
			ASSERT( pPopup != NULL );
			HMENU hPopupData;
			if( bDeep )
				hPopupData = pPopup->ExportToMenu();
			else
				hPopupData = ::CreatePopupMenu();
			if( ( ! (::IsMenu(hPopupData)) )
				||
				(!	menu.AppendMenu(
						MF_STRING|MF_POPUP,
						UINT(hPopupData),
						sMiText
						)
					)
				)
			{
				ASSERT( FALSE );
				//continue;
			}
			if( bStupidNT4XX )
			{
				VERIFY( ::DestroyMenu( hPopupData ) );
			}
			continue;
		} // if( mi.IsPopup() )

		if( mi.IsSeparator() )
		{
			VERIFY( menu.AppendMenu( MF_SEPARATOR ) );
			continue;
		} // if( mi.IsSeparator() )

		CExtSafeString sMiText( mi.GetText() );
		CExtSafeString sMiAccelText( mi.GetAccelText() );
		if( !sMiAccelText.IsEmpty() )
		{
			sMiText += _T("\t");
			sMiText += sMiAccelText;
		}
		VERIFY(
			menu.AppendMenu(
				MF_STRING,
				mi.GetCmdID(),
				sMiText
				)
			);

	} // for( int nItem = 0; nItem < nCount; nItem++ )

	return menu.Detach();
}

BOOL CExtPopupMenuWnd::UpdateFromMenu( 
	HWND hWndCmdRecv,
	CMenu * pBuildMenu,
	bool bPopupMenu, // = true
	bool bTopLevel // = true
	)
{
	ASSERT_VALID( this );

	if( hWndCmdRecv != NULL )
		m_hWndCmdReciever = hWndCmdRecv;
	ASSERT( m_hWndCmdReciever != NULL );
	ASSERT( ::IsWindow(m_hWndCmdReciever) );

	if( pBuildMenu == NULL
		|| (!(::IsMenu(pBuildMenu->GetSafeHmenu())))
		)
	{
		ASSERT( FALSE );
		return false;
	}
	if( bPopupMenu )
	{
		pBuildMenu = pBuildMenu->GetSubMenu(0);
		if( pBuildMenu == NULL
			|| (!(::IsMenu(pBuildMenu->GetSafeHmenu())))
			)
		{
			ASSERT( FALSE );
			return false;
		}
	}

	if(	!g_CmdManager->UpdateFromMenu(
			g_CmdManager->ProfileNameFromWnd( m_hWndCmdReciever ),
			pBuildMenu->GetSafeHmenu()
			)
		)
	{
		ASSERT( FALSE );
		return false;
	}

	if( !_BuildItems( pBuildMenu, bTopLevel ) )
		return FALSE;
	return TRUE;
}

#if (!defined __EXT_MFC_NO_CUSTOMIZE)
bool CExtPopupMenuWnd::UpdateFromCmdTree(
	HWND hWndCmdRecv,
	CExtCustomizeCmdTreeNode * pNode,
	bool bTopLevel // = true
	)
{
	ASSERT_VALID( this );
	ASSERT_VALID( pNode );
	m_pNode = pNode;

	if( hWndCmdRecv != NULL )
		m_hWndCmdReciever = hWndCmdRecv;
	ASSERT( m_hWndCmdReciever != NULL );
	ASSERT( ::IsWindow(m_hWndCmdReciever) );

__EXT_MFC_SAFE_LPCTSTR strProfileName =
		g_CmdManager->ProfileNameFromWnd( m_hWndCmdReciever );
bool bCustomizeMode = false;
CExtCustomizeSite * pSite =
		CExtCustomizeSite::GetCustomizeSite( m_hWndCmdReciever );
	if( pSite != NULL )
		bCustomizeMode = pSite->IsCustomizeMode();

INT iter = 0;
	for( ; iter < m_items_all.GetSize(); iter++)
	{
		MENUITEMDATA & mi = m_items_all[ iter ];
		if( mi.IsPopup() )
		{
			mi.GetPopup()->m_hWndCmdReciever = m_hWndCmdReciever;
			mi.GetPopup()->_OnCancelMode();
			VERIFY( mi.GetPopup()->_BuildItems( NULL, false ) );
			mi.DestroyPopup();
		}
	} // for( ; iter < m_items_all.GetSize(); iter++)
	m_items_all.RemoveAll();

	if( pNode == NULL )
		return true;
	ASSERT_VALID( pNode );

	m_bTopLevel = bTopLevel;
	if( m_bTopLevel )
		m_pWndParentMenu = NULL;

	// build items loop
int nMruUpdateIndex = -1, nInsertedIndex = 0;
int	nMenuItemCount = pNode->GetNodeCount();
	m_items_all.RemoveAll();
	for( int nItemIndex = 0; nItemIndex < nMenuItemCount; nItemIndex++ )
	{
		CExtCustomizeCmdTreeNode * pChildNode =
			pNode->ElementAt( nItemIndex );
		ASSERT_VALID( pChildNode );
		if( pChildNode->GetFlags() & __ECTN_GROUP_START )
		{
			VERIFY(
				ItemInsert(
					CExtPopupMenuWnd::TYPE_SEPARATOR,
					nInsertedIndex++
					)
				);
		} // if( pChildNode->GetFlags() & __ECTN_GROUP_START )
		UINT nMenuItemID = pChildNode->GetCmdID( false );
		if(		ID_FILE_MRU_FIRST <= nMenuItemID
			&&	nMenuItemID <= ID_FILE_MRU_LAST
			&&	(! bCustomizeMode )
			)
		{
			if( nMruUpdateIndex < 0 )
				nMruUpdateIndex = nInsertedIndex;
			continue;
		}
		MENUITEMDATA mi;
		mi.SetCmdReciever( m_hWndCmdReciever );
		VERIFY(
			mi.UpdateFromCmdTree(
				m_hWndCmdReciever,
				pChildNode,
				nInsertedIndex
				)
			);
		ASSERT( !mi.IsSeparator() );
		CExtCmdItem * pCmdItem = NULL;
		if( mi.IsPopup() )
		{
			mi.GetPopup()->m_hWndCmdReciever = m_hWndCmdReciever;
			mi.GetPopup()->UpdateFromCmdTree(
				hWndCmdRecv,
				pChildNode,
				false
				);
			mi.GetPopup()->m_pWndParentMenu = this;
		} // if( mi.IsPopup() )
		else
		{
			pCmdItem =
				g_CmdManager->CmdGetPtr(
					strProfileName,
					mi.GetCmdID()
					);
			mi.SetAccelText( pCmdItem->m_sAccelText );
		} // else from if( mi.IsPopup() )

		mi.SetText( pChildNode->GetTextInMenu( pCmdItem ) );
		mi.AccelCharInit();
		mi.MeasureItem();

		_InsertItem( -1, mi );
		nInsertedIndex++;
	} // for( int nItemIndex = 0; nItemIndex < nMenuItemCount; nItemIndex++ )

int nMruInsertCount = 0;
	if( nMruUpdateIndex >= 0 )
	{ // insert recently opened file items
		//ASSERT( nMruUpdateIndex <= nMenuItemCount );
		CRecentFileList * pRecentFileList =
			InternalFriendlyWinApp::_GetFriendlyApp()->
				_GetRecentFileList();
		if( pRecentFileList != NULL )
		{ // can be null !?
			int nRecentCount =
				pRecentFileList->GetSize();
			TCHAR sCurrDir[_MAX_PATH+1];
			::memset(sCurrDir,0,sizeof(sCurrDir));
			::GetCurrentDirectory(_MAX_PATH,sCurrDir);
			int nLenCurDir = _tcslen(sCurrDir);
			for( nItemIndex=0; nItemIndex<nRecentCount; nItemIndex++ )
			{
				CExtSafeString sDisplayName( _T("") );
				if(	!pRecentFileList->GetDisplayName(
						*((CString *)&sDisplayName),
						nItemIndex,
						sCurrDir,
						nLenCurDir,
						TRUE
						)
					)
					continue;
				ASSERT( !sDisplayName.IsEmpty() );
				UINT nCmdID = ID_FILE_MRU_FIRST + nItemIndex;
				ASSERT( nCmdID <= ID_FILE_MRU_LAST );
				CExtCmdItem * pCmdItem =
					g_CmdManager->CmdGetPtr(
						g_CmdManager->ProfileNameFromWnd( m_hWndCmdReciever ),
						nCmdID
						);
				if( pCmdItem == NULL )
					pCmdItem =
						g_CmdManager->CmdAllocPtr(
							g_CmdManager->ProfileNameFromWnd( m_hWndCmdReciever ),
							nCmdID
							);
				ASSERT( pCmdItem != NULL );
				if( pCmdItem == NULL )
					return false;
				int nDisplayIndex = nItemIndex+1;
				if( nDisplayIndex < 10 )
					pCmdItem->m_sMenuText.Format(
						_T("&%d %s"),
						nDisplayIndex,
						sDisplayName
						);
				else
					pCmdItem->m_sMenuText.Format(
						_T("%d&%d %s"),
						nDisplayIndex/10,
						nDisplayIndex%10,
						sDisplayName
						);
				
#if (defined _AFXDLL && !defined __STATPROFUIS_WITH_DLLMFC__)
				CExtLocalResourceHelper _LRH;
#endif // #if (defined _AFXDLL && !defined __STATPROFUIS_WITH_DLLMFC__)
				
				CExtSafeString sRecentFileFmt1,sRecentFileFmt2;
				if( !sRecentFileFmt1.LoadString(IDS_RECENT_FILE_FMT_1) )
				{
#if (defined _AFXDLL && !defined __STATPROFUIS_WITH_DLLMFC__)
					ASSERT( FALSE );
#endif // #if (defined _AFXDLL && !defined __STATPROFUIS_WITH_DLLMFC__)
					sRecentFileFmt1 = _T("Recent file %d");
				}
				if( !sRecentFileFmt2.LoadString(IDS_RECENT_FILE_FMT_2) )
				{
#if (defined _AFXDLL && !defined __STATPROFUIS_WITH_DLLMFC__)
					ASSERT( FALSE );
#endif // #if (defined _AFXDLL && !defined __STATPROFUIS_WITH_DLLMFC__)
					sRecentFileFmt2 = _T("Recent file %d (\"%s\")");
				}
				pCmdItem->m_sToolbarText.Format(
					(LPCTSTR)sRecentFileFmt1,
					nItemIndex + 1
					);
				pCmdItem->m_sTipTool.Format(
					(LPCTSTR)sRecentFileFmt2,
					nItemIndex + 1,
					sDisplayName
					);
				pCmdItem->m_sTipStatus = pCmdItem->m_sTipTool;

				BOOL bInsRetVal =
					ItemInsert(
						nCmdID,
						nMruUpdateIndex + nItemIndex
						);
				
				if( !bInsRetVal )
				{
					ASSERT( FALSE );
					return false;
				}
				nMruInsertCount++;
			} // for( nItemIndex=0; nItemIndex<nRecentCount; nItemIndex++ )
		} // can be null !?
/*
		if( nMruInsertCount > 0 )
		{
			if(		nMruUpdateIndex > 0
				&&	(! _GetItemRef( nMruUpdateIndex - 1 ).IsSeparator() )
				)
			{
				if( !ItemInsert(
						ID_SEPARATOR,
						nMruUpdateIndex
						)
					)
				{
					ASSERT( FALSE );
					return false;
				}
				nMruInsertCount++;
				nMruUpdateIndex++;
			}
			if(		( nMruUpdateIndex + nMruInsertCount ) < m_items_all.GetSize()
				&&	(! _GetItemRef( nMruUpdateIndex + nMruInsertCount ).IsSeparator() )
				)
			{
				if( !ItemInsert(
						ID_SEPARATOR,
						nMruUpdateIndex + nMruInsertCount
						)
					)
				{
					ASSERT( FALSE );
					return false;
				}
				nMruInsertCount++;
			}
		} // if( nMruInsertCount > 0 )
*/
		if(		nMruInsertCount == 0
			&&	nMruUpdateIndex > 0
			&&	nMruUpdateIndex < (ItemGetCount()-1)
			&&	_GetItemRef( nMruUpdateIndex ).IsSeparator()
			&&	_GetItemRef( nMruUpdateIndex-1 ).IsSeparator()
			)
			m_items_all.RemoveAt( nMruUpdateIndex );
	} // insert recently opened file items

	_SyncItems();
	return true;
}
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)


CExtPopupMenuSite & CExtPopupMenuWnd::GetSite() const
{
	return CExtPopupMenuSite::g_DefPopupMenuSite;
}

CExtPopupMenuWnd * CExtPopupMenuWnd::GetTrackingMenu()
{
CExtPopupMenuWnd * pPopup =
		CExtPopupMenuSite::g_DefPopupMenuSite.GetInstance();
	if( !(::IsWindow(pPopup->GetSafeHwnd())) )
		return NULL;
	ASSERT_VALID( pPopup );
	return pPopup;
}

void CExtPopupMenuWnd::CancelMenuTracking()
{
	if( !CExtPopupMenuSite::g_DefPopupMenuSite.IsEmpty()
		&& !CExtPopupMenuSite::g_DefPopupMenuSite.IsShutdownMode()
		)
	{
		CExtPopupMenuSite::g_DefPopupMenuSite.DoneInstance();
		ASSERT( CExtPopupMenuSite::g_DefPopupMenuSite.IsEmpty() );
		ASSERT( !CExtPopupMenuSite::g_DefPopupMenuSite.IsShutdownMode() );
	}
}

BOOL CExtPopupMenuWnd::IsMenuTracking()
{
	if( CExtPopupMenuSite::g_DefPopupMenuSite.IsEmpty()
		//|| CExtPopupMenuSite::g_DefPopupMenuSite.GetCapture() == NULL
		)
		return FALSE;
	return TRUE;
}

BOOL CExtPopupMenuWnd::TrackPopupMenu(
	DWORD dwTrackFlags,
	int x,
	int y,
	LPCRECT lpRect, // = NULL
	LPVOID pCbPaintCombinedCookie, // = NULL
	pCbPaintCombinedContent pCbPaintCombinedContent, // = NULL
	UINT * lpnResultCmdID, // = NULL
	bool bCookieIsObject // = false
	)
{
	ASSERT_VALID( this );

	if( lpnResultCmdID != NULL )
		*lpnResultCmdID = 0;

	ASSERT( m_hWndCmdReciever != NULL );
	ASSERT( ::IsWindow(m_hWndCmdReciever) );
CWnd * pWndCmdReciever =
		CWnd::FromHandlePermanent( m_hWndCmdReciever );
	if(		pWndCmdReciever != NULL
		&&	CExtControlBar::FindHelpMode( pWndCmdReciever )
		)
		dwTrackFlags |= TPMX_HELP_CTX_MODE;

#if (!defined __EXT_MFC_NO_CUSTOMIZE)
	m_pCustomizeSite =
		CExtCustomizeSite::GetCustomizeSite( m_hWndCmdReciever );
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)
	
	ASSERT(
		(dwTrackFlags&(TPMX_CUSTOMIZE_MODE|TPMX_HELP_CTX_MODE))
		!= (TPMX_CUSTOMIZE_MODE|TPMX_HELP_CTX_MODE)
		);

	if( (dwTrackFlags&TPMX_CUSTOMIZE_MODE) != 0 )
	{
		dwTrackFlags &= ~
			(	TPMX_COMBINE_MASK
				|TPMX_SELECT_ANY
				|TPMX_DO_MESSAGE_LOOP
				|TPMX_OWNERDRAW_FIXED
			);
		dwTrackFlags |=
			TPMX_NO_SHADOWS
			|TPMX_NO_HIDE_RARELY
			|TPMX_NO_WM_COMMAND
			|TPMX_NO_CMD_UI;
	} // if( (dwTrackFlags&TPMX_CUSTOMIZE_MODE) != 0 )

HWND hWndCurrentFocus = ::GetFocus();
	if( hWndCurrentFocus != NULL )
	{
		CWnd * pWndTest = CWnd::FromHandlePermanent( hWndCurrentFocus );
		if( pWndTest == NULL )
		{
			HWND hWnd = ::GetParent( hWndCurrentFocus );
			if( hWnd != NULL )
				pWndTest = CWnd::FromHandlePermanent( hWnd );
		} // if( pWndTest == NULL )
		if( pWndTest != NULL )
		{
			CComboBox * pComboTest =
				DYNAMIC_DOWNCAST( CComboBox, pWndTest );
			if( pComboTest == NULL )
			{
				pWndTest = pWndTest->GetParent();
				if( pWndTest != NULL )
				{
					pComboTest =
						DYNAMIC_DOWNCAST( CComboBox, pWndTest );
				}
			} // if( pComboTest == NULL )
			if(		pComboTest != NULL
				&&	(pComboTest->GetStyle() & (CBS_DROPDOWN|CBS_DROPDOWNLIST)) != 0
				&&	pComboTest->GetDroppedState()
				)
				pComboTest->ShowDropDown( FALSE );
		} // if( pWndTest != NULL )
	} // if( hWndCurrentFocus != NULL )

CExtPopupMenuSite & _site = GetSite();
bool bSiteWasEmpty = _site.IsEmpty();
	if( !bSiteWasEmpty )
	{
		if( _site.IsShutdownMode() )
			return FALSE;
		_site.DoneInstance();
	}

//bool bCaptureChanged = false;
HWND hWndCapture = ::GetCapture();
CWnd * pWndCapture = FromHandlePermanent( hWndCapture );
	if( pWndCapture != NULL )
	{
		ReleaseCapture();
		if( ::IsWindow(hWndCapture) )
		{
			ASSERT_VALID( pWndCapture );
			pWndCapture->SendMessage(WM_CANCELMODE);
		}
//		bCaptureChanged = true;
	}

	ASSERT( _site.IsEmpty() );
	ASSERT( !_site.IsShutdownMode() );

	ASSERT( m_hWndCmdReciever != NULL );
	ASSERT( ::IsWindow(m_hWndCmdReciever) );

//	if( !bSiteWasEmpty
//		|| CExtToolControlBar::g_bMenuTracking
//		|| bCaptureChanged
//		)
//	{
//		PassMsgLoop( CExtPopupBaseWnd::g_bEnableOnIdleCalls );
//		if( ! ::IsWindow(m_hWndCmdReciever) )
//			return FALSE;
//	}
//	if( !_site.IsEmpty() )
//		return FALSE;

	ASSERT( m_bTopLevel );
	ASSERT( _site.IsEmpty() );

	if( (dwTrackFlags&TPMX_CUSTOMIZE_MODE) == 0 )
	{
		_site.SetInstance( this );
		if( lpnResultCmdID != NULL )
			_site.SetTargetCmdIdPtr( lpnResultCmdID );
	}

	m_dwTrackFlags = dwTrackFlags;

	if( (dwTrackFlags&TPMX_CUSTOMIZE_MODE) == 0 )
		_UpdateCmdUI();

	if(	! _TrackPopupMenu(
			dwTrackFlags,
			x,
			y,
			lpRect,
			pCbPaintCombinedCookie,
			pCbPaintCombinedContent,
			bCookieIsObject
			)
		)
	{
		//ASSERT( FALSE );
		if( (dwTrackFlags&TPMX_CUSTOMIZE_MODE) == 0 )
		{
			_site.DoneInstance();
			ASSERT( _site.IsEmpty() );
			ASSERT( !_site.IsShutdownMode() );
		} // if( (dwTrackFlags&TPMX_CUSTOMIZE_MODE) == 0 )
		return FALSE;
	}
	if( (dwTrackFlags&TPMX_DO_MESSAGE_LOOP) == 0 )
		return TRUE;
	// do popup menu message loop
	while( IsMenuTracking() )
	{
		WaitMessage();
		HWND hWndThis = GetSafeHwnd();
		CExtPopupMenuWnd::PassMsgLoop( CExtPopupBaseWnd::g_bEnableOnIdleCalls );
		if( !::IsWindow(hWndThis) )
			break;
	} // while( IsMenuTracking() )
	
	if( !CExtToolControlBar::g_bMenuTracking )
	{
		_site.DoneInstance();
		ASSERT( _site.IsEmpty() );
		ASSERT( !_site.IsShutdownMode() );
	}

	return TRUE;
}

void CExtPopupMenuWnd::PassMsgLoop(
	bool bEnableOnIdleCalls
	)
{
#ifdef _USRDLL
	// If this is a DLL, need to set up MFC state
	AFX_MANAGE_STATE(AfxGetStaticModuleState());
#endif
MSG msg;
	// Process all the messages in the message queue
	while( PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE) )
	{
		if( !AfxGetThread()->PumpMessage() )
		{
			PostQuitMessage(0);
			return;
		} // if( !AfxGetThread()->PumpMessage() )
	} // while( PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE) )
	if( bEnableOnIdleCalls )
	{
		for(	LONG nIdleCounter = 0L;
				::AfxGetThread()->OnIdle(nIdleCounter);
				nIdleCounter ++
				);
	}
}

CSize CExtPopupMenuWnd::_CalcTrackSize()
{
	ASSERT_VALID( this );

int nMenuShadowSize = _GetPopupShadowSize();
int nMenuBorderSize = g_PaintManager->GetMenuBorderSize();
int nXtraSz = nMenuBorderSize*2 + nMenuShadowSize;
CSize _size( m_sizeFullItems );
	if( m_bExpandAvailable )
		_size.cy += _GetSpecBtnHeight(); // xpand btn
	_size += CSize( nXtraSz + m_nLeftAreaWidth, nXtraSz );
	if( _size.cx < (nMenuShadowSize*2 + 10) )
		_size.cx = nMenuShadowSize*2 + 10;
	if( _size.cy < (nMenuShadowSize*2 + 10) )
		_size.cy = nMenuShadowSize*2 + 10;
	return _size;
}

CRect CExtPopupMenuWnd::_CalcTrackRect()
{
	ASSERT_VALID( this );

	m_eCombineAlign = __CMBA_NONE;

	if( IsKeyPressed(VK_CONTROL) )
	{
		int i=1;
		i;
	}

CExtPaintManager::monitor_parms_t _mp;
	if( m_bExcludeAreaSpec )
		CExtPaintManager::stat_GetMonitorParms( _mp, m_rcExcludeArea );
	else if( m_pWndParentMenu != NULL )
	{
		ASSERT_VALID( m_pWndParentMenu );
		ASSERT( m_pWndParentMenu->GetSafeHwnd() != NULL );
		ASSERT( ::IsWindow( m_pWndParentMenu->GetSafeHwnd() ) );
		CExtPaintManager::stat_GetMonitorParms( _mp, m_pWndParentMenu );
	} // else if( m_pWndParentMenu != NULL )
	else
		CExtPaintManager::stat_GetMonitorParms( _mp, m_ptTrack );
CRect rcDesktop = g_bUseDesktopWorkArea
		? _mp.m_rcWorkArea
		: _mp.m_rcMonitor
		;

CSize _size = _CalcTrackSize();
int nMenuShadowSize =
		_GetPopupShadowSize();
int nMenuBorderSize =
		g_PaintManager->GetMenuBorderSize();
int nGapShift = 0;
	if( !m_bCombineWithEA )
		nGapShift = nMenuBorderSize + nMenuShadowSize;

	if( (m_dwTrackFlags&TPMX_ALIGN_MASK) == 0 && (!m_bCombineWithEA) )
	{
		if( m_pWndParentMenu->GetSafeHwnd() != NULL )
		{
			if( (m_pWndParentMenu->m_dwTrackFlags&TPMX_ALIGN_MASK) != 0 )
				m_dwTrackFlags |= m_pWndParentMenu->m_dwTrackFlags& (~TPMX_ALIGN_MASK);
			else
			{
				CRect rc1;
				m_pWndParentMenu->GetWindowRect(&rc1);
				if( m_pWndParentMenu->m_pWndParentMenu->GetSafeHwnd() != NULL )
				{
					CRect rc2;
					m_pWndParentMenu->m_pWndParentMenu->GetWindowRect(&rc2);
					int x1 = rc1.left + rc1.Width()/2;
					int x2 = rc2.left + rc2.Width()/2;
					if( x1 >= x2 )
						m_dwTrackFlags |= TPMX_LEFTALIGN;
					else
						m_dwTrackFlags |= TPMX_RIGHTALIGN;
				}
			}
		}
	}

CRect wr(m_ptTrack,_size);
//	wr.NormalizeRect();
int nCombineOffset = 0;
	if(	m_bCombineWithEA )
	{
		if( (m_dwTrackFlags&TPMX_ALIGN_MASK)
				== TPMX_TOPALIGN )
		{
			nCombineOffset = 1;
			wr.OffsetRect(0,-nCombineOffset);
		}
		if( (m_dwTrackFlags&TPMX_ALIGN_MASK)
				== TPMX_LEFTALIGN )
		{
			nCombineOffset = 1;
			wr.OffsetRect(-nCombineOffset,0);
		}
		if( (m_dwTrackFlags&TPMX_ALIGN_MASK)
				== TPMX_BOTTOMALIGN )
		{
			nCombineOffset =
				-nMenuShadowSize - 1;
			wr.OffsetRect(0,-nCombineOffset);
		}
		if( (m_dwTrackFlags&TPMX_ALIGN_MASK)
				== TPMX_RIGHTALIGN )
		{
			nCombineOffset =
				-nMenuShadowSize - 1;
			wr.OffsetRect(-nCombineOffset,0);
		}
	} // if(	m_bCombineWithEA )

	if(wr.bottom > rcDesktop.bottom)
	{
		if( m_bExcludeAreaSpec )
		{
			wr.OffsetRect(
				0,
				-wr.Height()
					+ m_rcExcludeArea.Height()
					+ nGapShift
					+ (m_bCombineWithEA ?
						nMenuShadowSize : 0)
				);
		} // if( m_bExcludeAreaSpec )
		if(wr.bottom > rcDesktop.bottom)
			wr.OffsetRect(
				0,
				m_bExcludeAreaSpec
					? -(wr.bottom - rcDesktop.bottom)
					: - wr.Height()
				);
	} // if(wr.bottom > rcDesktop.bottom)
	if(wr.top < rcDesktop.top)
		wr.OffsetRect( 0, rcDesktop.top - wr.top );

	if(wr.right > rcDesktop.right)
	{
		if( !m_bTopLevel && m_bExcludeAreaSpec )
			wr.OffsetRect(
				-wr.Width() - m_rcExcludeArea.Width(),
				0
				);
		if(wr.right > rcDesktop.right)
			wr.OffsetRect(
				m_bExcludeAreaSpec
					? -(wr.right - rcDesktop.right)
					: -wr.Width(),
				0
				);
	} // if(wr.right > rcDesktop.right)
	if(wr.left < rcDesktop.left)
	{
		if( !m_bTopLevel && m_bExcludeAreaSpec )
			wr.OffsetRect(
				wr.Width() + m_rcExcludeArea.Width(),
				0
				);
		if(wr.left < rcDesktop.left)
			wr.OffsetRect( rcDesktop.left - wr.left, 0 );
	} // if(wr.left < rcDesktop.left)

	if( m_bExcludeAreaSpec || m_bCombineWithEA )
	{
		CRect rcIntersection;
		if(	rcIntersection.IntersectRect(
				&wr,
				&m_rcExcludeArea
				)
			|| m_bCombineWithEA
			)
		{ // if need adjust with exclude area
			CRect rcFree(0,0,0,0);
			if( m_rcExcludeArea.left > rcDesktop.left )
				rcFree.left =
					m_rcExcludeArea.left - rcDesktop.left;
			if( m_rcExcludeArea.right < rcDesktop.right )
				rcFree.right =
					rcDesktop.right - m_rcExcludeArea.right;
			if( m_rcExcludeArea.top > rcDesktop.top )
				rcFree.top =
					m_rcExcludeArea.top - rcDesktop.top;
			if( m_rcExcludeArea.bottom < rcDesktop.bottom )
				rcFree.bottom =
					rcDesktop.bottom - m_rcExcludeArea.bottom;
			if( (m_dwTrackFlags&TPMX_ALIGN_MASK)
					== TPMX_LEFTALIGN
				&& rcFree.right > wr.Width()
				)
				wr.OffsetRect(
					wr.left - m_rcExcludeArea.right
						+ (m_bCombineWithEA ?
							nCombineOffset : 0)
						,
					0
					);
			if( (m_dwTrackFlags&TPMX_ALIGN_MASK)
					== TPMX_RIGHTALIGN
				&& rcFree.left > wr.Width()
				)
				wr.OffsetRect(
					m_rcExcludeArea.left - wr.right
						- (m_bCombineWithEA ?
							nCombineOffset : 0)
						,
					0
					);

//			if( (m_dwTrackFlags&TPMX_ALIGN_MASK)
//					== TPMX_TOPALIGN
//				&& rcFree.bottom > wr.Height()
//				)
//				wr.OffsetRect(
//					0,
//					wr.top - m_rcExcludeArea.bottom
//						+ (m_bCombineWithEA ?
//							nCombineOffset : 0)
//					);

			if( (m_dwTrackFlags&TPMX_ALIGN_MASK)
					== TPMX_TOPALIGN
				)
			{
				if( rcFree.bottom > wr.Height() )
					wr.OffsetRect(
						0,
						wr.top - m_rcExcludeArea.bottom
							+ (m_bCombineWithEA ?
								nCombineOffset : 0)
						);
				else
				{
					if( ::IsWindow(GetSafeHwnd()) )
					{
						CRect rcWndOld;
						GetWindowRect( &rcWndOld );
						ShowWindow( SW_HIDE );
						_FreeWinObjects();
						HWND hWndThis = GetSafeHwnd();
						bool bWasCreated =
							(hWndThis != NULL && ::IsWindow(hWndThis))
								? true : false;
						CExtPopupMenuWnd::PassMsgLoop( CExtPopupBaseWnd::g_bEnableOnIdleCalls );
						if( bWasCreated && !::IsWindow(hWndThis) )
							return CRect(0,0,0,0);
						if( !rcWndOld.IsRectEmpty() )
						{
							CWnd * pWndTLP = GetTopLevelParent();
							if( pWndTLP != NULL )
							{
								ASSERT_VALID( pWndTLP );
								if( pWndTLP->IsWindowVisible() )
								{
									CRect rcTLP;
									pWndTLP->GetWindowRect( &rcTLP );
									if( !rcTLP.IsRectEmpty() )
									{
										CRect rcIntersection;
										if(	rcIntersection.IntersectRect(
												&rcTLP,
												&rcWndOld
												)
											)
											pWndTLP->UpdateWindow();
									} // if( !rcTLP.IsRectEmpty() )
								} // if( pWndTLP->IsWindowVisible() )
							} // if( pWndTLP != NULL )
						} // if( !rcWndOld.IsRectEmpty() )
					}
					m_dwTrackFlags &= ~TPMX_ALIGN_MASK;
					m_dwTrackFlags |= TPMX_BOTTOMALIGN;
					return _CalcTrackRect();
				}

			}

			if( (m_dwTrackFlags&TPMX_ALIGN_MASK)
					== TPMX_BOTTOMALIGN
					&& rcFree.top > wr.Height()
				)
				wr.OffsetRect(
					0,
					m_rcExcludeArea.top - wr.bottom
						- (m_bCombineWithEA ?
							nCombineOffset : 0)
					);
		} // if need adjust with exclude area
	} // if( m_bExcludeAreaSpec || m_bCombineWithEA )

	if(wr.right > rcDesktop.right)
	{
		wr.OffsetRect( -(wr.right - rcDesktop.right), 0 );
		if( m_bTopLevel )
		{
			m_bExcludeAreaSpec = false;
			m_bCombineWithEA = false;
		}
	} // if(wr.right > rcDesktop.right)
	if(wr.left < rcDesktop.left)
	{
		wr.OffsetRect( rcDesktop.left - wr.left, 0 );
		if( m_bTopLevel )
		{
			m_bExcludeAreaSpec = false;
			m_bCombineWithEA = false;
		}
	} // if(wr.left < rcDesktop.left)
	if(wr.bottom > rcDesktop.bottom)
	{
		wr.OffsetRect( 0, -(wr.bottom - rcDesktop.bottom) );
		if( m_bTopLevel )
		{
			m_bExcludeAreaSpec = false;
			m_bCombineWithEA = false;
		}
	} // if(wr.bottom > rcDesktop.bottom)
	if(wr.top < rcDesktop.top)
	{
		wr.OffsetRect( 0, rcDesktop.top - wr.top );
		if( m_bTopLevel )
		{
			m_bExcludeAreaSpec = false;
			m_bCombineWithEA = false;
		}
	} // if(wr.top < rcDesktop.top)
	if(wr.bottom > rcDesktop.bottom)
	{
		wr.bottom = rcDesktop.bottom;
		m_bScrollingAvailable = true;
	}

	if( m_bCombineWithEA )
	{
		ASSERT( m_bExcludeAreaSpec );
		if( wr.bottom == m_rcExcludeArea.top - nCombineOffset )
			m_eCombineAlign = __CMBA_BOTTOM;
		if( wr.top == m_rcExcludeArea.bottom  - nCombineOffset )
			m_eCombineAlign = __CMBA_TOP;
		if( wr.left == m_rcExcludeArea.right - nCombineOffset )
			m_eCombineAlign = __CMBA_LEFT;
		if( wr.right == m_rcExcludeArea.left - nCombineOffset  )
			m_eCombineAlign = __CMBA_RIGHT;
		if( m_eCombineAlign == __CMBA_NONE )
		{
			m_bCombineWithEA = false;
			return _CalcTrackRect();
		} // if( m_eCombineAlign == __CMBA_NONE )
		// init window region
		if( m_rgnWnd.GetSafeHandle() != NULL )
		{
			VERIFY(
				m_rgnWnd.DeleteObject()
				);
		}
		CRect rcExcludeArea(m_rcExcludeArea);
		rcExcludeArea.InflateRect(
			0,
			0,
			nMenuShadowSize,
			nMenuShadowSize
			);
		CRect rcFullWnd(
			min(wr.left,rcExcludeArea.left),
			min(wr.top,rcExcludeArea.top),
			max(wr.right,rcExcludeArea.right),
			max(wr.bottom,rcExcludeArea.bottom)
			);

		if( !m_bTopLevel )
		{
			if( m_eCombineAlign == __CMBA_LEFT
				|| m_eCombineAlign == __CMBA_RIGHT
				)
				rcExcludeArea.DeflateRect( 0, 0, 0, nMenuShadowSize );
			else if( m_eCombineAlign == __CMBA_TOP
				|| m_eCombineAlign == __CMBA_BOTTOM
				)
				rcExcludeArea.DeflateRect( 0, 0, nMenuShadowSize, 0 );
		}
		
		CRgn rgnAreaWnd,rgnAreaExclude;
		if(	(!m_rgnWnd.CreateRectRgnIndirect(
				&rcFullWnd ))
			||
			(!rgnAreaExclude.CreateRectRgnIndirect(
				&rcExcludeArea ))
			||
			(!rgnAreaWnd.CreateRectRgnIndirect(
				&wr ))
			||
			m_rgnWnd.CombineRgn(
				&rgnAreaWnd,
				&rgnAreaExclude,
				RGN_OR
				) == ERROR
			||
			m_rgnWnd.OffsetRgn(
				-rcFullWnd.TopLeft()
				) == ERROR
			)
		{
			if( m_rgnWnd.GetSafeHandle() != NULL )
			{
				VERIFY(
					m_rgnWnd.DeleteObject()
					);
			}
			m_bCombineWithEA = false;
			return _CalcTrackRect();
		}
		ASSERT( m_rgnWnd.GetSafeHandle() != NULL );
		
//		VERIFY( m_rgnWnd.DeleteObject() );
//		VERIFY(
//			m_rgnWnd.CreateRectRgnIndirect(
//				&rcFullWnd
//				)
//			);

		m_rcClient = wr;
		m_rcClient.OffsetRect( -rcFullWnd.TopLeft() );
		m_rcClient.DeflateRect(
			0,
			0,
			nMenuShadowSize,
			nMenuShadowSize
			);
		ASSERT( m_rcClient.top <= m_rcClient.bottom );
		ASSERT( m_rcClient.left <= m_rcClient.right );

		if( !m_bTopLevel )
		{
			if( m_eCombineAlign == __CMBA_RIGHT )
				rcFullWnd.OffsetRect( nMenuShadowSize + 1, 0 );
			else if( m_eCombineAlign == __CMBA_LEFT )
				rcFullWnd.OffsetRect( -2, 0 );
		}

		return rcFullWnd;
	} // if( m_bCombineWithEA )

	m_rcClient = wr;
	m_rcClient.OffsetRect( -wr.TopLeft() );
	m_rcClient.DeflateRect(
		0,
		0,
		nMenuShadowSize,
		nMenuShadowSize
		);
	ASSERT( m_rcClient.top <= m_rcClient.bottom );
	ASSERT( m_rcClient.left <= m_rcClient.right );

	return wr;
}

BOOL CExtPopupMenuWnd::_TrackPopupMenu(
	DWORD dwTrackFlags,
	int x,
	int y,
	LPCRECT lpRect,
	LPVOID pCbPaintCombinedCookie, // = NULL
	pCbPaintCombinedContent pCbPaintCombinedContent, // = NULL
	bool bCookieIsObject // = false
	)
{
	ASSERT_VALID( this );

bool bForceExpandRarelyUsed = (dwTrackFlags&TPMX_NO_HIDE_RARELY)
		? true : false;
	if( !g_bMenuExpanding )
		bForceExpandRarelyUsed = true;

	ASSERT( m_hWndCmdReciever != NULL );
	ASSERT( ::IsWindow(m_hWndCmdReciever) );

	ASSERT( GetSafeHwnd() == NULL );

CExtPopupMenuSite & _site = GetSite();

	if(		(!_FindCustomizeMode())
		&&	_site.IsTopPupup(this)
		)
	{
		ASSERT( m_bTopLevel );
		MsgPrepareMenuData_t _mpmd( this );
		_mpmd.SendMessage( m_hWndCmdReciever );
		if( _mpmd.m_bMenuCanceled )
			return FALSE;
		if( _mpmd.m_bMenuChanged )
		{
			_UpdateCmdUI();
		}
		ASSERT( m_bTopLevel );
		ASSERT( _site.IsTopPupup(this) );
	}

	if( !_FindCustomizeMode() )
	{ // BLOCK: update system commands
		INT iter = 0;
		for(; iter < m_items_all.GetSize(); ++iter )
		{
			MENUITEMDATA & mi = m_items_all[ iter ];
			if( mi.IsSeparator() )
				continue;
			UINT nCmdID = mi.GetCmdID();
			if( !CExtCmdManager::IsSystemCommand(nCmdID))
				continue;
			WINDOWPLACEMENT wndpl;
			::memset(&wndpl,0,sizeof(WINDOWPLACEMENT));
			wndpl.length = sizeof(WINDOWPLACEMENT);
			VERIFY(
				::GetWindowPlacement(
					mi.GetCmdReciever(),
					&wndpl
					)
				);
			DWORD dwWndStyle = (DWORD)
				::GetWindowLong(
					mi.GetCmdReciever(),
					GWL_STYLE
					);
			DWORD dwWndExStyle = (DWORD)
				::GetWindowLong(
					mi.GetCmdReciever(),
					GWL_EXSTYLE
					);
			bool bSysCmdEnabled = false;
			switch( nCmdID )
			{
			case SC_CLOSE:
				{
					bSysCmdEnabled = true;
					HMENU hSysMenu = ::GetSystemMenu( mi.GetCmdReciever(), FALSE );
					MENUITEMINFO _mii;
					::memset( &_mii, 0, sizeof(MENUITEMINFO) );
					_mii.cbSize = sizeof(MENUITEMINFO);
					_mii.fMask = MIIM_STATE;
					if(		hSysMenu != NULL
						&&	::GetMenuItemInfo(
								hSysMenu,
								SC_CLOSE,
								FALSE,
								&_mii
								)
						)
					{
						if( (_mii.fState & MFS_DISABLED) != 0 )
							bSysCmdEnabled = false;
					} // if( hSysMenu != NULL ...
				}
			break;
			case SC_SIZE:
			case SC_MOVE:
				if(		wndpl.showCmd != SW_SHOWMINIMIZED
					&&	wndpl.showCmd != SW_SHOWMAXIMIZED
					)
					bSysCmdEnabled = true;
			break;
			case SC_MINIMIZE:
				if(		(dwWndStyle & WS_MINIMIZEBOX) != 0
					&&	wndpl.showCmd != SW_SHOWMINIMIZED
					)
					bSysCmdEnabled = true;
			break;
			case SC_MAXIMIZE:
				if(		(dwWndStyle & WS_MAXIMIZEBOX) != 0
					&&	wndpl.showCmd != SW_SHOWMAXIMIZED
					)
					bSysCmdEnabled = true;
			break;
			case SC_RESTORE:
				if(		(dwWndStyle & (WS_MINIMIZEBOX|WS_MAXIMIZEBOX)) != 0
					&&	(	wndpl.showCmd == SW_SHOWMAXIMIZED
						||	wndpl.showCmd == SW_SHOWMINIMIZED
						//||wndpl.showCmd == SW_SHOWNORMAL
						)
					)
					bSysCmdEnabled = true;
			break;
			case SC_CONTEXTHELP:
				if( (dwWndExStyle & WS_EX_CONTEXTHELP) != 0 )
					bSysCmdEnabled = true;
			break;
//			case SC_NEXTWINDOW:
//			case SC_PREVWINDOW:
//			case SC_VSCROLL:
//			case SC_HSCROLL:
//			case SC_MOUSEMENU:
//			case SC_KEYMENU:
//			case SC_ARRANGE:
//			case SC_TASKLIST:
//			case SC_SCREENSAVE:
//#if(WINVER >= 0x0400)
//			case SC_DEFAULT:
//			case SC_MONITORPOWER:
//			case SC_SEPARATOR:
//#endif /* WINVER >= 0x0400 */
			case SC_HOTKEY:
			default:
				continue;
			} // switch( nCmdID )
			CExtCmdItem * pCmdItem =
				g_CmdManager->CmdGetPtr(
					g_CmdManager->ProfileNameFromWnd( m_hWndCmdReciever ),
					nCmdID
					);
			ASSERT( pCmdItem != NULL );
			pCmdItem->StateEnable( bSysCmdEnabled );
			mi.Enable( bSysCmdEnabled );
		} // for(; iter < m_items_all.end(); ++iter )
	} // BLOCK: update system commands

CWnd * pWndCmdReciever =
		CWnd::FromHandle( m_hWndCmdReciever );
	ASSERT_VALID( pWndCmdReciever );
//	pWndCmdReciever->ActivateTopParent();
//	pWndCmdReciever->BringWindowToTop();
//	pWndCmdReciever->SetFocus();
	
	//_site._Hook( true );

	// adjust own data
bool bOldTopLevel = m_bTopLevel;
bool bOldExpandAvailable = m_bExpandAvailable;
	_Init();
	m_bTopLevel = bOldTopLevel;
	m_bExpandAvailable = bOldExpandAvailable;
	m_dwTrackFlags = dwTrackFlags;
	m_pCbPaintCombinedCookie = pCbPaintCombinedCookie;
	m_pCbPaintCombinedContent = pCbPaintCombinedContent;
	m_bCookieIsObject = bCookieIsObject;
	if( !m_bTopLevel )
	{
		ASSERT( m_pWndParentMenu != NULL );
		if( m_pWndParentMenu->m_bExpandWasPressed )
		{
			if( m_bExpandAvailable )
			{
				m_bExpandAvailable = false;
				m_bExpandWasPressed = true;
				_SyncItems();
			}
			else
				m_bExpandWasPressed = true;
		}
	} // if( !m_bTopLevel )
	else
	{
		if( bForceExpandRarelyUsed )
		{
			if( m_bExpandAvailable )
			{
				m_bExpandAvailable = false;
				m_bExpandWasPressed = true;
				_SyncItems();
			}
			else
				m_bExpandWasPressed = true;
		} // if( bForceExpandRarelyUsed )
		else
			_SyncItems();
	} // else from if( !m_bTopLevel )

	// adjust screen position
	m_ptTrack.x = x;
	m_ptTrack.y = y;
	if( m_ptTrack.x < 0 || m_ptTrack.y < 0 )
	{
		if( ! ::GetCursorPos(&m_ptTrack) )
			return FALSE;
	}

	if( lpRect != NULL )
	{
		m_rcExcludeArea = *lpRect;
		m_bExcludeAreaSpec = true;
	}
	else
	{
		m_bExcludeAreaSpec = false;
		m_rcExcludeArea.left = m_ptTrack.x - __EXCLUDE_AREA_GAP_DX;
		m_rcExcludeArea.right = m_ptTrack.x + __EXCLUDE_AREA_GAP_DX;
		m_rcExcludeArea.top = m_ptTrack.y - __EXCLUDE_AREA_GAP_DY;
		m_rcExcludeArea.bottom = m_ptTrack.y + __EXCLUDE_AREA_GAP_DY;
	}

	// adjust combine with exclude area mode
	m_bCombineWithEA = false;
	if( m_bExcludeAreaSpec
		// && m_bTopLevel 
		)
	{
		switch( (dwTrackFlags&TPMX_COMBINE_MASK) )
		{
		case TPMX_COMBINE_ANY_SUITABLE:
			m_bCombineWithEA = true;
		break;
		case TPMX_COMBINE_DEFAULT:
			m_bCombineWithEA =
				g_PaintManager->
					IsMenuMustCombineExcludeArea();
		break;
		} // switch( (dwTrackFlags&TPMX_COMBINE_MASK) )
	} // if( m_bExcludeAreaSpec ...

CSize _size = _CalcTrackSize();
bool bPointAdjusted = true;
	if( m_bExcludeAreaSpec )
	{
		switch( (m_dwTrackFlags & TPMX_ALIGN_MASK) )
		{
		case TPMX_LEFTALIGN:
			m_ptTrack.x = m_rcExcludeArea.right;
			m_ptTrack.y = m_rcExcludeArea.top;
		break;
		case TPMX_RIGHTALIGN:
			m_ptTrack.x = m_rcExcludeArea.left - _size.cx;
			m_ptTrack.y = m_rcExcludeArea.top;
		break;
		case TPMX_TOPALIGN:
			m_ptTrack.x = m_rcExcludeArea.left;
			m_ptTrack.y = m_rcExcludeArea.bottom;
		break;
		case TPMX_BOTTOMALIGN:
			m_ptTrack.x = m_rcExcludeArea.left;
			m_ptTrack.y = m_rcExcludeArea.top - _size.cy;
		break;
		default:
			bPointAdjusted = false;
		break;
		} // switch( (m_dwTrackFlags & TPMX_ALIGN_MASK) )
	} // if( m_bExcludeAreaSpec )
	if( !bPointAdjusted )
	{
		if( (m_dwTrackFlags & TPMX_ALIGN_MASK)
				== TPMX_RIGHTALIGN )
			m_ptTrack.x -= _size.cx;
		else
		{
			if( (m_dwTrackFlags & TPMX_ALIGN_MASK)
					== TPMX_CENTERALIGN )
				m_ptTrack.x -= _size.cx/2;
		}
		if( (m_dwTrackFlags & TPMX_ALIGN_MASK)
				== TPMX_BOTTOMALIGN )
			m_ptTrack.y -= _size.cy;
		else
		{
			if( (m_dwTrackFlags & TPMX_ALIGN_MASK)
					== TPMX_VCENTERALIGN )
				m_ptTrack.y -= _size.cy/2;
		}
	} // if( !bPointAdjusted )

//#ifdef _DEBUG
bool bCreateResult =
//#endif // _DEBUG
		_CreateHelper( pWndCmdReciever );
	//ASSERT( bCreateResult );
	if( !bCreateResult )
	{
		//_OnCancelMode();
		return FALSE;
	}

	if( dwTrackFlags & TPMX_SELECT_ANY )
	{
		int nItem = _GetNextItem(__NI_ANY);
		if( nItem >= 0 )
			_ItemFocusSet(
				nItem,
				FALSE,
				FALSE
				);
	}

	if( _FindCustomizeMode() )
		m_AnimationType = __AT_NONE;
	else
	{
		m_AnimationType = g_DefAnimationType;
		if( CExtToolControlBar::g_bMenuTracking )
			m_AnimationType = __AT_NONE;

		m_ePlaySoundOnAnimationFinished =
			CExtSoundPlayer::__ON_MENU_POPUP_DISPLAYED;
		_StartAnimation();
	} // if( _FindCustomizeMode() )
	if( m_AnimationType == __AT_NONE )
	{
		m_AnimationType = __AT_CONTENT_DISPLAY;
		_StartAnimation();
		ASSERT( m_AnimationType == __AT_CONTENT_DISPLAY );
	}

	if( m_rgnWnd.GetSafeHandle() != NULL )
	{
		ASSERT( m_bExcludeAreaSpec );
		ASSERT( m_bCombineWithEA );
		ASSERT( m_eCombineAlign != __CMBA_NONE );
		CRgn rgnTmp;
		VERIFY( rgnTmp.CreateRectRgn(0,0,0,0) );
		rgnTmp.CopyRgn( &m_rgnWnd );
		ASSERT( rgnTmp.GetSafeHandle() != NULL );
		VERIFY(
			SetWindowRgn(
				(HRGN)rgnTmp.Detach(),
				FALSE
				)
			);
	} // if( m_rgnWnd.GetSafeHandle() != NULL )
	SetWindowPos(
		&CWnd::wndTopMost, 0, 0, 0, 0,
		SWP_NOACTIVATE
			|SWP_NOMOVE|SWP_NOSIZE
			|SWP_SHOWWINDOW
			//|SWP_NOREDRAW //|SWP_NOSENDCHANGING
			|SWP_NOZORDER //|SWP_NOOWNERZORDER
			//|SWP_NOCOPYBITS
		);

	ASSERT( IsWindowVisible() );

	if( !_FindCustomizeMode() )
		_SetCapture();
#if (!defined __EXT_MFC_NO_CUSTOMIZE)
	else
	{
		CExtCustomizeSite * pSite = _FindCustomizeSite();
		ASSERT( pSite != NULL );
		pSite->RegisterCommandDropTarget( this, this );
	}
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)

	return TRUE;
}

bool CExtPopupMenuWnd::_CreateHelper(
	CWnd * pWndCmdReciever
	)
{
	ASSERT_VALID( this );

bool bHasInplaceItems = false;
int nCount = ItemGetCount();
	for( int i = 0; i < nCount; i++ )
	{
		MENUITEMDATA & mi = _GetItemRef( i );
		if( !mi.IsInplaceEdit() )
			continue;
		//ASSERT( mi.GetInplaceEditPtr() == NULL );
		mi.ResetActiveInplaceEditPtr();
		bHasInplaceItems = true;
		break;
	} // for( int i = 0; i < nCount; i++ )
	if( bHasInplaceItems )
		_SyncItems();

CRect wr = _CalcTrackRect();
	if( wr.IsRectEmpty() )
		return false;

HCURSOR hCursor = ::LoadCursor(NULL, IDC_ARROW);
	ASSERT( hCursor != NULL );
CExtSafeString strMenuClassName =
		::AfxRegisterWndClass(
			__POPUP_WNDCLASS_STYLES__,
			hCursor,
			(HBRUSH)(COLOR_BTNFACE + 1),
			NULL
			);
	ASSERT( !strMenuClassName.IsEmpty() );

BOOL bCreateResult =
		__BaseClassOfCExtPopupBaseWnd::CreateEx(
			_FindCustomizeMode() ? 0 : WS_EX_TOPMOST,
			strMenuClassName,
			NULL,
			WS_POPUP,
			wr,
			pWndCmdReciever,
			0 // IDC_STATIC
			);
	if( !bCreateResult )
	{
		ASSERT( FALSE );
		return false;
	}

	_RecalcLayoutImpl();

	if( !_FindHelpMode() )
		::SetCursor( hCursor );

//HWND hWndOwn = GetSafeHwnd();
//	ASSERT( hWndOwn != NULL );
//	ASSERT( ::IsWindow(hWndOwn) );
//	PassMsgLoop( CExtPopupBaseWnd::g_bEnableOnIdleCalls ); // update all bottom
//	if( !::IsWindow(hWndOwn) )
//		return false;

	if( bHasInplaceItems )
	{
		visible_items_t v;
		_GetVisibleItems( NULL, v );
		int nCount = v.GetSize();
		for( i = 0; i < nCount; i++ )
		{
//			MENUITEMDATA & mi = _GetItemRef( i );
VisibleItemDefinition_t & vi = v[ i ];
MENUITEMDATA & mi = _GetItemRef( vi.m_nIndex );
			if( !mi.IsInplaceEdit() )
				continue;
			//ASSERT( mi.GetInplaceEditPtr() == NULL );
			mi.ResetActiveInplaceEditPtr();
//			VisibleItemDefinition_t & vi = v[ i ];
			CRect rc = mi.AdjustInplaceEditRect( vi.m_rcItem );
			mi.CreateInplaceEdit( this, rc );
		} // for( i = 0; i < nCount; i++ )
	} // if( bHasInplaceItems )

	return true;
}

BOOL CExtPopupMenuWnd::DestroyWindow()
{
	ASSERT_VALID( this );
int nCount = ItemGetCount();
	for( int i = 0; i < nCount; i++ )
	{
		MENUITEMDATA & mi = _GetItemRef( i );
		if( mi.IsInplaceEdit() )
		{
			if( mi.GetInplaceEditPtr() != NULL )
			{
				ASSERT_VALID( mi.GetInplaceEditPtr() );
				ASSERT( mi.GetInplaceEditPtr()->GetSafeHwnd() != NULL && (::IsWindow(mi.GetInplaceEditPtr()->GetSafeHwnd())) );
				mi.GetInplaceEditPtr()->DestroyWindow();
			} // if( mi.GetInplaceEditPtr() != NULL )
			mi.ResetActiveInplaceEditPtr();
		}
	} // for( int i = 0; i < nCount; i++ )
	if( !(::IsWindow(GetSafeHwnd())) )
		return TRUE;
#if (!defined __EXT_MFC_NO_CUSTOMIZE)
	if( _FindCustomizeMode() )
	{
		CExtCustomizeSite * pSite = _FindCustomizeSite();
		ASSERT( pSite != NULL );
		pSite->UnRegisterCommandDropTarget( this );
	} // if( _FindCustomizeMode() )
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)
	return CExtPopupBaseWnd::DestroyWindow();
}

void CExtPopupMenuWnd::_GetItemRect(
	int nIndex,
	RECT & rectItem
	)
{
	ASSERT_VALID( this );

CRect rcClient;
	_GetClientRect( &rcClient );

	rcClient.left += m_nLeftAreaWidth;

	if( m_bScrollingAvailable )
	{
		ASSERT( !m_rcScrollTop.IsRectEmpty() );
		ASSERT( !m_rcScrollBottom.IsRectEmpty() );
		if( nIndex == IDX_SCROLL_TOP )
		{
			rectItem = m_rcScrollTop;
			return;
		}
		if( nIndex == IDX_SCROLL_BOTTOM )
		{
			rectItem = m_rcScrollBottom;
			return;
		}
	}
	if( m_bExpandAvailable
		&& nIndex == IDX_EXPAND
		)
	{
		rectItem = m_rcExpandBtn;
		return;
	}

int nCountOfItems = m_items_all.GetSize();
	if( nCountOfItems == 0 )
	{
		((CRect *)(&rectItem))->SetRectEmpty();
		return;
	}
	ASSERT( nIndex >= 0 && nIndex < nCountOfItems );
MENUITEMDATA & mi = m_items_all[nIndex];
	if( !mi.IsDisplayed() )
	{
		::SetRectEmpty( &rectItem );
		return;
	}

int nMenuBorderSize =
		g_PaintManager->GetMenuBorderSize();
int y = m_nDyScrollOffset + nMenuBorderSize;

CRect rcItem;
	rcItem.SetRectEmpty();
	if( mi.IsToolButton() )
	{
		rcItem.left =
			nMenuBorderSize
			+ 1 + __EXT_MENU_TOOLBTN_GAP
			;
		rcItem.right =
			mi.GetMeasuredWidth()
			;
	} // if( mi.IsToolButton() )
	else
	{
		rcItem.left =
			nMenuBorderSize
			+ 1
			;
		rcItem.right =
			m_sizeFullItems.cx
			+ nMenuBorderSize
			- 1 
			;
	} // else from if( mi.IsToolButton() )

INT iter = 0;
	for(	int i = 0;
			i < nIndex
				&& iter != m_items_all.GetSize();
			i++, iter++
			)
	{
		MENUITEMDATA & mi = m_items_all[ iter ];
		if( !mi.IsDisplayed() )
			continue;
		const RECT & rcBase =
			mi.GetBaseRect();
		y +=  rcBase.bottom - rcBase.top;
	}
	ASSERT( iter != m_items_all.GetSize() );
	rcItem.OffsetRect(0,y);
	mi = m_items_all[ iter ];
	ASSERT( mi.IsDisplayed() );
const RECT & rcBase = mi.GetBaseRect();
	rcItem.bottom =
		rcItem.top + rcBase.bottom - rcBase.top;
	
	// FIX for combined exclude area
	rcItem.OffsetRect( rcClient.TopLeft() );
	
	rectItem = rcItem;
}

void CExtPopupMenuWnd::_GetVisibleItems(
	HDC hDcTest, // may be NULL
	visible_items_t & v
	)
{
	ASSERT_VALID( this );

	v.RemoveAll();
INT iter = 0;
	for(	int nIndex = 0;
			iter != m_items_all.GetSize();
			iter++, nIndex++
			)
	{ // find visible items
		MENUITEMDATA & mi = m_items_all[ iter ];
		if( !mi.IsDisplayed() )
			continue;
		CRect rcItem;
		_GetItemRect( nIndex, rcItem );
		if( rcItem.IsRectEmpty() )
			continue;
		if(		hDcTest != NULL
			&&	(! ::RectVisible( hDcTest, &rcItem ) )
			)
			continue;
		VisibleItemDefinition_t vi;
		vi.m_nIndex = nIndex;
		vi.m_nHelperCmdID = mi.GetCmdID();
		vi.m_rcItem = rcItem;
		if( mi.IsSeparator() )
		{
			vi.m_bHelperIsSeparator = true;
			v.Add( vi );
			continue;
		}
		if( mi.IsPopup() )
		{
			vi.m_bHelperIsPopup = true;
			CExtCmdItem * pCmdItem = mi.GetCmd();
			if( pCmdItem != NULL )
			{
				vi.m_bRarelyUsed =
					(	(!_FindCustomizeMode())
					&&	pCmdItem->StateIsRarelyUsed()
					) ? true : false;
			} // if( pCmdItem != NULL )
			else
				vi.m_bRarelyUsed =
						(!_FindCustomizeMode())
					&&	mi.IsAllItemsRarelyUsed()
					&&	(!mi.IsForceDisplayed())
					;
			v.Add( vi );
			continue;
		}
		if( mi.IsExtraMark() )
			vi.m_bRarelyUsed = false;
		else
		{
			CExtCmdItem * pCmdItem = mi.GetCmd();
			if( pCmdItem != NULL )
				vi.m_bRarelyUsed =
					(	(!_FindCustomizeMode())
					&&	pCmdItem->StateIsRarelyUsed()
					) ? true : false;
			else
				vi.m_bRarelyUsed = false;
		} // else from if( mi.IsExtraMark() )
		v.Add( vi );
	} // find visible items
INT vis_iter = 0;
	for( ; vis_iter < v.GetSize(); ++vis_iter )
	{ // setup prev/next rarely used flags
		VisibleItemDefinition_t & vi = v[ vis_iter ];
		INT iter_prev = vis_iter;
		INT iter_next = vis_iter;
		if( vis_iter != 0 )
		{
			--iter_prev;
			if( v[iter_prev].m_bRarelyUsed )
				vi.m_bRarelyUsedPrev = true;
		} // if( vis_iter != v.begin() )
		++iter_next;
		if( iter_next != v.GetSize() )
		{
			if( v[iter_next].m_bRarelyUsed )
				vi.m_bRarelyUsedNext = true;
		} // if( iter_next != v.end() )

		if( vi.m_bHelperIsSeparator )
		{
			if(		vi.m_bRarelyUsedPrev
				&&	vi.m_bRarelyUsedNext
				&&	(!_FindCustomizeMode())
				)
			{
				vi.m_bRarelyUsed = true;
				ASSERT( vis_iter != 0 );
				v[iter_prev].m_bRarelyUsedNext = true;
				ASSERT( iter_next != 0 );
				v[iter_next].m_bRarelyUsedPrev = true;
			}
		}
	} // setup prev/next rarely used flags
}

void CExtPopupMenuWnd::stat_paint_combined_menu_toolbtn(
	LPVOID pCookie,
	CDC & dc,
	const CWnd & refWndMenu,
	const CRect & rcExcludeArea, // in screen coords
	int eCombineAlign // CExtPopupMenuWnd::e_combine_align_t values
	)
{
	eCombineAlign;
INT nIndex = (INT)pCookie;
	ASSERT( refWndMenu.GetSafeHwnd() != NULL );
	ASSERT( ::IsWindow( refWndMenu.GetSafeHwnd() ) );
	ASSERT( dc.GetSafeHdc() != NULL );

	if( rcExcludeArea.IsRectEmpty() )
		return;

	ASSERT_KINDOF( CExtPopupMenuWnd, (&refWndMenu) );
CExtPopupMenuWnd * pPopup =
		(CExtPopupMenuWnd *)(&refWndMenu);
	ASSERT_VALID( pPopup );
	ASSERT( ! pPopup->m_bTopLevel );
CExtPopupMenuWnd * pPopup2 = pPopup->m_pWndParentMenu;
	ASSERT_VALID( pPopup2 );
	ASSERT( 0 <= nIndex && nIndex < pPopup2->ItemGetCount() );
CExtPopupMenuWnd::MENUITEMDATA & mi = pPopup2->ItemGetInfo(nIndex);

CRect rcItem;
	pPopup2->_GetItemRect( nIndex, rcItem );
CRect rcClientExcludeArea( rcExcludeArea );
	pPopup->ScreenToClient( &rcClientExcludeArea );
	rcItem.OffsetRect( - rcItem.TopLeft() );
	rcItem.OffsetRect( rcClientExcludeArea.TopLeft() );
CRect rcTargetClient;
	pPopup->_GetClientRect( &rcTargetClient );
	dc.ExcludeClipRect( &rcTargetClient );

CExtPopupMenuWnd::DRAWITEMDATA _DrawItemData(
		&dc,
		&rcItem,
		&mi,
		pPopup,
		( pPopup->GetSite()->m_dwTrackFlags&TPMX_OWNERDRAW_FIXED ) ? true : false,
		mi.IsPopup(),
		false, // g_bMenuHighlightRarely && vi.m_bRarelyUsed,
		false, // g_bMenuHighlightRarely && vi.m_bRarelyUsedPrev,
		false  // g_bMenuHighlightRarely && vi.m_bRarelyUsedNext
		);

bool bPainted =
		(_DrawItemData.m_bMenuOwnerDrawFixed)
			? _DrawItemData.DoOwnerDrawPainting()
			: false
			;
	if( !bPainted )
		_DrawItemData.PaintDefault();

	dc.SelectClipRgn( NULL );
}

void CExtPopupMenuWnd::DRAWITEMDATA::PaintDefault(
	bool bForceNoIcon, // = false
	bool bForceNoText, // = false
	bool bForceNoCheck, // = false
	bool bForceEnabled, // = false
	bool bForceUnselected // = false
	)
{
	ASSERT( m_pDC != NULL );
	ASSERT( m_pDC->GetSafeHdc() != NULL );
	ASSERT( m_pRectItem != NULL );
	ASSERT( m_pItemData != NULL );
	ASSERT( m_pPopup != NULL );

#if (!defined __EXT_MFC_NO_CUSTOMIZE)
CExtCustomizeSite * pSite = NULL;
bool bCustomizeMode = false;
#if (!defined __EXT_MFC_NO_BUILTIN_TEXTFIELD)
bool bResizingNode = false;
#endif // (!defined __EXT_MFC_NO_BUILTIN_TEXTFIELD)
	if( m_pPopup->_FindCustomizeMode() )
	{
		pSite = m_pPopup->_FindCustomizeSite();
		ASSERT( pSite != NULL );
		bCustomizeMode = true;
		bForceNoCheck = bForceEnabled = true;
//		bForceUnselected = m_pItemData->IsPopup() ? false : true;
#if (!defined __EXT_MFC_NO_BUILTIN_TEXTFIELD)
		CExtCustomizeCmdTreeNode * pNode = ((MENUITEMDATA *)m_pItemData)->GetCmdNode();
		if( pNode != NULL )
		{
			ASSERT_VALID( pNode );
			if( pNode == pSite->GetResizingNode() )
				bResizingNode = true;
		}
#endif // (!defined __EXT_MFC_NO_BUILTIN_TEXTFIELD)
	}
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)

	if( m_pItemData->IsToolButton() )
	{
		bool bSelDraw =
			bForceUnselected ? false : m_pItemData->IsSelected();
		bool bTransparent = !m_pItemData->IsSelected();
		if( bSelDraw && m_pItemData->IsPopup() )
		{
			const CExtPopupMenuWnd * pChildPopup = m_pItemData->GetPopup();
			if(		pChildPopup->GetSafeHwnd() != NULL
				&&	::IsWindow( pChildPopup->GetSafeHwnd() )
				&&	(pChildPopup->GetStyle() & WS_VISIBLE) != NULL
				)
			{
				bSelDraw = false;
				bTransparent = true;
			}
		} // if( bSelDraw && m_pItemData->IsPopup() )
		CExtPaintManager::PAINTPUSHBUTTONDATA _ppbd(
			m_pPopup,
			true,
			*m_pRectItem,
			bForceNoText ? _T("") : m_pItemData->GetText(),
			( bForceNoIcon ) ? NULL : ((MENUITEMDATA *)m_pItemData)->GetIconPtr(),
			true,
			bSelDraw, // hover
			bSelDraw, // pushed
			false,
			bForceEnabled || m_pItemData->IsEnabled() || m_pItemData->IsForceEnabled(),
			m_pItemData->IsSelected(), // border
			false,
			false,
			CExtPaintManager::__ALIGN_VERT,
			NULL,
			m_pItemData->IsPopup() ? true : false,
			0,
			bTransparent // transparent
			);
		g_PaintManager->PaintPushButton( *m_pDC, _ppbd );
	} // if( m_pItemData->IsToolButton() )
	else
	{
		CExtCmdIcon * pIcon =
			( bForceNoIcon )
				? NULL
				: ((MENUITEMDATA *)m_pItemData)->GetIconPtr();
		if( pIcon != NULL && pIcon->IsEmpty() )
			pIcon = NULL;
		CExtCmdIcon _iconLarge;
		if( g_bMenuLargeIcons && pIcon != NULL )
		{
			CSize _sizeIcon = pIcon->GetSize();
			_sizeIcon.cx *= 2;
			_sizeIcon.cy *= 2;
			if(	_iconLarge.CreateScaledCopy(
					*pIcon,
					_sizeIcon
					)
				)
				pIcon = &_iconLarge;
#ifdef _DEBUG
			else
			{
				ASSERT( FALSE );
			}
#endif // _DEBUG
		} // if( g_bMenuLargeIcons && pIcon != NULL )
		CExtPaintManager::PAINTMENUITEMDATA _pmid(
			m_pPopup,
			CRect( *m_pRectItem ),
			m_pItemData->GetIconAreaWidth(),
			bForceNoText ? _T("") : m_pItemData->GetText(),
			bForceNoText ? _T("") : m_pItemData->GetAccelText(),
			pIcon,
			m_bPopupItem,
			bForceUnselected ? false : m_pItemData->IsSelected(),
			bForceNoCheck ? false : m_pItemData->GetCheck(),
			bForceNoCheck ? false : m_pItemData->GetRadio(),
			m_pItemData->IsIndeterminated(),
			bForceEnabled || m_pItemData->IsEnabled() || m_pItemData->IsForceEnabled(),
			m_bRarelyUsed,
			m_bRarelyUsedPrevious,
			m_bRarelyUsedNext,
			m_pItemData->GetCmdID()
			);
		_pmid.m_bForceNoLeftGradient = m_pItemData->IsForceNoLeftGradient();
		if( ((MENUITEMDATA *)m_pItemData)->IsInplaceEdit() )
		{
			_pmid.m_rcInPlaceWnd = m_pItemData->AdjustInplaceEditRect( *m_pRectItem );
			_pmid.m_strInPlaceText = m_pItemData->GetInplaceEditText();
		} // if( ((MENUITEMDATA *)m_pItemData)->IsInplaceEdit() )
		if( m_pItemData->IsExtraMark() )
		{
			_pmid.m_bXtraMark = true;
			_pmid.m_bXtraChecked = m_pItemData->IsExtraChecked();
		} // if( m_pItemData->IsExtraMark() )
		ASSERT( !_pmid.m_bHelperPopupDropped );
		if(		m_pItemData->IsPopup()
			&&	m_pItemData->GetPopup()->GetSafeHwnd() != NULL
			&&	m_pItemData->GetPopup()->IsWindowVisible()
			)
			_pmid.m_bHelperPopupDropped = true;
#if (!defined __EXT_MFC_NO_CUSTOMIZE)
#if (!defined __EXT_MFC_NO_BUILTIN_TEXTFIELD)
		if( bResizingNode )
			_pmid.m_bSelected = true;
#endif // (!defined __EXT_MFC_NO_BUILTIN_TEXTFIELD)
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)
		g_PaintManager->PaintMenuItem( *m_pDC, _pmid );
	} // else from if( m_pItemData->IsToolButton() )
#if (!defined __EXT_MFC_NO_CUSTOMIZE)
	if( m_pPopup->m_nHelperDropIndexBefore >= 0 )
	{
		int nCount = m_pPopup->ItemGetCount();
		ASSERT( m_pPopup->m_nHelperDropIndexBefore <= nCount );
		int nAlignAt = 0;
		int nItemIndex = m_pItemData->GetIndex();
		if( nItemIndex == m_pPopup->m_nHelperDropIndexBefore )
			nAlignAt = -1;
		else if(	nItemIndex == ( nCount - 1 )
				&&	m_pPopup->m_nHelperDropIndexBefore == nCount
			)
			nAlignAt = 1;
		else if(	( nItemIndex + 1 ) == m_pPopup->m_nHelperDropIndexBefore
				&&	m_pPopup->_GetItemRef( nItemIndex + 1 ).IsSeparator()
				)
		{
			nItemIndex;
			nAlignAt = 1;
		}
		if( nAlignAt != 0 )
		{ // if paint drop divider
			CSize _sizeDDM = g_PaintManager->GetDropDividerMerics();
			CRect rcItem;
			ASSERT( !m_pPopup->_GetItemRef(nItemIndex).IsSeparator() );
			m_pPopup->_GetItemRect( nItemIndex, rcItem );
			int nY =
				( nAlignAt > 0 )
					? rcItem.bottom - _sizeDDM.cy/2
					: rcItem.top + _sizeDDM.cy/2
					;
			rcItem.top = rcItem.bottom = nY;
			g_PaintManager->PaintDropDivider(
				*m_pDC,
				rcItem,
				true,
				false
				);
		} // if( nAlignAt != 0 )
	} // if( m_pPopup->m_nHelperDropIndexBefore >= 0 )
	if( bCustomizeMode )
	{
		ASSERT( pSite != NULL );
		if(
				(
					pSite != NULL
				&&
							(	pSite->CustomizedNodeGet() != NULL
							&&	pSite->CustomizedNodeGet()  == ((MENUITEMDATA*)m_pItemData)->GetCmdNode()
							)
				)
			||
				(	m_pPopup->m_pDragSrcNode != NULL
				&&	((MENUITEMDATA*)m_pItemData)->GetCmdNode() == m_pPopup->m_pDragSrcNode
				)
#if (!defined __EXT_MFC_NO_BUILTIN_TEXTFIELD)
			||	bResizingNode
#endif // (!defined __EXT_MFC_NO_BUILTIN_TEXTFIELD)
			)
		{
			CRect rcItem = m_pRectItem;
			g_PaintManager->PaintDragSourceRect(
				*m_pDC,
				rcItem
				);
		}
	} // if( bCustomizeMode )
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)
}

bool CExtPopupMenuWnd::DRAWITEMDATA::DoOwnerDrawPainting()
{
	ASSERT( m_pDC != NULL );
	ASSERT( m_pDC->GetSafeHdc() != NULL );
	ASSERT( m_pRectItem != NULL );
	ASSERT( m_pItemData != NULL );
	ASSERT( m_pPopup != NULL );
	HWND hWndNotify =
		m_pPopup->m_hWndCmdReciever;
	ASSERT( hWndNotify != NULL );
	ASSERT( ::IsWindow(hWndNotify) );
	LRESULT lResult =
		::SendMessage(
			hWndNotify,
			CExtPopupMenuWnd::g_nMsgPopupDrawItem,
			0,
			LPARAM( *this )
			);
	return lResult ? true : false;
}

bool CExtPopupMenuWnd::DRAWLEFTAREADATA::DoOwnerDrawPainting()
{
	ASSERT( m_pDC != NULL );
	ASSERT( m_pDC->GetSafeHdc() != NULL );
	ASSERT( m_pRectLeftArea != NULL );
	ASSERT( m_pPopup != NULL );
	HWND hWndNotify =
		m_pPopup->m_hWndCmdReciever;
	ASSERT( hWndNotify != NULL );
	ASSERT( ::IsWindow(hWndNotify) );
	LRESULT lResult =
		::SendMessage(
			hWndNotify,
			CExtPopupMenuWnd::g_nMsgPopupDrawLeftArea,
			0,
			LPARAM( *this )
			);
	return lResult ? true : false;
}

void CExtPopupMenuWnd::_DoPaint(
	CDC & dcPaint,
	bool bUseBackBuffer // = true
	)
{
	ASSERT_VALID( this );

	ASSERT_VALID( (&dcPaint) );
	ASSERT( dcPaint.GetSafeHdc() != NULL );

	if( m_hWnd != NULL )
	{
		ASSERT( ::IsWindow(m_hWnd) );
		CExtPaintManager::stat_ExcludeChildAreas(
			dcPaint.GetSafeHdc(),
			m_hWnd
			);
	} // if( m_hWnd != NULL )

	ASSERT( m_hWndCmdReciever != NULL );
	ASSERT( ::IsWindow(m_hWndCmdReciever) );

CRect rcRealClient;
	GetClientRect( &rcRealClient );
CRect rcClient;
	_GetClientRect( &rcClient );

CPalette * pOldPalette = NULL, * pOldPalette2 = NULL;
    if( dcPaint.GetDeviceCaps(RASTERCAPS) & RC_PALETTE )
    {
        pOldPalette =
			dcPaint.SelectPalette( &g_PaintManager->m_PaletteWide, FALSE );
        dcPaint.RealizePalette();
    }

//bUseBackBuffer = false;
//bUseBackBuffer = true;
	//dcPaint.SetViewportOrg( CPoint(0,0) );
CExtMemoryDC mdc;
	if( bUseBackBuffer )
	{
		mdc.__InitMemoryDC(
			&dcPaint,
			&rcClient // &rcRealClient
			);
		//mdc.SetViewportOrg( CPoint(0,0) );
		if( pOldPalette != NULL )
		{
			pOldPalette2 =
				mdc.SelectPalette( &g_PaintManager->m_PaletteWide, FALSE );
			mdc.RealizePalette();
		}
	}
CDC & dcDummyRef = mdc;
CDC & dc = bUseBackBuffer ? dcDummyRef : dcPaint;

CFont * pOldFont = (CFont *)
		dc.SelectObject(
			&g_PaintManager->m_FontNormal
			);

	dc.FillSolidRect(
		&rcClient,
		g_PaintManager->GetMenuFrameFillColor()
		);

	g_PaintManager->PaintMenuBorder(
		dc,
		rcClient,
		this
		);

CRect rcExpand;
	if( m_bExpandAvailable )
	{
		_GetItemRect(
			IDX_EXPAND,
			rcExpand
			);
		CRect rcExcludePart( rcExpand );
		rcExcludePart.InflateRect( 0, 1 );
		rcExcludePart.left = rcRealClient.left;
		rcExcludePart.right = rcRealClient.right;
		dc.ExcludeClipRect( rcExcludePart );
	}
CRect rcScrollTop,rcScrollBottom;
int nMaxScrollPos = 0;
	if( m_bScrollingAvailable )
	{
		if( m_nDyScrollOffset != 0 )
		{
			_GetItemRect(
				IDX_SCROLL_TOP,
				rcScrollTop
				);
			CRect rcExcludePart( rcScrollTop );
			rcExcludePart.InflateRect( 0, 1 );
			rcExcludePart.left = rcRealClient.left;
			rcExcludePart.right = rcRealClient.right;
			dc.ExcludeClipRect( rcExcludePart );
		}
		nMaxScrollPos = _GetMaxScrollPos();
		if( m_nDyScrollOffset != nMaxScrollPos )
		{
			_GetItemRect(
				IDX_SCROLL_BOTTOM,
				rcScrollBottom
				);
			CRect rcExcludePart( rcScrollBottom );
			rcExcludePart.InflateRect( 0, 1 );
			rcExcludePart.left = rcRealClient.left;
			rcExcludePart.right = rcRealClient.right;
			dc.ExcludeClipRect( rcExcludePart );
		}
	}
int nMenuBorderSize =
		g_PaintManager->GetMenuBorderSize();
int nMenuShadowSize =
		_GetPopupShadowSize();

//	if( rcClient.left >= rcRealClient.left )
//	{
//		CRect rcExcludePart(rcRealClient);
//		rcExcludePart.right =
//			rcClient.left + nMenuBorderSize;
//		dc.ExcludeClipRect( rcExcludePart );
//	}
//	if( rcClient.right <= rcRealClient.right )
//	{
//		CRect rcExcludePart(rcRealClient);
//		rcExcludePart.left =
//			rcClient.right - nMenuBorderSize;
//		dc.ExcludeClipRect( rcExcludePart );
//	}

	if( rcClient.top >= rcRealClient.top )
	{
		CRect rcExcludePart(rcRealClient);
		rcExcludePart.bottom =
			rcClient.top + nMenuBorderSize;
		dc.ExcludeClipRect( rcExcludePart );
	}
	if( rcClient.bottom <= rcRealClient.bottom )
	{
		CRect rcExcludePart(rcRealClient);
		rcExcludePart.top =
			rcClient.bottom - nMenuBorderSize;
		dc.ExcludeClipRect( rcExcludePart );
	}

visible_items_t v;
	_GetVisibleItems( dc.GetSafeHdc(), v );
INT vis_iter = 0;
bool bPrevToolButton = false;
	for( ; vis_iter < v.GetSize(); ++vis_iter )
	{ // paint visible items
		VisibleItemDefinition_t & vi = v[ vis_iter ];
		ASSERT(
			vi.m_nIndex >= 0
			&&
			vi.m_nIndex < m_items_all.GetSize()
			);
		ASSERT( !vi.m_rcItem.IsRectEmpty() );
		ASSERT( dc.RectVisible(&vi.m_rcItem) );
		MENUITEMDATA & mi =
			m_items_all[vi.m_nIndex];
		ASSERT( mi.IsDisplayed() );
		ASSERT( mi.GetCmdID() == vi.m_nHelperCmdID );
		if( vi.m_bHelperIsSeparator )
		{
			ASSERT( mi.IsSeparator() );
			if( bPrevToolButton )
			{
				CRect rcSep( vi.m_rcItem );
				rcSep.top += rcSep.Height()/2 - 1;
				rcSep.bottom = rcSep.top + 2;
				g_PaintManager->PaintSeparator(
					dc,
					rcSep,
					false,
					false,
					this
					);
			} // if( bPrevToolButton )
			else
				g_PaintManager->PaintMenuSeparator(
					dc,
					vi.m_rcItem,
					mi.GetIconAreaWidth(),
					g_bMenuHighlightRarely && vi.m_bRarelyUsed,
					this
					);
			bPrevToolButton = false;
			continue;
		}
		ASSERT( !mi.IsSeparator() );
		ASSERT( mi.IsPopup() == vi.m_bHelperIsPopup );
		
		DRAWITEMDATA _DrawItemData(
			&dc,
			&vi.m_rcItem,
			&mi,
			this,
			(		(! _FindCustomizeMode() )
				&&	( GetSite()->m_dwTrackFlags&TPMX_OWNERDRAW_FIXED ) != 0 // fix 2.23 ( == replaced with != )
			) ? true : false,
			vi.m_bHelperIsPopup,
			g_bMenuHighlightRarely && vi.m_bRarelyUsed,
			g_bMenuHighlightRarely && vi.m_bRarelyUsedPrev,
			g_bMenuHighlightRarely && vi.m_bRarelyUsedNext
			);
		
		bool bPainted =
			(_DrawItemData.m_bMenuOwnerDrawFixed)
				? _DrawItemData.DoOwnerDrawPainting()
				: false
				;
		if( !bPainted )
			_DrawItemData.PaintDefault();

		bPrevToolButton = mi.IsToolButton();
	} // paint visible items

CPoint point( 0, 0 );
	::GetCursorPos( &point );
	ScreenToClient( &point );
	dc.SelectClipRgn( NULL );

	if( m_bExpandAvailable )
	{
		bool bHover =
			(rcExpand.PtInRect(point))? true : false;
		bool bPushed = bHover;
		g_PaintManager->PaintMenuExpandButton(
			dc,
			rcExpand,
			bHover,
			bPushed,
			this
			);
	} // if( m_bExpandAvailable )

	if( m_bScrollingAvailable )
	{
		if( m_nDyScrollOffset != 0 )
		{
			bool bHover =
				(rcScrollTop.PtInRect(point))? true : false;
			bool bPushed =
				( m_nScrollingDirection > 0 ) ? true : false;
			bPushed = bPushed || bHover;
			CExtPaintManager::PAINTPUSHBUTTONDATA _ppbd(
				this,
				true,
				rcScrollTop,
				_T("t"), // up arrow
				NULL,
				true,false/*bHover*/,bPushed,false,
				true,true,false,false,
				CExtPaintManager::__ALIGN_HORIZ_CENTER
					| CExtPaintManager::__ALIGN_VERT,
				(HFONT)g_PaintManager->m_FontMarlett.GetSafeHandle()
				);
			g_PaintManager->PaintPushButton( dc, _ppbd );
		}
		if( m_nDyScrollOffset != nMaxScrollPos )
		{
			bool bHover =
				(rcScrollBottom.PtInRect(point))? true : false;
			bool bPushed =
				( m_nScrollingDirection < 0 ) ? true : false;
			bPushed = bPushed || bHover;
			CExtPaintManager::PAINTPUSHBUTTONDATA _ppbd(
				this,
				true,
				rcScrollBottom,
				_T("u"), // down arrow
				NULL,
				true,false/*bHover*/,bPushed,false,
				true,true,false,false,
				CExtPaintManager::__ALIGN_HORIZ_CENTER
					| CExtPaintManager::__ALIGN_VERT,
				(HFONT)g_PaintManager->m_FontMarlett.GetSafeHandle()
				);
			g_PaintManager->PaintPushButton( dc, _ppbd );
		}
	} // if( m_bScrollingAvailable )

	if( m_nLeftAreaWidth > 0 )
	{
		CRect rcLeftArea( rcClient );
		rcLeftArea.right = rcLeftArea.left + m_nLeftAreaWidth;
		rcLeftArea.OffsetRect( nMenuBorderSize, 0 );
		rcLeftArea.DeflateRect( 0, nMenuBorderSize );
		DRAWLEFTAREADATA _DrawLeftAreaData( &dc, &rcLeftArea, this );
		_DrawLeftAreaData.DoOwnerDrawPainting();
	}

	if( m_bCombineWithEA )
	{
		ASSERT( m_eCombineAlign != __CMBA_NONE );
		dc.SelectClipRgn(NULL);
		CRect rcExcludeClient( m_rcExcludeArea );
		ScreenToClient( &rcExcludeClient );
		g_PaintManager->PaintMenuCombinedArea(
			dc,
			rcExcludeClient,
			rcClient,
			m_eCombineAlign,
			this
			);
		if( m_pCbPaintCombinedContent != NULL )
			m_pCbPaintCombinedContent(
				m_pCbPaintCombinedCookie,
				dc,
				*this,
				m_rcExcludeArea,
				m_eCombineAlign
				);
	} // if( m_bCombineWithEA )

	dc.SelectObject( pOldFont );
	if( bUseBackBuffer )
	{
		ASSERT( mdc.GetSafeHdc() != NULL );
		if( pOldPalette2 != NULL )
			mdc.SelectPalette( pOldPalette2, FALSE );
		mdc.__Flush();
	}

	if( _IsPopupWithShadows()
		&& m_bAnimFinished
		&& nMenuShadowSize > 0
		)
	{ // if we need to paint shadow for client area (and combined exclude area)
		dcPaint.SelectClipRgn(NULL);
		CRect
			rcExcludeClient( 0,0,0,0 ),
			rcExcludeScreen( 0,0,0,0 ),
			rcBaseScreen( 0,0,0,0 );
		if( m_bCombineWithEA )
		{
			if( _IsPopupWithShadows()
				&& m_bAnimFinished
				&& nMenuShadowSize > 0
				&& m_bTopLevel
				)
			{ // if we need to paint shadow for combined exclude area
				rcExcludeScreen = m_rcExcludeArea;
				rcExcludeClient = rcExcludeScreen;
				ScreenToClient( &rcExcludeClient );
				dcPaint.ExcludeClipRect( &rcClient );
				rcBaseScreen = rcClient;
				ClientToScreen( &rcBaseScreen );
				VERIFY(
					m_ShadowCMBA.Paint(
						dcPaint,
						rcExcludeClient,
						rcExcludeScreen,
						rcBaseScreen,
						nMenuShadowSize
						)
					);
				dcPaint.SelectClipRgn(NULL);
			} // if we need to paint shadow for combined exclude area

			CRect rcExcludePart( m_rcExcludeArea );
			ScreenToClient( &rcExcludePart );
			dcPaint.ExcludeClipRect( &rcExcludePart );
		} // if( m_bCombineWithEA )
		VERIFY(
			m_ShadowMain.Paint(
				dcPaint,
				rcClient,
				rcBaseScreen,
				rcExcludeScreen,
				nMenuShadowSize
				)
			);

	} // if we need to paint shadow for client area (and combined exclude area)

	if( pOldPalette != NULL )
		dcPaint.SelectPalette( pOldPalette, FALSE );
}

#if _MFC_VER < 0x700
void CExtPopupMenuWnd::OnActivateApp(BOOL bActive, HTASK hTask) 
#else
void CExtPopupMenuWnd::OnActivateApp(BOOL bActive, DWORD hTask) 
#endif
{
	ASSERT_VALID( this );
	bActive;
	hTask;
	_OnCancelMode();
}

bool CExtPopupMenuWnd::_StartScrolling(int nButtonIndex)
{
	ASSERT_VALID( this );

	if( GetSafeHwnd() == NULL )
		return FALSE;

	if( (nButtonIndex == IDX_SCROLL_TOP
			|| nButtonIndex == IDX_SCROLL_BOTTOM)
//		&& m_nCurIndex != nButtonIndex
		)
	{
		ASSERT( m_bScrollingAvailable );
		_ItemFocusDelay();
		_ItemFocusCancel( FALSE );
		m_nCurIndex = nButtonIndex;
		Invalidate( FALSE );
		SetTimer(
			ID_TIMER_SCROLLING,
			ID_PERIOD_SCROLLING,
			NULL
			);
		if( !_FindCustomizeMode() )
			_SetCapture();
		return true;
	}
	return false;
}

bool CExtPopupMenuWnd::_PtInWndArea( CPoint ptClient )
{
	if( GetSafeHwnd() == NULL )
		return false;

	ClientToScreen( &ptClient );
HWND hWndFromPoint = ::WindowFromPoint(ptClient);
	if( hWndFromPoint == NULL )
		return false;
	if( hWndFromPoint == m_hWnd )
		return true;
	return false;
}

bool CExtPopupMenuWnd::_OnMouseClick(
	UINT nFlags,
	CPoint point,
	bool & bNoEat
	)
{
	ASSERT_VALID( this );

	if( GetSafeHwnd() == NULL )
		return false;

	if( !m_bAnimFinished )
		return true;

CExtPopupMenuSite & _site = GetSite();
	if(	_site.IsShutdownMode()
		|| _site.IsEmpty()
		|| _site.GetAnimated() != NULL
		)
		return true;

CPoint ptScreenClick( point );
	ClientToScreen( &ptScreenClick );
HWND hWndFromPoint = ::WindowFromPoint( ptScreenClick );
	if(		hWndFromPoint != NULL
		&&	(::GetWindowLong(hWndFromPoint,GWL_STYLE)&WS_CHILD) != 0
		&&	::GetParent(hWndFromPoint) == m_hWnd
		)
	{
		CWnd * pWnd = CWnd::FromHandlePermanent( hWndFromPoint );
		if( pWnd != NULL )
		{
			int nCount = ItemGetCount();
			for( int i = 0; i < nCount; i++ )
			{
				MENUITEMDATA & mi = _GetItemRef( i );
				if( !mi.IsInplaceEdit() )
					continue;
				if( ((LPVOID)mi.GetInplaceEditPtr()) != ((LPVOID)pWnd) )
					continue;
				if( m_nCurIndex == i )
					break;
				_ItemFocusSet( i, FALSE, TRUE, TRUE );
				break;
			} // for( int i = 0; i < nCount; i++ )
		} // if( pWnd != NULL )
		bNoEat = true;
		return false;
	}

bool bLButtonUpCall =
		(nFlags==WM_LBUTTONUP || nFlags==WM_NCLBUTTONUP)
			? true : false;
/*
CRect rectWindow;
	GetWindowRect( &rectWindow );
	ScreenToClient( &rectWindow );
	if( !rectWindow.PtInRect(point) )
*/
	if( bLButtonUpCall && (!_PtInWndArea(point)) )
	{

		if( m_wndToolTip.GetSafeHwnd() != NULL )
		{
			CPoint ptScreen( point );
			ClientToScreen( &ptScreen );
			if( m_wndToolTip.GetSafeHwnd() == ::WindowFromPoint(ptScreen) )
				return true; // eat!
		}

		if( m_pWndParentMenu != NULL
			&& m_pWndParentMenu->GetSafeHwnd() != NULL
			)
		{
			ASSERT_VALID( m_pWndParentMenu );
			ClientToScreen( &point );
			m_pWndParentMenu->ScreenToClient( &point );

			HWND hWndOwn = GetSafeHwnd();
			ASSERT( hWndOwn != NULL );
			ASSERT( ::IsWindow(hWndOwn) );
			CExtPopupMenuWnd * pWndParentMenu = m_pWndParentMenu;
			if(	pWndParentMenu->_OnMouseClick(
					nFlags,
					point,
					bNoEat
					)
				)
			{
				if( bNoEat )
					return false;
				if( ::IsWindow(hWndOwn) )
					_OnCancelMode();
				return true;
			}
			return false;
		}

		// fixed in v. 2.20
		if( nFlags == WM_RBUTTONUP
			|| nFlags == WM_LBUTTONUP
			)
		{
			return true;
		}

		_OnCancelMode();
		return false;
	} // if( bLButtonUpCall && (!_PtInWndArea(point)) )

bool bInplaceControlArea = false, bInplaceDropDownArea = false;
int nHitTest =
		_HitTest(
			point,
			&bInplaceControlArea,
			&bInplaceDropDownArea
			);
	if( bLButtonUpCall )
	{
		if( _StartScrolling(nHitTest) )
			return true;
	}

	if( nHitTest < 0 )
	{
		if( bLButtonUpCall )
		{
			if( (nHitTest == IDX_SCROLL_TOP
					|| nHitTest == IDX_SCROLL_BOTTOM)
				//&& m_nCurIndex != nHitTest
				)
			{
				return true;
			}

			if( nHitTest == IDX_EXPAND )
			{
				if(	(!m_bExpandWasPressed)
					&& m_bExpandAvailable
					)
					_DoExpand();
				return true;
			}

			// fixed in v. 2.20
			if(		nFlags != WM_RBUTTONUP
				&&	nFlags != WM_LBUTTONUP
				)
			{
				_OnCancelMode();
				return true;
			}
		} // if( bLButtonUpCall )


		if(		m_eCombineAlign != __CMBA_NONE
			&&	m_bTopLevel
			&&	(!bLButtonUpCall)
			)
		{
			CRect rcExcludeAreaTest( m_rcExcludeArea );
			ScreenToClient( &rcExcludeAreaTest );
			if( rcExcludeAreaTest.PtInRect( point ) )
			{
				_OnCancelMode();
				return true;
			} // if( rcExcludeAreaTest.PtInRect( point ) )
		} // if( m_eCombineAlign != __CMBA_NONE ...

		return false;
	}
	ASSERT( nHitTest < m_items_all.GetSize() );

	if( !bLButtonUpCall )
		return true;

MENUITEMDATA & mi = _GetItemRef(nHitTest);
	if( (!mi.IsEnabled()) || mi.IsSeparator() )
		//return false;
		return true;
	if(		mi.IsInplaceEdit()
		&&	mi.IsPopup()
		&&	(! mi.IsAllowInplaceEditActivation() )
		)
	{
		bInplaceControlArea = false;
		bInplaceDropDownArea = true;
	}

	if(		mi.IsInplaceEdit()
		&&	(!mi.IsPopup())
		&&	(! bInplaceDropDownArea )
		&&	(! _FindHelpMode() )
		)
	{
		_SetCapture();
		_ItemFocusSet( nHitTest, FALSE, TRUE );
		CWnd * pWndInplace = mi.GetInplaceEditPtr();
		if( pWndInplace != NULL )
		{
			ASSERT_VALID( pWndInplace );
			ASSERT( pWndInplace->GetSafeHwnd() != NULL && (::IsWindow(pWndInplace->GetSafeHwnd())) );
			if( mi.IsAllowInplaceEditActivation() )
			{
				if( (pWndInplace->GetStyle() & WS_VISIBLE) == 0 )
				{
					CRect rcInplaceEdit;
					_GetItemRect( nHitTest, rcInplaceEdit );
					rcInplaceEdit = mi.AdjustInplaceEditRect( rcInplaceEdit );
					pWndInplace->SetWindowPos(
						NULL,
						rcInplaceEdit.left, rcInplaceEdit.top,
						rcInplaceEdit.Width(), rcInplaceEdit.Height(),
						SWP_NOZORDER|SWP_NOOWNERZORDER
							|SWP_NOACTIVATE|SWP_SHOWWINDOW
						);
				} // if( (pWndInplace->GetStyle() & WS_VISIBLE) == 0 )
				pWndInplace->SetFocus();
			} // if( mi.IsAllowInplaceEditActivation() )
		} // if( pWndInplace != NULL )
		return true;
	} // if( mi.IsInplaceEdit() ...
	if( mi.IsPopup() )
	{
		if( mi.GetPopup()->GetSafeHwnd() != NULL )
			return false;
#if (!defined __EXT_MFC_NO_CUSTOMIZE)
		if( mi.IsInplaceEdit() && _FindHelpMode() )
		{
			CExtCustomizeCmdTreeNode * pNode = mi.GetCmdNode();
			if( pNode != NULL )
				_EndSequence(
					pNode->GetCmdID( false ),
					mi.GetCmdReciever()
					);
		} // if( mi.IsInplaceEdit() && _FindHelpMode() )
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)

		if( mi.IsInplaceEdit() && bInplaceDropDownArea )
			_ItemFocusCancel( FALSE );
		if( m_nDelayedFocusItemIndex < 0 ) // fix 2.23 condition for care about current animation status
			_ItemFocusSet(
				nHitTest,
				TRUE,
				TRUE
				);
		return true;
	} // if( mi.IsPopup() )

	if( mi.IsExtraMark() )
	{
		ASSERT( mi.GetExtraMarkCallback() != NULL );
		mi.GetExtraMarkCallback()( this, &mi );
		CClientDC dc( this );
		_DoPaint( dc );
	} // if( mi.IsExtraMark() )
	else if( mi.IsExecutableCmdID() )
	{
		if(	!(		mi.GetCmdDeliverCb() != NULL
				&&	mi.GetCmdDeliverCb()( this, &mi )
				)
			)
			_EndSequence( mi.GetCmdID(), mi.GetCmdReciever() );
	} // else if( mi.IsExecutableCmdID() )
	else
		_OnCancelMode();
//	return false;
	return true;
}

void CExtPopupMenuWnd::_EndSequence(
	UINT nCmdID, // = 0
	HWND hWndDeliver // = NULL
	)
{
	ASSERT_VALID( this );

#ifdef _DEBUG
	if( hWndDeliver != NULL )
	{
		ASSERT( ::IsWindow(hWndDeliver) );
	}
#endif // _DEBUG
	ASSERT( m_hWndCmdReciever != NULL );
	ASSERT( ::IsWindow(m_hWndCmdReciever) );

CExtPopupMenuSite & _site = GetSite();
UINT * lpnResultCmdID = _site.GetTargetCmdIdPtr();
	if( lpnResultCmdID != NULL )

		*lpnResultCmdID = nCmdID;
CExtCmdItem * pCmdItem = NULL;
	if( nCmdID > 0 && ((m_dwTrackFlags&TPMX_NO_WM_COMMAND)==0) )
	{
		pCmdItem =
			g_CmdManager->CmdGetPtr(
				g_CmdManager->ProfileNameFromWnd( m_hWndCmdReciever ),
				nCmdID
				);
		ASSERT( pCmdItem != NULL );
	} // if( nCmdID > 0 && ((m_dwTrackFlags&TPMX_NO_WM_COMMAND)==0) )

CExtPopupMenuWnd * pTopPopup = _site.GetInstance();
	ASSERT_VALID( pTopPopup );
HWND hWndTopPopup = pTopPopup->GetSafeHwnd();
	ASSERT(
		hWndTopPopup != NULL
		&& ::IsWindow( hWndTopPopup )
		);

	if( hWndDeliver == NULL )
		hWndDeliver = m_hWndCmdReciever;

CWnd * pTopLevelParent = GetTopLevelParent();
HWND hWndTopLevelParent = pTopLevelParent->GetSafeHwnd();

CRect rcBkUpdate( 0, 0, 0, 0 );
	// hide all sequence
	CExtPopupMenuWnd * pPopup = this;
	for( ; pPopup != NULL; pPopup = pPopup->m_pWndParentMenu )
	{
		ASSERT_VALID( pPopup );
		ASSERT( pPopup->GetSafeHwnd() != NULL );
		ASSERT( ::IsWindow( pPopup->GetSafeHwnd() ) );
		CRect rcPopup;
		pPopup->GetWindowRect( &rcPopup );
		if( rcBkUpdate.IsRectEmpty() )
			rcBkUpdate = rcPopup;
		else
		{
			CRect rcPrev( rcBkUpdate );
			rcBkUpdate.UnionRect( &rcPrev, &rcPopup );
		}
		if(	pPopup->m_wndToolTip.GetSafeHwnd() != NULL
			&& ::IsWindow( pPopup->m_wndToolTip.GetSafeHwnd() )
			&& pPopup->m_wndToolTip.IsWindowVisible()
			)
		{
			CRect rcToolTip;
			pPopup->m_wndToolTip.GetWindowRect( &rcToolTip );
			CRect rcPrev( rcBkUpdate );
			rcBkUpdate.UnionRect( &rcPrev, &rcToolTip );
		}
		pPopup->ShowWindow( SW_HIDE );
	} // for( ; pPopup != NULL; pPopup = pPopup->m_pWndParentMenu )

	// allow bottom windows repaint
	if(	!rcBkUpdate.IsRectEmpty()
		&&	hWndTopLevelParent != NULL
		&& ::IsWindow(hWndTopLevelParent)
		)
	{
		::ScreenToClient(
			hWndTopLevelParent, (LPPOINT)&rcBkUpdate);
		::ScreenToClient(
			hWndTopLevelParent, ((LPPOINT)&rcBkUpdate)+1
			);

#if (WINVER >= 0x0500)
		ASSERT( WS_EX_LAYOUTRTL == 0x00400000L );
#endif
		if(		(	(DWORD)
					::GetWindowLong(
						hWndTopLevelParent,
						GWL_EXSTYLE
						)
				) & 0x00400000L // WS_EX_LAYOUTRTL under Win 5x
			)
		{
			//CRect::SwapLeftRight( &rcBkUpdate );
			LONG temp = rcBkUpdate.left;
			rcBkUpdate.left = rcBkUpdate.right;
			rcBkUpdate.right = temp;
		}
		
		::RedrawWindow(
			hWndTopLevelParent,
			&rcBkUpdate,
			NULL,
			RDW_INVALIDATE|RDW_ERASE
				|RDW_UPDATENOW|RDW_ERASENOW
				|RDW_VALIDATE
				|RDW_FRAME|RDW_ALLCHILDREN
			);
	}

	// top popup (and all children) finally must be closed
	if( ::IsWindow( hWndTopPopup ) )
		::PostMessage( hWndTopPopup, WM_CLOSE, 0, 0 );

	if( CExtToolControlBar::g_bMenuTracking )
		CExtToolControlBar::_CloseTrackingMenus();
//CExtToolControlBar * pToolBar = CExtToolControlBar::_GetMenuTrackingBar();
//	if( pToolBar != NULL )
//		pToolBar->PostMessage( WM_CANCELMODE );

	if(		pCmdItem != NULL
		&&	::IsWindow(hWndDeliver)
		&&	(! _FindCustomizeMode() )
		)
	{
		// if command target still exists -> deliver command to it
		VERIFY( pCmdItem->Deliver(hWndDeliver) );
		g_SoundPlayer->PlaySound(
			CExtSoundPlayer::__ON_MENU_CMD_CLICKED
			);
	} // if( pCmdItem != NULL && ...
}

void CExtPopupMenuWnd::OnMouseMove(UINT nFlags, CPoint point) 
{
	nFlags;
	point;
#if (!defined __EXT_MFC_NO_CUSTOMIZE)
	if( (!_FindCustomizeMode()) )
		return;
int nIndex = _HitTest( point );
	if( nIndex >= 0 )
		return;
	if(		nIndex == IDX_SCROLL_TOP
		||	nIndex == IDX_SCROLL_BOTTOM
		)
		_StartScrolling( nIndex );
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)
}

void CExtPopupMenuWnd::OnLButtonDown(UINT nFlags, CPoint point)
{
	nFlags;
	point;
#if (!defined __EXT_MFC_NO_CUSTOMIZE)
	if( (!_FindCustomizeMode()) )
		return;
int nIndex = _HitTest( point );
	if( nIndex < 0 )
		return;
	ASSERT( nIndex < ItemGetCount() );
MENUITEMDATA & mi = _GetItemRef( nIndex );
	if( mi.IsSeparator() )
		return;
CExtCustomizeSite * pSite = _FindCustomizeSite();
	ASSERT( pSite != NULL );
CExtCustomizeCmdTreeNode * pClickedCmdNode = mi.GetCmdNode();
	ASSERT_VALID( pClickedCmdNode );
#if (!defined __EXT_MFC_NO_BUILTIN_TEXTFIELD)
	if(		mi.IsSelected()
		&&	(pClickedCmdNode->GetFlags() & __ECTN_TBB_RESIZABLE) != 0
		)
	{ // if button can be resized
		int nDdWidth = g_PaintManager->GetDropDividerMerics().cx / 2;
		if( nDdWidth < 2 )
			nDdWidth = 2;
		CRect rcItem( 0, 0, 0, 0 );
		_GetItemRect( nIndex, rcItem );
		CRect rcH( rcItem );
		rcH.right = rcH.left + nDdWidth;
		int nInitialResizingStateH = 0;
		if( rcH.PtInRect(point) )
			nInitialResizingStateH = -1;
		else
		{
			rcH = rcItem;
			rcH.left = rcH.right - nDdWidth;
			if( rcH.PtInRect(point) )
				nInitialResizingStateH = 1;
		} // else from if( rcH.PtInRect(point) )
		if( nInitialResizingStateH != 0 )
		{
			int nWidthMin = 0, nWidthMax = 0;
			pSite->OnGetCmdItemMinMaxSizeH(
				NULL,
				pClickedCmdNode,
				&nWidthMin,
				&nWidthMax
				);
			CRect rcInplaceEdit = mi.AdjustInplaceEditRect( rcItem );
			rcInplaceEdit.top = rcItem.top;
			rcInplaceEdit.bottom = rcItem.bottom;
			int nDdExtent = 0;
			if( mi.IsPopup() )
			{
				nDdExtent = ::GetSystemMetrics(SM_CXHTHUMB);
				rcInplaceEdit.right += nDdExtent;
			}
			if( !pSite->OnCmdNodeResizeH(
					nInitialResizingStateH,
					m_hWnd,
					NULL,
					pClickedCmdNode,
					nWidthMin,
					nWidthMax,
					rcInplaceEdit // rcItem
					)
				)
				return; // resizing is canceled
//			if( nDdExtent != 0 )
//				pClickedCmdNode->TextFieldWidthSet(
//					pClickedCmdNode->TextFieldWidthGet() - nDdExtent
//					);
			int nSavedIndex = m_nCurIndex;
			m_nCurIndex = -1;
			_BuildItems( NULL, m_bTopLevel );
			VERIFY( UpdateFromCmdTree( m_hWndCmdReciever, m_pNode, m_bTopLevel ) );
			_SyncItems();
			ShowWindow( SW_HIDE	);
			_RecalcLayoutImpl();
			VERIFY(
				SetWindowRgn(
					NULL,
					FALSE
					)
				);
			ASSERT( !IsWindowVisible() );
			_FreeWinObjects();
			// adjust screen position
			CRect rcWnd = _CalcTrackRect();
			if( m_rgnWnd.GetSafeHandle() != NULL )
			{
				ASSERT( m_bExcludeAreaSpec );
				ASSERT( m_bCombineWithEA );
				ASSERT( m_eCombineAlign != __CMBA_NONE );
				CRgn rgnTmp;
				VERIFY( rgnTmp.CreateRectRgn(0,0,0,0) );
				rgnTmp.CopyRgn( &m_rgnWnd );
				ASSERT( rgnTmp.GetSafeHandle() != NULL );
				VERIFY(
					SetWindowRgn(
						(HRGN)rgnTmp.Detach(),
						FALSE
						)
					);
			} // if( m_rgnWnd.GetSafeHandle() != NULL )
			SetWindowPos(
				NULL,
				rcWnd.left, rcWnd.top, rcWnd.Width(), rcWnd.Height(),
				SWP_NOACTIVATE
					|SWP_NOZORDER //|SWP_NOOWNERZORDER
				);
			if( m_bScrollingAvailable )
				_RecalcLayoutImpl();
			ShowWindow( SW_SHOWNA );
			UpdateWindow();
			_ItemFocusSet( nSavedIndex, FALSE, FALSE, FALSE );
			ASSERT( m_pDragSrcNode == NULL );
			m_pDragSrcNode = pClickedCmdNode;
			CClientDC dc( this );
			_DoPaint( dc );
			m_pDragSrcNode = NULL;
			return;
		} // if( nInitialResizingStateH != 0 )
	} // if button can be resized
#endif // (!defined __EXT_MFC_NO_BUILTIN_TEXTFIELD)
	ASSERT( m_pDragSrcNode == NULL );
	ASSERT( m_nDragSrcIdx < 0 );
	m_pDragSrcNode = pClickedCmdNode;
	m_nDragSrcIdx = nIndex;
	m_bHelperNoRemoveSrc = false;
CRect rcItem( 0, 0, 1, 1 );
	_DoResetChainPositions();
	m_ptHelperDragStart = point;
	m_bHelperNoHideChild = true;
	m_bHelperDragOverPassed = false;
	_ItemFocusSet( nIndex, TRUE, TRUE, FALSE );
HWND hWndOwn = m_hWnd;
ASSERT( hWndOwn != NULL && ::IsWindow(hWndOwn) );
	pSite->DoDragCmdNode(
		this,
		NULL,
		m_pDragSrcNode,
		rcItem
		);
	if( ! ::IsWindow(hWndOwn) )
		return;
	m_pDragSrcNode = NULL;
	m_bHelperNoHideChild = false;
	m_nDragSrcIdx = -1;
	m_bHelperNoRemoveSrc = false;
	m_bHelperDragOverPassed = false;
#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)
}

void CExtPopupMenuWnd::OnRButtonDown(UINT nFlags, CPoint point) 
{
	nFlags;
	point;
#if (!defined __EXT_MFC_NO_CUSTOMIZE)
	if( (!_FindCustomizeMode()) )
		return;
int nIndex = _HitTest( point );
	if( nIndex < 0 )
		return;
	ASSERT( nIndex < ItemGetCount() );
MENUITEMDATA & mi = _GetItemRef( nIndex );
	if( mi.IsSeparator() )
		return;
	_ItemFocusSet( mi.GetIndex(), TRUE, TRUE, FALSE );
CExtCustomizeCmdTreeNode * pNode = mi.GetCmdNode();
	ASSERT_VALID( pNode );
CExtCustomizeSite * pSite = _FindCustomizeSite();
	ASSERT( pSite != NULL );
CRect rcItem( 0, 0, 1, 1 );
	_DoResetChainPositions();

CExtCmdItem * pCmdItem =
	g_CmdManager->CmdGetPtr(
		g_CmdManager->ProfileNameFromWnd(m_hWnd),
		pNode->GetCmdID( false )
		);
	ASSERT( pCmdItem != NULL );
	if( !pSite->CustomizedNodeSet( pNode ) )
		return;
	{ // BLOCK
		CClientDC dc( this );
		_DoPaint( dc );
	} // BLOCK
bool bCanAddRemoveSeparator = (nIndex > 0) ? true : false;
bool bDelete = false;
HWND hWndOwn = m_hWnd;
	ASSERT( hWndOwn != NULL && ::IsWindow(hWndOwn) );
	if( !pSite->OnCustomizeTreeNode(
			NULL,
			pNode,
			pCmdItem,
			bDelete,
			bCanAddRemoveSeparator,
			this
			)
		)
	{
		if( pSite->CustomizedNodeGet() == pNode )
		{
			VERIFY( pSite->CustomizedNodeSet( NULL ) );
		}
		if(		hWndOwn == NULL
			||	(! ::IsWindow(hWndOwn) )
			)
			return;
		CClientDC dc( this );
		_DoPaint( dc );
		return;
	}
	VERIFY( pSite->CustomizedNodeSet( NULL ) );

	if( !::IsWindow(hWndOwn) )
		return;
	
	m_nCurIndex = -1;
	_BuildItems( NULL, m_bTopLevel );
	if( bDelete )
	{
		ASSERT_VALID( pNode->GetParentNode() );
		int nOwnNodeIndex = pNode->GetOwnIndex();
		if( nOwnNodeIndex < (pNode->GetParentNode()->GetNodeCount()-1) )
			pNode->GetParentNode()->ElementAt(nOwnNodeIndex+1)
				->ModifyFlags( 0, __ECTN_GROUP_START );
		pNode->RemoveSelf( pCmdItem );
	}
	ASSERT_VALID( m_pNode );
	VERIFY( UpdateFromCmdTree( m_hWndCmdReciever, m_pNode, m_bTopLevel ) );
	
	_SyncItems();
	ShowWindow( SW_HIDE	);
	_RecalcLayoutImpl();
	VERIFY(
		SetWindowRgn(
			NULL,
			FALSE
			)
		);
	ASSERT( !IsWindowVisible() );
	_FreeWinObjects();
// adjust screen position
CRect rcWnd = _CalcTrackRect();
	if( m_rgnWnd.GetSafeHandle() != NULL )
	{
		ASSERT( m_bExcludeAreaSpec );
		ASSERT( m_bCombineWithEA );
		ASSERT( m_eCombineAlign != __CMBA_NONE );
		CRgn rgnTmp;
		VERIFY( rgnTmp.CreateRectRgn(0,0,0,0) );
		rgnTmp.CopyRgn( &m_rgnWnd );
		ASSERT( rgnTmp.GetSafeHandle() != NULL );
		VERIFY(
			SetWindowRgn(
				(HRGN)rgnTmp.Detach(),
				FALSE
				)
			);
	} // if( m_rgnWnd.GetSafeHandle() != NULL )
	SetWindowPos(
		NULL,
		rcWnd.left, rcWnd.top, rcWnd.Width(), rcWnd.Height(),
		SWP_NOACTIVATE
			|SWP_NOZORDER //|SWP_NOOWNERZORDER
		);
	if( m_bScrollingAvailable )
		_RecalcLayoutImpl();
	ShowWindow( SW_SHOWNA );

#endif // (!defined __EXT_MFC_NO_CUSTOMIZE)
}

void CExtPopupMenuWnd::OnShowWindow(BOOL bShow, UINT nStatus) 
{
	CExtPopupBaseWnd::OnShowWindow(bShow, nStatus);
	ASSERT_VALID( this );
	if(		_FindCustomizeMode()
		&&	bShow
		)
	{
		CClientDC dc( this );
		_DoPaint( dc );
	}
}

void CExtPopupMenuWnd::OnCancelMode() 
{
	ASSERT_VALID( this );

	if( _FindCustomizeMode() )
		return;

	//_OnCancelMode();
CExtPopupMenuSite & _site = GetSite();
	_site.DoneInstance();
	ASSERT( _site.IsEmpty() );
	ASSERT( !_site.IsShutdownMode() );

	if( CExtToolControlBar::g_bMenuTracking )
		CExtToolControlBar::_CloseTrackingMenus();
}

void CExtPopupMenuWnd::_FreeWinObjects()
{
	ASSERT_VALID( this );

	if( m_rgnWnd.GetSafeHandle() != NULL )
	{
		VERIFY(
			m_rgnWnd.DeleteObject()
			);
	}
	m_ShadowMain.Destroy();
	m_ShadowCMBA.Destroy();
	_SurfacesDelete();
	if( !(::IsWindow(GetSafeHwnd())) )
		return;
	KillTimer(ID_TIMER_ANIMATION);
	//KillTimer(ID_TIMER_DELAY_SHOW);
	//KillTimer(ID_TIMER_ITEM_FOCUS_DELAY);
	//KillTimer(ID_TIMER_SCROLLING);
}

void CExtPopupMenuWnd::_OnCancelMode(
	bool bNcDestroy // = false
	) 
{
	ASSERT_VALID( this );

	// update status bar message
	CExtControlBar::stat_SetMessageString(
		GetSafeOwner()
		);

bool bCusomizeMode = _FindCustomizeMode();
	if( !bCusomizeMode )
	{
		_CoolTipHide( false );
		_FreeWinObjects();
		_ReleaseCapture();
	} // if( !bCusomizeMode )

INT iter = 0;
	for( ; iter < m_items_all.GetSize(); iter++ )
	{
		MENUITEMDATA & mi = m_items_all[ iter ];
		mi.SetSelected( false );

		if( mi.IsPopup() )
		{
			if( mi.GetPopup()->GetSafeHwnd() != NULL )
				mi.GetPopup()->_OnCancelMode();
		}
	}
	m_nCurIndex = IDX_NOTHING;

	if( bNcDestroy )
		return;

	if( ! ::IsWindow(GetSafeHwnd()) )
		return;
bool bTopLevel = m_bTopLevel;
	ShowWindow( SW_HIDE );
	if( !bCusomizeMode )
		PostMessage( WM_CLOSE );

	if(		CExtToolControlBar::g_bMenuTracking && bTopLevel
		&&	(!bCusomizeMode)
		)
	{
		CExtToolControlBar::_CloseTrackingMenus();
//		CExtToolControlBar * pToolBar = CExtToolControlBar::_GetMenuTrackingBar();
//		if( pToolBar != NULL )
//			pToolBar->SendMessage( WM_CANCELMODE );
	}
}

void CExtPopupMenuWnd::_ItemFocusSet(
	int nCurIndex,
	BOOL bEnableDropChild,
	BOOL bRepaint,
	BOOL bSelectAnyInChild // = TRUE
	)
{
	ASSERT_VALID( this );

	if( m_nCurIndex != nCurIndex )
	{
		_ItemFocusCancel( FALSE );
		ASSERT( m_nCurIndex < 0 );
		m_nCurIndex = nCurIndex;
		if( m_nCurIndex < 0 )
			return;
	}

bool bResetMessageString = true;
bool bWasSet = false;
MENUITEMDATA & mi = _GetItemRef(m_nCurIndex);
	if( mi.IsEnabled() && mi.IsDisplayed() )
	{
		mi.SetSelected( true );
		bWasSet = true;

		// adjust scrolling
		int nMenuBorderSize =
			g_PaintManager->GetMenuBorderSize();
		if( m_bScrollingAvailable )
		{
			int nMetric;
			int nMaxScrollPos = _GetMaxScrollPos();
			CRect rcItem,rcClient,
				rcScrollBtnUp,rcScrollBtnDown;
			_GetItemRect( IDX_SCROLL_TOP, rcScrollBtnUp );
			_GetItemRect( IDX_SCROLL_BOTTOM, rcScrollBtnDown );
			_GetClientRect( rcClient );
			_GetItemRect( m_nCurIndex, rcItem );

			nMetric = rcClient.bottom;
			if( m_nDyScrollOffset != nMaxScrollPos )
			{
				nMetric -= rcScrollBtnDown.Height();
				if( m_bExpandAvailable )
				{
					CRect rcExpand;
					_GetItemRect( IDX_EXPAND, rcExpand );
					nMetric -= rcExpand.Height();
				}
			}
			if( rcItem.bottom >= nMetric )
			{
				m_nDyScrollOffset -=
					rcItem.bottom - nMetric
					+ nMenuBorderSize*2;
			}

			nMetric = rcClient.top;
			if( m_nDyScrollOffset != 0 )
			{
				nMetric += rcScrollBtnUp.Height();
			}
			if( rcItem.top <= nMetric )
			{
				m_nDyScrollOffset +=
					nMetric - rcItem.top
					+ nMenuBorderSize*2;
			}

			if( m_nDyScrollOffset > 0 )
				m_nDyScrollOffset = 0;
			else
			{
				if( m_nDyScrollOffset < nMaxScrollPos )
					m_nDyScrollOffset = nMaxScrollPos;
			}
		} // if( m_bScrollingAvailable )

	}

	// update status bar message
CWnd * pWndOwner = GetOwner();
	if( pWndOwner != NULL )
	{
		ASSERT_VALID( pWndOwner );
		if( bWasSet && (!mi.IsPopup()) && (!mi.IsSeparator()) )
		{
			UINT nCmdID = mi.GetCmdID();
			if( CExtCmdManager::IsCommand( nCmdID ) )
			{
				UINT nCmdIDToSend = nCmdID;
				bool bAbandonSend = false;
				if( CExtCmdManager::IsSystemCommand( nCmdID ) )
				{
					switch( nCmdID )
					{
					case SC_CLOSE:
						nCmdIDToSend = AFX_IDS_SCCLOSE;
					break;
					case SC_SIZE:
						nCmdIDToSend = AFX_IDS_SCSIZE;
					break;
					case SC_MOVE:
						nCmdIDToSend = AFX_IDS_SCMOVE;
					break;
					case SC_MINIMIZE:
						nCmdIDToSend = AFX_IDS_SCMINIMIZE;
					break;
					case SC_MAXIMIZE:
						nCmdIDToSend = AFX_IDS_SCMAXIMIZE;
					break;
					case SC_RESTORE:
						nCmdIDToSend = AFX_IDS_SCRESTORE;
					break;
					case SC_NEXTWINDOW:
						nCmdIDToSend = AFX_IDS_SCNEXTWINDOW;
					break;
					case SC_PREVWINDOW:
						nCmdIDToSend = AFX_IDS_SCPREVWINDOW;
					break;
					case SC_TASKLIST:
						nCmdIDToSend = AFX_IDS_SCTASKLIST;
					break;
					default:
						bAbandonSend = true;
					break;
					} // switch( nCmdID )
				} // if( CExtCmdManager::IsSystemCommand( nCmdID ) )
				if( !bAbandonSend )
				{
					CExtControlBar::stat_SetMessageString(
						pWndOwner,
						nCmdIDToSend
						);
					bResetMessageString = false;
				} // if( !bAbandonSend )
			} // if( CExtCmdManager::IsCommand( nCmdID ) )
		} // if( ! ( mi.IsPopup() || mi.IsSeparator() ) )
		if( bResetMessageString )
			CExtControlBar::stat_SetMessageString( pWndOwner );
	} // if( bWasSet )
	

	if( bRepaint && ::IsWindowVisible(GetSafeHwnd()) )
	{
//		if( m_rgnWnd.GetSafeHandle() != NULL )
//			RedrawWindow(
//				NULL,
//				&m_rgnWnd,
//				RDW_INVALIDATE|RDW_UPDATENOW|RDW_NOERASE
//					|RDW_INTERNALPAINT
//				);
//		else
//		{
			CClientDC dc( this );
			_DoPaint( dc );
//		}
	}
	
	if( mi.IsPopup() )
	{
		if( mi.IsInplaceEdit() )
		{
			HWND hWndInplaceEdit = mi.GetInplaceEditPtr()->GetSafeHwnd();
			if(		hWndInplaceEdit != NULL
				&&	::IsWindow( hWndInplaceEdit )
				&&	(::GetWindowLong(hWndInplaceEdit,GWL_STYLE)&WS_VISIBLE) != 0
				)
				bEnableDropChild = false;
		} // if( mi.IsInplaceEdit() )
	} // if( mi.IsPopup() )
	else
		bEnableDropChild = false;
	if(		bWasSet
		&&	bEnableDropChild
		&&	mi.GetPopup()->_CanStartLevelTracking()
		)
	{ // if new popup tracking
		if( !_FindCustomizeMode() )
			_ReleaseCapture();
		CRect rectItem;
		_GetItemRect(
			m_nCurIndex,
			rectItem
			);
		rectItem.left -= m_nLeftAreaWidth;
		CPoint point;
		point.x = rectItem.right;
		point.y = rectItem.top,
		ClientToScreen(&point);
		ClientToScreen( &rectItem );
		ASSERT( mi.GetPopup()->m_pWndParentMenu == this );
		bool bDisplayedSuccessfully = false;
		if( mi.GetPopup()->GetSafeHwnd() == NULL )
		{
			bDisplayedSuccessfully = 
				mi.GetPopup()->
					_TrackPopupMenu(
						( mi.IsChildCombine() ? TPMX_COMBINE_DEFAULT : 0 )
						| ( m_dwTrackFlags &
								(TPMX_NO_SHADOWS
								|TPMX_NO_CMD_UI
								|TPMX_NO_WM_COMMAND
								)
							)
						,
					point.x,point.y,
					&rectItem,
					(LPVOID)m_nCurIndex,
					stat_paint_combined_menu_toolbtn
					) ? true : false;
		} // if( mi.GetPopup()->GetSafeHwnd() == NULL )
		else
		{
			bDisplayedSuccessfully = true;
			if( !mi.GetPopup()->IsWindowVisible() )
			{
				mi.GetPopup()->SetWindowPos(
					&CWnd::wndTopMost, 0, 0, 0, 0,
					SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE
						|SWP_NOREDRAW
						|SWP_SHOWWINDOW
					);
				CClientDC dc( mi.GetPopup() );
				mi.GetPopup()->_DoPaint( dc );
			} // if( !mi.GetPopup()->IsWindowVisible() )
		} // else from
		if( bDisplayedSuccessfully && bSelectAnyInChild )
		{ // if track-popup succeeded and we need to select any child item
			int nCountOfPopupItems =
				mi.GetPopup()->m_items_all.GetSize();
			if( nCountOfPopupItems > 0 )
			{
				int nIndex = mi.GetPopup()->_GetNextItem(__NI_ANY);
				if( nIndex >= 0 )
					mi.GetPopup()->_ItemFocusSet(
						nIndex,
						FALSE,
						( GetSite().GetAnimated() == NULL ) ?
							TRUE : FALSE
						);
			}
		} // if track-popup succeeded and we need to select any child item
		if( bDisplayedSuccessfully && mi.IsInplaceEdit() )
		{
			CClientDC dc( this );
			_DoPaint( dc );
		}
	} // if new popup tracking
}

bool CExtPopupMenuWnd::_CoolTipIsVisible()
{
	ASSERT_VALID( this );

	if( _FindCustomizeMode() )
		return false;
	if( !(::IsWindow(GetSafeHwnd())) )
		return false;
	if( CExtPopupMenuSite::g_DefPopupMenuSite.GetCapture() != this )
		return false;
HWND hWndToolTip =
		m_wndToolTip.GetSafeHwnd();
	if(	hWndToolTip != NULL
		&&
		::IsWindow( hWndToolTip )
		&&
		::IsWindowVisible( hWndToolTip )
		)
		return true;
	return false;
}

void CExtPopupMenuWnd::_CoolTipHide(
	bool bAdvOperation // = true
	)
{
	ASSERT_VALID( this );

	if( !(::IsWindow(GetSafeHwnd())) )
		return;

HWND hWndToolTip =
		m_wndToolTip.GetSafeHwnd();
	if(	hWndToolTip == NULL
		||
		(!(::IsWindow(hWndToolTip)))
		)
		return;
	
	if( bAdvOperation && ( GetSite().GetAnimated() == NULL ) )
	{
		m_AnimationType = __AT_CONTENT_DISPLAY;
		_StartAnimation();
	}
	m_wndToolTip.Hide();

}

void CExtPopupMenuWnd::_ItemFocusCancel( BOOL bRepaint )
{
	ASSERT_VALID( this );

	if( !_FindCustomizeMode() )
		_CoolTipHide();

	if( m_nCurIndex < 0 )
	{
		m_nCurIndex = IDX_NOTHING;
	} // if( m_nCurIndex < 0 )
	else
	{
		ASSERT( m_nCurIndex < m_items_all.GetSize() );
		MENUITEMDATA & mi = _GetItemRef(m_nCurIndex);
		if( mi.IsInplaceEdit() )
		{
			mi.SetTempSelectedInplaceEditText( NULL );
			CWnd * pWndInplace = mi.GetInplaceEditPtr();
			if( pWndInplace != NULL )
			{
				ASSERT_VALID( pWndInplace );
				ASSERT( pWndInplace->GetSafeHwnd() != NULL && (::IsWindow(pWndInplace->GetSafeHwnd())) );
				if( (pWndInplace->GetStyle() & WS_VISIBLE) != 0 )
					pWndInplace->ShowWindow( SW_HIDE );
			} // if( pWndInplace != NULL )
		}
		mi.SetSelected( false );
		m_nCurIndex = IDX_NOTHING;

		if( mi.IsPopup() )
			mi.GetPopup()->_OnCancelMode();
	} // else from if( m_nCurIndex < 0 )
	
	// update status bar message
CWnd * pWndOwner = GetOwner();
	if( pWndOwner != NULL )
		CExtControlBar::stat_SetMessageString( pWndOwner );

	if( bRepaint && ::IsWindowVisible(GetSafeHwnd()) )
	{
		CClientDC dc( this );
		_DoPaint( dc );
	}
}

bool CExtPopupMenuWnd::_CanStartLevelTracking()
{
	ASSERT_VALID( this );
	return true;
}

bool CExtPopupMenuWnd::_OnMouseWheel(
	WPARAM wParam,
	LPARAM lParam,
	bool & bNoEat
	)
{
	ASSERT_VALID( this );
	wParam;
	lParam;
	bNoEat;
	return true;
}

bool CExtPopupMenuWnd::_OnMouseMove(
	UINT nFlags,
	CPoint point,
	bool & bNoEat
	)
{
	ASSERT_VALID( this );

	if( GetSafeHwnd() == NULL )
		return false;

	if( !m_bAnimFinished )
		return true;

CExtPopupMenuSite & _site = GetSite();
	if(	_site.IsShutdownMode()
		|| _site.IsEmpty()
		|| _site.GetAnimated() != NULL
		)
		return true;

CPoint ptScreenClick( point );
	ClientToScreen( &ptScreenClick );
HWND hWndFromPoint = ::WindowFromPoint( ptScreenClick );
	if(		hWndFromPoint != NULL
		&&	(::GetWindowLong(hWndFromPoint,GWL_STYLE)&WS_CHILD) != 0
		&&	::GetParent(hWndFromPoint) == m_hWnd
		)
	{
		CWnd * pWnd = CWnd::FromHandlePermanent( hWndFromPoint );
		if( pWnd != NULL )
		{
			int nCount = ItemGetCount();
			for( int i = 0; i < nCount; i++ )
			{
				MENUITEMDATA & mi = _GetItemRef( i );
				if( !mi.IsInplaceEdit() )
					continue;
				if( ((LPVOID)mi.GetInplaceEditPtr()) != ((LPVOID)pWnd) )
					continue;
				if( m_nCurIndex == i )
					break;
				_ItemFocusSet( i, FALSE, TRUE, TRUE );
				break;
			} // for( int i = 0; i < nCount; i++ )
		} // if( pWnd != NULL )
		bNoEat = true;
		return false;
	}
HWND hWndFocus = ::GetFocus();
	if(		hWndFocus != NULL
		&&	(::GetWindowLong(hWndFocus,GWL_STYLE)&WS_CHILD) != 0
		&&	::GetParent(hWndFocus) == m_hWnd
		)
		return true;

/*
CRect rectWindow;
	GetWindowRect( &rectWindow );
	ScreenToClient( &rectWindow );
	if( !rectWindow.PtInRect(point) )
*/
	if( !_PtInWndArea(point) )
	{
//		_ItemFocusCancel( TRUE );
		if( m_pWndParentMenu != NULL
			&& m_pWndParentMenu->GetSafeHwnd() != NULL
			)
		{
			ASSERT_VALID( m_pWndParentMenu );
			ClientToScreen( &point );
			m_pWndParentMenu->ScreenToClient( &point );
			if( m_pWndParentMenu->_OnMouseMove(
					nFlags,
					point,
					bNoEat
					)
				)
			{
				if( bNoEat )
					return false;
				_OnCancelMode();
				return true;
			}
		}
		return false;
	}

int nCurIndex = _HitTest(point);
	if( nCurIndex == IDX_EXPAND )
	{
		_ItemFocusCancel( TRUE );
		if( g_bMenuDelayExpanding )
		{
			_SetCapture();
			if( m_nWaitingExpandTickCount == 0 )
			{
				SetTimer(
					ID_TIMER_DELAY_EXPAND,
					ID_TOTAL_DELAY_EXPAND/ID_FREQ_DELAY_EXPAND,
					NULL
					);
				m_nWaitingExpandTickCount = 1;
			}
		} // if( g_bMenuDelayExpanding )
		return true;
	}
	if( _StartScrolling(nCurIndex) )
		return true;

	if( nCurIndex >= 0 )
	{
#ifdef _DEBUG
		int nCountOfItems = m_items_all.GetSize();
		ASSERT( nCurIndex < nCountOfItems );
#endif // _DEBUG
		MENUITEMDATA & mi = _GetItemRef(nCurIndex);
		if( (!mi.IsEnabled()) || mi.IsSeparator() )
			return false;
		int nOldCurIndex = m_nCurIndex; 
		if( nOldCurIndex != nCurIndex )
		{
			_ItemFocusDelay();
			_SetCapture();
			_ItemFocusSet(
				nCurIndex,
				FALSE,
				TRUE
				);
			MENUITEMDATA & mi = _GetItemRef(nCurIndex);
			if( mi.IsPopup() )
			{
				m_wndToolTip.Hide();
				if( mi.GetPopup()->GetSafeHwnd() == NULL )
					_ItemFocusDelay( nCurIndex );
				return true;
			}
			if(	g_bMenuShowCoolTips
				&& nCurIndex != nOldCurIndex
				&& GetSite().GetCapture() == this
				)
			{
				CExtSafeString sTipText = mi.GetTip();
				if( !sTipText.IsEmpty() )
				{
					CRect rcItem;
					_GetItemRect(nCurIndex,rcItem);
					ClientToScreen( &rcItem );
					m_wndToolTip.SetText( sTipText );
					VERIFY(
						m_wndToolTip.Show(
							this,
							rcItem
							)
						);
				} // if( !sTipText.IsEmpty() )
			} // if( g_bMenuShowCoolTips ....
		} // if( nOldCurIndex != nCurIndex )

		return (nOldCurIndex == nCurIndex) ? false : true;
	} // if( nCurIndex >= 0 )

	return false;
}

void CExtPopupMenuWnd::_ItemFocusDelay(
	int nItemIndex // = IDX_NOTHING
	)
{
	ASSERT_VALID( this );

	if( !(::IsWindow(GetSafeHwnd())) )
		return;
	if( m_nDelayedFocusItemIndex != nItemIndex )
	{
		if( m_nDelayedFocusItemIndex >= 0 )
			KillTimer( ID_TIMER_ITEM_FOCUS_DELAY );
		//m_nDelayedFocusItemIndex = IDX_NOTHING;
	}
	if( nItemIndex < 0 )
	{
		m_nDelayedFocusItemIndex = IDX_NOTHING;
		return;
	}
	if( m_nDelayedFocusItemIndex == nItemIndex )
		return;
	ASSERT( nItemIndex>=0 && nItemIndex<m_items_all.GetSize() );
	m_nDelayedFocusItemIndex = nItemIndex;
	ASSERT( _GetItemRef(m_nDelayedFocusItemIndex).IsPopup() );
	SetTimer(
		ID_TIMER_ITEM_FOCUS_DELAY,
		ID_PERIOD_ITEM_FOCUS_DELAY,
		NULL
		);
}

int CExtPopupMenuWnd::_GetMaxScrollPos()
{
	ASSERT_VALID( this );

	ASSERT( m_bScrollingAvailable );
CRect rcClient;
	_GetClientRect( &rcClient );
int nClientHeight =
		rcClient.Height();
int nMenuBorderSize =
		g_PaintManager->GetMenuBorderSize();
int nMenuShadowSize =
		_GetPopupShadowSize();
int nMaxScrollPos = m_sizeFullItems.cy;
	nMaxScrollPos += nMenuBorderSize*2;
	nMaxScrollPos += nMenuShadowSize;
	nMaxScrollPos -= nClientHeight;
	ASSERT( nMaxScrollPos > 0 );
	if( m_bExpandAvailable )
		nMaxScrollPos += _GetSpecBtnHeight(); // xpand btn
	return -nMaxScrollPos;
}

void CExtPopupMenuWnd::OnTimer(UINT nIDEvent) 
{
	ASSERT_VALID( this );

	switch( nIDEvent )
	{
	case ID_TIMER_DELAY_EXPAND:
	{
		if( m_nWaitingExpandTickCount <
				ID_TOTAL_DELAY_EXPAND
			)
		{
			if( m_nWaitingExpandTickCount <= 1 )
				m_nWaitingExpandTickCount = 0;
			m_nWaitingExpandTickCount +=
				ID_FREQ_DELAY_EXPAND;
			return;
		}
		VERIFY( KillTimer(ID_TIMER_DELAY_EXPAND) );
		m_nWaitingExpandTickCount = 0;
		if( m_bExpandAvailable
			&& (!m_bExpandWasPressed)
			&& ( GetSite().GetAnimated() == NULL )
			)
		{ // if expand can be performed
			CPoint point;
			if( ! ::GetCursorPos(&point) )
				return;
			ScreenToClient( &point );
			CRect rcExpand;
			_GetItemRect( IDX_EXPAND, rcExpand );
			if( rcExpand.PtInRect(point) )
				_DoExpand();
		} // if expand can be performed
		return;
	}
	//case ID_TIMER_DELAY_EXPAND

	case ID_TIMER_SCROLLING:
	{
		_ItemFocusDelay();
		if( m_nCurIndex >= 0 )
			_ItemFocusCancel(TRUE);

		CPoint point;
		if( ! ::GetCursorPos(&point) )
			return;
		ScreenToClient( &point );

		m_nScrollingDirection = 0;

		CRect rcItem;
		_GetItemRect(IDX_SCROLL_TOP,rcItem);
		if( rcItem.PtInRect(point) )
			m_nScrollingDirection = __SCROLLING_PIXEL_STEP;
		else
		{
			_GetItemRect(IDX_SCROLL_BOTTOM,rcItem);
			if( rcItem.PtInRect(point) )
				m_nScrollingDirection = (-__SCROLLING_PIXEL_STEP);
		}

		m_nDyScrollOffset += m_nScrollingDirection;

		bool bKillThisTimer =
			(m_nScrollingDirection == 0) ? true : false;
		if( m_nDyScrollOffset > 0 )
		{
			m_nDyScrollOffset = 0;
			bKillThisTimer = true;
		}
		else
		{
			int nMaxScrollPos = _GetMaxScrollPos();
			if( m_nDyScrollOffset < nMaxScrollPos )
			{
				m_nDyScrollOffset = nMaxScrollPos;
				bKillThisTimer = true;
			}
		}

		if( bKillThisTimer )
		{
			VERIFY( KillTimer(ID_TIMER_SCROLLING) );
			m_nScrollingDirection = 0;
		}
		Invalidate( FALSE );
		return;
	}
	// case ID_TIMER_SCROLLING

	case ID_TIMER_ITEM_FOCUS_DELAY:
	{
		if( GetSite().GetAnimated() != NULL )
			return;
		KillTimer( ID_TIMER_ITEM_FOCUS_DELAY );
		if( GetSite().IsShutdownMode() )
			return;
		if( m_nDelayedFocusItemIndex >= 0 )
		{
			ASSERT( m_nDelayedFocusItemIndex>=0 && m_nDelayedFocusItemIndex<m_items_all.GetSize() );
			ASSERT( _GetItemRef(m_nDelayedFocusItemIndex).IsPopup() );
			CRect rcItem;
			_GetItemRect(m_nDelayedFocusItemIndex,rcItem);
			CPoint point;
			if( ! ::GetCursorPos( &point ) )
				return;
			ScreenToClient( &point );
			if( rcItem.PtInRect(point) )
			{
				_ItemFocusSet(
					m_nDelayedFocusItemIndex,
					TRUE,
					TRUE,
					FALSE
					);
			}
		} // if( m_nDelayedFocusItemIndex >= 0 )
		m_nDelayedFocusItemIndex = IDX_NOTHING;
		return;
	}
	// case ID_TIMER_ITEM_FOCUS_DELAY
	
	default:
		CExtPopupBaseWnd::OnTimer(nIDEvent);
	break; // default
	} // switch( nIDEvent )
}

CExtPopupMenuWnd * CExtPopupMenuWnd::_GetCapture()
{
	return GetSite().GetCapture();
}

void CExtPopupMenuWnd::_SetCapture()
{
	ASSERT_VALID( this );
	ASSERT( !_FindCustomizeMode() );

CExtPopupMenuSite & _site = GetSite();
	if( GetSafeHwnd() != NULL )
	{
		ASSERT( ::IsWindow(GetSafeHwnd()) );
		_site.SetCapture( this );
	}
	else
		_site.SetCapture( NULL );
}

void CExtPopupMenuWnd::_ReleaseCapture()
{
	ASSERT_VALID( this );
	ASSERT( !_FindCustomizeMode() );

CExtPopupMenuSite & _site = GetSite();
	if(		_site.IsEmpty()
		||	_site.IsShutdownMode()
		)
		return;
	if( _site.GetCapture() == this )
		_site.SetCapture( NULL );
}

int CExtPopupMenuWnd::_GetNextItem(
	next_item_t nit
	)
{
	ASSERT_VALID( this );

int nCountOfItems = m_items_all.GetSize();
bool bCanExpand = false;
	if( m_bExpandAvailable
		&& (!m_bExpandWasPressed)
		)
	{
		if( IsAllItemsRarelyUsed() )
			return IDX_EXPAND;
		bCanExpand = true;
	}
	if( nit == __NI_NOTHING ||  nCountOfItems == 0 )
	{
		if( bCanExpand )
			return IDX_EXPAND;
		return IDX_NOTHING;
	}

	if( nit == __NI_ANY && m_nCurIndex >= 0 )
		return m_nCurIndex;

	if( m_nCurIndex < 0 )
	{
		INT iter = 0;
		for( ; iter < m_items_all.GetSize(); ++iter )
		{
			MENUITEMDATA & mi = m_items_all[ iter ];
			if( mi.IsEnabled() && mi.IsDisplayed() )
				return mi.GetIndex();
		}
		if( bCanExpand )
			return IDX_EXPAND;
		return IDX_NOTHING;
	}

	if( nit == __NI_NEXT )
	{
		if( nCountOfItems < 2 )
		{
			if( bCanExpand )
				return IDX_EXPAND;
			return IDX_NOTHING;
		}

		INT iter = m_nCurIndex + 1;
		for( ; iter < m_items_all.GetSize(); ++iter )
		{
			MENUITEMDATA & mi = m_items_all[ iter ];
			if( mi.IsEnabled() && mi.IsDisplayed() )
				return mi.GetIndex();
		}
		if( bCanExpand )
			return IDX_EXPAND;
		if( m_nCurIndex == 0 )
			return IDX_NOTHING;
		iter = 0;
		INT iter2 = m_nCurIndex - 1;
		do
		{
			MENUITEMDATA & mi = m_items_all[ iter ];
			if( mi.IsEnabled() && mi.IsDisplayed() )
				return mi.GetIndex();
			iter++;
		} while( iter != iter2 );
		return IDX_NOTHING;
	}
	if( nit == __NI_PREV )
	{
		if( nCountOfItems < 2 )
			return IDX_NOTHING;

		if( m_nCurIndex != 0 )
		{
			int nIndex = m_nCurIndex - 1;
			INT iter = nIndex;
			for( ; true;  )
			{
				MENUITEMDATA & mi = m_items_all[ iter ];
				if( mi.IsEnabled() && mi.IsDisplayed() )
					return mi.GetIndex();
				if( nIndex == 0 )
					break;
				--iter;
				--nIndex;
			}
		}
		int nIndex = m_nCurIndex + 1;
		INT iter2 = nIndex;
		INT iter = m_items_all.GetSize() - 1;
		do
		{
			MENUITEMDATA & mi = m_items_all[ iter ];
			if( mi.IsEnabled() && mi.IsDisplayed() )
				return mi.GetIndex();
			iter--;
		} while( iter != iter2 );

		return IDX_NOTHING;
	}

	return IDX_NOTHING;
}

bool CExtPopupMenuWnd::_OnKeyDown(
	UINT nChar,
	UINT nRepCnt,
	UINT nFlags,
	bool & bNoEat
	)
{
	ASSERT_VALID( this );

	ASSERT( m_hWndCmdReciever != NULL );
	ASSERT( ::IsWindow(m_hWndCmdReciever) );

	nRepCnt;
	if( GetSafeHwnd() == NULL )
		return true;

	if( !m_bAnimFinished )
		return true;

CExtPopupMenuSite & _site = GetSite();
	if(	_site.IsShutdownMode()
		|| _site.IsEmpty()
		|| _site.GetAnimated() != NULL
		)
		return true;

HWND hWndFocus = ::GetFocus();
	if(		hWndFocus != NULL
		&&	(::GetWindowLong(hWndFocus,GWL_STYLE)&WS_CHILD) != 0
		&&	::GetParent(hWndFocus) == m_hWnd
		)
	{
		bool bAlt =
			( (::GetAsyncKeyState(VK_MENU)&0x8000) != 0 )
				? true : false;
		bool bCtrl =
			( (::GetAsyncKeyState(VK_CONTROL)&0x8000) != 0 )
				? true : false;
		bool bShift =
			( (::GetAsyncKeyState(VK_SHIFT)&0x8000) != 0 )
				? true : false;
		if( bAlt )
			PostMessage( WM_CANCELMODE );
		else if( nChar == VK_ESCAPE )
			SetFocus();
		else if( (nChar == VK_INSERT || nChar == _T('C')) && bCtrl )
				::SendMessage( hWndFocus, WM_COPY, 0, 0 );
		else if(	( nChar == _T('X') && bCtrl )
				||	( nChar == VK_DELETE && bShift )
				)
				::SendMessage( hWndFocus, WM_CUT, 0, 0 );
		else if(	( nChar == _T('V') && bCtrl )
				||	( nChar == VK_INSERT && bShift )
				)
				::SendMessage( hWndFocus, WM_PASTE, 0, 0 );
		else if( nChar == VK_DELETE )
				::SendMessage( hWndFocus, CExtPopupMenuWnd::CInPlaceEditWnd::g_nMsgDeleteSelection, 0, 0 );
		else if( nChar == _T('A') && bCtrl )
				::SendMessage( hWndFocus, CExtPopupMenuWnd::CInPlaceEditWnd::g_nMsgSelectAll, 0, 0 );
		else
			bNoEat = true;
		return (!bNoEat);
	}

next_item_t nit = __NI_NOTHING;
	switch( nChar )
	{
	case VK_MENU:
		_EndSequence();
		return true;
	case VK_SPACE:
		return true;
	case VK_RETURN:
	{
		if( m_nCurIndex < 0 )
			return true; // break;
		MENUITEMDATA & mi = _GetItemRef(m_nCurIndex);
		if( mi.IsInplaceEdit() )
		{
			CWnd * pWndInplace = mi.GetInplaceEditPtr();
			if( pWndInplace != NULL )
			{
				ASSERT_VALID( pWndInplace );
				ASSERT( pWndInplace->GetSafeHwnd() != NULL && (::IsWindow(pWndInplace->GetSafeHwnd())) );
				if( mi.IsAllowInplaceEditActivation() )
				{
					if( (pWndInplace->GetStyle() & WS_VISIBLE) == 0 )
					{
						CRect rcInplaceEdit;
						_GetItemRect( m_nCurIndex, rcInplaceEdit );
						rcInplaceEdit = mi.AdjustInplaceEditRect( rcInplaceEdit );
						pWndInplace->SetWindowPos(
							NULL,
							rcInplaceEdit.left, rcInplaceEdit.top,
							rcInplaceEdit.Width(), rcInplaceEdit.Height(),
							SWP_NOZORDER|SWP_NOOWNERZORDER
								|SWP_NOACTIVATE|SWP_SHOWWINDOW
							);
					} // if( (pWndInplace->GetStyle() & WS_VISIBLE) == 0 )
					pWndInplace->SetFocus();
				} // if( mi.IsAllowInplaceEditActivation() )
			} // if( pWndInplace != NULL )
			return true;
		}
		if( mi.IsExtraMark() )
		{
			ASSERT( mi.GetExtraMarkCallback() != NULL );
			mi.GetExtraMarkCallback()( this, &mi );
			CClientDC dc( this );
			_DoPaint( dc );
			return true;
		} // if( mi.IsExtraMark() )
		if( mi.IsExecutableCmdID() )
		{
			if(	!(		mi.GetCmdDeliverCb() != NULL
					&&	mi.GetCmdDeliverCb()( this, &mi )
					)
				)
				_EndSequence( mi.GetCmdID(), mi.GetCmdReciever() );
			return true;
		}
	} // case VK_RETURN

	case VK_RIGHT:
	{
		bool bSendChangeMenu = false;
		if( m_nCurIndex < 0 )
		{
			if( m_items_all.GetSize() == 0 )
				return true; // false;
//			nit = __NI_ANY;
			bSendChangeMenu = true;
		}
		else
		{
			MENUITEMDATA & mi = _GetItemRef(m_nCurIndex);
			if( !mi.IsPopup() )
			{
				bSendChangeMenu = true;
			}
			else
			{
				if( mi.GetPopup()->GetSafeHwnd() == NULL )
				{
					_ItemFocusDelay();
					_ItemFocusSet(
						m_nCurIndex,
						TRUE,
						TRUE
						);
				}
			}
		}
		if( bSendChangeMenu && nChar==VK_RIGHT )
		{
			ASSERT( m_hWndCmdReciever != NULL );
			ASSERT( ::IsWindow(m_hWndCmdReciever) );
			if( CExtToolControlBar::g_bMenuTracking )
				::PostMessage(
					m_hWndCmdReciever,
					CExtPopupMenuWnd::g_nMsgPopupNext,
					0,
					LPARAM( this )
					);
			return true;
		}
	}
	break; // case VK_RIGHT

	case VK_LEFT:
		if( m_pWndParentMenu == NULL )
		{
			if( CExtToolControlBar::g_bMenuTracking )
				::PostMessage(
					m_hWndCmdReciever,
					CExtPopupMenuWnd::g_nMsgPopupPrev,
					0,
					LPARAM( this )
					);
			return true;
		}
		else
		{
			ASSERT( !m_bTopLevel );
			int nParentCurIndex =
				m_pWndParentMenu->m_nCurIndex;
			ASSERT(
				nParentCurIndex >= 0
				&&
				nParentCurIndex <=
					m_pWndParentMenu->m_items_all.GetSize()
				);
			m_pWndParentMenu->_ItemFocusCancel(
				FALSE
				);
			m_pWndParentMenu->_ItemFocusSet(
				nParentCurIndex,
				FALSE,
				TRUE
				);
			m_pWndParentMenu->_SetCapture();
			return true;
		}

	case VK_ESCAPE:
		_EndSequence();
		return true;
	// case VK_ESCAPE
	
	case VK_UP:
		nit = __NI_PREV;
	break; // case VK_UP
	case VK_DOWN:
		if( IsKeyPressed( VK_CONTROL ) )
		{
			if( m_bExpandAvailable )
				_DoExpand();
			return true;
		}
		nit = __NI_NEXT;
	break; // case VK_DOWN
	case VK_NEXT:
		nit = __NI_PAGE_DOWN;
	break; // case VK_NEXT
	case VK_PRIOR:
		nit = __NI_PAGE_UP;
	break; // case VK_PRIOR

	default:
	//if( _istalnum(nChar) )
	{ // BLOCK: try analyze quick char access
		if( IsKeyPressed(VK_SHIFT)
			|| IsKeyPressed(VK_CONTROL)
			|| IsKeyPressed(VK_MENU)
			|| ( (nFlags & (1<<29)) != 0 ) // ALT pressed?
			)
			return false;
		BYTE lpKeyState[256];
		::GetKeyboardState( lpKeyState );
		UINT wScanCode = ::MapVirtualKey( nChar, 0 );
		HKL hKeyboardLayout =
			::GetKeyboardLayout(
				( ::AfxGetThread() ) -> m_nThreadID
				);
#if (defined _UNICODE)
		TCHAR szChar[2] = { _T('\0'), _T('\0') };
		::ToUnicodeEx(
			nChar,
			wScanCode,
			lpKeyState,
			szChar, 1,
			1,
			hKeyboardLayout
			);
		WORD nMapped = WORD( szChar[0] );
#else
		WORD nMapped = 0;
		::ToAsciiEx(
			nChar,
			wScanCode,
			lpKeyState,
			&nMapped,
			1,
			hKeyboardLayout
			);
		//TCHAR szChar[2] = { (TCHAR)nMapped, _T('\0') };
#endif
		INT nNextIdx =
			ItemFindByAccessChar(
				(TCHAR)nMapped,
				m_nCurIndex // (m_nCurIndex >= 0) ? m_nCurIndex : -1
				);
		if(		nNextIdx < 0
			&&	m_nCurIndex >= 0
			&&	ItemFindByAccessChar( (TCHAR)nMapped, -1 )
					== m_nCurIndex
			)
		{ // if only 1 with this char
			MENUITEMDATA & mi =
				_GetItemRef( m_nCurIndex );
			if( mi.IsInplaceEdit() && (!mi.IsPopup()) )
			{
				CWnd * pWndInplace = mi.GetInplaceEditPtr();
				if( pWndInplace != NULL )
				{
					ASSERT_VALID( pWndInplace );
					ASSERT( pWndInplace->GetSafeHwnd() != NULL && (::IsWindow(pWndInplace->GetSafeHwnd())) );
					if( mi.IsAllowInplaceEditActivation() )
					{
						if( (pWndInplace->GetStyle() & WS_VISIBLE) == 0 )
						{
							CRect rcInplaceEdit;
							_GetItemRect( m_nCurIndex, rcInplaceEdit );
							rcInplaceEdit = mi.AdjustInplaceEditRect( rcInplaceEdit );
							pWndInplace->SetWindowPos(
								NULL,
								rcInplaceEdit.left, rcInplaceEdit.top,
								rcInplaceEdit.Width(), rcInplaceEdit.Height(),
								SWP_NOZORDER|SWP_NOOWNERZORDER
									|SWP_NOACTIVATE|SWP_SHOWWINDOW
								);
						} // if( (pWndInplace->GetStyle() & WS_VISIBLE) == 0 )
						pWndInplace->SetFocus();
					} // if( mi.IsAllowInplaceEditActivation() )
				} // if( pWndInplace != NULL )
				return true;
			} // if( mi.IsInplaceEdit() && (!mi.IsPopup()) )
			if( mi.IsExtraMark() )
			{
				ASSERT( mi.GetExtraMarkCallback() != NULL );
				mi.GetExtraMarkCallback()( this, &mi );
				CClientDC dc( this );
				_DoPaint( dc );
				return true;
			} // if( mi.IsExtraMark() )
			if( mi.IsExecutableCmdID() )
			{
				if(	!(		mi.GetCmdDeliverCb() != NULL
						&&	mi.GetCmdDeliverCb()( this, &mi )
						)
					)
					_EndSequence( mi.GetCmdID(), mi.GetCmdReciever() );
				return true;
			} // if( mi.IsExecutableCmdID() )
		} // if only 1 with this char
		if( m_nCurIndex != nNextIdx
			&& nNextIdx >= 0
			)
		{
			_ItemFocusSet( nNextIdx, TRUE, TRUE );
			if( ItemFindByAccessChar(
					(TCHAR)nMapped,
					nNextIdx
					) < 0
				)
			{ // if only 1 with this char
				MENUITEMDATA & mi =
					_GetItemRef( nNextIdx );
				if( mi.IsInplaceEdit() && (!mi.IsPopup()) )
				{
					CWnd * pWndInplace = mi.GetInplaceEditPtr();
					if( pWndInplace != NULL )
					{
						ASSERT_VALID( pWndInplace );
						ASSERT( pWndInplace->GetSafeHwnd() != NULL && (::IsWindow(pWndInplace->GetSafeHwnd())) );
						if( mi.IsAllowInplaceEditActivation() )
						{
							if( (pWndInplace->GetStyle() & WS_VISIBLE) == 0 )
							{
								CRect rcInplaceEdit;
								_GetItemRect( nNextIdx, rcInplaceEdit );
								rcInplaceEdit = mi.AdjustInplaceEditRect( rcInplaceEdit );
								pWndInplace->SetWindowPos(
									NULL,
									rcInplaceEdit.left, rcInplaceEdit.top,
									rcInplaceEdit.Width(), rcInplaceEdit.Height(),
									SWP_NOZORDER|SWP_NOOWNERZORDER
										|SWP_NOACTIVATE|SWP_SHOWWINDOW
									);
							} // if( (pWndInplace->GetStyle() & WS_VISIBLE) == 0 )
							pWndInplace->SetFocus();
						} // if( mi.IsAllowInplaceEditActivation() )
					} // if( pWndInplace != NULL )
					return true;
				} // if( mi.IsInplaceEdit() && (!mi.IsPopup()) )
				if( mi.IsExtraMark() )
				{
					ASSERT( mi.GetExtraMarkCallback() != NULL );
					mi.GetExtraMarkCallback()( this, &mi );
					CClientDC dc( this );
					_DoPaint( dc );
					return true;
				} // if( mi.IsExtraMark() )
				if( mi.IsExecutableCmdID() )
				{
					if(	!(		mi.GetCmdDeliverCb() != NULL
							&&	mi.GetCmdDeliverCb()( this, &mi )
							)
						)
						_EndSequence( mi.GetCmdID(), mi.GetCmdReciever() );
					return true;
				} // if( mi.IsExecutableCmdID() )
			} // if only 1 with this char
			return true;
		}

	} // BLOCK: try analyze quick char access

	} // switch( nChar )

	if( nit != __NI_NOTHING )
	{
		int nItemIndex = _GetNextItem(nit);
		if( m_items_all.GetSize() > 0
			&& nItemIndex >= 0
			&& nItemIndex != m_nCurIndex
			)
		{
			_ItemFocusSet(
				nItemIndex,
				FALSE,
				TRUE
				);
			return true; // false;
		}
		if( nItemIndex == IDX_EXPAND )
		{
			ASSERT( m_bExpandAvailable );
			ASSERT( !m_bExpandWasPressed );
			int nItemIndex = m_nCurIndex;
			_DoExpand();
			if( nItemIndex >= 0 )
			{
				_ItemFocusSet(
					nItemIndex,
					FALSE,
					//m_bAnimFinished
					( GetSite().GetAnimated() == NULL )
						? TRUE : FALSE
					);
				int i = _GetNextItem(__NI_NEXT);
				_ItemFocusSet(
					(i>0) ? i : nItemIndex,
					FALSE,
					//m_bAnimFinished
					( GetSite().GetAnimated() == NULL )
						? TRUE : FALSE
					);
			}
			return true;
		}
	} // if( nit != __NI_NOTHING )

	return false;
}

INT CExtPopupMenuWnd::ItemFindByText(
	__EXT_MFC_SAFE_LPCTSTR sText,
	INT nStartIdx, // = -1
	BOOL bRestartAt0 // = TRUE
	) const
{
	bRestartAt0;
	ASSERT_VALID( this );

	if( sText == NULL || sText[0] == _T('\0') )
	{
		ASSERT( FALSE );
		return -1;
	}

int nCount = m_items_all.GetSize(); //ItemGetCount();
int nIdx = (nStartIdx >= 0) ? (nStartIdx + 1) : 0;
	for( ; nIdx < nCount; nIdx++ )
	{
		const MENUITEMDATA & mi = _GetItemRef(nIdx);
//		if( !mi.AccelCharIsSet() )
//			continue;
//		if( !mi.IsDisplayed() )
//			continue;
//		if( !mi.IsEnabled() )
//			continue;
		if( _tcscmp( sText, mi.GetText() ) == 0 )
		{
			if( nStartIdx != nIdx )
				return nIdx;
		}
	} // for( nIdx = nStartIdx; nIdx < nCount; nIdx++ )
	if( nStartIdx == 0 )
		return -1;
	for( nIdx = 0; nIdx<nStartIdx; nIdx++ )
	{
		const MENUITEMDATA & mi = _GetItemRef(nIdx);
//		if( !mi.AccelCharIsSet() )
//			continue;
//		if( !mi.IsDisplayed() )
//			continue;
//		if( !mi.IsEnabled() )
//			continue;
		if( _tcscmp( sText, mi.GetText() ) == 0 )
		{
			if( nStartIdx != nIdx )
				return nIdx;
		}
	} // for( nIdx = 0; nIdx<nStartIdx; nIdx++ )
	return -1;
}


INT CExtPopupMenuWnd::ItemFindByAccessChar(
	__EXT_MFC_SAFE_TCHAR chrAccess,
	INT nStartIdx, // = -1
	BOOL bRestartAt0 // = TRUE
	) const
{
	ASSERT_VALID( this );

	bRestartAt0;
	if( chrAccess == _T('0') )
		return -1;
TCHAR szChar[2] = { chrAccess, _T('\0') };
	::CharUpper( szChar );

int cAccelSearch = szChar[0]; //toupper(nChar);
	if( cAccelSearch == 0 )
		return -1;
int nCount = m_items_all.GetSize(); //ItemGetCount();
int nIdx = (nStartIdx >= 0) ? (nStartIdx + 1) : 0;
	for( ; nIdx < nCount; nIdx++ )
	{
		const MENUITEMDATA & mi = _GetItemRef(nIdx);
		if( !mi.AccelCharIsSet() )
			continue;
		if( !mi.IsDisplayed() )
			continue;
		if( !mi.IsEnabled() )
			continue;
		TCHAR cAccel = mi.AccelCharGet();
		if( cAccelSearch ==
				cAccel // _totupper(cAccel)
			)
		{
			if( nStartIdx != nIdx )
				return nIdx;
		}
	} // for( nIdx = nStartIdx; nIdx < nCount; nIdx++ )
	if( nStartIdx == 0 )
		return -1;
	for( nIdx = 0; nIdx<nStartIdx; nIdx++ )
	{
		const MENUITEMDATA & mi = _GetItemRef(nIdx);
		if( !mi.AccelCharIsSet() )
			continue;
		if( !mi.IsDisplayed() )
			continue;
		if( !mi.IsEnabled() )
			continue;
		TCHAR cAccel = mi.AccelCharGet();
		if( cAccelSearch ==
				cAccel // _totupper(cAccel)
				)
		{
			if( nStartIdx != nIdx )
				return nIdx;
		}
	} // for( nIdx = 0; nIdx<nStartIdx; nIdx++ )
	return -1;
}

BOOL CExtPopupMenuWnd::IsCmdKeyActivation(
	LPARAM lParam // = 0
	)
{
	if( (lParam & (1<<29)) != 0 ) // ALT pressed?
		return TRUE;
	
static int nTestKeys[] = {
	VK_MENU,VK_RMENU,VK_LMENU,
	VK_CONTROL,VK_RCONTROL,VK_LCONTROL,
	VK_SHIFT,VK_RSHIFT,VK_LSHIFT
};
	for( int i=0; i<sizeof(nTestKeys)/sizeof(int); i++ )
	{
		if( IsKeyPressed(nTestKeys[i]) )
		{
//			if(		nTestKeys[i] == VK_CONTROL
//				||	nTestKeys[i] == VK_RCONTROL
//				||	nTestKeys[i] == VK_LCONTROL
//				)
//			{
//				if( IsKeyPressed(VK_DOWN) )
//					return FALSE;
//			}
			return TRUE;
		}
	}
	return FALSE;
}

INT CExtPopupMenuWnd::ItemGetCount() const
{
	ASSERT_VALID( this );

	ASSERT_VALID( this );

//	ASSERT( GetTrackingMenu() != this );
INT nCountOfItems = m_items_all.GetSize();
	return nCountOfItems;
}

INT CExtPopupMenuWnd::ItemFindPosForCmdID(
	UINT nCmdID,
	INT nPosStart // = -1
	) const
{
	ASSERT_VALID( this );

INT nPos = (nPosStart < 0) ? 0 : nPosStart + 1;
INT nCount = ItemGetCount();
	for( ; nPos < nCount; nPos++ )
	{
		UINT nCmdID2 = ItemGetCmdID( nPos );
		if( nCmdID == nCmdID2 )
			return nPos;
	}
	return -1; // not found
}

UINT CExtPopupMenuWnd::ItemGetCmdID( // menu_item_type_t values can be returned
	INT nPos
	) const
{
	ASSERT_VALID( this );

	ASSERT( GetTrackingMenu() != this );
INT nCountOfItems = ItemGetCount();
	if( nPos < 0 || nPos >= nCountOfItems )
	{
		ASSERT( FALSE );
		return TYPE_SEPARATOR;
	}
const MENUITEMDATA & mi = _GetItemRef(nPos);
UINT nCmdID = mi.GetCmdID();
	return nCmdID;
}

bool CExtPopupMenuWnd::ItemSetPopupIcon(
	INT nPos,
	HICON hIcon // = NULL // no icon by default
	)
{
	ASSERT_VALID( this );

	ASSERT( GetTrackingMenu() != this );
INT nCountOfItems = ItemGetCount();
	if( nPos < 0 || nPos >= nCountOfItems )
	{
		ASSERT( FALSE );
		return false;
	}
MENUITEMDATA & mi = _GetItemRef(nPos);
	return mi.SetPopupIcon( hIcon );
}

bool CExtPopupMenuWnd::ItemSetPopupText(
	INT nPos,
	__EXT_MFC_SAFE_LPCTSTR sText // NULL if empty
	)
{
	ASSERT_VALID( this );

	ASSERT( GetTrackingMenu() != this );
INT nCountOfItems = ItemGetCount();
	if( nPos < 0 || nPos >= nCountOfItems )
	{
		ASSERT( FALSE );
		return false;
	}
MENUITEMDATA & mi = _GetItemRef(nPos);
	if( !mi.SetPopupText( sText ) )
		return false;
	mi.MeasureItem();
	return true;
}

bool CExtPopupMenuWnd::ItemSetPopupAccelText(
	INT nPos,
	__EXT_MFC_SAFE_LPCTSTR sText // NULL if empty
	)
{
	ASSERT_VALID( this );

	ASSERT( GetTrackingMenu() != this );
INT nCountOfItems = ItemGetCount();
	if( nPos < 0 || nPos >= nCountOfItems )
	{
		ASSERT( FALSE );
		return false;
	}
MENUITEMDATA & mi = _GetItemRef(nPos);
	return mi.SetPopupAccelText( sText );
}

HICON CExtPopupMenuWnd::ItemGetIcon( INT nPos ) const
{
	ASSERT_VALID( this );

	ASSERT( GetTrackingMenu() != this );
INT nCountOfItems = ItemGetCount();
	if( nPos < 0 || nPos >= nCountOfItems )
	{
		ASSERT( FALSE );
		return NULL;
	}
const MENUITEMDATA & mi = _GetItemRef(nPos);
CExtCmdIcon * pIcon = ((MENUITEMDATA &)mi).GetIconPtr();
	if( pIcon == NULL || pIcon->IsEmpty() )
		return NULL;
	return pIcon->GetIcon();
}

CExtPopupMenuWnd::MENUITEMDATA & CExtPopupMenuWnd::ItemGetInfo( INT nPos )
{
	ASSERT_VALID( this );
INT nCountOfItems = ItemGetCount();
	if( nPos < 0 || nPos >= nCountOfItems )
	{
		ASSERT( FALSE );
		AfxThrowNotSupportedException();
	}
	return _GetItemRef( nPos );
}

const CExtPopupMenuWnd::MENUITEMDATA & CExtPopupMenuWnd::ItemGetInfo( INT nPos ) const
{
	ASSERT_VALID( this );
INT nCountOfItems = ItemGetCount();
	if( nPos < 0 || nPos >= nCountOfItems )
	{
		ASSERT( FALSE );
		AfxThrowNotSupportedException();
	}
	return _GetItemRef( nPos );
}


CExtSafeString CExtPopupMenuWnd::ItemGetText( INT nPos ) const
{
	ASSERT_VALID( this );

	ASSERT( GetTrackingMenu() != this );
INT nCountOfItems = ItemGetCount();
	if( nPos < 0 || nPos >= nCountOfItems )
	{
		ASSERT( FALSE );
		return CExtSafeString( _T("") );
	}
const MENUITEMDATA & mi = _GetItemRef(nPos);
	return CExtSafeString( mi.GetText() );
}

CExtSafeString CExtPopupMenuWnd::ItemGetAccelText( INT nPos ) const
{
	ASSERT_VALID( this );

	ASSERT( GetTrackingMenu() != this );
INT nCountOfItems = ItemGetCount();
	if( nPos < 0 || nPos >= nCountOfItems )
	{
		ASSERT( FALSE );
		return CExtSafeString( _T("") );
	}
const MENUITEMDATA & mi = _GetItemRef(nPos);
	return CExtSafeString( mi.GetAccelText() );
}

bool CExtPopupMenuWnd::ItemIsDisplayed(
	INT nPos
	) const
{
const MENUITEMDATA & mi = _GetItemRef( nPos );
	return mi.IsDisplayed();
}

void CExtPopupMenuWnd::ItemSetDisplayed(
	INT nPos,
	bool bForceDisplayed // = true
	)
{
MENUITEMDATA & mi = _GetItemRef( nPos );
	mi.SetForceDisplayed( bForceDisplayed );
	_SyncItems();
}

CExtPopupMenuWnd * CExtPopupMenuWnd::ItemGetPopup(
	INT nPos
	)
{
	ASSERT_VALID( this );

	ASSERT( GetTrackingMenu() != this );
const CExtPopupMenuWnd * pChild =
		((const CExtPopupMenuWnd *)this)->
			ItemGetPopup( nPos );
	if( pChild == NULL )
		return NULL;
	return
		const_cast
			<CExtPopupMenuWnd *>
				(pChild);
}

void CExtPopupMenuWnd::_DoExpand()
{
	ASSERT_VALID( this );

	ASSERT( !_FindCustomizeMode() );

	_ItemFocusDelay();
	_CoolTipHide( false );
	if( ( GetSite().GetAnimated() != NULL )
		|| _CoolTipIsVisible()
		)
		return;

	ASSERT( m_bExpandAvailable );
	ASSERT( !m_bExpandWasPressed );
	ASSERT( ::IsWindow(GetSafeHwnd()) );
	ASSERT( ( GetSite().GetAnimated() == NULL ) );
	
	m_bExpandWasPressed = true;
CSize m_sizeFullItems2 = m_sizeFullItems;
	_SyncItems();
	_RecalcLayoutImpl();

	if( m_sizeFullItems != m_sizeFullItems2 )
	{ // if size of all items was changed
		ASSERT(
				m_sizeFullItems.cx >= m_sizeFullItems2.cx
			&&	m_sizeFullItems.cy >= m_sizeFullItems2.cy
			);

		CRect rcWndOld;
		GetWindowRect( &rcWndOld );
		
		VERIFY(
			SetWindowRgn(
				NULL,
				FALSE
				)
			);
		ShowWindow( SW_HIDE	);
		ASSERT( !IsWindowVisible() );

		if( !rcWndOld.IsRectEmpty() )
		{
			CWnd * pWndTLP = GetTopLevelParent();
			if( pWndTLP != NULL )
			{
				ASSERT_VALID( pWndTLP );
				if( pWndTLP->IsWindowVisible() )
				{
					CRect rcTLP;
					pWndTLP->GetWindowRect( &rcTLP );
					if( !rcTLP.IsRectEmpty() )
					{
						CRect rcIntersection;
						if(	rcIntersection.IntersectRect(
								&rcTLP,
								&rcWndOld
								)
							)
							pWndTLP->UpdateWindow();
					} // if( !rcTLP.IsRectEmpty() )
				} // if( pWndTLP->IsWindowVisible() )
			} // if( pWndTLP != NULL )
		} // if( !rcWndOld.IsRectEmpty() )

		_FreeWinObjects();

		ASSERT( ::IsWindow(GetSafeHwnd()) );
		ASSERT( ( GetSite().GetAnimated() == NULL ) );

		m_bAnimFinished = false;
		m_AnimationType = __AT_CONTENT_DISPLAY;

		// adjust screen position
		CRect rcWnd = _CalcTrackRect();
		
		if( m_rgnWnd.GetSafeHandle() != NULL )
		{
			ASSERT( m_bExcludeAreaSpec );
			ASSERT( m_bCombineWithEA );
			ASSERT( m_eCombineAlign != __CMBA_NONE );
			CRgn rgnTmp;
			VERIFY( rgnTmp.CreateRectRgn(0,0,0,0) );
			rgnTmp.CopyRgn( &m_rgnWnd );
			ASSERT( rgnTmp.GetSafeHandle() != NULL );
			VERIFY(
				SetWindowRgn(
					(HRGN)rgnTmp.Detach(),
					FALSE
					)
				);
		} // if( m_rgnWnd.GetSafeHandle() != NULL )
		
		m_bAnimFinished = true;

		m_ePlaySoundOnAnimationFinished =
			CExtSoundPlayer::__ON_MENU_EXPAND_CLICKED;
		m_AnimationType =
			g_bMenuExpandAnimation
				? __AT_CONTENT_EXPAND
				: __AT_CONTENT_DISPLAY
				;
		_StartAnimation();
		if( m_AnimationType == __AT_NONE )
		{
			m_AnimationType = __AT_CONTENT_DISPLAY;
			_StartAnimation();
			ASSERT( m_AnimationType == __AT_CONTENT_DISPLAY );
		}

		if( m_bScrollingAvailable )
			_RecalcLayoutImpl();
		SetWindowPos(
			NULL,
			rcWnd.left, rcWnd.top, rcWnd.Width(), rcWnd.Height(),
			SWP_NOACTIVATE
				|SWP_SHOWWINDOW
				//|SWP_NOREDRAW //|SWP_NOSENDCHANGING
				|SWP_NOZORDER //|SWP_NOOWNERZORDER
				//|SWP_NOCOPYBITS
			);

		ASSERT( IsWindowVisible() );

	} // if size of all items was changed
	else
		UpdateWindow();

	ASSERT( m_hWndCmdReciever != NULL );
	ASSERT( ::IsWindow(m_hWndCmdReciever) );
	::SendMessage(
		m_hWndCmdReciever,
		g_nMsgNotifyMenuExpanded,
		0,
		LPARAM( this )
		);
}

bool CExtPopupMenuWnd::IsAllItemsRarelyUsed() const
{
	ASSERT_VALID( this );

INT _iter = 0;
	for( ; _iter < m_items_all.GetSize(); ++_iter )
	{
		const MENUITEMDATA & mi = m_items_all[ _iter ];
		if( mi.IsDisplayed() || mi.IsExtraMark() )
			return false;
	} // for( ; _iter != m_items_all.end(); ++_iter )
	return true;
}

void CExtPopupMenuWnd::_SyncItems()
{
	ASSERT_VALID( this );

	ASSERT( m_hWndCmdReciever != NULL );
	ASSERT( ::IsWindow(m_hWndCmdReciever) );

INT nIconAreaWidthLager = (__EXT_MENU_ICON_CX+__EXT_MENU_GAP*2);
	for( INT _iter = 0; _iter < m_items_all.GetSize(); ++_iter )
	{
		MENUITEMDATA & mi = m_items_all[ _iter ];
		int nWidth = mi.GetIconAreaWidth();
		nIconAreaWidthLager =
			max( nIconAreaWidthLager, nWidth );
	} // for( INT _iter = 0; _iter < m_items_all.GetSize(); ++_iter )
	for( _iter = 0; _iter < m_items_all.GetSize(); ++_iter )
	{
		MENUITEMDATA & mi = m_items_all[ _iter ];
		mi.UpdateIconAreaWidth( nIconAreaWidthLager );
	} // for( _iter = 0; _iter < m_items_all.GetSize(); ++_iter )

	m_bExpandAvailable = false;
	m_sizeFullItems.cx = m_sizeFullItems.cy = 1;
int nItemIndex = 0;
INT _iterLast = m_items_all.GetSize();
INT _iterLastVisSep = _iterLast;
bool bAtLeastOneDisplayed = false;
	for( _iter = 0; _iter < m_items_all.GetSize(); ++_iter )
	{
		MENUITEMDATA & mi = m_items_all[ _iter ];
		mi.SetIndex( nItemIndex++ );

		if( m_bExpandWasPressed )
		{
			mi.SetDisplayed( true );
		} // if( m_bExpandWasPressed )
		else
		{
			if( mi.IsPopup() )
			{ // if popup sub-menu
				ASSERT( mi.GetPopup() != NULL );
				mi.GetPopup()->_SyncItems();
				CExtCmdItem * pCmdItem = mi.GetCmd();
				if( pCmdItem != NULL )
				{
					bool bRarelyUsed =
						(	(!_FindCustomizeMode())
						&&	pCmdItem->StateIsRarelyUsed()
						) ? true : false;
					if( bRarelyUsed )
					{
						_iterLast = m_items_all.GetSize();
						mi.SetDisplayed( false );
					}
					else
					{
						_iterLast = _iter;
						_iterLastVisSep = m_items_all.GetSize();
						mi.SetDisplayed( true );
					}
				} // if( pCmdItem != NULL )
				else if( mi.IsAllItemsRarelyUsed() )
				{ // if all not displayed
					_iterLast = m_items_all.GetSize();
					mi.SetDisplayed( false );
				} // if all not displayed
				else
				{ // if at least one displayed
					_iterLast = _iter;
					_iterLastVisSep = m_items_all.GetSize();
					mi.SetDisplayed( true );
				} // if at least one displayed
			} // if popup sub-menu
			else
			{ // if separator or command item
				if( mi.IsSeparator() )
				{ // if separator
					if( _iterLast != m_items_all.GetSize()
						||
						(	 _iterLast == m_items_all.GetSize()
							&& (_iterLastVisSep == m_items_all.GetSize())
							&& bAtLeastOneDisplayed
							)
						)
					{
						_iterLastVisSep = _iter;
						mi.SetDisplayed( true );
					}
					else
					{
						_iterLast = m_items_all.GetSize();
						mi.SetDisplayed( false );
					}
				} // if separator
				else
				{ // if command item
					CExtCmdItem * pCmdItem = mi.GetCmd();
					if( pCmdItem == NULL || mi.IsExtraMark() )
					{
						_iterLast = m_items_all.GetSize();
						mi.SetDisplayed( true );
					}
					else if( pCmdItem->StateIsRarelyUsed() )
					{ // if command rarely used
						_iterLast = m_items_all.GetSize();
						mi.SetDisplayed( false );
					} // if command rarely used
					else
					{ // if basic command or frequently used
						_iterLast = _iter;
						_iterLastVisSep = m_items_all.GetSize();
						mi.SetDisplayed( true );
					} // if basic command or frequently used
				} // if command item
			} // if separator or command item
		} // else from if( m_bExpandWasPressed )

		if( mi.IsDisplayed() )
		{
			bAtLeastOneDisplayed = true;
			m_sizeFullItems.cy += mi.GetMeasuredHeight();
			if( m_sizeFullItems.cx < mi.GetMeasuredWidth() )
				m_sizeFullItems.cx = mi.GetMeasuredWidth();
		} // if( mi.IsDisplayed() )
		else
		{
			ASSERT( !m_bExpandWasPressed );
			m_bExpandAvailable = true;
		} // else from if( mi.IsDisplayed() )
	} // for( _iter = 0; _iter < m_items_all.GetSize(); ++_iter )

	if( _iterLastVisSep != m_items_all.GetSize() )
	{ // remove last separator
		if( _iterLastVisSep >= _iterLast
			||
			_iterLast == m_items_all.GetSize()
			)
		{
			m_items_all[_iterLastVisSep].SetDisplayed( false );
			m_sizeFullItems.cy -=
				m_items_all[_iterLastVisSep].GetMeasuredHeight();
		}
	} // remove last separator

static const INT nMixDx = 80;
	if( m_sizeFullItems.cx < nMixDx )
		m_sizeFullItems.cx = nMixDx;
}

const CExtPopupMenuWnd * CExtPopupMenuWnd::ItemGetPopup(
	INT nPos
	) const
{
	ASSERT_VALID( this );

	ASSERT( GetTrackingMenu() != this );
INT nCountOfItems = ItemGetCount();
	if( nPos < 0 || nPos >= nCountOfItems )
	{
		ASSERT( FALSE );
		return NULL;
	}
const MENUITEMDATA & mi = _GetItemRef(nPos);
/*
UINT nCmdID = mi.GetCmdID();
	if( nCmdID != TYPE_POPUP )
		return NULL;
	ASSERT( mi.IsPopup() );
*/

	if( !mi.IsPopup() )
		return NULL;

	return mi.GetPopup();
}

BOOL CExtPopupMenuWnd::ItemRemove(
	INT nPos // = -1 // remove all
	)
{
	ASSERT_VALID( this );

	ASSERT( GetTrackingMenu() != this );

	if( nPos < 0 )
	{
		if( !_BuildItems( NULL, false ) )
		{
			ASSERT( FALSE );
			return FALSE;
		}
		_SyncItems();
		return TRUE;
	} // if( nPos < 0 )

INT nCountOfItems = ItemGetCount();
	if( nPos >= nCountOfItems )
	{
		ASSERT( FALSE );
		return FALSE;
	}

MENUITEMDATA & mi = _GetItemRef(nPos);
	if( mi.IsPopup() )
	{
		mi.GetPopup()->_OnCancelMode();
		VERIFY( mi.GetPopup()->_BuildItems( NULL, false ) );
		mi.DestroyPopup();
	}
	m_items_all.RemoveAt( nPos );
	ASSERT( nCountOfItems == m_items_all.GetSize() + 1 );
	m_nCurIndex = -1;

	_SyncItems();

	return TRUE;
}

BOOL CExtPopupMenuWnd::ItemInsertSpecPopup( // insert specific popup implementation
	CExtPopupMenuWnd * pSpecPopup,
	INT nPos, // = -1 // append
	__EXT_MFC_SAFE_LPCTSTR sText, // = NULL
	HICON hIcon // = NULL
	)
{
	ASSERT_VALID( this );

	ASSERT( pSpecPopup != NULL );

INT nCountOfMenuItems = ItemGetCount();
	if( nPos < 0 )
		nPos = nCountOfMenuItems;
	if( nPos > nCountOfMenuItems )
	{
		ASSERT( FALSE );
		return FALSE;
	}

	ASSERT( m_hWndCmdReciever != NULL );
	ASSERT( ::IsWindow(m_hWndCmdReciever) );

MENUITEMDATA mi;
	mi.SetCmdReciever( m_hWndCmdReciever );

	pSpecPopup->m_bTopLevel = false;
	mi.SetPopup( nPos, sText, hIcon, pSpecPopup );
	ASSERT( mi.GetPopup()->m_pWndParentMenu == NULL ); // still not initialized
	ASSERT( !mi.GetPopup()->m_bTopLevel );
	mi.GetPopup()->m_pWndParentMenu = this;
	mi.SetDisplayed( true );

	_InsertItem( nPos, mi );

	if( m_bTopLevel )
		_SyncItems();
	else
	{
		ASSERT( m_pWndParentMenu != NULL );
		m_pWndParentMenu->_SyncItems();
	}

	return TRUE;
}

BOOL CExtPopupMenuWnd::ItemInsert(
	UINT nCmdID, // = TYPE_SEPARATOR,
	INT nPos, // = -1 // append
	__EXT_MFC_SAFE_LPCTSTR sText, // = NULL // for TYPE_POPUP only
	HICON hIcon, // = NULL // for TYPE_POPUP only
	HWND hWndSpecCmdReciever // = NULL // specific command reciever
	)
{
	ASSERT_VALID( this );
	ASSERT( GetTrackingMenu() != this );
INT nCountOfMenuItems = ItemGetCount();
	if( nPos < 0 )
		nPos = nCountOfMenuItems;
	if( nPos > nCountOfMenuItems )
	{
		ASSERT( FALSE );
		return FALSE;
	}
	ASSERT( m_hWndCmdReciever != NULL );
	ASSERT( ::IsWindow(m_hWndCmdReciever) );
MENUITEMDATA mi;
	mi.SetCmdReciever( 
		(hWndSpecCmdReciever != NULL)
			? hWndSpecCmdReciever
			: m_hWndCmdReciever
		);
	switch( nCmdID )
	{
	case TYPE_POPUP:
		mi.SetPopup( nPos, sText, hIcon );
		break; // case TYPE_POPUP
	case TYPE_SEPARATOR:
		mi.SetSeparator( nPos );
		break; // case TYPE_SEPARATOR
	default:
	{
		ASSERT( m_hWndCmdReciever != NULL );
		ASSERT( ::IsWindow(m_hWndCmdReciever) );
		CExtCmdItem * pCmdItem =
			g_CmdManager->CmdGetPtr(
				g_CmdManager->ProfileNameFromWnd(
					(hWndSpecCmdReciever != NULL)
						? hWndSpecCmdReciever
						: m_hWndCmdReciever
					),
				nCmdID
				);
		ASSERT( pCmdItem != NULL );
		if( pCmdItem == NULL )
			return FALSE;
		VERIFY(
			mi.UpdateCmdManagerCommand(
				pCmdItem,
				nPos
				)
			);
	}
	break; // default
	} // switch( nCmdID )
	if( mi.IsPopup() )
	{
		ASSERT( mi.GetPopup()->m_pWndParentMenu == NULL ); // still not initialized
		mi.GetPopup()->m_pWndParentMenu = this;
		ASSERT( !mi.GetPopup()->m_bTopLevel );
	}
	_InsertItem( nPos, mi );
	if( m_bTopLevel )
		_SyncItems();
	else
	{
		//ASSERT( m_pWndParentMenu != NULL );
		//m_pWndParentMenu->_SyncItems();
		if( m_pWndParentMenu != NULL )
			m_pWndParentMenu->_SyncItems();
	}
	return TRUE;
}

BOOL CExtPopupMenuWnd::ItemInsertCommand( // no references to command manager
	UINT nCmdID, // = TYPE_SEPARATOR
	INT nPos, // = -1 // append
	__EXT_MFC_SAFE_LPCTSTR sItemText, // = NULL
	__EXT_MFC_SAFE_LPCTSTR sAccelText, // = NULL
	HICON hIcon, // = NULL
	bool bCopyIcon, // = true
	int nCheck, // = 0 // 0 - no check, 1 - checked, 2 - indeterminate, 3 - radio
	HWND hWndSpecCmdReciever // = NULL
	)
{
CExtCmdIcon icon;
	if( hIcon != NULL )
		icon.AssignFromHICON( hIcon, bCopyIcon );
BOOL bRetVal =
		ItemInsertCommand(
			nCmdID, nPos, sItemText, sAccelText,
			icon, nCheck, hWndSpecCmdReciever
			);
	return bRetVal;
}

BOOL CExtPopupMenuWnd::ItemInsertCommand( // no references to command manager
	UINT nCmdID,
	INT nPos, // -1 append
	__EXT_MFC_SAFE_LPCTSTR sItemText, // may be NULL
	__EXT_MFC_SAFE_LPCTSTR sAccelText, // may be NULL
	const CExtCmdIcon & icon,
	int nCheck, // = 0 // 0 - no check, 1 - checked, 2 - indeterminate, 3 - radio
	HWND hWndSpecCmdReciever // = NULL
	)
{
	ASSERT_VALID( this );
	ASSERT( GetTrackingMenu() != this );
INT nCountOfMenuItems = ItemGetCount();
	if( nPos < 0 )
		nPos = nCountOfMenuItems;
	if( nPos > nCountOfMenuItems )
	{
		ASSERT( FALSE );
		return FALSE;
	}
	ASSERT( m_hWndCmdReciever != NULL );
	ASSERT( ::IsWindow(m_hWndCmdReciever) );
MENUITEMDATA mi;
	mi.SetCmdReciever( 
		(hWndSpecCmdReciever != NULL)
			? hWndSpecCmdReciever
			: m_hWndCmdReciever
		);
	mi.SetNoCmdUI( true );

	switch( nCmdID )
	{
	case TYPE_POPUP:
		mi.SetPopup(
			nPos,
			(sItemText == NULL) ? _T("") : sItemText,
			NULL
			);
		mi.SetPopupIcon( icon );
		break; // case TYPE_POPUP
	case TYPE_SEPARATOR:
		mi.SetSeparator( nPos );
		break; // case TYPE_SEPARATOR
	default:
	{
		ASSERT( m_hWndCmdReciever != NULL );
		ASSERT( ::IsWindow(m_hWndCmdReciever) );
		mi.SetCmdID( nCmdID );
		mi.SetText( (sItemText == NULL) ? _T("") : sItemText );
		mi.SetAccelText( (sAccelText == NULL) ? _T("") : sAccelText );
		mi.AccelCharInit();
		mi.SetPopupIcon( icon );
		switch( nCheck )
		{
		case 1: mi.Check( true ); break;
		case 2: mi.Indeterminate( true ); break;
		case 3: mi.Radio( true ); break;
		} // switch( nCheck )
		mi.MeasureItem();
	}
	break; // default
	} // switch( nCmdID )
	mi.SetIndex( nPos );
	mi.SetDisplayed( true );
	if( mi.IsPopup() )
	{
		ASSERT( mi.GetPopup()->m_pWndParentMenu == NULL ); // still not initialized
		mi.GetPopup()->m_pWndParentMenu = this;
		ASSERT( !mi.GetPopup()->m_bTopLevel );
	}
	_InsertItem( nPos, mi );
	if( m_bTopLevel )
		_SyncItems();
	else
	{
		//ASSERT( m_pWndParentMenu != NULL );
		//m_pWndParentMenu->_SyncItems();
		if( m_pWndParentMenu != NULL )
			m_pWndParentMenu->_SyncItems();
	}
	return TRUE;
}

void CExtPopupMenuWnd::SetLeftAreaWidth(
	UINT nWidth // = 0
	)
{
	m_nLeftAreaWidth = nWidth;
}

UINT CExtPopupMenuWnd::GetLeftAreaWidth() const
{
	return m_nLeftAreaWidth;
}

BOOL CExtPopupMenuWnd::CreatePopupMenu( HWND hWndCmdRecv )
{
	ASSERT_VALID( this );
	ASSERT( ::IsWindow(hWndCmdRecv) );

	ASSERT( GetTrackingMenu() != this );
	if( m_bTopLevel
		|| m_pWndParentMenu != NULL
		|| ItemGetCount() != 0
		)
	{
		// already created
		ASSERT( FALSE );
		return FALSE;
	}
	m_sizeFullItems.cx = m_sizeFullItems.cy = 1;
	m_bTopLevel = true;
	m_pWndParentMenu = NULL;
	m_hWndCmdReciever = hWndCmdRecv;
	
	return TRUE;
}

void CExtPopupMenuWnd::SetCmdTargetToAllItems(
	HWND hWndSpecCmdReciever, // = NULL
	bool bOnlyThisLevel // = false
	)
{
	ASSERT_VALID( this );

	ASSERT( GetTrackingMenu() != this );

INT iter = 0;
	for( ; iter < m_items_all.GetSize(); iter++)
	{
		MENUITEMDATA & mi = m_items_all[ iter ];
		if( mi.IsSeparator() )
			continue;
		if( mi.IsPopup() )
		{
			if( !bOnlyThisLevel )
				mi.GetPopup()->SetCmdTargetToAllItems(
					hWndSpecCmdReciever,
					true
					);
		}
		else
		{
			mi.SetCmdReciever( hWndSpecCmdReciever );
		}
	}
}

//CExtPopupMenuWnd::const_items_container_t &
//	CExtPopupMenuWnd::_GetItemsContaner() const
//{
//	return m_items_all;
//}
//
//CExtPopupMenuWnd::items_container_t &
//	CExtPopupMenuWnd::_GetItemsContaner()
//{
//	return m_items_all;
//}

CExtPopupMenuWnd::MENUITEMDATA &
	CExtPopupMenuWnd::_GetItemRef(int nIndex)
{
	ASSERT_VALID( this );

	ASSERT( nIndex >= 0 && nIndex < m_items_all.GetSize() );
MENUITEMDATA & mi = m_items_all[nIndex];
	return mi;
}

const CExtPopupMenuWnd::MENUITEMDATA &
	CExtPopupMenuWnd::_GetItemRef(int nIndex) const
{
	ASSERT_VALID( this );

	return
		(const_cast< CExtPopupMenuWnd * > (this)) ->
			_GetItemRef(nIndex);
}

void CExtPopupMenuWnd::_InsertItem(
	int nInsertBefore,
	MENUITEMDATA & mi
	)
{
	ASSERT_VALID( this );

	m_items_all.InsertAt(
		(nInsertBefore < 0)
			? m_items_all.GetSize()
			: nInsertBefore
			,
		mi
		);
}

bool CExtPopupBaseWnd::_IsPopupWithShadows() const
{
	if( ! CExtPopupMenuWnd::g_bMenuWithShadows )
		return false;

	return true;
}

bool CExtPopupMenuWnd::_IsPopupWithShadows() const
{
	if( ! CExtPopupBaseWnd::_IsPopupWithShadows() )
		return false;

	if( m_dwTrackFlags & TPMX_NO_SHADOWS )
		return false;

	return true;
}

int CExtPopupBaseWnd::_GetPopupShadowSize() const
{
	if( !_IsPopupWithShadows() )
		return 0;
//int nBitsPerPixel = CExtPaintManager::stat_GetBPP();
//	if( nBitsPerPixel <= 8 )
//		return 0;
	return g_PaintManager->GetMenuShadowSize();
};

int CExtPopupMenuWnd::_GetPopupShadowSize() const
{
	return CExtPopupBaseWnd::_GetPopupShadowSize();
}

#if (!defined __EXT_MFC_NO_CUSTOMIZE)
void CExtPopupMenuWnd::_SetDropIndexBefore(
	int nIndex // = -1 // reset
	)
{
	ASSERT_VALID( this );
	if( m_nHelperDropIndexBefore == nIndex )
		return;
	m_nHelperDropIndexBefore = nIndex;
	if(		GetSafeHwnd() == NULL
		||	(! ::IsWindow(GetSafeHwnd()) )
		)
		return;
CClientDC dc( this );
	_DoPaint( dc );
}

// CExtCustomizeSite::ICustomizeDropTarget
DROPEFFECT CExtPopupMenuWnd::OnCustomizeTargetOver(
	CExtCustomizeSite::CCmdDragInfo & _dragInfo,
	CPoint point,
	DWORD dwKeyState
	)
{
	ASSERT_VALID( this );
	ASSERT( !_dragInfo.IsEmpty() );
	dwKeyState;
	point;

	if( m_pDragSrcNode != NULL )
		m_bHelperDragOverPassed = true;

	ASSERT_VALID( m_pNode );
	ASSERT_VALID( _dragInfo.m_pDropNodeC );
	if(		m_pNode == _dragInfo.m_pDropNodeC
		||	_dragInfo.m_pDropNodeC->IsChild( m_pNode )
		)
		return DROPEFFECT_NONE;

//	_DoResetChainPositions();

	if( ItemGetCount() == 0 )
	{
		if( (dwKeyState & MK_CONTROL) != NULL )
			return DROPEFFECT_COPY;
		return DROPEFFECT_MOVE;
	}

int nIndex = _HitTest( point );
	if( nIndex < 0 )
	{
		if(		nIndex == IDX_SCROLL_TOP
			||	nIndex =