www.pudn.com > uoth_src.zip > MainWnd.cpp


//----------------------------------------------------------------------------- 
//  
// @doc 
// 
// @module	MainWnd.cpp - Main window | 
// 
// This module contains the main window. 
// 
// Copyright (c) 2002 - Descartes Systems Sciences, Inc. 
// 
// All rights reserved. 
// 
// Redistribution and use in source and binary forms, with or without  
// modification, are permitted provided that the following conditions are  
// met: 
//  
// 1. Redistributions of source code must retain the above copyright notice,  
//    this list of conditions and the following disclaimer.  
// 2. Neither the name of Descartes Systems Sciences, Inc nor the names of  
//    its contributors may be used to endorse or promote products derived  
//    from this software without specific prior written permission. 
// 
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS  
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT  
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR  
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT  
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,  
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED  
// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR  
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF  
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING  
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS  
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
// 
// @end 
// 
// $History: Cnf.cpp $ 
//       
//----------------------------------------------------------------------------- 
 
#include "stdafx.h" 
#include "resource.h" 
#include "MainWnd.h" 
#include "uoth.h" 
#include "GeneralOptionsPage.h" 
#include "DisplayOptionsPage.h" 
#include "LevelInfoDlg.h" 
#include "AddRemoveMapDlg.h" 
#include "PrintOutput.h" 
#include "Region.h" 
#include "Treasure.h" 
#include "Character.h" 
#include "RuneLibrary.h" 
#include "ManageCharactersDlg.h" 
#include "ManageRuneLibrariesDlg.h" 
#include "FilterDlg.h" 
#include "TreasureInfoDlg.h" 
#include "Scroll.h" 
#include "UOAMExportDlg.h" 
 
// 
// Debug NEW 
// 
 
#if defined (_DEBUG) 
#define new DEBUG_NEW 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#endif 
 
// 
// Global variables 
// 
 
extern TCHAR g_szAppName []; 
extern TCHAR g_szSettingsFile []; 
extern bool g_fPrettyDrawing; 
extern bool g_fTacksCorrect; 
extern CPrinter g_sPrinter; 
extern CDevMode g_sDevMode; 
extern CImageList g_ilSmall; 
extern CImageList g_ilLarge; 
extern TB_Command g_asCommands []; 
extern int g_nCommands; 
extern CRect g_rectPrintMargins; 
extern CFilter g_sFilter; 
extern COLORREF g_clrRegionWithout; 
extern COLORREF g_clrRegionWith; 
extern COLORREF g_clrTackWithout; 
extern COLORREF g_clrTackWith; 
extern bool g_fTreasureInfoInd; 
 
 
// 
// This is a hacked out routine from WTL's control bar support.  There 
// really should be a better way of doing this. 
// 
 
	BOOL UpdateSimpleReBarBandCtrl(HWND hWndReBar, HWND hWndBand, int nRBIndex,  
		int cxWidth = 0, BOOL bFullWidthAlways = FALSE) 
	{ 
		ATLASSERT(::IsWindow(hWndReBar));	// must be already created 
#ifdef _DEBUG 
		// block - check if this is really a rebar 
		{ 
			TCHAR lpszClassName[sizeof(REBARCLASSNAME)]; 
			::GetClassName(hWndReBar, lpszClassName, sizeof(REBARCLASSNAME)); 
			ATLASSERT(lstrcmp(lpszClassName, REBARCLASSNAME) == 0); 
		} 
#endif //_DEBUG 
		ATLASSERT(::IsWindow(hWndBand));	// must be already created 
 
		// Get number of buttons on the toolbar 
		::SendMessage (hWndBand, TB_AUTOSIZE, 0, 0); 
		int nBtnCount = (int)::SendMessage(hWndBand, TB_BUTTONCOUNT, 0, 0L); 
 
		// Set band info structure 
		REBARBANDINFO rbBand; 
		rbBand.cbSize = sizeof(REBARBANDINFO); 
#if (_WIN32_IE >= 0x0400) 
		rbBand.fMask = RBBIM_CHILDSIZE | RBBIM_SIZE | RBBIM_IDEALSIZE; 
#else 
		rbBand.fMask = RBBIM_CHILDSIZE | RBBIM_SIZE; 
#endif //!(_WIN32_IE >= 0x0400) 
 
		// Calculate the size of the band 
		BOOL bRet; 
		RECT rcTmp; 
		if(nBtnCount > 0) 
		{ 
			bRet = (BOOL)::SendMessage(hWndBand, TB_GETITEMRECT, nBtnCount - 1, (LPARAM)&rcTmp); 
			ATLASSERT(bRet); 
			rbBand.cx = (cxWidth != 0) ? cxWidth : rcTmp.right; 
			rbBand.cyMinChild = rcTmp.bottom - rcTmp.top; 
			if(bFullWidthAlways) 
			{ 
				rbBand.cxMinChild = rbBand.cx; 
			} 
//			else if(lpstrTitle == 0) 
//			{ 
//				bRet = (BOOL)::SendMessage(hWndBand, TB_GETITEMRECT, 0, (LPARAM)&rcTmp); 
//				ATLASSERT(bRet); 
//				rbBand.cxMinChild = rcTmp.right; 
//			} 
			else 
			{ 
				rbBand.cxMinChild = 0; 
			} 
		} 
		else	// no buttons, either not a toolbar or really has no buttons 
		{ 
			bRet = ::GetWindowRect(hWndBand, &rcTmp); 
			ATLASSERT(bRet); 
			rbBand.cx = (cxWidth != 0) ? cxWidth : (rcTmp.right - rcTmp.left); 
			rbBand.cxMinChild = (bFullWidthAlways) ? rbBand.cx : 0; 
			rbBand.cyMinChild = rcTmp.bottom - rcTmp.top; 
		} 
 
#if (_WIN32_IE >= 0x0400) 
		rbBand.cxIdeal = rbBand.cx; 
#endif //(_WIN32_IE >= 0x0400) 
 
		// Add the band 
		LRESULT lRes = ::SendMessage(hWndReBar, RB_SETBANDINFO, nRBIndex, (LPARAM)&rbBand); 
		if(lRes == 0) 
		{ 
			ATLTRACE2(atlTraceUI, 0, _T("Failed to add a band to the rebar.\n")); 
			return FALSE; 
		} 
		::InvalidateRect (hWndBand, NULL, TRUE); 
		return TRUE; 
	} 
 
//----------------------------------------------------------------------------- 
// 
// @mfunc  constructor. 
// 
// @rdesc None. 
// 
//----------------------------------------------------------------------------- 
 
CMainWnd::CMainWnd () 
{ 
	m_fStayOnTop = false; 
} 
 
//----------------------------------------------------------------------------- 
// 
// @mfunc  destructor. 
// 
// @rdesc None. 
// 
//----------------------------------------------------------------------------- 
 
CMainWnd::~CMainWnd () 
{ 
} 
 
//----------------------------------------------------------------------------- 
// 
// @mfunc Create the window 
// 
// @rdesc Handle of the window 
// 
//----------------------------------------------------------------------------- 
 
HWND CMainWnd::Create () 
{ 
 
	// 
	// Load the menu 
	// 
 
	HMENU hMenu = ::LoadMenu (_Module .GetResourceInstance (),  
		MAKEINTRESOURCE (IDR_MAIN_WND)); 
 
	// 
	// Get the stay on top setting 
	// 
 
	m_fStayOnTop = ::GetPrivateProfileInt (PROFILE_SETTINGS,  
		PROFILE_STAYONTOP, 0, g_szSettingsFile) != 0; 
 
	// 
	// Get the creation rect 
	// 
 
	CRect rcCreate (CW_USEDEFAULT, CW_USEDEFAULT, 0, 0); 
	TCHAR szText [256]; 
	::GetPrivateProfileString (PROFILE_SETTINGS, 
		PROFILE_WINPLACEMENT, _T ( ""), szText, _countof (szText), 
		g_szSettingsFile); 
	if (_tcslen (szText) > 0)  
	{ 
		_stscanf (szText, _T ( "%d %d %d %d"), 
			&rcCreate .left, &rcCreate .top, &rcCreate .right, 
			&rcCreate .bottom); 
	} 
 
	// 
	// Create the window 
	// 
 
	DWORD dwStyle = WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN; 
	DWORD dwExStyle = 0; 
	if (m_fStayOnTop) 
		dwExStyle |= WS_EX_TOPMOST; 
	HWND hWndMain = CFrameWindowImpl ::Create ( 
		NULL, rcCreate, g_szAppName, dwStyle, dwExStyle,  
		hMenu); 
	if (hWndMain == NULL) 
		return hWndMain; 
 
	// 
	// Load acceleratiors 
	// 
 
	m_hAccel = ::LoadAccelerators (_Module .GetResourceInstance (),  
		MAKEINTRESOURCE (GetWndClassInfo() .m_uCommonResourceID)); 
 
	// 
	// Initialize the tacks 
	// 
 
	InitializeTacks (); 
 
	// 
	// Show the window 
	// 
 
	::ShowWindow (hWndMain, SW_SHOWNORMAL); 
	return hWndMain; 
} 
 
//----------------------------------------------------------------------------- 
// 
// @mfunc Initialize the window 
// 
// @parm UINT | uMsg | Message 
// 
// @parm WPARAM | wParam | Message w-parameter 
// 
// @parm LPARAM | lParam | Message l-parameter 
// 
// @parm BOOL & | bHandled | If handled, set to true 
// 
// @rdesc Routine results 
// 
//----------------------------------------------------------------------------- 
 
LRESULT CMainWnd::OnCreate (UINT uMsg,  
	WPARAM wParam, LPARAM lParam, BOOL &bHandled)  
{ 
 
	// 
	// Get profile settings 
	// 
 
	m_nTextStyle = (TB_TextStyle) ::GetPrivateProfileInt (PROFILE_SETTINGS,  
		PROFILE_TBTEXTSTYLE, PROFILE_TBTEXTSTYLE_DEFAULT, g_szSettingsFile); 
	m_nIconStyle = (TB_IconStyle) ::GetPrivateProfileInt (PROFILE_SETTINGS,  
		PROFILE_TBICONSTYLE, PROFILE_TBICONSTYLE_DEFAULT, g_szSettingsFile); 
 
	// 
	// Create command bar window 
	// 
 
	HWND hWndCmdBar = m_wndCommandBar .Create (m_hWnd, rcDefault, 
		NULL, ATL_SIMPLE_CMDBAR_PANE_STYLE); 
 
	// 
	// Attach the menu 
	// 
 
	m_wndCommandBar .AttachMenu (GetMenu ()); 
 
	// 
	// Load command bar images 
	// 
 
	CSize sizeIcon; 
	g_ilSmall .GetIconSize (sizeIcon); 
	m_wndCommandBar .SetImageSize (sizeIcon .cx, sizeIcon .cy); 
	m_wndCommandBar .m_hImageList = g_ilSmall .Duplicate (); 
	for (int i = 0; i < g_ilSmall .GetImageCount (); i++) 
	{ 
		int j; 
		for (j = 0; j < g_nCommands; j++) 
		{ 
			if (g_asCommands [j] .iBitmap == i) 
				break; 
		} 
		if (j < g_nCommands) 
            m_wndCommandBar .m_arrCommand .Add (g_asCommands [j] .nCmd); 
		else 
			m_wndCommandBar .m_arrCommand .Add (-1); 
	} 
 
	// 
	// Remove the old menu 
	// 
 
	SetMenu (NULL); 
 
	// 
	// Create the toolbar 
	// 
 
	m_wndToolBar = ::CreateWindowEx (0, TOOLBARCLASSNAME, NULL,  
		ATL_SIMPLE_TOOLBAR_PANE_STYLE, 0, 0, 100, 100, m_hWnd,  
		(HMENU) LongToHandle (ATL_IDW_TOOLBAR), _Module .GetModuleInstance (), 
		NULL); 
 
	// 
	// Do extended initialization of the toolbar 
	// 
 
	m_wndToolBar .SetButtonStructSize (sizeof (TBBUTTON)); 
	m_wndToolBar .SetExtendedStyle (TBSTYLE_EX_DRAWDDARROWS); 
	m_wndToolBar .SetMaxTextRows (0); 
 
	// 
	// Add the toolbar to the list of updated ui elements 
	// 
 
	UIAddToolBar (m_wndToolBar); 
 
	// 
	// Load all the buttons 
	// 
 
	LoadToolbarButtons (); 
	UpdateToolbar (); 
 
	// 
	// Create the rebar 
	// 
 
	CreateSimpleReBar (ATL_SIMPLE_REBAR_NOBORDER_STYLE); 
	AddSimpleReBarBand (hWndCmdBar); 
	AddSimpleReBarBand (m_wndToolBar, NULL, TRUE); 
 
	// 
	// Remove the bars from the bands 
	// 
 
	REBARBANDINFO rbi; 
	memset (&rbi, 0, sizeof (rbi)); 
	rbi .cbSize = REBARBANDINFO_V3_SIZE; 
	rbi .fMask  = RBBIM_STYLE; 
	::SendMessage (m_hWndToolBar, RB_GETBANDINFO, 0, (LPARAM) &rbi); 
	rbi .fStyle |= RBBS_NOGRIPPER; 
	::SendMessage (m_hWndToolBar, RB_SETBANDINFO, 0, (LPARAM) &rbi); 
	::SendMessage (m_hWndToolBar, RB_GETBANDINFO, 1, (LPARAM) &rbi); 
	rbi .fStyle |= RBBS_NOGRIPPER; 
	::SendMessage (m_hWndToolBar, RB_SETBANDINFO, 1, (LPARAM) &rbi); 
 
	// 
	// Create status bar 
	// 
 
	CreateSimpleStatusBar (); 
 
	// 
	// Create the contained window 
	// 
 
	m_hwndMap .Create (this); 
	m_hWndClient = m_hwndMap .m_hWnd; 
 
	// 
	// Update the toolbars 
	// 
 
	UpdateSimpleReBarBandCtrl (m_hWndToolBar, m_wndCommandBar, 0);  
	UpdateSimpleReBarBandCtrl (m_hWndToolBar, m_wndToolBar, 1);  
 
	// 
	// Add the idle handler 
	// 
 
	CMessageLoop *pLoop = _Module .GetMessageLoop (); 
	pLoop ->AddIdleHandler (this); 
	pLoop ->AddMessageFilter (this); 
 
	// 
	// Return FALSE 
	// 
 
	bHandled = FALSE; 
	return false; 
} 
 
//----------------------------------------------------------------------------- 
// 
// @mfunc Handle the user press app exit 
// 
// @parm WORD | wNotifyCode | Command notification code 
//  
// @parm WORD | wID | ID of the control 
// 
// @parm HWND | hWndCtl | Handle of the control 
// 
// @parm BOOL & | bHandled | If handled, set to true 
// 
// @rdesc Routine results 
// 
//----------------------------------------------------------------------------- 
 
LRESULT CMainWnd::OnAppExit (WORD wNotifyCode,  
	WORD wID, HWND hWndCtl, BOOL &bHandled)  
{ 
	 
	// 
	// Close the window 
	// 
 
	PostMessage (WM_CLOSE, 0, 0); 
	return TRUE; 
} 
 
//----------------------------------------------------------------------------- 
// 
// @mfunc Handle the UOAM export 
// 
// @parm WORD | wNotifyCode | Command notification code 
//  
// @parm WORD | wID | ID of the control 
// 
// @parm HWND | hWndCtl | Handle of the control 
// 
// @parm BOOL & | bHandled | If handled, set to true 
// 
// @rdesc Routine results 
// 
//----------------------------------------------------------------------------- 
 
LRESULT CMainWnd::OnFileUOAMExport (WORD wNotifyCode,  
	WORD wID, HWND hWndCtl, BOOL &bHandled)  
{ 
	CUOAMExportDlg::DoUOAMExport (); 
	return TRUE; 
} 
 
//----------------------------------------------------------------------------- 
// 
// @mfunc Handle the user press about 
// 
// @parm WORD | wNotifyCode | Command notification code 
//  
// @parm WORD | wID | ID of the control 
// 
// @parm HWND | hWndCtl | Handle of the control 
// 
// @parm BOOL & | bHandled | If handled, set to true 
// 
// @rdesc Routine results 
// 
//----------------------------------------------------------------------------- 
 
LRESULT CMainWnd::OnAppAbout (WORD wNotifyCode,  
	WORD wID, HWND hWndCtl, BOOL &bHandled)  
{ 
	CString str (MAKEINTRESOURCE (IDS_COPYRIGHT)); 
	::MessageBox (m_hWnd, str, g_szAppName, MB_OK); 
	return TRUE; 
} 
 
//----------------------------------------------------------------------------- 
// 
// @mfunc Handle the view options 
// 
// @parm WORD | wNotifyCode | Command notification code 
//  
// @parm WORD | wID | ID of the control 
// 
// @parm HWND | hWndCtl | Handle of the control 
// 
// @parm BOOL & | bHandled | If handled, set to true 
// 
// @rdesc Routine results 
// 
//----------------------------------------------------------------------------- 
 
LRESULT CMainWnd::OnViewOptions (WORD wNotifyCode,  
	WORD wID, HWND hWndCtl, BOOL &bHandled)  
{ 
	TCHAR szText [32]; 
 
	// 
	// Create the pages 
	// 
 
	CGeneralOptionsPage sPage1; 
	CDisplayOptionsPage sPage2; 
 
	// 
	// Initialize the page contents 
	// 
 
	sPage1 .m_fTreasureInfoInd = g_fTreasureInfoInd; 
 
	sPage2 .m_fPrettyDrawing = g_fPrettyDrawing; 
	sPage2 .m_fTacksCorrect = g_fTacksCorrect; 
	sPage2 .m_clrRegionWithout = g_clrRegionWithout; 
	sPage2 .m_clrRegionWith = g_clrRegionWith; 
	sPage2 .m_clrTackWithout = g_clrTackWithout; 
	sPage2 .m_clrTackWith = g_clrTackWith; 
 
	// 
	// Display 
	//  
 
	CPropertySheet sSheet (g_szAppName, 0, m_hWnd); 
	sSheet .AddPage (sPage1); 
	sSheet .AddPage (sPage2); 
#if !defined (_WIN32_WCE) 
	sSheet .m_psh .dwFlags |= PSH_NOAPPLYNOW; 
//	sSheet .m_psh .dwFlags |= PSH_USEICONID | PSH_HASHELP; 
//	sSheet .m_psh .pszIcon = MAKEINTRESOURCE (IDR_NORMAL_FRAME); 
#endif 
	if (sSheet .DoModal () == IDOK) 
	{ 
 
		// 
		// Save the settings from the pages 
		// 
 
		g_fTreasureInfoInd = sPage1 .m_fTreasureInfoInd; 
 
		g_fPrettyDrawing = sPage2 .m_fPrettyDrawing; 
		g_fTacksCorrect = sPage2 .m_fTacksCorrect; 
		g_clrRegionWithout = sPage2 .m_clrRegionWithout; 
		g_clrRegionWith = sPage2 .m_clrRegionWith; 
		g_clrTackWithout = sPage2 .m_clrTackWithout; 
		g_clrTackWith = sPage2 .m_clrTackWith; 
 
		// 
		// Save the settings 
		// 
 
		::WritePrivateProfileString (PROFILE_SETTINGS,  
			PROFILE_TREASUREINFOIND, g_fTreasureInfoInd ? _T ( "1") : _T ( "0"),  
			g_szSettingsFile); 
		::WritePrivateProfileString (PROFILE_SETTINGS,  
			PROFILE_BEAUTYOVERSPEED, g_fPrettyDrawing ? _T ( "1") : _T ( "0"),  
			g_szSettingsFile); 
		::WritePrivateProfileString (PROFILE_SETTINGS,  
			PROFILE_TACKSCORRECT, g_fTacksCorrect ? _T ( "1") : _T ( "0"),  
			g_szSettingsFile); 
 
		//  
		// Save the colors 
		// 
 
		_sntprintf (szText, _countof (szText), _T ( "%u"), g_clrRegionWith); 
		::WritePrivateProfileString (PROFILE_SETTINGS,  
			PROFILE_WITHHIGHLIGHT, szText, g_szSettingsFile); 
		_sntprintf (szText, _countof (szText), _T ( "%u"), g_clrRegionWithout); 
		::WritePrivateProfileString (PROFILE_SETTINGS,  
			PROFILE_WITHOUTHIGHLIGHT, szText, g_szSettingsFile); 
 
		_sntprintf (szText, _countof (szText), _T ( "%u"), g_clrTackWith); 
		::WritePrivateProfileString (PROFILE_SETTINGS,  
			PROFILE_TACKWITHCOLOR, szText, g_szSettingsFile); 
		_sntprintf (szText, _countof (szText), _T ( "%u"), g_clrTackWithout); 
		::WritePrivateProfileString (PROFILE_SETTINGS,  
			PROFILE_TACKWITHOUTCOLOR, szText, g_szSettingsFile); 
 
		// 
		// Initialize the tacks 
		// 
 
		InitializeTacks (); 
 
		// 
		// Reset the treasure dialog 
		// 
 
		CTreasureInfoDlg::Reset (); 
	} 
	return 1; 
} 
 
//----------------------------------------------------------------------------- 
// 
// @mfunc Show the world 
// 
// @parm WORD | wNotifyCode | Command notification code 
//  
// @parm WORD | wID | ID of the control 
// 
// @parm HWND | hWndCtl | Handle of the control 
// 
// @parm BOOL & | bHandled | If handled, set to true 
// 
// @rdesc Routine results 
// 
//----------------------------------------------------------------------------- 
 
LRESULT CMainWnd::OnViewWorld (WORD wNotifyCode,  
	WORD wID, HWND hWndCtl, BOOL &bHandled)  
{ 
	ShowWorld (); 
	return TRUE; 
} 
 
//----------------------------------------------------------------------------- 
// 
// @mfunc Show a region 
// 
// @parm WORD | wNotifyCode | Command notification code 
//  
// @parm WORD | wID | ID of the control 
// 
// @parm HWND | hWndCtl | Handle of the control 
// 
// @parm BOOL & | bHandled | If handled, set to true 
// 
// @rdesc Routine results 
// 
//----------------------------------------------------------------------------- 
 
LRESULT CMainWnd::OnViewRegion (WORD wNotifyCode,  
	WORD wID, HWND hWndCtl, BOOL &bHandled)  
{ 
	ShowRegion (wID - ID_VIEW_REGION_FIRST + 1, -1); 
	return TRUE; 
} 
 
//----------------------------------------------------------------------------- 
// 
// @mfunc Change the stay on top setting 
// 
// @parm WORD | wNotifyCode | Command notification code 
//  
// @parm WORD | wID | ID of the control 
// 
// @parm HWND | hWndCtl | Handle of the control 
// 
// @parm BOOL & | bHandled | If handled, set to true 
// 
// @rdesc Routine results 
// 
//----------------------------------------------------------------------------- 
 
LRESULT CMainWnd::OnViewStayOnTop (WORD wNotifyCode,  
	WORD wID, HWND hWndCtl, BOOL &bHandled)  
{ 
 
	// 
	// Toggle the bit 
	// 
 
	m_fStayOnTop = !m_fStayOnTop; 
 
	// 
	// Change the window setting 
	// 
 
	SetWindowPos (m_fStayOnTop ? HWND_TOPMOST : HWND_NOTOPMOST, 
		0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); 
 
	// 
	// Save the setting 
	// 
 
	::WritePrivateProfileString (PROFILE_SETTINGS,  
		PROFILE_STAYONTOP, m_fStayOnTop ? _T ( "1") : _T ( "0"),  
		g_szSettingsFile); 
	return TRUE; 
} 
 
//----------------------------------------------------------------------------- 
// 
// @mfunc Handle idle processing 
// 
// @rdesc Routine results 
// 
//----------------------------------------------------------------------------- 
 
BOOL CMainWnd::OnIdle () 
{ 
 
	// 
	// Commands we don't support that a child might 
	// 
 
	UIEnable (ID_EDIT_COPY, FALSE); 
	UIEnable (ID_EDIT_NEXT_REGION, FALSE); 
	UIEnable (ID_EDIT_PREVIOUS_REGION, FALSE); 
	UIEnable (ID_EDIT_NEXT_TREASURE, FALSE); 
	UIEnable (ID_EDIT_PREVIOUS_TREASURE, FALSE); 
 
	// 
	// Commands we support 
	// 
 
	UIEnable (ID_EDIT_I_JUST_GOT, TRUE); 
	UIEnable (ID_EDIT_I_JUST_COMPLETED, TRUE); 
	UIEnable (ID_VIEW_TREASURE_INFORMATION, TRUE); 
	UIEnable (ID_VIEW_LEVEL_INFORMATION, TRUE); 
 
	// 
	// Invoke idle for client 
	//  
 
	if (m_hWndClient == m_hwndRegion .m_hWnd) 
		m_hwndRegion .OnIdle (this); 
	else if (m_hWndClient == m_hwndMap .m_hWnd) 
		m_hwndMap .OnIdle (this); 
 
	// 
	// Update the checks 
	// 
 
	UISetCheck (ID_VIEW_STAY_ON_TOP, m_fStayOnTop); 
 
	// 
	// Update the toolbar 
	// 
 
	UIUpdateToolBar (); 
	return FALSE; 
} 
 
//----------------------------------------------------------------------------- 
// 
// @mfunc Handle hot item change 
// 
// @parm int | idCtrl | Id of the control 
// 
// @parm LPNMHDR | pnmh | Notify message header 
// 
// @parm BOOL & | bHandled | If handled, set to true 
// 
// @rdesc Routine results 
// 
//----------------------------------------------------------------------------- 
 
LRESULT CMainWnd::OnHotItemChange (int idCtrl,  
	LPNMHDR pnmh, BOOL &bHandled)  
{ 
	// 
	// Get the tooltip notify structure 
	// 
 
	NMTBHOTITEM *pHIC = (NMTBHOTITEM *) pnmh; 
	 
	// 
	// Return if this is not the toolbar 
	// 
 
	if (pHIC ->hdr .hwndFrom != m_wndToolBar) 
		return FALSE; 
 
	// 
	// If no control 
	// 
 
	if (pHIC ->dwFlags & HICF_LEAVING) 
	{ 
		SetStatusBarText (NULL); 
	} 
 
	// 
	// If new control 
	// 
 
	else if (pHIC ->idNew != 0) 
	{ 
		// 
		// Get the control id 
		// 
 
		UINT nID = pHIC ->idNew; 
 
		// 
		// If disabled, then display nothing 
		// 
 
		UINT nState = m_wndToolBar .GetState (nID); 
		if ((nState & TBSTATE_ENABLED) == 0) 
		{ 
			SetStatusBarText (NULL); 
		} 
 
		// 
		// Otherwise 
		// 
 
		else 
		{ 
			TCHAR szText [128]; 
			TCHAR szText2 [128]; 
			::LoadString (_Module .GetResourceInstance (),  
				nID, szText, _countof (szText)); 
			ExtractString (szText2, _countof (szText2), 
				szText, 0, '\n'); 
			SetStatusBarText (szText2); 
		} 
	} 
	return FALSE; 
} 
 
//----------------------------------------------------------------------------- 
// 
// @mfunc Set the status bar text 
// 
// @parm LPCTSTR | pszText | Text to set or NULL for idle 
// 
// @rdesc None. 
// 
//----------------------------------------------------------------------------- 
 
void CMainWnd::SetStatusBarText (LPCTSTR pszText) 
{ 
 
	// 
	// If NULL, display idle 
	// 
 
	if (pszText == NULL) 
	{ 
		TCHAR szText [128]; 
		::LoadString (_Module .GetResourceInstance (),  
			ATL_IDS_IDLEMESSAGE, szText, _countof (szText)); 
		::SetWindowText (m_hWndStatusBar, szText); 
		::SendMessage (m_hWndStatusBar, SB_SIMPLE, 0, 0); 
	} 
 
	// 
	// Otherwise 
	// 
 
	else 
	{ 
		::SendMessage (m_hWndStatusBar, SB_SETTEXT,  
			SBT_NOBORDERS | 255, (LPARAM) pszText); 
		::SendMessage (m_hWndStatusBar, SB_SIMPLE, 1, 0); 
	} 
} 
 
//----------------------------------------------------------------------------- 
// 
// @mfunc Show the region window 
// 
// @parm int | nRegion | Region number 
// 
// @parm int | nTreasure | Treasure number 
// 
// @rdesc None. 
// 
//----------------------------------------------------------------------------- 
 
void CMainWnd::ShowRegion (int nRegion, int nTreasure) 
{ 
 
	// 
	// If we haven't created the region window, then create 
	// 
 
	if (m_hwndRegion .m_hWnd == NULL) 
		m_hwndRegion .Create (this); 
 
	// 
	// Set the region and treasure 
	// 
 
	m_hwndRegion .SetRegion (nRegion, nTreasure); 
 
	// 
	// Show the window 
	// 
 
	if (m_hWndClient != m_hwndRegion .m_hWnd) 
	{ 
		::ShowWindow (m_hWndClient, SW_HIDE); 
		m_hWndClient = m_hwndRegion .m_hWnd; 
		UpdateLayout (); 
		::ShowWindow (m_hWndClient, SW_SHOW); 
	} 
} 
 
//----------------------------------------------------------------------------- 
// 
// @mfunc Show the world window 
// 
// @rdesc None. 
// 
//----------------------------------------------------------------------------- 
 
void CMainWnd::ShowWorld () 
{ 
 
	// 
	// Show the window 
	// 
 
	if (m_hWndClient != m_hwndMap .m_hWnd) 
	{ 
		::ShowWindow (m_hWndClient, SW_HIDE); 
		m_hWndClient = m_hwndMap .m_hWnd; 
		UpdateLayout (); 
		::ShowWindow (m_hWndClient, SW_SHOW); 
	} 
} 
 
//----------------------------------------------------------------------------- 
// 
// @mfunc Handle the region drop down 
// 
// @parm WORD | wNotifyCode | Command notification code 
//  
// @parm WORD | wID | ID of the control 
// 
// @parm HWND | hWndCtl | Handle of the control 
// 
// @parm BOOL & | bHandled | If handled, set to true 
// 
// @rdesc Routine results 
// 
//----------------------------------------------------------------------------- 
 
LRESULT CMainWnd::OnViewRegionDropDown (WORD wNotifyCode,  
	WORD wID, HWND hWndCtl, BOOL& bHandled)  
{ 
 
	// 
	// Create the menu 
	// 
 
	HMENU hMenu = ::CreatePopupMenu (); 
	for (int ir = 0, iMenu = 0; ir < CRegion::gm_vRegions .GetCount (); ++ir) 
	{ 
		CRegion *pRegion = &CRegion::gm_vRegions [ir]; 
		if (!pRegion ->IsValid ()) 
			continue; 
		::InsertMenu (hMenu, iMenu, MF_STRING | MF_BYPOSITION,  
			ID_VIEW_REGION_FIRST + pRegion ->m_nIndex - 1,  
			pRegion ->m_strName); 
		iMenu++; 
	} 
 
	// 
	// Get the rectangle 
	// 
 
	CRect rect; 
	int nIndex = ::SendMessage (hWndCtl, TB_COMMANDTOINDEX,  
		wID, (LPARAM) &rect); 
	::SendMessage (hWndCtl, TB_GETITEMRECT, nIndex, (LPARAM) &rect); 
	::ClientToScreen (hWndCtl, (LPPOINT) &rect .left); 
	::ClientToScreen (hWndCtl, (LPPOINT) &rect .right); 
 
	// 
	// Track the popup.  Normally, we would use CommandBar to show the nice 
	// and cute icons.  But since this popup doesn't have any, we don't  
	// waste the extended screen space. 
	// 
 
	::TrackPopupMenuEx (hMenu, TPM_LEFTALIGN | TPM_TOPALIGN,  
		rect .left, rect .bottom, m_hWnd, NULL); 
 
	// 
	// Destroy the menu 
	// 
 
	::DestroyMenu (hMenu); 
	return TRUE; 
} 
 
//----------------------------------------------------------------------------- 
// 
// @mfunc Handle final window message 
// 
// @parm HWND | hWnd | Handle of the window 
// 
// @rdesc None 
// 
//----------------------------------------------------------------------------- 
 
void CMainWnd::OnFinalMessage (HWND hWnd) 
{ 
	// 
	// Remove the idle handler 
	// 
 
	CMessageLoop *pLoop = _Module .GetMessageLoop (); 
	pLoop ->RemoveIdleHandler (this); 
	pLoop ->RemoveMessageFilter (this); 
} 
 
//----------------------------------------------------------------------------- 
// 
// @mfunc Handle window destruction 
// 
// @parm UINT | uMsg | Message 
// 
// @parm WPARAM | wParam | Message w-parameter 
// 
// @parm LPARAM | lParam | Message l-parameter 
// 
// @parm BOOL & | bHandled | If handled, set to true 
// 
// @rdesc Routine results 
// 
//----------------------------------------------------------------------------- 
 
LRESULT CMainWnd::OnDestroy (UINT uMsg,  
	WPARAM wParam, LPARAM lParam, BOOL &bHandled)  
{ 
 
	// 
	// Mark as not handled so the WCE rundown code gets called 
	// 
 
	bHandled = FALSE; 
 
	// 
	// Save the window size  
	// 
 
	TCHAR szText [255]; 
	WINDOWPLACEMENT place; 
	place .length = sizeof (place); 
	::GetWindowPlacement (m_hWnd, &place); 
	_sntprintf (szText, _countof (szText), _T ( "%d %d %d %d"), 
	    place .rcNormalPosition .left, place .rcNormalPosition .top,  
		place .rcNormalPosition .right, place .rcNormalPosition .bottom); 
	::WritePrivateProfileString (PROFILE_SETTINGS,  
		PROFILE_WINPLACEMENT, szText, g_szSettingsFile); 
	 
	// 
	// Return 
	// 
 
	return false; 
} 
 
//----------------------------------------------------------------------------- 
// 
// @mfunc Initialize the tacks 
// 
// @rdesc None. 
// 
//----------------------------------------------------------------------------- 
 
void CMainWnd::InitializeTacks ()  
{ 
 
	// 
	// Invoke the main routine 
	// 
 
	CTreasure::InitializeTacks (m_hWnd); 
 
	// 
	// Invalidate the client 
	// 
 
	if (m_hWndClient) 
		::InvalidateRect (m_hWndClient, NULL, FALSE); 
} 
 
//----------------------------------------------------------------------------- 
// 
// @mfunc View the treasure information 
// 
// @parm WORD | wNotifyCode | Command notification code 
//  
// @parm WORD | wID | ID of the control 
// 
// @parm HWND | hWndCtl | Handle of the control 
// 
// @parm BOOL & | bHandled | If handled, set to true 
// 
// @rdesc Routine results 
// 
//----------------------------------------------------------------------------- 
 
LRESULT CMainWnd::OnViewTreasureInformation (WORD wNotifyCode,  
	WORD wID, HWND hWndCtl, BOOL &bHandled)  
{ 
 
	// 
	// Invoke the helper 
	// 
 
	CTreasureInfoDlg::Show (1); 
	return TRUE; 
} 
 
//----------------------------------------------------------------------------- 
// 
// @mfunc View the level information 
// 
// @parm WORD | wNotifyCode | Command notification code 
//  
// @parm WORD | wID | ID of the control 
// 
// @parm HWND | hWndCtl | Handle of the control 
// 
// @parm BOOL & | bHandled | If handled, set to true 
// 
// @rdesc Routine results 
// 
//----------------------------------------------------------------------------- 
 
LRESULT CMainWnd::OnViewLevelInformation (WORD wNotifyCode,  
	WORD wID, HWND hWndCtl, BOOL &bHandled)  
{ 
 
	// 
	// Display the dialog 
	// 
 
	CLevelInfoDlg dlg (1); 
	dlg .DoModal (); 
	return TRUE; 
} 
 
//----------------------------------------------------------------------------- 
// 
// @mfunc Edit treasure map counts 
// 
// @parm WORD | wNotifyCode | Command notification code 
//  
// @parm WORD | wID | ID of the control 
// 
// @parm HWND | hWndCtl | Handle of the control 
// 
// @parm BOOL & | bHandled | If handled, set to true 
// 
// @rdesc Routine results 
// 
//----------------------------------------------------------------------------- 
 
LRESULT CMainWnd::OnEditIJustGot (WORD wNotifyCode,  
	WORD wID, HWND hWndCtl, BOOL &bHandled)  
{ 
 
	// 
	// Display the dialog 
	// 
 
	CAddRemoveMapDlg dlg (0, wID == ID_EDIT_I_JUST_GOT); 
	dlg .DoModal (); 
	return TRUE; 
} 
 
//----------------------------------------------------------------------------- 
// 
// @mfunc Handle the user press print 
// 
// @parm WORD | wNotifyCode | Command notification code 
//  
// @parm WORD | wID | ID of the control 
// 
// @parm HWND | hWndCtl | Handle of the control 
// 
// @parm BOOL & | bHandled | If handled, set to true 
// 
// @rdesc Routine results 
// 
//----------------------------------------------------------------------------- 
 
LRESULT CMainWnd::OnFilePrint (WORD wNotifyCode,  
	WORD wID, HWND hWndCtl, BOOL &bHandled)  
{ 
	CPrintOutput sPrint; 
	sPrint .Print (m_hWnd); 
	return TRUE; 
} 
 
//----------------------------------------------------------------------------- 
// 
// @mfunc Change to the specified character 
// 
// @parm WORD | wNotifyCode | Command notification code 
//  
// @parm WORD | wID | ID of the control 
// 
// @parm HWND | hWndCtl | Handle of the control 
// 
// @parm BOOL & | bHandled | If handled, set to true 
// 
// @rdesc Routine results 
// 
//----------------------------------------------------------------------------- 
 
LRESULT CMainWnd::OnViewCharacter (WORD wNotifyCode,  
	WORD wID, HWND hWndCtl, BOOL &bHandled)  
{ 
	TCHAR szString [256]; 
	CMenuItemInfo mii; 
	mii .fMask = MIIM_TYPE | MIIM_STATE | MIIM_SUBMENU; 
	mii .fType = MFT_STRING; 
	mii .dwTypeData = szString; 
	mii .cch = _countof (szString); 
	if (::GetMenuItemInfo (m_wndCommandBar .GetMenu (),  
		wID, FALSE, &mii)) 
	{ 
		CCharacter *pCharacter = CCharacter::Find (szString); 
		if (pCharacter) 
			CCharacter::SetCurrent (pCharacter); 
	} 
	return TRUE; 
} 
 
//----------------------------------------------------------------------------- 
// 
// @mfunc Manage the characters 
// 
// @parm WORD | wNotifyCode | Command notification code 
//  
// @parm WORD | wID | ID of the control 
// 
// @parm HWND | hWndCtl | Handle of the control 
// 
// @parm BOOL & | bHandled | If handled, set to true 
// 
// @rdesc Routine results 
// 
//----------------------------------------------------------------------------- 
 
LRESULT CMainWnd::OnViewManageCharacters (WORD wNotifyCode,  
	WORD wID, HWND hWndCtl, BOOL &bHandled)  
{ 
	CManageCharactersDlg dlg; 
	dlg .DoModal (); 
	return TRUE; 
} 
 
//----------------------------------------------------------------------------- 
// 
// @mfunc Change to the specified rune library 
// 
// @parm WORD | wNotifyCode | Command notification code 
//  
// @parm WORD | wID | ID of the control 
// 
// @parm HWND | hWndCtl | Handle of the control 
// 
// @parm BOOL & | bHandled | If handled, set to true 
// 
// @rdesc Routine results 
// 
//----------------------------------------------------------------------------- 
 
LRESULT CMainWnd::OnViewRuneLibrary (WORD wNotifyCode,  
	WORD wID, HWND hWndCtl, BOOL &bHandled)  
{ 
	TCHAR szString [256]; 
	CMenuItemInfo mii; 
	mii .fMask = MIIM_TYPE | MIIM_STATE | MIIM_SUBMENU; 
	mii .fType = MFT_STRING; 
	mii .dwTypeData = szString; 
	mii .cch = _countof (szString); 
	if (::GetMenuItemInfo (m_wndCommandBar .GetMenu (),  
		wID, FALSE, &mii)) 
	{ 
		CRuneLibrary *pRuneLibrary = CRuneLibrary::Find (szString); 
		if (pRuneLibrary) 
			CRuneLibrary::SetCurrent (pRuneLibrary); 
	} 
	return TRUE; 
} 
 
//----------------------------------------------------------------------------- 
// 
// @mfunc Manage the rune libraries 
// 
// @parm WORD | wNotifyCode | Command notification code 
//  
// @parm WORD | wID | ID of the control 
// 
// @parm HWND | hWndCtl | Handle of the control 
// 
// @parm BOOL & | bHandled | If handled, set to true 
// 
// @rdesc Routine results 
// 
//----------------------------------------------------------------------------- 
 
LRESULT CMainWnd::OnViewManageRuneLibraries (WORD wNotifyCode,  
	WORD wID, HWND hWndCtl, BOOL &bHandled)  
{ 
	CManageRuneLibrariesDlg dlg; 
	dlg .DoModal (); 
	return TRUE; 
} 
 
//----------------------------------------------------------------------------- 
// 
// @mfunc Handle window menu popup 
// 
// @parm UINT | uMsg | Message 
// 
// @parm WPARAM | wParam | Message w-parameter 
// 
// @parm LPARAM | lParam | Message l-parameter 
// 
// @parm BOOL & | bHandled | If handled, set to true 
// 
// @rdesc Routine results 
// 
//----------------------------------------------------------------------------- 
 
LRESULT CMainWnd::OnInitMenuPopup (UINT uMsg,  
	WPARAM wParam, LPARAM lParam, BOOL &bHandled) 
{ 
 
	// 
	// Get information from the message 
	// 
 
	HMENU hMenu = (HMENU) wParam; 
	UINT nPos = LOWORD (lParam); 
	bool fIsWindowMenu = HIWORD (lParam) != 0; 
	if (!fIsWindowMenu) 
	{ 
 
		// 
		// See if this is the first time the region has been displayed 
		// 
 
		if (::GetMenuItemID (hMenu, 0) == ID_VIEW_DUMMY_REGION) 
		{ 
 
			// 
			// Delete the dummy item and add all the regions 
			// 
 
			::DeleteMenu (hMenu, 0, MF_BYPOSITION); 
			for (int ir = 0; ir < CRegion::gm_vRegions .GetCount (); ++ir) 
			{ 
				CRegion *pRegion = &CRegion::gm_vRegions [ir]; 
				if (!pRegion ->IsValid ()) 
					continue; 
				::AppendMenu (hMenu, MF_STRING, 
					ID_VIEW_REGION_FIRST + pRegion ->m_nIndex - 1,  
					(LPCTSTR) pRegion ->m_strName); 
			} 
		} 
 
		// 
		// See if this is the character menu 
		// 
 
		else if (::GetMenuItemID (hMenu, ::GetMenuItemCount (hMenu) - 1)  
			== ID_VIEW_CHARACTERS_MANAGE) 
		{ 
 
			// 
			// Delete all but the last menu item 
			// 
 
			while (::GetMenuItemCount (hMenu) > 1) 
				::DeleteMenu (hMenu, 0, MF_BYPOSITION); 
 
			// 
			// Collect a list of characters 
			// 
 
			int nChars = (int) CCharacter::gm_vCharacters .GetCount (); 
			CCharacter **ppChars = (CCharacter **) alloca ( 
				nChars * sizeof (CCharacter *)); 
			for (int ic = 0; ic < nChars; ++ic) 
				ppChars [ic] = &CCharacter::gm_vCharacters [ic]; 
 
			// 
			// Sort the list (ok, the sucky way, deal with it) 
			// 
 
			bool fSwapped = true; 
			while (fSwapped) 
			{ 
				fSwapped = false; 
				for (int i = 0; i + 1 < nChars; i++) 
				{ 
					if (_tcsicmp (ppChars [i] ->m_strName,  
						ppChars [i + 1] ->m_strName) > 0) 
					{ 
						fSwapped = true; 
						CCharacter *pTemp = ppChars [i]; 
						ppChars [i] = ppChars [i + 1]; 
						ppChars [i + 1] = pTemp; 
					} 
				} 
			} 
 
			// 
			// Populate 
			// 
 
			CCharacter *pCharacterCurr = CCharacter::GetCurrent (); 
			for (int i = 0; i < nChars; i++) 
			{ 
				UINT uFlags = MF_STRING | MF_BYPOSITION; 
				if (pCharacterCurr == ppChars [i]) 
					uFlags |= MF_CHECKED; 
				::InsertMenu (hMenu, i, uFlags, 
					ID_VIEW_CHARACTER_FIRST + i,  
					(LPCTSTR) ppChars [i] ->m_strName); 
			} 
 
			// 
			// Add sep 
			// 
 
			if (nChars > 0) 
			{ 
				::InsertMenu (hMenu, nChars,  
					MF_BYPOSITION | MF_SEPARATOR, 0, NULL); 
			} 
		} 
 
		// 
		// See if this is the rune library menu 
		// 
 
		else if (::GetMenuItemID (hMenu, ::GetMenuItemCount (hMenu) - 1)  
			== ID_VIEW_RUNE_LIBRARIES_MANAGE) 
		{ 
 
			// 
			// Delete all but the last menu item 
			// 
 
			while (::GetMenuItemCount (hMenu) > 1) 
				::DeleteMenu (hMenu, 0, MF_BYPOSITION); 
 
			// 
			// Collect a list of rune libraries 
			// 
 
			int nRuneLibs = (int) CRuneLibrary::gm_vRuneLibraries .GetCount (); 
			CRuneLibrary **ppRuneLibs = (CRuneLibrary **) alloca ( 
				nRuneLibs * sizeof (CRuneLibrary *)); 
			for (int irl = 0; irl < nRuneLibs; irl++) 
				ppRuneLibs [irl] = &CRuneLibrary::gm_vRuneLibraries [irl]; 
 
			// 
			// Sort the list (ok, the sucky way, deal with it) 
			// 
 
			bool fSwapped = true; 
			while (fSwapped) 
			{ 
				fSwapped = false; 
				for (int i = 0; i + 1 < nRuneLibs; i++) 
				{ 
					if (_tcsicmp (ppRuneLibs [i] ->m_strName,  
						ppRuneLibs [i + 1] ->m_strName) > 0) 
					{ 
						fSwapped = true; 
						CRuneLibrary *pTemp = ppRuneLibs [i]; 
						ppRuneLibs [i] = ppRuneLibs [i + 1]; 
						ppRuneLibs [i + 1] = pTemp; 
					} 
				} 
			} 
 
			// 
			// Populate 
			// 
 
			CRuneLibrary *pRuneLibraryCurr = CRuneLibrary::GetCurrent (); 
			for (int i = 0; i < nRuneLibs; i++) 
			{ 
				UINT uFlags = MF_STRING | MF_BYPOSITION; 
				if (pRuneLibraryCurr == ppRuneLibs [i]) 
					uFlags |= MF_CHECKED; 
				::InsertMenu (hMenu, i, uFlags, 
					ID_VIEW_RUNE_LIBRARY_FIRST + i,  
					(LPCTSTR) ppRuneLibs [i] ->m_strName); 
			} 
 
			// 
			// Add sep 
			// 
 
			if (nRuneLibs > 0) 
			{ 
				::InsertMenu (hMenu, nRuneLibs,  
					MF_BYPOSITION | MF_SEPARATOR, 0, NULL); 
			} 
		} 
	} 
	bHandled = FALSE; 
	return 0; 
} 
 
//----------------------------------------------------------------------------- 
// 
// @mfunc Load the toolbar buttons 
// 
// @rdesc None. 
// 
//----------------------------------------------------------------------------- 
 
void CMainWnd::LoadToolbarButtons () 
{ 
	TBBUTTON asTBBtn [100]; 
	TCHAR szText [1024]; 
 
	// 
	// Get the array to toolbar commands 
	// 
 
	::GetPrivateProfileString (PROFILE_SETTINGS, PROFILE_TBBUTTONS,  
		_T ( ""), szText, _countof (szText),	g_szSettingsFile); 
	int nButtons = DecodeToolbarButtons (szText, asTBBtn, _countof (asTBBtn)); 
	if (nButtons <= 0) 
	{ 
		_sntprintf (szText, _countof (szText),  
			_T ( "%d,0,%d,%d,%d,0,%d,%d,%d,%d,%d,0,%d"), 
			ID_VIEW_WORLD, ID_VIEW_REGION, ID_EDIT_PREVIOUS_REGION,  
			ID_EDIT_NEXT_REGION, ID_EDIT_PREVIOUS_TREASURE,  
			ID_EDIT_NEXT_TREASURE, ID_VIEW_TREASURE_INFORMATION, 
			ID_EDIT_I_JUST_GOT, ID_EDIT_I_JUST_COMPLETED, ID_APP_ABOUT); 
		nButtons = DecodeToolbarButtons (szText, asTBBtn, _countof (asTBBtn)); 
	} 
 
	// 
	// Add all the buttons 
	// 
 
	m_wndToolBar .AddButtons (nButtons, asTBBtn); 
	return; 
} 
 
//----------------------------------------------------------------------------- 
// 
// @mfunc Handle drop down 
// 
// @parm int | idCtrl | Id of the control 
// 
// @parm LPNMHDR | pnmh | Notify message header 
// 
// @parm BOOL & | bHandled | If handled, set to true 
// 
// @rdesc Routine results 
// 
//----------------------------------------------------------------------------- 
 
LRESULT CMainWnd::OnTBDropDown (int idCtrl,  
	LPNMHDR pnmh, BOOL &bHandled)  
{ 
	NMTOOLBAR *pnmTB = (NMTOOLBAR *) pnmh; 
 
	// 
	// If this is the view regions button 
	// 
 
	if (pnmTB ->iItem == ID_VIEW_REGION) 
	{ 
		OnViewRegionDropDown (0, pnmTB ->iItem,  
			pnmh ->hwndFrom, bHandled); 
		return TBDDRET_DEFAULT; 
	} 
	else 
		return TBDDRET_TREATPRESSED; 
} 
 
//----------------------------------------------------------------------------- 
// 
// @mfunc Handle toolbar right click 
// 
// @parm int | idCtrl | Id of the control 
// 
// @parm LPNMHDR | pnmh | Notify message header 
// 
// @parm BOOL & | bHandled | If handled, set to true 
// 
// @rdesc Routine results 
// 
//----------------------------------------------------------------------------- 
 
LRESULT CMainWnd::OnToolbarRClick (int idCtrl, LPNMHDR pnmh, BOOL &bHandled) 
{ 
	LPNMMOUSE pnmmouse = (LPNMMOUSE) pnmh; 
 
	// 
	// Load the popup menu 
	// 
 
	CMenu hMenu = ::LoadPopupMenu (_Module .GetResourceInstance (), 
		IDR_TOOLBAR_POPUP, 0); 
	if (hMenu .m_hMenu == NULL) 
		return TRUE; 
 
	// 
	// Track the popup 
	// 
 
	CPoint pt (pnmmouse ->pt); 
	::ClientToScreen (m_wndToolBar, &pt); 
//	m_wndCommandBar .TrackPopupMenu (hMenu,  
//		TPM_LEFTALIGN | TPM_TOPALIGN, 
//		pt .x, pt .y); 
	::TrackPopupMenuEx (hMenu,  
		TPM_LEFTALIGN | TPM_TOPALIGN,  
		pt .x, pt .y, m_hWnd, NULL); 
	return TRUE; 
} 
 
//----------------------------------------------------------------------------- 
// 
// @mfunc Handle customize of toolbar 
// 
// @parm WORD | wNotifyCode | Command notification code 
//  
// @parm WORD | wID | ID of the control 
// 
// @parm HWND | hWndCtl | Handle of the control 
// 
// @parm BOOL & | bHandled | If handled, set to true 
// 
// @rdesc Routine results 
// 
//----------------------------------------------------------------------------- 
 
LRESULT CMainWnd::OnPopupCustomizeToolbar (WORD wNotifyCode,  
	WORD wID, HWND hWndCtl, BOOL &bHandled)  
{ 
	m_wndToolBar .Customize (); 
	return TRUE; 
} 
 
//----------------------------------------------------------------------------- 
// 
// @mfunc Handle toolbar right click 
// 
// @parm int | idCtrl | Id of the control 
// 
// @parm LPNMHDR | pnmh | Notify message header 
// 
// @parm BOOL & | bHandled | If handled, set to true 
// 
// @rdesc Routine results 
// 
//----------------------------------------------------------------------------- 
 
LRESULT CMainWnd::OnCustomizeToolbar (int idCtrl, LPNMHDR pnmh, BOOL &bHandled) 
{ 
 
	// 
	// Allow any button to be inserted anywhere and also 
	// allow any button to be deleted 
	// 
 
	if (pnmh ->code == TBN_QUERYINSERT || 
		pnmh ->code == TBN_QUERYDELETE) 
	{ 
		return TRUE; 
	} 
   
	// 
	// Disable the help button 
	// 
 
	if (pnmh ->code == TBN_INITCUSTOMIZE) 
	{ 
 
		// 
		// Ok, this is an UNDOCUMENTED hack.  The initialize message 
		// actually contains the handle of the dialog for customization. 
		// 
 
		typedef struct hack_tagNMTOOLBARINIT 
		{ 
			NMHDR   hdr; 
			HWND	hWndDialog; 
		} hack_NMTOOLBARINIT; 
		hack_NMTOOLBARINIT *pNMHack = (hack_NMTOOLBARINIT *) pnmh; 
		HWND hDlg = pNMHack ->hWndDialog; 
 
		// 
		// If the dialog hasn't been created 
		// 
 
		if (m_sTBDlg .m_hWnd == NULL) 
		{ 
 
			// 
			// Get the rect of the dialog 
			// 
 
			CRect rectDlg; 
			::GetClientRect (hDlg, &rectDlg); 
			CRect rectScreenDlg; 
			::GetWindowRect (hDlg, &rectScreenDlg); 
 
			// 
			// Load our dialog 
			// 
 
			m_sTBDlg .Create (pNMHack ->hWndDialog, 0); 
 
			// 
			// Get the extra dialog rect 
			// 
 
			CRect rectSubDlg; 
			m_sTBDlg .GetClientRect (&rectSubDlg); 
 
			// 
			// Reposition the extra dialog rect 
			// 
 
			HWND hWndAfter = ::GetNextWindow ( 
				::GetDlgItem (hDlg, IDCANCEL), GW_HWNDPREV); 
			m_sTBDlg .SetWindowPos (hWndAfter, 0, rectDlg .bottom, 
				rectSubDlg .Width (),rectSubDlg .Height (), 0); 
 
			// 
			// Resize the main dialog 
			// 
 
			::SetWindowPos (hDlg, NULL, 0, 0, rectScreenDlg .Width (), 
				rectScreenDlg .Height () + rectSubDlg .Height (), 
				SWP_NOZORDER | SWP_NOMOVE); 
		} 
 
		// 
		// Get the current settings 
		// 
 
		m_sTBDlg .SetTextStyle (m_nTextStyle); 
		m_sTBDlg .SetIconStyle (m_nIconStyle); 
		return TBNRF_HIDEHELP; 
	} 
 
	// 
	// Get the button information 
	// 
 
    else if (pnmh ->code == TBN_GETBUTTONINFO) 
    { 
		LPTBNOTIFY pTbNotify = (LPTBNOTIFY) pnmh; 
 
		// 
		// If we have done all the entries, return 
		// 
 
		if (pTbNotify ->iItem >= g_nCommands) 
			return FALSE; 
 
 
		// 
		// Otherwise, populate the structure 
		// 
 
		TCHAR szBuffer [256]; 
		pTbNotify ->tbButton .iBitmap = g_asCommands [pTbNotify ->iItem] .iBitmap; 
		pTbNotify ->tbButton .idCommand = g_asCommands [pTbNotify ->iItem] .nCmd; 
		pTbNotify ->tbButton .fsState = TBSTATE_ENABLED; 
		pTbNotify ->tbButton .fsStyle = g_asCommands [pTbNotify ->iItem] .fsStyle; 
		pTbNotify ->tbButton .dwData = 0; 
		pTbNotify ->tbButton .iString = 0; 
		UpdateButton (&pTbNotify ->tbButton); 
 
		// 
		// Use the tooltip text as the text 
		// 
 
		::LoadString (_Module .GetResourceInstance (), 
			g_asCommands [pTbNotify ->iItem] .nCmd, szBuffer,  
			_countof (szBuffer)); 
		::ExtractString (pTbNotify ->pszText, 
			pTbNotify ->cchText, szBuffer, 1, '\n'); 
		return TRUE; 
	} 
 
	// 
	// Begin adjustment 
	// 
 
	else if (pnmh ->code == TBN_BEGINADJUST) 
	{ 
		return FALSE; 
	} 
 
	// 
	// End adjustment 
	// 
 
	else if (pnmh ->code == TBN_ENDADJUST) 
	{ 
 
		// 
		// Save the toolbar changes 
		// 
 
		m_nTextStyle = m_sTBDlg .GetTextStyle (); 
		m_nIconStyle = m_sTBDlg .GetIconStyle (); 
		TCHAR szText [32]; 
		_sntprintf (szText, _countof (szText), _T ( "%d"), m_nTextStyle); 
		::WritePrivateProfileString (PROFILE_SETTINGS,  
			PROFILE_TBTEXTSTYLE, szText, g_szSettingsFile); 
		_sntprintf (szText, _countof (szText), _T ( "%d"), m_nIconStyle); 
		::WritePrivateProfileString (PROFILE_SETTINGS,  
			PROFILE_TBICONSTYLE, szText, g_szSettingsFile); 
		 
		// 
		// Update the toobar 
		// 
 
		UpdateToolbar (); 
 
		// 
		// Save the settings 
		// 
 
		SaveToolbarButtons (); 
		return FALSE; 
	} 
 
	// 
	// Toolbar change 
	// 
 
	else if (pnmh ->code == TBN_TOOLBARCHANGE) 
	{ 
		return FALSE; 
	} 
 
	// 
	// Woops, bug 
	// 
 
	else 
	{ 
		//assert (FALSE); 
		return FALSE; 
	} 
} 
 
//----------------------------------------------------------------------------- 
// 
// @mfunc Update the toolbar settings 
// 
// @rdesc None. 
// 
//----------------------------------------------------------------------------- 
 
void CMainWnd::UpdateToolbar () 
{ 
 
	// 
	// Update the toolbar's list style 
	// 
	 
	if (m_nTextStyle == TBTS_RightText) 
		m_wndToolBar .ModifyStyle (0, TBSTYLE_LIST); 
	else 
		m_wndToolBar .ModifyStyle (TBSTYLE_LIST, 0); 
 
	// 
	// Next, update the mixed buttons flag 
	// 
 
	DWORD dwStyleEx = m_wndToolBar .GetExtendedStyle (); 
	if (m_nTextStyle == TBTS_RightText) 
		dwStyleEx |= TBSTYLE_EX_MIXEDBUTTONS; 
	else 
		dwStyleEx &= ~TBSTYLE_EX_MIXEDBUTTONS; 
	m_wndToolBar .SetExtendedStyle (dwStyleEx); 
 
	// 
	// Set the text rows 
	// 
 
	if (m_nTextStyle == TBTS_NoText) 
		m_wndToolBar .SetMaxTextRows (0); 
	else 
		m_wndToolBar .SetMaxTextRows (2); 
 
	// 
	// Update the image list 
	// 
 
	CSize sizeIcon; 
	CImageList *pImageList = m_nIconStyle ==  
		TBIS_SmallIcons ? &g_ilSmall : &g_ilLarge; 
	pImageList ->GetIconSize (sizeIcon); 
	m_wndToolBar .SetImageList (*pImageList); 
	m_wndToolBar .SetBitmapSize (sizeIcon); 
	m_wndToolBar .SetButtonSize (sizeIcon .cx + 7, sizeIcon .cy + 7); 
 
	// 
	// Collect information about all the buttons, update the  
	// data for the button, and delete them as we go. 
	// 
 
	int nCount = m_wndToolBar .GetButtonCount (); 
	TBBUTTON *pTBBtn = (TBBUTTON *) alloca (sizeof (TBBUTTON) * nCount); 
	for (int nIndex = 0; nIndex < nCount; nIndex++) 
	{ 
		m_wndToolBar .GetButton (0, &pTBBtn [nIndex]); 
		UpdateButton (&pTBBtn [nIndex]); 
		m_wndToolBar .DeleteButton (0); 
	} 
 
	// 
	// Readd the WHOLE bloody message 
	// 
 
	m_wndToolBar .AddButtons (nCount, pTBBtn); 
 
	// 
	// Update the rebars 
	// 
 
	if (m_hWndToolBar != NULL) 
	{ 
		UpdateSimpleReBarBandCtrl (m_hWndToolBar, m_wndCommandBar, 0);  
		UpdateSimpleReBarBandCtrl (m_hWndToolBar, m_wndToolBar, 1);  
		UpdateLayout (); 
	} 
} 
 
//----------------------------------------------------------------------------- 
// 
// @mfunc Update a button structure 
// 
// @parm TBBUTTON * | pButton | Pointer to the button 
// 
// @rdesc None. 
// 
//----------------------------------------------------------------------------- 
 
void CMainWnd::UpdateButton (TBBUTTON *pButton) 
{ 
 
	// 
	// Return if separator 
	// 
 
	if ((pButton ->fsStyle & BTNS_SEP) != 0) 
		return; 
 
	// 
	// Get the string 
	// 
 
	TCHAR szText [256]; 
	TCHAR szText2 [256]; 
	if (::LoadString (_Module .GetResourceInstance (), 
		pButton ->idCommand, szText, _countof (szText)) > 0) 
	{ 
		::ExtractString (szText2, _countof (szText2),  
			szText, 2, '\n'); 
	} 
	else 
		szText2 [0] = 0; 
	if (szText2 [0]) 
		pButton ->iString = m_wndToolBar .AddStrings (szText2); 
	else 
		pButton ->iString = 0; 
 
	// 
	// Update the style 
	// 
 
	if (m_nTextStyle == TBTS_NoText) 
	{ 
		pButton ->fsStyle &= ~BTNS_SHOWTEXT; 
		pButton ->fsStyle |= TBSTYLE_AUTOSIZE; 
	} 
	else if (m_nTextStyle == TBTS_BottomText) 
	{ 
		pButton ->fsStyle &= ~(TBSTYLE_AUTOSIZE | BTNS_SHOWTEXT); 
	} 
	else if (m_nTextStyle == TBTS_RightText) 
	{ 
		pButton ->fsStyle |= (TBSTYLE_AUTOSIZE | 
           (szText2 [0] ? BTNS_SHOWTEXT : 0)); 
	} 
	return; 
} 
 
//----------------------------------------------------------------------------- 
// 
// @mfunc Save the toolbar buttons 
// 
// @rdesc None. 
// 
//----------------------------------------------------------------------------- 
 
void CMainWnd::SaveToolbarButtons () 
{ 
	// 
	// Get the id for each of the buttons 
	// 
 
	int nCount = m_wndToolBar .GetButtonCount (); 
	int *pnIds = (int *) alloca (sizeof (int) * nCount); 
	for (int nIndex = 0; nIndex < nCount; nIndex++) 
	{ 
		TBBUTTON tb; 
		m_wndToolBar .GetButton (nIndex, &tb); 
		if ((tb .fsStyle & BTNS_SEP) != 0) 
			pnIds [nIndex] = 0; 
		else 
			pnIds [nIndex] = tb .idCommand; 
	} 
 
	// 
	// Format the string 
	// 
 
	LPTSTR pszData = (LPTSTR) alloca (sizeof (TCHAR) * nCount * 10 + 1); 
	LPTSTR psz = pszData; 
	for (int nIndex = 0; nIndex < nCount; nIndex++) 
	{ 
		if (psz != pszData) 
			*psz++ = ','; 
		_ltot (pnIds [nIndex], psz, 10); 
		psz += _tcslen (psz); 
	} 
	*psz++ = 0; 
	::WritePrivateProfileString (PROFILE_SETTINGS,  
		PROFILE_TBBUTTONS, pszData, g_szSettingsFile); 
} 
 
//----------------------------------------------------------------------------- 
// 
// @mfunc Handle page setup 
// 
// @parm WORD | wNotifyCode | Command notification code 
//  
// @parm WORD | wID | ID of the control 
// 
// @parm HWND | hWndCtl | Handle of the control 
// 
// @parm BOOL & | bHandled | If handled, set to true 
// 
// @rdesc Routine results 
// 
//----------------------------------------------------------------------------- 
 
LRESULT CMainWnd::OnFilePageSetup (WORD wNotifyCode,  
	WORD wID, HWND hWndCtl, BOOL &bHandled)  
{ 
 
	// 
	// Invoke the helper 
	// 
 
	PageSetup ();  
	return TRUE; 
} 
 
//----------------------------------------------------------------------------- 
// 
// @mfunc Handle request to edit the filter 
// 
// @parm WORD | wNotifyCode | Command notification code 
//  
// @parm WORD | wID | ID of the control 
// 
// @parm HWND | hWndCtl | Handle of the control 
// 
// @parm BOOL & | bHandled | If handled, set to true 
// 
// @rdesc Routine results 
// 
//----------------------------------------------------------------------------- 
 
LRESULT CMainWnd::OnEditFilter (WORD wNotifyCode,  
	WORD wID, HWND hWndCtl, BOOL &bHandled)  
{ 
 
	// 
	// Display the dialog 
	// 
 
	CFilterDlg dlg (&g_sFilter); 
	if (dlg .DoModal () == IDOK) 
		ApplyFilter (); 
	return TRUE; 
}