reman3/Rayman_X/cpa/tempgrp/Tut/TutLib/Src/Tut_Mngr.inc

1617 lines
70 KiB
PHP
Raw Blame History

/******************************************************************************
* *
* Tut_Mngr.cpp : definition of the low level functions of the *
* TUT_CTutorialManager class *
* *
* This class can take the control of all windows of the application *
* to create a tutorial or an automatic test *
* *
* Author : Alexis Vaisse *
* *
******************************************************************************/
//-----------------------------------------------------------------------------
// class TUT_CTutorialManager - m_fn_csGetTreeCtrlItemText
// Get the text of one item of a tree ctrl
//-----------------------------------------------------------------------------
CString TUT_CTutorialManager::m_fn_csGetTreeCtrlItemText (HWND _hTreeCtrl , HTREEITEM _hItem)
{
char szBuffer [256];
* szBuffer = 0;
TV_ITEM Item;
Item . mask = TVIF_TEXT;
Item . hItem = _hItem;
Item . pszText = szBuffer;
Item . cchTextMax = 255;
TreeView_GetItem (_hTreeCtrl , & Item);
return szBuffer;
}
//-----------------------------------------------------------------------------
// class TUT_CTutorialManager - m_fn_uiGetTreeCtrlState
// Get the state of one item of a tree ctrl
//-----------------------------------------------------------------------------
UINT TUT_CTutorialManager::m_fn_uiGetTreeCtrlState (HWND _hTreeCtrl , HTREEITEM _hItem , UINT _uiFlag)
{
TV_ITEM Item;
Item . mask = TVIF_STATE;
Item . hItem = _hItem;
Item . stateMask = _uiFlag;
TreeView_GetItem (_hTreeCtrl , & Item);
return Item . state;
}
//-----------------------------------------------------------------------------
// class TUT_CTutorialManager - m_fn_hFindStringInTree
// Recursiv function to find a string into a tree
//-----------------------------------------------------------------------------
HTREEITEM TUT_CTutorialManager::m_fn_hFindStringInTree (HWND _hTreeCtrl , HTREEITEM _hItem , CString _csText)
{
while (_hItem)
{
// Is it the good item ?
if (m_fn_csGetTreeCtrlItemText (_hTreeCtrl , _hItem) == _csText) return _hItem;
// Get the first child and recursiv call
HTREEITEM _hChildItem = TreeView_GetChild (_hTreeCtrl , _hItem);
if (_hChildItem)
{
HTREEITEM hResultItem = m_fn_hFindStringInTree (_hTreeCtrl , _hChildItem , _csText);
if (hResultItem) return hResultItem;
}
// Get the next brother
_hItem = TreeView_GetNextItem (_hTreeCtrl , _hItem , TVGN_NEXT);
}
return NULL; // Not found
}
//-----------------------------------------------------------------------------
// class TUT_CTutorialManager - m_fn_bIsItemVIsibleInTree
// Return TRUE if an item is visible in a tree
//-----------------------------------------------------------------------------
BOOL TUT_CTutorialManager::m_fn_bIsItemVisibleInTree (HWND _hTreeCtrl , HTREEITEM _hItemToFind)
{
HTREEITEM hItem = TreeView_GetFirstVisible (_hTreeCtrl);
while (hItem)
{
if (hItem == _hItemToFind) return TRUE;
hItem = TreeView_GetNextVisible (_hTreeCtrl , hItem);
}
return FALSE; // Not found
}
//-----------------------------------------------------------------------------
// class TUT_CTutorialManager - m_fn_bSearchWndDefinition
// Search a window name into the list
//-----------------------------------------------------------------------------
BOOL TUT_CTutorialManager::m_fn_bSearchWndDefinition (const CString _csName , int *_p_iIndex /* = NULL */)
{
int iMin = -1;
int iMax = m_oArrayOfWnd . GetSize ();
int iMiddle = (iMin + iMax) >> 1;
int iComp;
BOOL bFound = FALSE;
TUT_tdstWndDefinition * p_stWndDefinition;
while (iMax != iMin + 1)
{
p_stWndDefinition = m_oArrayOfWnd [iMiddle];
iComp = p_stWndDefinition -> csName . CompareNoCase (_csName);
if (iComp == 0) // Found
{
if (_p_iIndex) * _p_iIndex = iMiddle;
return TRUE;
}
else
if (iComp == -1)
{
iMin = iMiddle;
iMiddle = (iMin + iMax) >> 1;
}
else
{
iMax = iMiddle;
iMiddle = (iMin + iMax) >> 1;
}
}
// Not found : we set the position where to insert the new window
if (_p_iIndex) * _p_iIndex = iMin;
return FALSE;
}
//-----------------------------------------------------------------------------
// class TUT_CTutorialManager - m_fn_bSearchWndDefinition
// Search a window name into the list
//-----------------------------------------------------------------------------
BOOL TUT_CTutorialManager::m_fn_bSearchWndDefinition (HWND _hWnd , int * _p_iIndex /*=NULL*/ )
{
int iMin = 0;
int iMax = m_oArrayOfWnd . GetSize ();
int iIndex;
TUT_tdstWndDefinition * p_stWndDefinition;
for (iIndex = iMin ; iIndex < iMax ; iIndex ++)
{
p_stWndDefinition = m_oArrayOfWnd [iIndex];
if (p_stWndDefinition -> hWnd == _hWnd) // Found
{
if (_p_iIndex) * _p_iIndex = iIndex;
return TRUE;
}
}
// Not found : we set the position where to insert the new window
if (_p_iIndex) * _p_iIndex = -1;
return FALSE;
}
//-----------------------------------------------------------------------------
// class TUT_CTutorialManager - m_fnp_stFindWndDefinition
// Search a window name into the list
//-----------------------------------------------------------------------------
TUT_tdstWndDefinition * TUT_CTutorialManager::m_fnp_stFindWndDefinition (const CString _csName)
{
int iIndex;
return m_fn_bSearchWndDefinition (_csName , & iIndex) ? m_oArrayOfWnd [iIndex] : NULL;
}
//-----------------------------------------------------------------------------
// class TUT_CTutorialManager - m_fnp_stFindWndDefinition
// Search a window handle into the list
//-----------------------------------------------------------------------------
TUT_tdstWndDefinition * TUT_CTutorialManager::m_fnp_stFindWndDefinition (HWND _hWnd)
{
int iIndex;
return m_fn_bSearchWndDefinition (_hWnd , & iIndex) ? m_oArrayOfWnd [iIndex] : NULL;
}
//-----------------------------------------------------------------------------
// class TUT_CTutorialManager - m_fnp_stFindLabel
// Search a label name into the list
//-----------------------------------------------------------------------------
TUT_tdstLabelDefinition * TUT_CTutorialManager::m_fnp_stFindLabel (char * _szName)
{
int iCurrentContextNumber = m_oListOfContext . GetCount ();
POSITION Pos = m_oListOfLabel . GetHeadPosition ();
while (Pos)
{
TUT_tdstLabelDefinition * p_stLabelDef = m_oListOfLabel . GetNext (Pos);
if (p_stLabelDef -> csName . CompareNoCase (_szName) == 0 && p_stLabelDef -> iContextNumber == iCurrentContextNumber)
return p_stLabelDef;
}
return NULL; // Not found
}
//-----------------------------------------------------------------------------
// class TUT_CTutorialManager - m_fnp_stFindVariable
// Search a variable name into the list
//-----------------------------------------------------------------------------
TUT_tdstVariableDefinition * TUT_CTutorialManager::m_fnp_stFindVariable (char * _szName)
{
BOOL bDeclareVariable;
if (* _szName == TUT_C_cDeclarationOfVariable)
{
bDeclareVariable = TRUE;
_szName ++;
}
else bDeclareVariable = FALSE;
int iCurrentContextNumber = m_oListOfContext . GetCount ();
POSITION Pos = m_oListOfVariable . GetHeadPosition ();
TUT_tdstVariableDefinition * p_stGlobalVariableDef = NULL;
while (Pos)
{
TUT_tdstVariableDefinition * p_stVariableDef = m_oListOfVariable . GetNext (Pos);
if (p_stVariableDef -> csName . CompareNoCase (_szName) == 0) // We have found a variable
{
if (p_stVariableDef -> iContextNumber == iCurrentContextNumber) // Is this variable a local variable ?
{
if (bDeclareVariable) return NULL; // Declaration of a already existing variable -> error
else return p_stVariableDef; // Ok
}
else
if (p_stVariableDef -> iContextNumber == 0) // Is this variable a global variable ?
{
p_stGlobalVariableDef = p_stVariableDef;
}
}
}
// Here, we have not found a local variable
if (bDeclareVariable)
{
TUT_tdstVariableDefinition * p_stVariableDef = new TUT_tdstVariableDefinition;
m_oListOfVariable . AddTail (p_stVariableDef);
p_stVariableDef -> csName = _szName;
p_stVariableDef -> csValue = "";
p_stVariableDef -> iContextNumber = iCurrentContextNumber;
return p_stVariableDef;
}
else
{
if (p_stGlobalVariableDef) return p_stGlobalVariableDef;
else return NULL; // Not found
}
}
//-----------------------------------------------------------------------------
// class TUT_CTutorialManager - m_fnp_stFindOrCreateVariable
// Search a variable name into the list. If it does not exist, create it
//-----------------------------------------------------------------------------
TUT_tdstVariableDefinition * TUT_CTutorialManager::m_fnp_stFindOrCreateVariable (char * _szName)
{
TUT_tdstVariableDefinition * p_stVariableDef = m_fnp_stFindVariable (_szName);
if (p_stVariableDef == NULL)
{
p_stVariableDef = new TUT_tdstVariableDefinition;
m_oListOfVariable . AddTail (p_stVariableDef);
p_stVariableDef -> csName = _szName;
p_stVariableDef -> csValue = "";
p_stVariableDef -> iContextNumber = m_oListOfContext . GetCount ();
}
return p_stVariableDef;
}
//-----------------------------------------------------------------------------
// class TUT_CTutorialManager - m_fn_vSetValueToVariable
// Set a value to a variable
//-----------------------------------------------------------------------------
void TUT_CTutorialManager::m_fn_vSetValueToVariable (TUT_tdstVariableDefinition * _p_stVariableDef , long _lValue)
{
_p_stVariableDef -> csValue . Format ("%d" , _lValue);
}
//-----------------------------------------------------------------------------
// class TUT_CTutorialManager - m_fn_vSetGetLastError
// Put an error number into the GetLastError' global variable
//-----------------------------------------------------------------------------
void TUT_CTutorialManager::m_fn_vSetGetLastError (long _lErrorNumber)
{
// Fill the GetLastError variable
TUT_tdstVariableDefinition * p_stVariableDef = m_fnp_stFindOrCreateVariable (TUT_C_szGetLastError);
m_fn_vSetValueToVariable (p_stVariableDef , _lErrorNumber);
// Fill the GetLastErrorMessage variable
char * szMessage;
switch (_lErrorNumber)
{
case TUT_C_iNoError : szMessage = "No error"; break;
case TUT_C_iError_ListBoxItemNotFound : szMessage = "Item not found in list box"; break;
case TUT_C_iError_ComboBoxItemNotFound : szMessage = "Item not found in combo box"; break;
case TUT_C_iError_ListCtrlItemNotFound : szMessage = "Item not found in list control"; break;
case TUT_C_iError_ListBoxInvalidLine : szMessage = "Invalid line number in list box"; break;
case TUT_C_iError_ComboBoxInvalidLine : szMessage = "Invalid line number in combo box"; break;
case TUT_C_iError_ListCtrlInvalidLine : szMessage = "Invalid line number in list control"; break;
case TUT_C_iError_TreeCtrlItemNotFound : szMessage = "Item not found in tree control"; break;
case TUT_C_iError_SoundError : szMessage = "Wav file not found or sound error"; break;
case TUT_C_iError_UnregisteredWindow : szMessage = "Unregistered window"; break;
default : szMessage = NULL; break;
}
p_stVariableDef = m_fnp_stFindOrCreateVariable (TUT_C_szGetLastErrorMessage);
if (szMessage) p_stVariableDef -> csValue = szMessage;
else p_stVariableDef -> csValue . Format ("Unknown error code (%d)" , _lErrorNumber);
}
//-----------------------------------------------------------------------------
// class TUT_CTutorialManager - m_fn_iConvertToInt
// Convert a string into an integer. Return TUT_C_iErrorNotANumber if error
//-----------------------------------------------------------------------------
int TUT_CTutorialManager::m_fn_iConvertToInt (char * _szString)
{
char * szEndOfNumber;
long lValue = strtol (_szString , & szEndOfNumber , 10);
if (* szEndOfNumber != 0) return TUT_C_iErrorNotANumber;
return (int) lValue;
}
//-----------------------------------------------------------------------------
// class TUT_CTutorialManager - m_fn_iConvertToDouble
// Convert a string into a double. Return TUT_C_dErrorNotANumber if error
//-----------------------------------------------------------------------------
double TUT_CTutorialManager::m_fn_dConvertToDouble (char * _szString)
{
char * szEndOfNumber;
double dValue = strtod (_szString , & szEndOfNumber);
if (* szEndOfNumber != 0) return TUT_C_dErrorNotANumber;
return dValue;
}
//-----------------------------------------------------------------------------
// class TUT_CTutorialManager - m_fn_bAreParametersEqual
// Return TRUE if the two parameters are equal (can be integer, float or string)
//-----------------------------------------------------------------------------
BOOL TUT_CTutorialManager::m_fn_bAreParametersEqual (char * _szParameter1 , char * _szParameter2)
{
double dParameter1 = m_fn_dConvertToDouble (_szParameter1);
BOOL bIsDouble1 = dParameter1 != TUT_C_dErrorNotANumber;
double dParameter2 = m_fn_dConvertToDouble (_szParameter2);
BOOL bIsDouble2 = dParameter2 != TUT_C_dErrorNotANumber;
if (bIsDouble1 && bIsDouble2) return dParameter1 == dParameter2;
else return stricmp (_szParameter1 , _szParameter2) == 0;
}
//-----------------------------------------------------------------------------
// class TUT_CTutorialManager - m_fn_bIsParameter1LessThanParameter2
// Return TRUE if the first parameter is less than the seoncd parameter (can be integer, float or string)
//-----------------------------------------------------------------------------
BOOL TUT_CTutorialManager::m_fn_bIsParameter1LessThanParameter2 (char * _szParameter1 , char * _szParameter2)
{
double dParameter1 = m_fn_dConvertToDouble (_szParameter1);
BOOL bIsDouble1 = dParameter1 != TUT_C_dErrorNotANumber;
double dParameter2 = m_fn_dConvertToDouble (_szParameter2);
BOOL bIsDouble2 = dParameter2 != TUT_C_dErrorNotANumber;
if (bIsDouble1 && bIsDouble2) return dParameter1 < dParameter2;
else return stricmp (_szParameter1 , _szParameter2) < 0;
}
//-----------------------------------------------------------------------------
// class TUT_CTutorialManager - m_fn_bIsParameterTrue
// Return if a parameter is TRUE or FALSE
//-----------------------------------------------------------------------------
BOOL TUT_CTutorialManager::m_fn_bIsParameterTrue (char * _szParameter , int * _p_iReturnValue)
{
* _p_iReturnValue = TUT_C_iNoError;
if (stricmp (_szParameter , TUT_C_szTrue ) == 0) return TRUE;
if (stricmp (_szParameter , TUT_C_szFalse) == 0) return FALSE;
* _p_iReturnValue = TUT_C_iError_BooleanValueRequired;
return FALSE;
}
//-----------------------------------------------------------------------------
// class TUT_CTutorialManager - m_fn_bIsTestVerified
// Execute a test and return the result of this test
//-----------------------------------------------------------------------------
BOOL TUT_CTutorialManager::m_fn_bIsTestVerified (char * _szTestOperator , char * _szParameter1 ,
char * _szParameter2 , int * _p_iReturnValue)
{
BOOL bTestVerified;
* _p_iReturnValue = TUT_C_iNoError;
if (stricmp (_szTestOperator , "=") == 0 || stricmp (_szTestOperator , "==") == 0)
bTestVerified = m_fn_bAreParametersEqual (_szParameter1 , _szParameter2);
else
if (stricmp (_szTestOperator , "<>") == 0 || stricmp (_szTestOperator , "!=") == 0)
bTestVerified = ! m_fn_bAreParametersEqual (_szParameter1 , _szParameter2);
else
if (stricmp (_szTestOperator , "<") == 0)
bTestVerified = m_fn_bIsParameter1LessThanParameter2 (_szParameter1 , _szParameter2);
else
if (stricmp (_szTestOperator , "<=") == 0)
bTestVerified = ! m_fn_bIsParameter1LessThanParameter2 (_szParameter2 , _szParameter1);
else
if (stricmp (_szTestOperator , ">") == 0)
bTestVerified = m_fn_bIsParameter1LessThanParameter2 (_szParameter2 , _szParameter1);
else
if (stricmp (_szTestOperator , ">=") == 0)
bTestVerified = ! m_fn_bIsParameter1LessThanParameter2 (_szParameter1 , _szParameter2);
else
{
bTestVerified = FALSE;
* _p_iReturnValue = TUT_C_iError_TestOperatorRequired;
}
return bTestVerified;
}
//-----------------------------------------------------------------------------
// class TUT_CTutorialManager - m_fn_bMustActionBeExecuted
// Return if the current action must be executed
//-----------------------------------------------------------------------------
BOOL TUT_CTutorialManager::m_fn_bMustActionBeExecuted ()
{
// Not inside a test -> no problem
if (m_oListOfTest . GetCount () == 0) return TRUE;
TUT_tdstTestDefinition * p_stTestDef = m_oListOfTest . GetHead ();
// Return TRUE if test verified XOR we are in the else block
return p_stTestDef -> bTestVerified ^ p_stTestDef -> ePositionInTest == TUT_eAfterElse;
}
//-----------------------------------------------------------------------------
// class TUT_CTutorialManager - m_fn_vAddAnActionForTheTest
// Called each time an action is executed
//-----------------------------------------------------------------------------
void TUT_CTutorialManager::m_fn_vAddAnActionForTheTest ()
{
// Not inside a test -> nothing to do
if (m_oListOfTest . GetCount () == 0) return;
TUT_tdstTestDefinition * p_stTestDef = m_oListOfTest . GetHead ();
if (p_stTestDef -> ePositionInTest == TUT_eAfterIf) p_stTestDef -> ePositionInTest = TUT_eBeforeElse;
}
//-----------------------------------------------------------------------------
// class TUT_CTutorialManager - m_fn_vATestRightButtonDoubleClicAndPosition
// These five flags must be set to FALSE after one action
//-----------------------------------------------------------------------------
void TUT_CTutorialManager::m_fn_vTestRightButtonDoubleClicAndPosition ()
{
static BOOL sbPreviousValueUseRightButton = FALSE;
static BOOL sbPreviousValueUseDoubleClic = FALSE;
static BOOL sbPreviousValueUsePosition = FALSE;
static BOOL sbPreviousValueUseDrag = FALSE;
static BOOL sbPreviousValueUseDrop = FALSE;
if (sbPreviousValueUseRightButton) m_bUseRightButton = FALSE;
if (sbPreviousValueUseDoubleClic ) m_bUseDoubleClic = FALSE;
if (sbPreviousValueUsePosition ) m_bUsePosition = FALSE;
if (sbPreviousValueUseDrag ) m_bUseDrag = FALSE;
if (sbPreviousValueUseDrop ) m_bUseDrop = FALSE;
sbPreviousValueUseRightButton = m_bUseRightButton;
sbPreviousValueUseDoubleClic = m_bUseDoubleClic;
sbPreviousValueUsePosition = m_bUsePosition;
sbPreviousValueUseDrag = m_bUseDrag;
sbPreviousValueUseDrop = m_bUseDrop;
}
//-----------------------------------------------------------------------------
// class TUT_CTutorialManager - m_fn_vClearAllList
// Clear the list used by the class
//-----------------------------------------------------------------------------
void TUT_CTutorialManager::m_fn_vClearAllList (BOOL _bUnregisterControl)
{
if (_bUnregisterControl)
{
for (int iIndex = m_oArrayOfWnd . GetSize() - 1 ; iIndex >= 0 ; iIndex --)
delete m_oArrayOfWnd [iIndex];
m_oArrayOfWnd . RemoveAll ();
}
int iNumber;
iNumber = 0;
while (m_oListOfVariable . GetCount ())
{
TUT_tdstVariableDefinition *p_stVarDef = m_oListOfVariable . RemoveHead ();
delete p_stVarDef;
iNumber ++;
}
iNumber = 0;
while (m_oListOfLoop . GetCount ())
{
TUT_tdstLoopDefinition *p_stLoopDef = m_oListOfLoop . RemoveHead ();
delete p_stLoopDef;
iNumber ++;
}
iNumber = 0;
while (m_oListOfTest . GetCount ())
{
TUT_tdstTestDefinition *p_stTestDef = m_oListOfTest . RemoveHead ();
iNumber ++;
delete p_stTestDef;
}
iNumber = 0;
while (m_oListOfLabel . GetCount ())
{
TUT_tdstLabelDefinition *p_stLabelDef = m_oListOfLabel . RemoveHead ();
delete p_stLabelDef;
iNumber ++;
}
// Reset the variables
m_iNumberOfParameter = 0;
m_iNumberOfResult = 0;
m_bInsideAGoto = FALSE;
}
//-----------------------------------------------------------------------------
// class TUT_CTutorialManager - m_fn_vPreprocessString
// Remove spaces, tab and quotes at the beginning and the end of the string
// Remplace variable name by its value. Return FALSE if error
//-----------------------------------------------------------------------------
BOOL TUT_CTutorialManager::m_fn_vPreprocessString (char * & _szString)
{
if (_szString == NULL || * _szString == 0) return TRUE;;
// Remove spaces and tab at the beginning of the string
while (* _szString == ' ' || * _szString == '\t') _szString ++;
// Remove spaces and tab at the end of the string
char * p = _szString + strlen (_szString) - 1; // Points to the last character of the string
while (* _szString != 0 && (* p == ' ' || * p == '\t')) * (p--) = 0;
// Check if it is a variable name
int iNbVariable = 0;
while (* _szString == TUT_C_cBeginningOfVariable)
{
_szString ++;
iNbVariable ++;
}
if (iNbVariable)
{
while (iNbVariable --)
{
TUT_tdstVariableDefinition * p_stVariableDef = m_fnp_stFindVariable (_szString);
if (p_stVariableDef) _szString = (char *) (LPCTSTR) p_stVariableDef -> csValue;
else return FALSE; // Use of an unknown variable -> error
}
return TRUE;
}
// Remove quote at the beginning of the string
if (* _szString == '"') _szString ++;
// Remove quote at the end of the string
if (* _szString != 0 && * p == '"') * p = 0;
return TRUE;
}
//-----------------------------------------------------------------------------
// class TUT_CTutorialManager - m_fn_szStrtok
// same as strtok but don't stop at delimiter inside quote
//-----------------------------------------------------------------------------
char * TUT_CTutorialManager::m_fn_szStrtok (char * _szString , char _cDelimiter)
{
static char * p = NULL;
if (_szString != NULL) p = _szString; // in both cases,
else
{
if (p == NULL) return NULL;
else p ++; // p points to the first character
}
char * szReturnValue = p;
if (* szReturnValue == 0) return NULL; // end of the string -> return NULL
BOOL bInsideQuote = FALSE;
while (* p != 0 && (* p != _cDelimiter || bInsideQuote)) // Find delimiter or end of string
{
if (* p == '\"') bInsideQuote = ! bInsideQuote;
p ++;
}
if (* p != 0) * p = 0; // Put 0 instead of a delimiter
else p = NULL; // Eof of the string
return szReturnValue;
}
//-----------------------------------------------------------------------------
// class TUT_CTutorialManager - m_fn_iGetParameters
// Split a string into a variable number of parameters. Return 0 if no error
//-----------------------------------------------------------------------------
int TUT_CTutorialManager::m_fn_iGetParameters (char * _szString , int _iMinNumberOfParameter , int _iMaxNumberOfParameter ,
int * _p_iNumberOfParameter , ...)
{
va_list Marker;
va_start (Marker, _p_iNumberOfParameter); // Initialize variable arguments
* _p_iNumberOfParameter = 0;
char * szParameter = m_fn_szStrtok (_szString , ',');
while (szParameter != NULL)
{
(* _p_iNumberOfParameter) ++;
if (* _p_iNumberOfParameter > _iMaxNumberOfParameter) return TUT_C_iError_TooManyParameters;
char * * p_szParameter = va_arg (Marker , char * *); // Get the next argument
if (! m_fn_vPreprocessString (szParameter)) return TUT_C_iError_UnknownVariable;
* p_szParameter = m_fn_szHandleQuote (szParameter);
szParameter = m_fn_szStrtok (NULL , ',');
}
va_end (Marker);
if (* _p_iNumberOfParameter < _iMinNumberOfParameter) return TUT_C_iError_ParameterRequired;
return TUT_C_iNoError;
}
//-----------------------------------------------------------------------------
// class TUT_CTutorialManager - m_fn_vPumpMessage
// Dispatch messages
//-----------------------------------------------------------------------------
void TUT_CTutorialManager::m_fn_vPumpMessage ()
{
MSG Msg;
while (PeekMessage (& Msg , NULL , 0 , 0 , PM_REMOVE))
DispatchMessage (& Msg);
}
//-----------------------------------------------------------------------------
// class TUT_CTutorialManager - m_fn_vSleep
// Wait for the given duration (in millisecond)
//-----------------------------------------------------------------------------
void TUT_CTutorialManager::m_fn_vSleep (int _iDuration)
{
BOOL bLeftKeyPressed = (GetAsyncKeyState (VK_LSHIFT) & 0x8000) && (GetAsyncKeyState (VK_LCONTROL) & 0x8000);
m_fn_vPumpMessage ();
while (_iDuration > 0)
{
int iDelta = min (50 , _iDuration);
_iDuration -= iDelta;
// Are the control and shift keys pressed ?
if ((GetAsyncKeyState (VK_RCONTROL) & 0x8000) && (GetAsyncKeyState (VK_RSHIFT) & 0x8000)) return;
// Is the 'Escape' key pressed ?
if ((GetAsyncKeyState (VK_ESCAPE) & 0x8000)) return;
if (bLeftKeyPressed)
{
if ((GetAsyncKeyState (VK_LSHIFT) & 0x8000) == 0 && (GetAsyncKeyState (VK_LCONTROL) & 0x8000) == 0)
bLeftKeyPressed = FALSE;
}
else
{
if ((GetAsyncKeyState (VK_LSHIFT) & 0x8000) && (GetAsyncKeyState (VK_LCONTROL) & 0x8000)) return;
}
Sleep (iDelta);
m_fn_vPumpMessage ();
}
}
//-----------------------------------------------------------------------------
// class TUT_CTutorialManager - m_fn_vActivateWindow
// Activate a window and its parent (recursiv call)
//-----------------------------------------------------------------------------
void TUT_CTutorialManager::m_fn_vActivateWindow (HWND _hWnd)
{
SetForegroundWindow (_hWnd);
UpdateWindow (_hWnd);
}
//-----------------------------------------------------------------------------
// class TUT_CTutorialManager - m_fn_hOpenUserWindow
// Open one user window (a rich edit control inside a frame) and return its handle
//-----------------------------------------------------------------------------
HWND TUT_CTutorialManager::m_fn_hOpenUserWindow (char * _szWindowName , int _iLeft , int _iTop ,
int _iRight , int _iBottom)
{
// Compute the size of the frame to create
CRect ScreenPos;
GetWindowRect (GetDesktopWindow () , & ScreenPos);
CRect WindowPos;
WindowPos . left = ScreenPos . right * _iLeft / 100;
WindowPos . right = ScreenPos . right * _iRight / 100;
WindowPos . top = ScreenPos . bottom * _iTop / 100;
WindowPos . bottom = ScreenPos . bottom * _iBottom / 100;
// Create a new class for the frame
LPCTSTR lpszSmartClass = AfxRegisterWndClass (CS_HREDRAW | CS_VREDRAW , LoadCursor (NULL, IDC_ARROW) , (HBRUSH) (COLOR_WINDOW + 1));
// Create the frame window
HWND hWnd = CreateWindowEx (WS_EX_TOPMOST | WS_EX_TOOLWINDOW , lpszSmartClass , _szWindowName ,
WS_POPUP | WS_BORDER | WS_CAPTION | WS_VISIBLE ,
WindowPos . left , WindowPos . top , WindowPos . Width () , WindowPos . Height () ,
NULL /* No parent to avoid problem */ , NULL , AfxGetInstanceHandle () , NULL);
if (hWnd == NULL)
{
DWORD dwError = GetLastError ();
ASSERT (0);
}
// Create a text view
CRect ClientRect;
GetClientRect (hWnd , & ClientRect);
HWND hEditView = CreateWindowEx (WS_EX_LEFT , "RichEdit" , "" , WS_CHILD | WS_VISIBLE | WS_VSCROLL | ES_MULTILINE ,
ClientRect . left , ClientRect . top , ClientRect . Width () , ClientRect . Height () ,
hWnd , NULL , AfxGetInstanceHandle () , NULL);
if (hEditView == NULL)
{
DWORD dwError = GetLastError ();
ASSERT (0);
}
SendMessage (hEditView , EM_SETREADONLY , TRUE , 0);
return hEditView;
}
//-----------------------------------------------------------------------------
// class TUT_CTutorialManager - m_fn_vCloseUserWindow
// Close one user window
//-----------------------------------------------------------------------------
void TUT_CTutorialManager::m_fn_vCloseUserWindow (int _iIndex)
{
TUT_tdstWndDefinition * p_stWndDefinition = m_oArrayOfWnd [_iIndex];
HWND hWindow = p_stWndDefinition -> hWnd;
HWND hParent = GetParent (hWindow);
ASSERT (hParent);
DestroyWindow (hWindow);
DestroyWindow (hParent);
m_oArrayOfWnd . RemoveAt (_iIndex);
delete p_stWndDefinition;
if (m_p_stCurrentUserWindow == p_stWndDefinition) m_p_stCurrentUserWindow = NULL;
}
//-----------------------------------------------------------------------------
// class TUT_CTutorialManager - m_fn_vCloseAllUserWindow
// Close all open user windows
//-----------------------------------------------------------------------------
void TUT_CTutorialManager::m_fn_vCloseAllUserWindow ()
{
for (int iIndex = m_oArrayOfWnd . GetSize () - 1 ; iIndex >= 0 ; iIndex --)
{
TUT_tdstWndDefinition * p_stWndDefinition = m_oArrayOfWnd [iIndex];
if (p_stWndDefinition -> eType == TUT_eUserWindow) m_fn_vCloseUserWindow (iIndex);
}
if (m_hDebugWnd)
{
DestroyWindow (m_hDebugWnd);
m_hDebugWnd = NULL;
}
}
//-----------------------------------------------------------------------------
// class TUT_CTutorialManager - m_fn_vDeleteLocalLabelAndVariable
// Delete all local labels and variables
//-----------------------------------------------------------------------------
void TUT_CTutorialManager::m_fn_vDeleteLocalLabelAndVariable ()
{
int iCurrentContextNumber = m_oListOfContext . GetCount ();
POSITION Pos = m_oListOfVariable . GetHeadPosition ();
while (Pos)
{
POSITION SavePos = Pos;
TUT_tdstVariableDefinition * p_stVariableDef = m_oListOfVariable . GetNext (Pos);
if (p_stVariableDef -> iContextNumber == iCurrentContextNumber)
{
m_oListOfVariable . RemoveAt (SavePos);
delete p_stVariableDef;
}
}
Pos = m_oListOfLabel . GetHeadPosition ();
while (Pos)
{
POSITION SavePos = Pos;
TUT_tdstLabelDefinition * p_stLabelDef = m_oListOfLabel . GetNext (Pos);
if (p_stLabelDef -> iContextNumber == iCurrentContextNumber)
{
m_oListOfLabel . RemoveAt (SavePos);
delete p_stLabelDef;
}
}
}
//-----------------------------------------------------------------------------
// class TUT_CTutorialManager - m_fn_vCloseLogFile
// Close the given log file if it is open
//-----------------------------------------------------------------------------
void TUT_CTutorialManager::m_fn_vCloseLogFile (TUT_tdstLogFileDefinition * _p_stLogFile)
{
if (_p_stLogFile -> bOpen)
{
fclose (_p_stLogFile -> pFile);
_p_stLogFile -> bOpen = FALSE;
_p_stLogFile -> csName = "";
_p_stLogFile -> pFile = NULL;
}
}
//-----------------------------------------------------------------------------
// class TUT_CTutorialManager - m_fn_vCloseAllLogFiles
// Close the given log file if it is open
//-----------------------------------------------------------------------------
void TUT_CTutorialManager::m_fn_vCloseAllLogFiles ()
{
m_fn_vCloseLogFile (& m_stLogFile);
m_fn_vCloseLogFile (& m_stDebugLogFile);
}
//-----------------------------------------------------------------------------
// class TUT_CTutorialManager - m_fn_bFindColor
// Find RGB code of the given color name. Return FALSE if not found
//-----------------------------------------------------------------------------
BOOL TUT_CTutorialManager::m_fn_bFindColor (char * _szColorName , COLORREF * _p_xColor)
{
const TUT_tdstColorDefinition * p = g_a_stColorDefinition;
while (p -> szColorName)
{
if (stricmp (p -> szColorName , _szColorName) == 0)
{
* _p_xColor = p -> xColor;
return TRUE;
}
p ++;
}
return FALSE; // Not found
}
//-----------------------------------------------------------------------------
// class TUT_CTutorialManager - m_fn_iFindVirtualKeyCode
// Find a virtual key code with the given name. Return 0 if not found
//-----------------------------------------------------------------------------
int TUT_CTutorialManager::m_fn_iFindVirtualKeyCode (char * _szVirtualKeyCode)
{
if (strlen (_szVirtualKeyCode) == 1)
{
char cChar = (char) toupper (* _szVirtualKeyCode);
if (cChar >= 'A' && cChar <= 'Z') return cChar;
}
int i = -1;
char * szKeyName;
do
{
szKeyName = TUT_cgs_a_stKeyConversionTable [++ i] . szKeyName;
if (szKeyName == NULL) return 0; // End of the list : not found -> return 0;
} while (stricmp (szKeyName , _szVirtualKeyCode) != 0);
return TUT_cgs_a_stKeyConversionTable [i] . iVirtualKeyCode;
}
//-----------------------------------------------------------------------------
// class TUT_CTutorialManager - m_fn_iFindIdForMessageMox
// Find RGB code of the given color name. Return FALSE if not found
//-----------------------------------------------------------------------------
int TUT_CTutorialManager::m_fn_iFindIdForMessageBox (char * _szControlName)
{
if (stricmp (_szControlName , TUT_C_szOk ) == 0) return IDOK;
if (stricmp (_szControlName , TUT_C_szCancel) == 0) return IDCANCEL;
if (stricmp (_szControlName , TUT_C_szAbort ) == 0) return IDABORT;
if (stricmp (_szControlName , TUT_C_szRetry ) == 0) return IDRETRY;
if (stricmp (_szControlName , TUT_C_szIgnore) == 0) return IDIGNORE;
if (stricmp (_szControlName , TUT_C_szYes ) == 0) return IDYES;
if (stricmp (_szControlName , TUT_C_szNo ) == 0) return IDNO;
return 0; // Not found
}
//-----------------------------------------------------------------------------
// class TUT_CTutorialManager - m_fn_szGetWndNameType
// Return the name of the given window type
//-----------------------------------------------------------------------------
char * TUT_CTutorialManager::m_fn_szGetWndNameType (TUT_tdeWndType _eType)
{
switch (_eType)
{
case TUT_eWindow : return "Window";
case TUT_eMdiWindow : return "Mdi window";
case TUT_eButton : return "Button";
case TUT_eTextEdit : return "Text edit";
case TUT_eListBox : return "List box";
case TUT_eComboBox : return "Combo box";
case TUT_eTreeCtrl : return "Tree control";
case TUT_eListCtrl : return "List control";
case TUT_eSpin : return "Spin";
case TUT_eSlider : return "Slider";
case TUT_eScrollBar : return "Scrollbar";
case TUT_eUserWindow : return "User window";
case TUT_e3DView : return "3DView";
default : ASSERT (0);
return NULL;
}
}
//-----------------------------------------------------------------------------
// class TUT_CTutorialManager - m_fn_vShowError
// Open a message box with a message associated to the given error code
//-----------------------------------------------------------------------------
void TUT_CTutorialManager::m_fn_vShowError (int _iErrorCode , const CString _csFileName , int _iLineNumber , char * _szLine)
{
CString csMessage;
if (_iErrorCode == TUT_C_iError_FileNotFound) csMessage . Format ("File not found : %s" , _csFileName);
else
{
CString csText;
switch (_iErrorCode)
{
case TUT_C_iError_UnknownCommand : csText = "Unknown command"; break;
case TUT_C_iError_TooManyParameters : csText = "Too many parameters"; break;
case TUT_C_iError_ParameterRequired : csText = "More parameters are required"; break;
case TUT_C_iError_UnknownButton : csText = "Unknown button name"; break;
case TUT_C_iError_ButtonRequired : csText = "The control is not a button"; break;
case TUT_C_iError_InvalidCoordinates : csText = "Coordinates are not valid"; break;
case TUT_C_iError_NoWindowToWriteText : csText = "No open window to write text"; break;
case TUT_C_iError_InvalidNumber : csText = "Invalid number"; break;
case TUT_C_iError_UnknownTextEdit : csText = "Unknown text edit name"; break;
case TUT_C_iError_TextEditRequired : csText = "The control is not a text edit"; break;
case TUT_C_iError_UnknownWindow : csText = "Unknown window name"; break;
case TUT_C_iError_UnknownComboBox : csText = "Unknown combo box name"; break;
case TUT_C_iError_ListOrComboRequired : csText = "The control must be a combo box, a list box or a list control"; break;
case TUT_C_iError_UnknownMdiWindow : csText = "Unknown mdi window name"; break;
case TUT_C_iError_MdiWindowRequired : csText = "The control is not a mdi window"; break;
case TUT_C_iError_UnknownColor : csText = "Unknown color name"; break;
case TUT_C_iError_UnknownControl : csText = "Unknown control name"; break;
case TUT_C_iError_SelectCtrlRequired : csText = "The control is not a control with selection"; break;
case TUT_C_iError_InvalidTextAlignment : csText = "Invalid text alignment"; break;
case TUT_C_iError_UnknownTreeBox : csText = "Unknown tree box name"; break;
case TUT_C_iError_TreeBoxRequired : csText = "The control is not a tree box"; break;
case TUT_C_iError_FunctionNotCompiled : csText = "Not compiled function"; break;
case TUT_C_iError_Unknown3dObject : csText = "Unknown 3d object"; break;
case TUT_C_iError_NoMenuAvailable : csText = "No menu available"; break;
case TUT_C_iError_UnknownMenuName : csText = "Unknown menu name"; break;
case TUT_C_iError_NotASubMenu : csText = "Not a sub menu"; break;
case TUT_C_iError_EndLoopWithoutLoop : csText = "'EndLoop' without a 'Loop'"; break;
case TUT_C_iError_TestOperatorRequired : csText = "A test operator is required"; break;
case TUT_C_iError_OrIfWithoutAnIf : csText = "'OrIf' without an 'If'"; break;
case TUT_C_iError_ElseWithoutAnIf : csText = "'Else' without an 'If'"; break;
case TUT_C_iError_ElseInTheWrongPlace : csText = "Incorrect 'Else'"; break;
case TUT_C_iError_EndIfWithoutAnIf : csText = "'EndIf' without an 'If'"; break;
case TUT_C_iError_DebugWndAlreadyOpen : csText = "The debug window is already open"; break;
case TUT_C_iError_DebugWndNotOpen : csText = "The debug window is not open"; break;
case TUT_C_iError_InvalidMdiHandle : csText = "Invalid handle to a MDI window"; break;
case TUT_C_iError_InvalidParentMdiHandle : csText = "Invalid handle to a parent of a MDI window"; break;
case TUT_C_iError_InvalidListBoxHandle : csText = "Invalid handle to a list box"; break;
case TUT_C_iError_InvalidComboBoxHandle : csText = "Invalid handle to a combo box"; break;
case TUT_C_iError_InvalidTreeBoxHandle : csText = "Invalid handle to a tree box"; break;
case TUT_C_iError_InvalidMenuHandle : csText = "Invalid menu handle"; break;
case TUT_C_iError_InvalidMenuWndHandle : csText = "Invalid handle to a menu owner"; break;
case TUT_C_iError_InvalidButtonHandle : csText = "Invalid handle to a button"; break;
case TUT_C_iError_InvalidTextEditHandle : csText = "Invalid handle to a text edit"; break;
case TUT_C_iError_WindowOrMdiRequired : csText = "The control is not a window or a MDI window"; break;
case TUT_C_iError_InvalidWndOrMdiHandle : csText = "Invalid handle to a window or a MDI window"; break;
case TUT_C_iError_CtrlWithTextRequired : csText = "This type of control has no text"; break;
case TUT_C_iError_InvalidHandle : csText = "Invalid handle"; break;
case TUT_C_iError_BooleanValueRequired : csText = "A boolean value is required"; break;
case TUT_C_iError_ItemNotFoundInTree : csText = "The item was not found in the tree"; break;
case TUT_C_iError_ItemHasNoChild : csText = "The item has no child"; break;
case TUT_C_iError_InvalidChildNumber : csText = "Invalid child number"; break;
case TUT_C_iError_NotANumericVariable : csText = "A numeric variable is required"; break;
case TUT_C_iError_DivisionByZero : csText = "Division by zero"; break;
case TUT_C_iError_EmptyVariable : csText = "A not-empty variable is required"; break;
case TUT_C_iError_LogFileAlreadyOpen : csText = "A log file is already open"; break;
case TUT_C_iError_UnableToOpenLogFile : csText = "Unable to open the log file"; break;
case TUT_C_iError_LogFileNotOpen : csText = "The log file is not open"; break;
case TUT_C_iError_InvalidXBorder : csText = "'Left' or 'Right' is required"; break;
case TUT_C_iError_InvalidYBorder : csText = "'Top' or 'Bottom' is required"; break;
case TUT_C_iError_InvalidNumberOrPercent : csText = "Invalid number or percentage"; break;
case TUT_C_iError_InvalidListCtrlHandle : csText = "Invalid handle to a list control"; break;
case TUT_C_iError_LabelsWithSameName : csText = "This name is already used by another label"; break;
case TUT_C_iError_LabelNotFound : csText = "Label not found"; break;
case TUT_C_iError_ModelNotFound : csText = "Model not found"; break;
case TUT_C_iError_DragAtTheWrongPlace : csText = "'Drag' at the wrong place"; break;
case TUT_C_iError_DropAtTheWrongPlace : csText = "'Drop' at the wrong place"; break;
case TUT_C_iError_InvisibleControl : csText = "Use of an invisible control"; break;
case TUT_C_iError_DisabledControl : csText = "Use of a disabled control"; break;
case TUT_C_iError_NoMultipleSelection : csText = "The list is not a multiple selection list"; break;
case TUT_C_iError_UnknownListBox : csText = "Unknown list box name"; break;
case TUT_C_iError_ListBoxRequired : csText = "The control is not a list box"; break;
case TUT_C_iError_UnknownObject : csText = "Unknown object name"; break;
case TUT_C_iError_UnknownVariable : csText = "Unknown variable name or variable already declared";break;
case TUT_C_iError_CountCtrlRequired : csText = "A list box, list control or combo box is required"; break;
case TUT_C_iError_UnknownMessageBoxCtrl : csText = "Unknown message box control name"; break;
case TUT_C_iError_MessageBoxCtrlNotFound : csText = "Message box control not found"; break;
case TUT_C_iError_NoReturnValue : csText = "There is no return value"; break;
case TUT_C_iError_UnknownKey : csText = "Unknown key name"; break;
case TUT_C_iError_MultiLineRequired : csText = "The text edit is not multi-line"; break;
case TUT_C_iError_InvalidLineNumber : csText = "Invalid line number"; break;
case TUT_C_iError_LocalVariableExist : csText = "A local variable with the same name already exists";break;
case TUT_C_iError_GlobalVariableExist : csText = "A global variable with the same name already exists";break;
case TUT_C_iError_ListViewRequired : csText = "A List View control is required"; break;
case TUT_C_iError_UncoherentSelectionLimits : csText = "Limits of selection are incoherent"; break;
default : csText . Format ("Unknown error : code = %d" , _iErrorCode); break;
}
if (_iErrorCode == TUT_C_iError_LabelNotFound)
csMessage . Format ("Error n<> %d in file '%s' : %s (%s)" , _iErrorCode , _csFileName , csText , m_csLabelToFind);
else csMessage . Format ("Error n<> %d in file '%s' : %s (line %d : '%s')" , _iErrorCode , _csFileName , csText ,
_iLineNumber , _szLine);
}
// Give the focus to the tutorial thread
if (m_p_stCurrentUserWindow)
SetForegroundWindow (m_p_stCurrentUserWindow -> hWnd);
MessageBox (NULL , csMessage , "Tutorial manager" , MB_OK + MB_ICONSTOP + MB_TASKMODAL);
}
//-----------------------------------------------------------------------------
// class TUT_CTutorialManager - m_fn_vMoveMouseCursor
// Move the mouse cursor to the destination point
// Duration is in millisecond, speed in pixel/second and acceleration in pixel/second<6E>
//-----------------------------------------------------------------------------
void TUT_CTutorialManager::m_fn_vMoveMouseCursor (CPoint _stDestination, HWND _hWnd /*=NULL*/)
{
long lMaxDuration = m_lCurrentMaxDuration;
long lMinSpeed = m_lCurrentMinSpeed;
long lAcceleration = m_lCurrentAcceleration;
CPoint stCurrentMousePos;
GetCursorPos (& stCurrentMousePos);
CPoint stDelta = _stDestination - stCurrentMousePos;
long lCurrentDistance = (long) sqrt ((double) (stDelta . x * stDelta . x + stDelta . y * stDelta . y));
long lOptimumSpeed = lCurrentDistance * 1000 / lMaxDuration;
if (lOptimumSpeed < lMinSpeed) lOptimumSpeed = lMinSpeed;
long lCurrentSpeed = 0;
const long lDeltaT = m_bUseDrop ? 30 : 10; // one move every 10 milliseconds
long lTime = 0;
while (stCurrentMousePos != _stDestination && lTime < lMaxDuration)
{
long lDistanceToStop = lCurrentSpeed * lCurrentSpeed / 2 / lAcceleration;
long lCurrentAcceleration;
// breake ?
if (lCurrentDistance <= lDistanceToStop * 1100 / 1000) lCurrentAcceleration = - lAcceleration;
else
// accelerate ?
if (lCurrentSpeed < lOptimumSpeed * 1300 / 1000) lCurrentAcceleration = lAcceleration;
else lCurrentAcceleration = 0;
lCurrentSpeed += lCurrentAcceleration * lDeltaT / 1000;
POINT stTranslation;
stTranslation . x = lDeltaT * lCurrentSpeed * stDelta . x / lCurrentDistance / 1000;
stTranslation . y = lDeltaT * lCurrentSpeed * stDelta . y / lCurrentDistance / 1000;
if (stTranslation . x == 0)
{
if (stCurrentMousePos . x < _stDestination . x) stTranslation . x = 1; else
if (stCurrentMousePos . x > _stDestination . x) stTranslation . x = -1;
}
if (stTranslation . y == 0)
{
if (stCurrentMousePos . y < _stDestination . y) stTranslation . y = 1; else
if (stCurrentMousePos . y > _stDestination . y) stTranslation . y = -1;
}
stCurrentMousePos . x += stTranslation . x;
stCurrentMousePos . y += stTranslation . y;
SetCursorPos (stCurrentMousePos .x , stCurrentMousePos . y);
if (_hWnd)
{
CPoint stLocalMousePos = stCurrentMousePos;
ScreenToClient (_hWnd , & stLocalMousePos);
PostMessage (_hWnd , WM_MOUSEMOVE , 0 , MAKELPARAM (stLocalMousePos . x , stLocalMousePos . y) );
}
m_fn_vSleep (lDeltaT);
lTime += lDeltaT;
GetCursorPos (& stCurrentMousePos);
stDelta = _stDestination - stCurrentMousePos;
lCurrentDistance = (long) sqrt ((double) (stDelta . x * stDelta . x + stDelta . y * stDelta . y));
}
SetCursorPos (_stDestination . x , _stDestination . y);
if (_hWnd)
{
CPoint stLocalMousePos = _stDestination;
ScreenToClient (_hWnd , & stLocalMousePos);
PostMessage (_hWnd , WM_MOUSEMOVE , 0 , MAKELPARAM (stLocalMousePos . x , stLocalMousePos . y) );
}
}
//-----------------------------------------------------------------------------
// class TUT_CTutorialManager - m_fn_vMoveMouseCursor
// Move the mouse cursor to the center of the given window
//-----------------------------------------------------------------------------
void TUT_CTutorialManager::m_fn_vMoveMouseCursor (HWND _hWnd)
{
CRect WindowPos;
GetWindowRect (_hWnd , & WindowPos);
m_fn_vMoveMouseCursor (WindowPos . CenterPoint ());
}
//-----------------------------------------------------------------------------
// class TUT_CTutorialManager - m_fn_vClickOnControl
// Simulate a click on a control
//-----------------------------------------------------------------------------
void TUT_CTutorialManager::m_fn_vClickOnControl (HWND _hControl)
{
// Get the center of the control
CRect Rect;
GetClientRect (_hControl , & Rect);
LPARAM lParam = MAKELPARAM (Rect . CenterPoint () . x , Rect . CenterPoint () . y);
UINT uiMsgDown;
UINT uiMsgUp;
UINT uiMsgDblClk;
WPARAM wParam,wButton;
if (m_bUseRightButton)
{
uiMsgDown = WM_RBUTTONDOWN;
uiMsgUp = WM_RBUTTONUP;
uiMsgDblClk = WM_RBUTTONDBLCLK;
wButton = MK_RBUTTON;
}
else
{
uiMsgDown = WM_LBUTTONDOWN;
uiMsgUp = WM_LBUTTONUP;
uiMsgDblClk = WM_LBUTTONDBLCLK;
wButton = MK_LBUTTON;
}
wParam = (m_bUseShift ? MK_SHIFT : 0) + (m_bUseControl ? MK_CONTROL : 0);
m_fn_vSleep (60);
PostMessage (_hControl , uiMsgDown , wParam | wButton, lParam); // Clic on the button
m_fn_vSleep (60);
if (m_bUseDoubleClic)
{
PostMessage (_hControl , uiMsgUp , wParam , lParam);
m_fn_vSleep (60);
PostMessage (_hControl , uiMsgDblClk , wParam | wButton, lParam);
m_fn_vSleep (60);
}
PostMessage (_hControl , uiMsgUp , wParam , lParam); // Release the button
m_fn_vSleep (60);
}
//-----------------------------------------------------------------------------
// class TUT_CTutorialManager - m_fn_vSetTextInEdit
// Simulate an edition of text,
//-----------------------------------------------------------------------------
void TUT_CTutorialManager::m_fn_vSetTextInEdit (HWND _hTextEdit , const CString _csText)
{
HWND hParent = GetParent (_hTextEdit);
for (int i = 1 ; i <= _csText . GetLength () ; i ++)
{
SetWindowText (_hTextEdit , _csText . Left (i));
SendMessage (_hTextEdit , EM_SETSEL , i , i); // Put the caret at the end of the line
InvalidateRect (_hTextEdit , NULL , FALSE);
UpdateWindow (_hTextEdit);
SendMessage (_hTextEdit , EM_SETMODIFY , TRUE , 0);
if (_csText [i - 1] != ' ') m_fn_vSleep (m_iDurationBetweenKeys);
}
}
//-----------------------------------------------------------------------------
// class TUT_CTutorialManager - m_fn_vSelectLineInComboBox
// Simulate a selection into a combo box
//-----------------------------------------------------------------------------
void TUT_CTutorialManager::m_fn_vSelectLineInComboBox (HWND _hComboBox , int _iLineNumber)
{
m_fn_vSetGetLastError (TUT_C_iNoError);
int iComboBoxGetCount = SendMessage (_hComboBox , CB_GETCOUNT , 0 , 0);
if (_iLineNumber < 1 || _iLineNumber > iComboBoxGetCount)
{
m_fn_vSetGetLastError (TUT_C_iError_ComboBoxInvalidLine);
return;
}
SendMessage (_hComboBox , CB_SHOWDROPDOWN , TRUE , 0);
// To be sure the line will be visible
CRect stListRect;
SendMessage (_hComboBox , CB_GETDROPPEDCONTROLRECT , 0 , (LPARAM) & stListRect);
int iTopIndex = SendMessage (_hComboBox , CB_GETTOPINDEX , 0 , 0);
int iItemRect = SendMessage (_hComboBox , CB_GETITEMHEIGHT , 0 , 0);
int iNumberOfVisibleItem = stListRect . Height () / iItemRect - 2;
if (_iLineNumber - 1 < iTopIndex)
SendMessage (_hComboBox , CB_SETTOPINDEX , _iLineNumber - 1 , 0);
else
if (_iLineNumber - 1 > iTopIndex + iNumberOfVisibleItem - 1)
SendMessage (_hComboBox , CB_SETTOPINDEX , _iLineNumber - iNumberOfVisibleItem , 0);
iTopIndex = SendMessage (_hComboBox , CB_GETTOPINDEX , 0 , 0);
// Compute the position of the selected line to move the mouse to
CRect ComboPos;
GetWindowRect (_hComboBox , & ComboPos);
CPoint Pos = ComboPos . CenterPoint ();
Pos . y += ComboPos . Height () / 2 + iItemRect / 2 + iItemRect * (_iLineNumber - 1 - iTopIndex);
m_fn_vMoveMouseCursor (Pos);
SendMessage (_hComboBox , CB_SHOWDROPDOWN , FALSE , 0);
if (m_bUseRightButton)
{
LPARAM lParam = MAKELPARAM (Pos . x , Pos . y);
WPARAM wParam = (m_bUseShift ? MK_SHIFT : 0) | (m_bUseControl ? MK_CONTROL : 0);;
ScreenToClient (_hComboBox , & Pos);
PostMessage (_hComboBox , WM_RBUTTONDOWN , wParam + MK_RBUTTON , lParam);
PostMessage (_hComboBox , WM_RBUTTONUP , wParam , lParam);
}
else
{
HWND hParentWnd = GetParent (_hComboBox);
SendMessage (_hComboBox , CB_SETCURSEL , _iLineNumber - 1 , 0);
PostMessage (hParentWnd , WM_COMMAND , (CBN_SELCHANGE << 16) + GetDlgCtrlID (_hComboBox) , (LPARAM) _hComboBox);
}
}
//-----------------------------------------------------------------------------
// class TUT_CTutorialManager - m_fn_vSelectLineInListBox
// Simulate a selection into a list box
//-----------------------------------------------------------------------------
void TUT_CTutorialManager::m_fn_vSelectLineInListBox (HWND _hListBox , int _iLineNumber , BOOL _bAddToSelection /*=FALSE*/)
{
m_fn_vSetGetLastError (TUT_C_iNoError);
int iListBoxGetCount = SendMessage (_hListBox , LB_GETCOUNT , 0 , 0);
if (_iLineNumber < 1 || _iLineNumber > iListBoxGetCount)
{
m_fn_vSetGetLastError (TUT_C_iError_ListBoxInvalidLine);
return;
}
// To be sure the line will be visible
SendMessage(_hListBox , LVM_ENSUREVISIBLE , _iLineNumber - 1 , FALSE);
// Compute the position of the selected line to move the mouse to
CRect ListPos;
GetWindowRect (_hListBox , & ListPos);
CPoint Pos;
int iTopIndex = SendMessage (_hListBox , LB_GETTOPINDEX , 0 , 0);
int iItemHeight = SendMessage (_hListBox , LB_GETITEMHEIGHT , 0 , 0);
if (m_bUsePosition)
{
Pos . y = ListPos . top + iItemHeight * (_iLineNumber - 1 - iTopIndex);
if (m_bPercentForX)
if (m_bRightBorder ) Pos . x = ListPos . right - ListPos . Width () * m_iXPosition / 100;
else Pos . x = ListPos . left + ListPos . Width () * m_iXPosition / 100;
else
if (m_bRightBorder ) Pos . x = ListPos . right - m_iXPosition;
else Pos . x = ListPos . left + m_iXPosition;
if (m_bPercentForY)
if (m_bBottomBorder) Pos . y += iItemHeight - iItemHeight * m_iYPosition / 100;
else Pos . y += iItemHeight * m_iYPosition / 100;
else
if (m_bBottomBorder) Pos . y += iItemHeight - m_iYPosition;
else Pos . y += m_iYPosition;
}
else
{
Pos . x = min (ListPos . CenterPoint () . x , ListPos . left + 4 * iItemHeight);
Pos . y = ListPos . top + iItemHeight / 2 + iItemHeight * (_iLineNumber - 1 - iTopIndex);
}
m_fn_vMoveMouseCursor (Pos);
if (m_bUseRightButton)
{
ScreenToClient (_hListBox , & Pos);
LPARAM lParam = MAKELPARAM (Pos . x , Pos . y);
WPARAM wParam = (m_bUseShift ? MK_SHIFT : 0) | (m_bUseControl ? MK_CONTROL : 0);
PostMessage (_hListBox , WM_RBUTTONDOWN , wParam | MK_RBUTTON , lParam);
PostMessage (_hListBox , WM_RBUTTONUP , wParam , lParam);
}
else
if (m_bUseDoubleClic)
{
ScreenToClient (_hListBox , & Pos);
LPARAM lParam = MAKELPARAM (Pos . x , Pos . y);
WPARAM wParam = (m_bUseShift ? MK_SHIFT : 0) | (m_bUseControl ? MK_CONTROL : 0);
PostMessage (_hListBox , WM_LBUTTONDOWN , wParam | MK_LBUTTON , lParam);
PostMessage (_hListBox , WM_LBUTTONUP , wParam , lParam);
PostMessage (_hListBox , WM_LBUTTONDBLCLK , wParam | MK_LBUTTON , lParam);
PostMessage (_hListBox , WM_LBUTTONUP , wParam , lParam);
}
else
if (m_bUsePosition)
{
ScreenToClient (_hListBox , & Pos);
LPARAM lParam = MAKELPARAM (Pos . x , Pos . y);
WPARAM wParam = (m_bUseShift ? MK_SHIFT : 0) | (m_bUseControl ? MK_CONTROL : 0);
PostMessage (_hListBox , WM_LBUTTONDOWN , wParam | MK_LBUTTON , lParam);
PostMessage (_hListBox , WM_LBUTTONUP , wParam , lParam);
}
else
{
HWND hParentWnd = GetParent (_hListBox);
if (GetWindowLong (_hListBox , GWL_STYLE) & (LBS_EXTENDEDSEL | LBS_MULTIPLESEL))
{
// if not add, unselect all
if (! _bAddToSelection)
SendMessage (_hListBox , LB_SETSEL , FALSE , - 1);
SendMessage (_hListBox , LB_SETSEL , TRUE , _iLineNumber - 1);
}
else
SendMessage (_hListBox , LB_SETCURSEL , _iLineNumber - 1 , 0);
PostMessage (hParentWnd , WM_COMMAND , (LBN_SELCHANGE << 16) + GetDlgCtrlID (_hListBox) , (LPARAM) _hListBox);
}
}
//-----------------------------------------------------------------------------
// class TUT_CTutorialManager - m_fn_vSelectLineInListCtrl
// Simulate a selection into a list control
//-----------------------------------------------------------------------------
void TUT_CTutorialManager::m_fn_vSelectLineInListCtrl (HWND _hListCtrl , int _iLineNumber)
{
m_fn_vSetGetLastError (TUT_C_iNoError);
int iListCtrlGetCount = ListView_GetItemCount (_hListCtrl);
if (_iLineNumber < 1 || _iLineNumber > iListCtrlGetCount)
{
m_fn_vSetGetLastError (TUT_C_iError_ListCtrlInvalidLine);
return;
}
// To be sure the line will be visible
ListView_EnsureVisible (_hListCtrl , _iLineNumber - 1 , FALSE);
// Compute the position of the selected line to move the mouse to
CRect stItemRect;
ListView_GetItemRect (_hListCtrl , _iLineNumber - 1 , & stItemRect , LVIR_BOUNDS);
POINT stPos;
stPos . x = min (stItemRect . CenterPoint () . x , stItemRect . left + 2 * stItemRect . Height ());
stPos . y = stItemRect . CenterPoint () . y;
LPARAM lParam = MAKELPARAM (stPos . x , stPos . y);
WPARAM wParam = (m_bUseShift ? MK_SHIFT : 0) | (m_bUseControl ? MK_CONTROL : 0);
if (m_bUseRightButton)
{
ClientToScreen (_hListCtrl , & stPos);
m_fn_vMoveMouseCursor (stPos);
PostMessage (_hListCtrl , WM_RBUTTONDOWN , wParam + MK_RBUTTON , lParam);
PostMessage (_hListCtrl , WM_RBUTTONUP , wParam , lParam);
}
else
if (m_bUseDoubleClic)
{
ClientToScreen (_hListCtrl , & stPos);
m_fn_vMoveMouseCursor (stPos);
PostMessage (_hListCtrl , WM_LBUTTONDOWN , wParam + MK_LBUTTON , lParam);
PostMessage (_hListCtrl , WM_LBUTTONUP , wParam , lParam);
PostMessage (_hListCtrl , WM_LBUTTONDBLCLK , wParam + MK_LBUTTON , lParam);
PostMessage (_hListCtrl , WM_LBUTTONUP , wParam , lParam);
}
else
{
if (m_bUsePosition)
{
if (m_bPercentForX)
if (m_bRightBorder ) stPos . x = stItemRect . right - stItemRect . Width () * m_iXPosition / 100;
else stPos . x = stItemRect . left + stItemRect . Width () * m_iXPosition / 100;
else
if (m_bRightBorder ) stPos . x = stItemRect . right - m_iXPosition;
else stPos . x = stItemRect . left + m_iXPosition;
if (m_bPercentForY)
if (m_bBottomBorder) stPos . y = stItemRect . bottom - stItemRect . Height () * m_iYPosition / 100;
else stPos . y = stItemRect . top + stItemRect . Height () * m_iYPosition / 100;
else
if (m_bBottomBorder) stPos . y = stItemRect . bottom - m_iYPosition;
else stPos . y = stItemRect . top + m_iYPosition;
lParam = MAKELPARAM (stPos . x , stPos . y);
}
ClientToScreen (_hListCtrl , & stPos);
m_fn_vMoveMouseCursor (stPos);
PostMessage (_hListCtrl , WM_LBUTTONDOWN , wParam + MK_LBUTTON , lParam);
PostMessage (_hListCtrl , WM_LBUTTONUP , wParam , lParam);
}
}
//-----------------------------------------------------------------------------
// class TUT_CTutorialManager - m_fn_vEnsureVisibleInTree
// Make sure the given item of a tree is visible or invisible
//-----------------------------------------------------------------------------
void TUT_CTutorialManager::m_fn_vEnsureVisibleInTree (HWND _hTreeCtrl , HTREEITEM _hItem ,
BOOL _bEnsureVisible /* = TRUE */)
{
// Get the parent item. If there is no parent, we show the item and we return
HTREEITEM hParentItem = TreeView_GetParent (_hTreeCtrl , _hItem);
if (! hParentItem)
{
TreeView_EnsureVisible (_hTreeCtrl , _hItem);
return;
}
// If the parent is not visible, we make it visible (recursiv call)
if (! m_fn_bIsItemVisibleInTree (_hTreeCtrl , hParentItem))
m_fn_vEnsureVisibleInTree (_hTreeCtrl , hParentItem);
// Now that the parent is visible, we check if its children are visible
if (m_fn_uiGetTreeCtrlState (_hTreeCtrl , hParentItem , TVIS_EXPANDED) != TVIS_EXPANDED)
{
CRect Rect;
TreeView_GetItemRect (_hTreeCtrl , hParentItem , & Rect , FALSE);
POINT Pos;
Pos . x = Rect . left + Rect . Height () / 2;
Pos . y = Rect . CenterPoint () . y;
ClientToScreen (_hTreeCtrl , & Pos);
m_fn_vMoveMouseCursor (Pos);
TreeView_Expand (_hTreeCtrl , hParentItem , _bEnsureVisible ? TVE_EXPAND : TVE_COLLAPSE);
}
if (_bEnsureVisible) TreeView_EnsureVisible (_hTreeCtrl , _hItem);
}
//-----------------------------------------------------------------------------
// class TUT_CTutorialManager - m_fn_bSelectItemInTreeBox
// Simulate a selection in a tree box
// Return FALSE if there is no item with the given text
//-----------------------------------------------------------------------------
BOOL TUT_CTutorialManager::m_fn_bSelectItemInTreeBox (HWND _hTreeCtrl , CString _csTextToSelect)
{
HTREEITEM hRootItem = TreeView_GetRoot (_hTreeCtrl);
HTREEITEM hItemToSelect = m_fn_hFindStringInTree (_hTreeCtrl , hRootItem , _csTextToSelect);
if (! hItemToSelect) return FALSE; // Not found -> return FALSE
m_fn_vEnsureVisibleInTree (_hTreeCtrl , hItemToSelect , TRUE);
CRect Rect;
TreeView_GetItemRect (_hTreeCtrl , hItemToSelect , & Rect , FALSE);
POINT Pos;
Pos . x = Rect . left + Rect . Height () * 4;
Pos . y = Rect . CenterPoint () . y;
ClientToScreen (_hTreeCtrl , & Pos);
// Select the item
m_fn_vMoveMouseCursor (Pos);
TreeView_SelectItem (_hTreeCtrl , hItemToSelect);
// Send a second notification to the parent, because the first one sent by TreeView_SelectItem did not have action = TVC_BYMOUSE
NM_TREEVIEW stTreeView;
stTreeView . hdr . hwndFrom = _hTreeCtrl;
stTreeView . hdr . idFrom = GetDlgCtrlID (_hTreeCtrl);
stTreeView . hdr . code = TVN_SELCHANGED;
stTreeView . action = TVC_BYMOUSE;
SendMessage (GetParent (_hTreeCtrl) , WM_NOTIFY , GetDlgCtrlID (_hTreeCtrl) , (LPARAM) & stTreeView);
return TRUE;
}
//-----------------------------------------------------------------------------
// class TUT_CTutorialManager - m_fn_vWriteText
// Write a line of text into a tutorial window
//-----------------------------------------------------------------------------
void TUT_CTutorialManager::m_fn_vWriteText (HWND _hEditView , CString _csText)
{
ASSERT (IsWindow (_hEditView)); // The edit view must be correct
HWND hPreviousWnd = GetForegroundWindow ();
// Put the caret at the end of the text
int iNumberOfChar = GetWindowTextLength (_hEditView);
SendMessage (_hEditView , EM_SETSEL , iNumberOfChar , iNumberOfChar);
// Change the format
CHARFORMAT stCharFormat;
stCharFormat . cbSize = sizeof (CHARFORMAT);
stCharFormat . dwMask = CFM_COLOR | CFM_SIZE | CFM_FACE;
stCharFormat . dwEffects &= ~ CFE_AUTOCOLOR; // Remove the flag "auto color"
stCharFormat . crTextColor = m_xCurrentColor;
stCharFormat . yHeight = m_lCurrentHeight * GetDeviceCaps (GetDC (_hEditView) , LOGPIXELSY) * 180 / 1000;
strcpy (stCharFormat . szFaceName , "Arial");
SendMessage (_hEditView , EM_SETCHARFORMAT , SCF_SELECTION , (LPARAM) & stCharFormat);
PARAFORMAT stParaFormat;
stParaFormat . cbSize = sizeof (PARAFORMAT);
stParaFormat . dwMask = PFM_ALIGNMENT;
stParaFormat . wAlignment = (unsigned short) m_lCurrentAlignment;
SendMessage (_hEditView ,EM_SETPARAFORMAT , 0 , (LPARAM) & stParaFormat);
// Insert the new text
if (_csText . Right (1) == "\\") _csText = _csText . Left (_csText . GetLength () - 1); // If the string ends with '\', no line feed
else
{
_csText += (char)13;
_csText += (char)10;
}
SendMessage (_hEditView , EM_REPLACESEL , FALSE /* No Undo */ , (LPARAM) (LPCTSTR) _csText);
// Check if scroll is necessary
RECT stEditViewRect;
GetClientRect (_hEditView , & stEditViewRect);
POINT stEndOfTextPos;
BOOL bOk;
int iCounter = 0;
do
{
SendMessage (_hEditView , EM_POSFROMCHAR , (WPARAM) & stEndOfTextPos , GetWindowTextLength (_hEditView));
bOk = stEndOfTextPos . y <= stEditViewRect . bottom;
if (! bOk) SendMessage (_hEditView , EM_LINESCROLL , 0 , 1);
} while (bOk == FALSE && ++iCounter < 10); // To prevent from infinite loop
InvalidateRect (_hEditView , NULL , FALSE);
UpdateWindow (_hEditView);
SetForegroundWindow (hPreviousWnd);
}
//-----------------------------------------------------------------------------
// class TUT_CTutorialManager - m_fn_vSendKey
// Send a key
//-----------------------------------------------------------------------------
void TUT_CTutorialManager::m_fn_vSendKey (int _iVirtualKeyCode , BOOL _bKeyPressed)
{
keybd_event (_iVirtualKeyCode , _iVirtualKeyCode , _bKeyPressed ? 0 : KEYEVENTF_KEYUP , 0);
Sleep (10);
}
//-----------------------------------------------------------------------------
// class TUT_CTutorialManager - m_fn_szHandleQuote
// replace two consecutive quotes by a double-quote
//-----------------------------------------------------------------------------
char *TUT_CTutorialManager::m_fn_szHandleQuote(char * _szString)
{
char *cBegin = _szString;
char *cTarget = _szString;
char *cSource = _szString;
BOOL bPreviousQuote = FALSE;
while (*cSource)
{
if (*cSource == '\'')
{
if (bPreviousQuote)
{
*cTarget++ = '\"';
bPreviousQuote = FALSE;
}
else
{
bPreviousQuote = TRUE;
}
}
else
{
if (bPreviousQuote)
{
*cTarget++ = '\'';
}
*cTarget++ = *cSource;
bPreviousQuote = FALSE;
}
cSource++;
}
if (bPreviousQuote)
{
*cTarget++ = '\'';
}
*cTarget = 0;
return _szString;
}