7b90347b3f
- Aggiunta gestione dialoghi non modali.
1972 lines
70 KiB
C++
1972 lines
70 KiB
C++
//----------------------------------------------------------------------------
|
||
// EgalTech 2014-2014
|
||
//----------------------------------------------------------------------------
|
||
// File : LUA_General.cpp Data : 27.09.14 Versione : 1.5i5
|
||
// Contenuto : Funzioni generali per LUA.
|
||
//
|
||
//
|
||
//
|
||
// Modifiche : 27.09.14 DS Creazione modulo.
|
||
//
|
||
//
|
||
//----------------------------------------------------------------------------
|
||
|
||
//--------------------------- Include ----------------------------------------
|
||
#include "stdafx.h"
|
||
#include "DllMain.h"
|
||
#include "EXE.h"
|
||
#include "LUA.h"
|
||
#include "GenTools.h"
|
||
#include "resource.h"
|
||
#include "AuxDialogBox.h"
|
||
#include "/EgtDev/Include/ExeExecutor.h"
|
||
#include "/EgtDev/Include/EGkLuaAux.h"
|
||
#include "/EgtDev/Include/EGkStringUtils3d.h"
|
||
#include "/EgtDev/Include/EGnStringUtils.h"
|
||
#include "/EgtDev/Include/EGnFileUtils.h"
|
||
#include "/EgtDev/Include/EGnFileCompare.h"
|
||
#include "/EgtDev/Include/EGnStringKeyVal.h"
|
||
#include "/EgtDev/Include/EGnEgtUUID.h"
|
||
#include "/EgtDev/Include/EgtPerfCounter.h"
|
||
#include "/EgtDev/Include/EgtIniFile.h"
|
||
#include "/EgtDev/Include/EgtNumUtils.h"
|
||
#include "/EgtDev/Include/EgtStringConverter.h"
|
||
#include <sstream>
|
||
#include <Windowsx.h>
|
||
#include <shlobj.h>
|
||
|
||
using namespace std ;
|
||
|
||
//----------------------------------------------------------------------------
|
||
static PerformanceCounter s_Counter ;
|
||
|
||
//-------------------------------------------------------------------------------
|
||
static int
|
||
MyPrint( lua_State* L)
|
||
{
|
||
string sOut ;
|
||
int n = lua_gettop( L) ; /* number of arguments */
|
||
lua_getglobal( L, "tostring") ;
|
||
for ( int i = 1 ; i <= n ; ++ i) {
|
||
const char* s ;
|
||
lua_pushvalue( L, -1) ; /* function to be called */
|
||
lua_pushvalue( L, i) ; /* value to print */
|
||
lua_call( L, 1, 1) ;
|
||
s = lua_tostring( L, -1) ; /* get result */
|
||
if ( s == nullptr)
|
||
return luaL_error( L,
|
||
"'tostring' must return a string to 'print'") ;
|
||
if ( i > 1)
|
||
sOut += "\t" ;
|
||
sOut += s ;
|
||
lua_pop( L, 1) ; /* pop result */
|
||
}
|
||
if ( ! sOut.empty())
|
||
LOG_INFO( GetLogger(), sOut.c_str())
|
||
|
||
return 0 ;
|
||
}
|
||
|
||
//-------------------------------------------------------------------------------
|
||
static int
|
||
LuaEvalNumExpr( lua_State* L)
|
||
{
|
||
// un solo parametro stringa : sExpr
|
||
string sExpr ;
|
||
LuaCheckParam( L, 1, sExpr)
|
||
LuaClearStack( L) ;
|
||
// valuto l'espressione
|
||
double dVal ;
|
||
bool bOk = ExeLuaEvalNumExpr( sExpr, &dVal) ;
|
||
// restituisco il risultato
|
||
if ( bOk)
|
||
LuaSetParam( L, dVal) ;
|
||
else
|
||
LuaSetParam( L) ;
|
||
return 1 ;
|
||
}
|
||
|
||
//-------------------------------------------------------------------------------
|
||
static int
|
||
LuaPause( lua_State* L)
|
||
{
|
||
// 1 o 2 parametri : numero di millisecondi [, bForced]
|
||
int nTime ;
|
||
LuaCheckParam( L, 1, nTime)
|
||
bool bForced = false ;
|
||
LuaGetParam( L, 2, bForced) ;
|
||
LuaClearStack( L) ;
|
||
// se forzata o abilitata UI, controllo la durata della pausa e la eseguo
|
||
if ( bForced || ExeGetEnableUI()) {
|
||
const int MIN_TIME = 0 ;
|
||
const int MAX_TIME = 10000 ;
|
||
if ( nTime < MIN_TIME)
|
||
nTime = MIN_TIME ;
|
||
else if ( nTime > MAX_TIME)
|
||
nTime = MAX_TIME ;
|
||
Sleep( nTime) ;
|
||
}
|
||
// restituisco il risultato
|
||
LuaSetParam( L, true) ;
|
||
return 1 ;
|
||
}
|
||
|
||
//-------------------------------------------------------------------------------
|
||
static int
|
||
LuaGetKeyPressed( lua_State* L)
|
||
{
|
||
// 1 parametro : nKeyCode
|
||
int nKeyCode ;
|
||
LuaCheckParam( L, 1, nKeyCode)
|
||
LuaClearStack( L) ;
|
||
// se abilitata UI, controllo se il tasto indicato è premuto
|
||
bool bPressed = false ;
|
||
if ( ExeGetEnableUI()) {
|
||
bPressed = (( GetAsyncKeyState( nKeyCode) & 0x8000) != 0) ;
|
||
}
|
||
// restituisco il risultato
|
||
LuaSetParam( L, bPressed) ;
|
||
return 1 ;
|
||
}
|
||
|
||
//-------------------------------------------------------------------------------
|
||
static int
|
||
LuaStartCounter( lua_State* L)
|
||
{
|
||
// nessun parametro
|
||
LuaClearStack( L) ;
|
||
// avvio il contatore
|
||
s_Counter.Start() ;
|
||
return 0 ;
|
||
}
|
||
|
||
//-------------------------------------------------------------------------------
|
||
static int
|
||
LuaStopCounter( lua_State* L)
|
||
{
|
||
// nessun parametro
|
||
LuaClearStack( L) ;
|
||
// fermo il contatore
|
||
double dTime = s_Counter.Stop() ;
|
||
// restituisco il risultato
|
||
LuaSetParam( L, dTime) ;
|
||
return 1 ;
|
||
}
|
||
|
||
//-------------------------------------------------------------------------------
|
||
static int
|
||
LuaNumToString( lua_State* L)
|
||
{
|
||
// 1 o 2 parametri : dVal [, nDec]
|
||
double dVal ;
|
||
LuaCheckParam( L, 1, dVal)
|
||
int nDec = 3 ;
|
||
LuaGetParam( L, 2, nDec) ;
|
||
LuaClearStack( L) ;
|
||
// costruisco la stringa
|
||
string sVal = ToString( dVal, nDec) ;
|
||
// ritorno il risultato
|
||
LuaSetParam( L, sVal) ;
|
||
return 1 ;
|
||
}
|
||
|
||
//-------------------------------------------------------------------------------
|
||
static int
|
||
LuaSplitString( lua_State* L)
|
||
{
|
||
// 1 o 2 parametri : sVal [, sSep]
|
||
string sVal ;
|
||
string sSep = "," ;
|
||
bool bFound = LuaGetParam( L, 1, sVal) ;
|
||
LuaGetParam( L, 2, sSep) ;
|
||
LuaClearStack( L) ;
|
||
// se ricevuta stringa, la divido in parti separate da sSep
|
||
if ( bFound) {
|
||
// eseguo separazione (se tra i separatori c'è spazio ora tokenize collassa eventuali spazi consecutivi in uno solo)
|
||
STRVECTOR vsVal ;
|
||
Tokenize( sVal, sSep, vsVal) ;
|
||
// ritorno il risultato
|
||
LuaSetParam( L, vsVal) ;
|
||
}
|
||
// altrimenti restituisco nil
|
||
else
|
||
LuaSetParam( L) ;
|
||
return 1 ;
|
||
}
|
||
|
||
//-------------------------------------------------------------------------------
|
||
static int
|
||
LuaSplitStringPlus( lua_State* L)
|
||
{
|
||
// 2 parametri : sVal, sHea
|
||
string sVal ;
|
||
string sHea ;
|
||
bool bOk = LuaGetParam( L, 1, sVal) &&
|
||
LuaGetParam( L, 2, sHea) ;
|
||
LuaClearStack( L) ;
|
||
// se ricevute stringhe, divido la prima in parti con intestazioni della seconda (che conservo)
|
||
if ( bOk) {
|
||
STRVECTOR vsVal ;
|
||
TokenizePlus( sVal, sHea, vsVal) ;
|
||
// ritorno il risultato
|
||
LuaSetParam( L, vsVal) ;
|
||
}
|
||
// altrimenti restituisco nil
|
||
else
|
||
LuaSetParam( L) ;
|
||
return 1 ;
|
||
}
|
||
|
||
//-------------------------------------------------------------------------------
|
||
static int
|
||
LuaReplaceString( lua_State* L)
|
||
{
|
||
// 3 parametri : sVal, sOld, sNew
|
||
string sVal ;
|
||
LuaCheckParam( L, 1, sVal)
|
||
string sOld ;
|
||
LuaCheckParam( L, 2, sOld)
|
||
string sNew ;
|
||
LuaCheckParam( L, 3, sNew)
|
||
LuaClearStack( L) ;
|
||
// eseguo sostituzione nella stringa della sequenza indicata dal secondo parametro con quella del terzo
|
||
int nRes = ReplaceString( sVal, sOld, sNew) ;
|
||
// restituisco il risultato
|
||
LuaSetParam( L, sVal) ;
|
||
LuaSetParam( L, nRes) ;
|
||
return 2 ;
|
||
}
|
||
//-------------------------------------------------------------------------------
|
||
static int
|
||
LuaSetVal( lua_State* L)
|
||
{
|
||
// 2 parametri : Key, bVal|nVal|dVal|sVal|vtVal|ptVal|b3Val|frVal
|
||
string sKey ;
|
||
LuaCheckParam( L, 1, sKey)
|
||
bool bOk = false ;
|
||
string sNotes = "" ;
|
||
switch ( lua_type( L, 2)) {
|
||
case LUA_TBOOLEAN :
|
||
{ bool bVal ;
|
||
LuaGetParam( L, 2, bVal) ;
|
||
LuaClearStack( L) ;
|
||
bOk = SetVal( sKey, bVal, sNotes) ;
|
||
} break ;
|
||
case LUA_TNUMBER :
|
||
{ double dVal ;
|
||
LuaGetParam( L, 2, dVal) ;
|
||
LuaClearStack( L) ;
|
||
bOk = SetVal( sKey, dVal, sNotes) ;
|
||
} break ;
|
||
case LUA_TSTRING :
|
||
{ string sVal ;
|
||
LuaGetParam( L, 2, sVal) ;
|
||
LuaClearStack( L) ;
|
||
bOk = SetVal( sKey, (const string&) sVal, sNotes) ;
|
||
} break ;
|
||
case LUA_TTABLE :
|
||
{ Frame3d frVal ;
|
||
BBox3d b3Val ;
|
||
Vector3d vtVal ; // va bene anche per Point3d
|
||
INTVECTOR vnVal ;
|
||
DBLVECTOR vdVal ;
|
||
STRVECTOR vsVal ;
|
||
if ( LuaGetParam( L, 2, frVal)) {
|
||
LuaClearStack( L) ;
|
||
bOk = SetVal( sKey, frVal, sNotes) ;
|
||
}
|
||
else if ( LuaGetParam( L, 2, b3Val)) {
|
||
LuaClearStack( L) ;
|
||
bOk = SetVal( sKey, b3Val, sNotes) ;
|
||
}
|
||
else if ( LuaGetParam( L, 2, vtVal)) {
|
||
LuaClearStack( L) ;
|
||
bOk = SetVal( sKey, vtVal, sNotes) ;
|
||
}
|
||
else if ( LuaGetParam( L, 2, vnVal)) {
|
||
LuaClearStack( L) ;
|
||
bOk = SetVal( sKey, vnVal, sNotes) ;
|
||
}
|
||
else if ( LuaGetParam( L, 2, vdVal)) {
|
||
LuaClearStack( L) ;
|
||
bOk = SetVal( sKey, vdVal, sNotes) ;
|
||
}
|
||
else if ( LuaGetParam( L, 2, vsVal)) {
|
||
LuaClearStack( L) ;
|
||
bOk = SetVal( sKey, vsVal, sNotes) ;
|
||
}
|
||
} break ;
|
||
}
|
||
// restituisco il risultato
|
||
if ( bOk)
|
||
LuaSetParam( L, sNotes) ;
|
||
else
|
||
LuaSetParam(L, "") ;
|
||
return 1 ;
|
||
}
|
||
|
||
//-------------------------------------------------------------------------------
|
||
static int
|
||
LuaGetVal( lua_State* L)
|
||
{
|
||
// 2 o 3 parametri : String, Key, sType
|
||
string sVal ;
|
||
LuaCheckParam( L, 1, sVal)
|
||
string sKey ;
|
||
LuaCheckParam( L, 2, sKey)
|
||
string sType = "s" ;
|
||
LuaGetParam( L, 3, sType) ;
|
||
LuaClearStack( L) ;
|
||
// recupero l'info
|
||
if ( sType == "b" || sType == "B") {
|
||
bool bVal ;
|
||
if ( GetVal( sVal, sKey, bVal))
|
||
LuaSetParam( L, bVal) ;
|
||
else
|
||
LuaSetParam( L) ;
|
||
}
|
||
else if ( sType == "i" || sType == "I") {
|
||
int nVal ;
|
||
if ( GetVal( sVal, sKey, nVal))
|
||
LuaSetParam( L, nVal) ;
|
||
else
|
||
LuaSetParam( L) ;
|
||
}
|
||
else if ( sType == "d" || sType == "D") {
|
||
double dVal ;
|
||
if ( GetVal( sVal, sKey, dVal))
|
||
LuaSetParam( L, dVal) ;
|
||
else
|
||
LuaSetParam( L) ;
|
||
}
|
||
else if ( sType == "v" || sType == "V") {
|
||
Vector3d vtVal ;
|
||
if ( GetVal( sVal, sKey, vtVal))
|
||
LuaSetParam( L, vtVal) ;
|
||
else
|
||
LuaSetParam( L) ;
|
||
}
|
||
else if ( sType == "p" || sType == "P") {
|
||
Point3d ptVal ;
|
||
if ( GetVal( sVal, sKey, ptVal))
|
||
LuaSetParam( L, ptVal) ;
|
||
else
|
||
LuaSetParam( L) ;
|
||
}
|
||
else if ( sType == "x" || sType == "X") {
|
||
BBox3d b3Val ;
|
||
if ( GetVal( sVal, sKey, b3Val))
|
||
LuaSetParam( L, b3Val) ;
|
||
else
|
||
LuaSetParam( L) ;
|
||
}
|
||
else if ( sType == "f" || sType == "F") {
|
||
Frame3d frVal ;
|
||
if ( GetVal( sVal, sKey, frVal))
|
||
LuaSetParam( L, frVal) ;
|
||
else
|
||
LuaSetParam( L) ;
|
||
}
|
||
else if ( sType == "vi" || sType == "vI") {
|
||
INTVECTOR vnVal ;
|
||
if ( GetVal( sVal, sKey, vnVal))
|
||
LuaSetParam( L, vnVal) ;
|
||
else
|
||
LuaSetParam( L) ;
|
||
}
|
||
else if ( sType == "vd" || sType == "vD") {
|
||
DBLVECTOR vdVal ;
|
||
if ( GetVal( sVal, sKey, vdVal))
|
||
LuaSetParam( L, vdVal) ;
|
||
else
|
||
LuaSetParam( L) ;
|
||
}
|
||
else if ( sType == "vs" || sType == "vS") {
|
||
STRVECTOR vsVal ;
|
||
if ( GetVal( sVal, sKey, vsVal))
|
||
LuaSetParam( L, vsVal) ;
|
||
else
|
||
LuaSetParam( L) ;
|
||
}
|
||
else { // "s" "S"
|
||
string sInfo ;
|
||
if ( GetVal( sVal, sKey, sInfo))
|
||
LuaSetParam( L, sInfo) ;
|
||
else
|
||
LuaSetParam( L) ;
|
||
}
|
||
return 1 ;
|
||
}
|
||
|
||
//-------------------------------------------------------------------------------
|
||
static int
|
||
LuaGetUUID( lua_State* L)
|
||
{
|
||
// nessun parametro
|
||
LuaClearStack( L) ;
|
||
// recupero UUID e lo trasformo in stringa
|
||
EgtUUID uuId ;
|
||
bool bOk = CreateEgtUUID( uuId) ;
|
||
// restituisco il risultato
|
||
if ( bOk)
|
||
LuaSetParam( L, ToString( uuId)) ;
|
||
else
|
||
LuaSetParam( L) ;
|
||
return 1 ;
|
||
}
|
||
|
||
//-------------------------------------------------------------------------------
|
||
static int
|
||
LuaExecTsc( lua_State* L)
|
||
{
|
||
// 1 parametro : file
|
||
string sFile ;
|
||
LuaCheckParam( L, 1, sFile)
|
||
LuaClearStack( L) ;
|
||
// eseguo lo script TSC
|
||
bool bOk = ExeTscExecFile( sFile) ;
|
||
// restituisco il risultato
|
||
LuaSetParam( L, bOk) ;
|
||
return 1 ;
|
||
}
|
||
|
||
//-------------------------------------------------------------------------------
|
||
static int
|
||
LuaExecTscLine( lua_State* L)
|
||
{
|
||
// 1 parametro : linea
|
||
string sLine ;
|
||
LuaCheckParam( L, 1, sLine)
|
||
LuaClearStack( L) ;
|
||
// eseguo la linea TSC
|
||
bool bOk = ExeTscExecLine( sLine) ;
|
||
// restituisco il risultato
|
||
LuaSetParam( L, bOk) ;
|
||
return 1 ;
|
||
}
|
||
|
||
//-------------------------------------------------------------------------------
|
||
static int
|
||
LuaSetTscVar( lua_State* L)
|
||
{
|
||
// 2 parametri : nome, valore
|
||
string sName ;
|
||
LuaCheckParam( L, 1, sName)
|
||
int nVal ;
|
||
LuaCheckParam( L, 2, nVal)
|
||
LuaClearStack( L) ;
|
||
// assegno il valore alla variabile Tsc
|
||
bool bOk = ExeTscSetVariable( sName, nVal) ;
|
||
// restituisco il risultato
|
||
LuaSetParam( L, bOk) ;
|
||
return 1 ;
|
||
}
|
||
|
||
//-------------------------------------------------------------------------------
|
||
static int
|
||
LuaGetTscVar( lua_State* L)
|
||
{
|
||
// 1 parametro : nome
|
||
string sName ;
|
||
LuaCheckParam( L, 1, sName)
|
||
LuaClearStack( L) ;
|
||
// recupero il valore della variabile Tsc
|
||
int nVal ;
|
||
bool bOk = ExeTscGetVariable( sName, nVal) ;
|
||
// restituisco il risultato
|
||
if ( bOk)
|
||
LuaSetParam( L, nVal) ;
|
||
else
|
||
LuaSetParam( L) ;
|
||
return 1 ;
|
||
}
|
||
|
||
//-------------------------------------------------------------------------------
|
||
static int
|
||
LuaGetDebugLevel( lua_State* L)
|
||
{
|
||
// nessun parametro
|
||
LuaClearStack( L) ;
|
||
// restituisco il livello di debug
|
||
int nDebugLev = ExeGetDebugLevel() ;
|
||
LuaSetParam( L, nDebugLev) ;
|
||
return 1 ;
|
||
}
|
||
|
||
//-------------------------------------------------------------------------------
|
||
static int
|
||
LuaGetUserLevel( lua_State* L)
|
||
{
|
||
// nessun parametro
|
||
LuaClearStack( L) ;
|
||
// restituisco il livello utente
|
||
int nUserLev = ExeGetUserLevel() ;
|
||
LuaSetParam( L, nUserLev) ;
|
||
return 1 ;
|
||
}
|
||
|
||
//-------------------------------------------------------------------------------
|
||
static int
|
||
LuaOutLog( lua_State* L)
|
||
{
|
||
// 1 o 2 parametri : stringa da emettere [, DebugLevel = 0]
|
||
string sOut ;
|
||
LuaCheckParam( L, 1, sOut)
|
||
int nDbgLev = 0 ;
|
||
LuaGetParam( L, 2, nDbgLev) ;
|
||
LuaClearStack( L) ;
|
||
// accodo il messaggio nel file di log
|
||
ExeOutLog( sOut, nDbgLev) ;
|
||
// non c'è risultato
|
||
return 0 ;
|
||
}
|
||
|
||
//-------------------------------------------------------------------------------
|
||
static int
|
||
LuaGetEnableUI( lua_State* L)
|
||
{
|
||
// nessun parametro
|
||
LuaClearStack( L) ;
|
||
// accodo il messaggio nel file di log
|
||
bool bOk = ExeGetEnableUI() ;
|
||
// restituisco lo stato di abilitazione dell'interfaccia utente
|
||
LuaSetParam( L, bOk) ;
|
||
return 1 ;
|
||
}
|
||
|
||
//-------------------------------------------------------------------------------
|
||
static int
|
||
LuaOutBox( lua_State* L)
|
||
{
|
||
// 2, 3 o 4 parametri : sOut, sTitle [, sIcon] [, sButtons]
|
||
string sOut ;
|
||
LuaCheckParam( L, 1, sOut)
|
||
string sTitle ;
|
||
LuaCheckParam( L, 2, sTitle)
|
||
string sIcon ;
|
||
LuaGetParam( L, 3, sIcon) ;
|
||
int nIcon = 0 ;
|
||
ToUpper( sIcon) ;
|
||
if ( sIcon == "ERROR")
|
||
nIcon = MB_ICONERROR ;
|
||
else if ( sIcon == "WARNING")
|
||
nIcon = MB_ICONWARNING ;
|
||
else if ( sIcon == "INFO")
|
||
nIcon = MB_ICONINFORMATION ;
|
||
else if ( sIcon == "QUESTION")
|
||
nIcon = MB_ICONQUESTION ;
|
||
string sButtons ;
|
||
LuaGetParam( L, 4, sButtons) ;
|
||
int nButtons = MB_OKCANCEL ;
|
||
ToUpper( sButtons) ;
|
||
if ( sButtons == "OK")
|
||
nButtons = MB_OK ;
|
||
else if ( sButtons == "OKCANCEL")
|
||
nButtons = MB_OKCANCEL ;
|
||
else if ( sButtons == "ABORTRETRYIGNORE")
|
||
nButtons = MB_ABORTRETRYIGNORE ;
|
||
else if ( sButtons == "YESNOCANCEL")
|
||
nButtons = MB_YESNOCANCEL ;
|
||
else if ( sButtons == "YESNO")
|
||
nButtons = MB_YESNO ;
|
||
else if ( sButtons == "RETRYCANCEL")
|
||
nButtons = MB_RETRYCANCEL ;
|
||
else if ( sButtons == "CANCELTRYCONTINUE")
|
||
nButtons = MB_CANCELTRYCONTINUE ;
|
||
LuaClearStack( L) ;
|
||
// emetto finestra di dialogo (solo se ablitata UI)
|
||
int nRes = ExeMessageBox( sOut, sTitle, nButtons | nIcon) ;
|
||
// risultato
|
||
if ( nRes == IDOK || nRes == IDRETRY || nRes == IDYES || nRes == IDTRYAGAIN)
|
||
LuaSetParam( L, true) ;
|
||
else if ( nRes == IDNO || nRes == IDCONTINUE || nRes == IDIGNORE)
|
||
LuaSetParam( L, false) ;
|
||
else
|
||
LuaSetParam( L) ;
|
||
return 1 ;
|
||
}
|
||
|
||
//-------------------------------------------------------------------------------
|
||
static int
|
||
LuaProcessEvents( lua_State* L)
|
||
{
|
||
// 2 parametri : nProg, nPause
|
||
int nProg ;
|
||
LuaCheckParam( L, 1, nProg)
|
||
int nPause ;
|
||
LuaCheckParam( L, 2, nPause)
|
||
LuaClearStack( L) ;
|
||
// lancio aggiornamento interfaccia (viene fatto solo se abilitata UI)
|
||
int nRes = ExeProcessEvents( nProg, nPause) ;
|
||
// restituisco il risultato
|
||
LuaSetParam( L, nRes) ;
|
||
return 1 ;
|
||
}
|
||
|
||
//-------------------------------------------------------------------------------
|
||
static int
|
||
LuaOutText( lua_State* L)
|
||
{
|
||
// 1 parametro : sText
|
||
string sText ;
|
||
LuaCheckParam( L, 1, sText)
|
||
LuaClearStack( L) ;
|
||
// lancio emissione testo (viene fatto solo se abilitata UI)
|
||
bool bOk = ExeOutText( sText) ;
|
||
// restituisco il risultato
|
||
LuaSetParam( L, bOk) ;
|
||
return 1 ;
|
||
}
|
||
|
||
//-------------------------------------------------------------------------------
|
||
static int
|
||
LuaFileDialog( lua_State* L)
|
||
{
|
||
// 3 parametri : bOpenVsSave, sFile, sFilter
|
||
bool bOpenVsSave ;
|
||
LuaCheckParam( L, 1, bOpenVsSave)
|
||
string sFile ;
|
||
LuaCheckParam( L, 2, sFile)
|
||
string sFilter ;
|
||
LuaCheckParam( L, 3, sFilter)
|
||
LuaClearStack( L) ;
|
||
// se abilitata UI, emetto la finestra di dialogo
|
||
if ( ExeGetEnableUI()) {
|
||
// Converto i parametri nel formato wide
|
||
AtoWEX<MAX_PATH> wsFileName( sFile.c_str()) ;
|
||
AtoW wsFilter( sFilter.c_str()) ;
|
||
// Converto L'/' in L'\\' nel nome file proposto
|
||
for ( wchar_t* pC = wsFileName.m_psz ; *pC != L'\0' ; ++ pC) {
|
||
if ( *pC == L'/')
|
||
*pC = L'\\' ;
|
||
}
|
||
// Cambio L'|' in L'\0' nel filtro
|
||
for ( wchar_t* pC = wsFilter.m_psz ; *pC != L'\0' ; ++ pC) {
|
||
if ( *pC == L'|')
|
||
*pC = L'\0' ;
|
||
}
|
||
// Riempio la struttura dati per il dialogo
|
||
OPENFILENAME ofn ;
|
||
ZeroMemory( &ofn, sizeof( ofn)) ;
|
||
ofn.lStructSize = sizeof( ofn) ;
|
||
ofn.hwndOwner = ExeGetMainWindowHandle() ;
|
||
ofn.lpstrFilter = LPWSTR( wsFilter) ;
|
||
ofn.lpstrFile = LPWSTR( wsFileName) ;
|
||
ofn.nMaxFile = MAX_PATH ;
|
||
ofn.Flags = OFN_DONTADDTORECENT | OFN_PATHMUSTEXIST ;
|
||
// Visualizzo il dialogo
|
||
if ( bOpenVsSave) {
|
||
ofn.Flags |= OFN_FILEMUSTEXIST | OFN_HIDEREADONLY ;
|
||
if ( GetOpenFileName( &ofn) != FALSE)
|
||
LuaSetParam( L, wstrztoA( wsFileName)) ;
|
||
else
|
||
LuaSetParam( L) ;
|
||
}
|
||
else {
|
||
ofn.Flags |= OFN_OVERWRITEPROMPT ;
|
||
if ( GetSaveFileName( &ofn) != FALSE)
|
||
LuaSetParam( L, wstrztoA( wsFileName)) ;
|
||
else
|
||
LuaSetParam( L) ;
|
||
}
|
||
}
|
||
else
|
||
LuaSetParam( L) ;
|
||
return 1 ;
|
||
}
|
||
|
||
//-------------------------------------------------------------------------------
|
||
static int
|
||
LuaExistsFile( lua_State* L)
|
||
{
|
||
// 1 parametro : sFile
|
||
string sFile ;
|
||
LuaCheckParam( L, 1, sFile)
|
||
LuaClearStack( L) ;
|
||
// verifico esistenza file
|
||
bool bOk = ExistsFile( sFile) ;
|
||
// restituisco il risultato
|
||
LuaSetParam( L, bOk) ;
|
||
return 1 ;
|
||
}
|
||
|
||
//-------------------------------------------------------------------------------
|
||
static int
|
||
LuaCopyFile( lua_State* L)
|
||
{
|
||
// 2 parametri : sFile, sNewFile
|
||
string sFile ;
|
||
LuaCheckParam( L, 1, sFile)
|
||
string sNewFile ;
|
||
LuaCheckParam( L, 2, sNewFile)
|
||
LuaClearStack( L) ;
|
||
// copio il file
|
||
bool bOk = CopyFileEgt( sFile, sNewFile) ;
|
||
// restituisco il risultato
|
||
LuaSetParam( L, bOk) ;
|
||
return 1 ;
|
||
}
|
||
|
||
//-------------------------------------------------------------------------------
|
||
static int
|
||
LuaRenameFile( lua_State* L)
|
||
{
|
||
// 2 parametri : sFile, sNewFile
|
||
string sFile ;
|
||
LuaCheckParam( L, 1, sFile)
|
||
string sNewFile ;
|
||
LuaCheckParam( L, 2, sNewFile)
|
||
LuaClearStack( L) ;
|
||
// rinomino il file
|
||
bool bOk = RenameFile( sFile, sNewFile) ;
|
||
// restituisco il risultato
|
||
LuaSetParam( L, bOk) ;
|
||
return 1 ;
|
||
}
|
||
|
||
//-------------------------------------------------------------------------------
|
||
static int
|
||
LuaEraseFile( lua_State* L)
|
||
{
|
||
// 1 parametro : file
|
||
string sFile ;
|
||
LuaCheckParam( L, 1, sFile)
|
||
LuaClearStack( L) ;
|
||
// cancello il file
|
||
bool bOk = EraseFile( sFile) ;
|
||
// restituisco il risultato
|
||
LuaSetParam( L, bOk) ;
|
||
return 1 ;
|
||
}
|
||
|
||
//-------------------------------------------------------------------------------
|
||
static int
|
||
LuaFindAllFiles( lua_State* L)
|
||
{
|
||
// 1 parametro : specifiche del file
|
||
string sFileSpec ;
|
||
LuaCheckParam( L, 1, sFileSpec)
|
||
LuaClearStack( L) ;
|
||
// recupero tutti i file che rispondono alle specifiche
|
||
STRVECTOR vsFiles ;
|
||
bool bOk = FindAllFiles( sFileSpec, vsFiles) ;
|
||
// restituisco il risultato
|
||
if ( bOk)
|
||
LuaSetParam( L, vsFiles) ;
|
||
else
|
||
LuaSetParam( L) ;
|
||
return 1 ;
|
||
}
|
||
|
||
//-------------------------------------------------------------------------------
|
||
static int
|
||
LuaCompareFilesLastWriteTime( lua_State* L)
|
||
{
|
||
// 2 parametri : file1, file2
|
||
string sFile1 ;
|
||
LuaCheckParam( L, 1, sFile1)
|
||
string sFile2 ;
|
||
LuaCheckParam( L, 2, sFile2)
|
||
LuaClearStack( L) ;
|
||
// confronto la data di ultima scrittura dei due file
|
||
int nRes ;
|
||
bool bOk = CompareFilesLastWriteTime( sFile1, sFile2, nRes) ;
|
||
// restituisco il risultato
|
||
if ( bOk)
|
||
LuaSetParam( L, nRes) ;
|
||
else
|
||
LuaSetParam( L) ;
|
||
return 1 ;
|
||
}
|
||
|
||
//-------------------------------------------------------------------------------
|
||
int
|
||
CALLBACK DirectoryBoxProc( HWND hwndDlg, UINT uMsg, LPARAM lParam, LPARAM lpData)
|
||
{
|
||
if ( uMsg == BFFM_INITIALIZED)
|
||
SendMessage( hwndDlg, BFFM_SETSELECTION, TRUE, lpData) ;
|
||
return 0 ;
|
||
}
|
||
|
||
//-------------------------------------------------------------------------------
|
||
static int
|
||
LuaDirectoryDialog( lua_State* L)
|
||
{
|
||
// 2 parametri : sText, sDir
|
||
string sText ;
|
||
LuaCheckParam( L, 1, sText)
|
||
string sDir ;
|
||
LuaCheckParam( L, 2, sDir)
|
||
LuaClearStack( L) ;
|
||
// se abilitata UI, emetto la finestra di dialogo
|
||
if ( ExeGetEnableUI()) {
|
||
// Converto i parametri nel formato wide
|
||
AtoWEX<MAX_PATH> wsText( sText.c_str()) ;
|
||
AtoWEX<MAX_PATH> wsDirName( sDir.c_str()) ;
|
||
// Converto L'/' in L'\\' nel nome directory proposto
|
||
for ( wchar_t* pC = wsDirName.m_psz ; *pC != L'\0' ; ++ pC) {
|
||
if ( *pC == L'/')
|
||
*pC = L'\\' ;
|
||
}
|
||
// Riempio la struttura dati per il dialogo
|
||
BROWSEINFO bi = { 0} ;
|
||
bi.hwndOwner = ExeGetMainWindowHandle() ;
|
||
bi.lpszTitle = LPWSTR( wsText) ;
|
||
bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_USENEWUI ;
|
||
bi.lpfn = DirectoryBoxProc ;
|
||
bi.lParam = (LPARAM) LPWSTR( wsDirName) ;
|
||
// Visualizzo il dialogo
|
||
LPITEMIDLIST pIdl = SHBrowseForFolder( &bi) ;
|
||
if ( pIdl != NULL) {
|
||
// recupero la path della directory
|
||
WCHAR wPath[MAX_PATH] ;
|
||
if ( SHGetPathFromIDList( pIdl, wPath) != FALSE)
|
||
LuaSetParam( L, wstrztoA( wPath)) ;
|
||
else
|
||
LuaSetParam( L) ;
|
||
// free memory used
|
||
IMalloc* pImalloc = NULL ;
|
||
if ( SUCCEEDED( SHGetMalloc( &pImalloc))) {
|
||
pImalloc->Free( pIdl) ;
|
||
pImalloc->Release() ;
|
||
}
|
||
|
||
}
|
||
else
|
||
LuaSetParam( L) ;
|
||
}
|
||
else
|
||
LuaSetParam( L) ;
|
||
return 1 ;
|
||
}
|
||
|
||
//-------------------------------------------------------------------------------
|
||
static int
|
||
LuaExistsDirectory( lua_State* L)
|
||
{
|
||
// 1 parametro : sDir
|
||
string sDir ;
|
||
LuaCheckParam( L, 1, sDir)
|
||
LuaClearStack( L) ;
|
||
// verifico esistenza direttorio
|
||
bool bOk = ExistsDirectory( sDir) ;
|
||
// restituisco il risultato
|
||
LuaSetParam( L, bOk) ;
|
||
return 1 ;
|
||
}
|
||
|
||
//-------------------------------------------------------------------------------
|
||
static int
|
||
LuaCreateDirectory( lua_State* L)
|
||
{
|
||
// 1 parametro : sDir
|
||
string sDir ;
|
||
LuaCheckParam( L, 1, sDir)
|
||
LuaClearStack( L) ;
|
||
// creo direttorio
|
||
bool bOk = CreateDirectoryEgt( sDir) ;
|
||
// restituisco il risultato
|
||
LuaSetParam( L, bOk) ;
|
||
return 1 ;
|
||
}
|
||
|
||
//-------------------------------------------------------------------------------
|
||
static int
|
||
LuaEmptyDirectory( lua_State* L)
|
||
{
|
||
// 1 parametro : sDir
|
||
string sDir ;
|
||
LuaCheckParam( L, 1, sDir)
|
||
LuaClearStack( L) ;
|
||
// svuoto il direttorio
|
||
bool bOk = EmptyDirectory( sDir) ;
|
||
// restituisco il risultato
|
||
LuaSetParam( L, bOk) ;
|
||
return 1 ;
|
||
}
|
||
|
||
//-------------------------------------------------------------------------------
|
||
static int
|
||
LuaEraseDirectory( lua_State* L)
|
||
{
|
||
// 1 parametro : sDir
|
||
string sDir ;
|
||
LuaCheckParam( L, 1, sDir)
|
||
LuaClearStack( L) ;
|
||
// cancello direttorio (deve essere vuoto)
|
||
bool bOk = EraseDirectory( sDir) ;
|
||
// restituisco il risultato
|
||
LuaSetParam( L, bOk) ;
|
||
return 1 ;
|
||
}
|
||
|
||
//-------------------------------------------------------------------------------
|
||
static int
|
||
LuaEraseNonEmptyDirectory( lua_State* L)
|
||
{
|
||
// 1 parametro : sDir
|
||
string sDir ;
|
||
LuaCheckParam( L, 1, sDir)
|
||
LuaClearStack( L) ;
|
||
// cancello direttorio (deve essere vuoto)
|
||
bool bOk = EraseNonEmptyDirectory( sDir) ;
|
||
// restituisco il risultato
|
||
LuaSetParam( L, bOk) ;
|
||
return 1 ;
|
||
}
|
||
|
||
//-------------------------------------------------------------------------------
|
||
static int
|
||
LuaTextFileCompare( lua_State* L)
|
||
{
|
||
// 4 parametri : file1, file2, inizio commento, file diff
|
||
string sFile1 ;
|
||
LuaCheckParam( L, 1, sFile1)
|
||
string sFile2 ;
|
||
LuaCheckParam( L, 2, sFile2)
|
||
string sRemStart ;
|
||
LuaCheckParam( L, 3, sRemStart)
|
||
string sFileDiff ;
|
||
LuaCheckParam( L, 4, sFileDiff)
|
||
LuaClearStack( L) ;
|
||
// eseguo il confronto
|
||
int nDiff ;
|
||
bool bOk = TextFileCompare( sFile1, sFile2, sRemStart, sFileDiff, nDiff) ;
|
||
LuaSetParam( L, bOk) ;
|
||
LuaSetParam( L, nDiff) ;
|
||
return 2 ;
|
||
}
|
||
|
||
//-------------------------------------------------------------------------------
|
||
static int
|
||
LuaBinaryFileCompare( lua_State* L)
|
||
{
|
||
// 3 parametri : file1, file2, file diff
|
||
string sFile1 ;
|
||
LuaCheckParam( L, 1, sFile1)
|
||
string sFile2 ;
|
||
LuaCheckParam( L, 2, sFile2)
|
||
string sFileDiff ;
|
||
LuaCheckParam( L, 3, sFileDiff)
|
||
LuaClearStack( L) ;
|
||
// eseguo il confronto
|
||
int nDiff ;
|
||
bool bOk = BinaryFileCompare( sFile1, sFile2, sFileDiff, nDiff) ;
|
||
LuaSetParam( L, bOk) ;
|
||
LuaSetParam( L, nDiff) ;
|
||
return 2 ;
|
||
}
|
||
|
||
//-------------------------------------------------------------------------------
|
||
static int
|
||
LuaGetStringFromIni( lua_State* L)
|
||
{
|
||
// 4 parametri : sSec, sKey, sDef, sIniFile
|
||
string sSec ;
|
||
LuaCheckParam( L, 1, sSec)
|
||
string sKey ;
|
||
LuaCheckParam( L, 2, sKey)
|
||
string sDef ;
|
||
LuaCheckParam( L, 3, sDef)
|
||
string sIniFile ;
|
||
LuaCheckParam( L, 4, sIniFile)
|
||
LuaClearStack( L) ;
|
||
// leggo da file INI
|
||
string sVal = GetPrivateProfileStringUtf8( sSec.c_str(), sKey.c_str(), sDef.c_str(), sIniFile.c_str()) ;
|
||
LuaSetParam( L, sVal) ;
|
||
return 1 ;
|
||
}
|
||
|
||
//-------------------------------------------------------------------------------
|
||
static int
|
||
LuaWriteStringToIni( lua_State* L)
|
||
{
|
||
// 4 parametri : sSec, sKey, sVal, sIniFile
|
||
string sSec ;
|
||
LuaCheckParam( L, 1, sSec)
|
||
string sKey ;
|
||
LuaCheckParam( L, 2, sKey)
|
||
string sVal ;
|
||
LuaCheckParam( L, 3, sVal)
|
||
string sIniFile ;
|
||
LuaCheckParam( L, 4, sIniFile)
|
||
LuaClearStack( L) ;
|
||
// scrivo su file INI
|
||
bool bOk = WritePrivateProfileStringUtf8( sSec.c_str(), sKey.c_str(), sVal.c_str(), sIniFile.c_str()) ;
|
||
LuaSetParam( L, bOk) ;
|
||
return 1 ;
|
||
}
|
||
|
||
//-------------------------------------------------------------------------------
|
||
static int
|
||
LuaGetIniFile( lua_State* L)
|
||
{
|
||
// nessun parametro
|
||
LuaClearStack( L) ;
|
||
// recupero la path del file Ini dell'eseguibile
|
||
string sIniFile = ExeGetIniFile() ;
|
||
// restituisco il risultato
|
||
if ( ! sIniFile.empty())
|
||
LuaSetParam( L, sIniFile) ;
|
||
else
|
||
LuaSetParam( L) ;
|
||
return 1 ;
|
||
}
|
||
|
||
//-------------------------------------------------------------------------------
|
||
static int
|
||
LuaGetTempDir( lua_State* L)
|
||
{
|
||
// nessun parametro
|
||
LuaClearStack( L) ;
|
||
// recupero la path del direttorio temporaneo dell'eseguibile
|
||
string sTempDir ;
|
||
ExeGetTempDir( sTempDir) ;
|
||
// restituisco il risultato
|
||
if ( ! sTempDir.empty())
|
||
LuaSetParam( L, sTempDir) ;
|
||
else
|
||
LuaSetParam( L) ;
|
||
return 1 ;
|
||
}
|
||
|
||
//-------------------------------------------------------------------------------
|
||
static int
|
||
LuaGetExeVersion( lua_State* L)
|
||
{
|
||
// nessun parametro
|
||
LuaClearStack( L) ;
|
||
// costruisco la stringa con le versioni
|
||
string sVer ;
|
||
if ( ! ExeGetExecutableVersion( sVer))
|
||
sVer = "ExeVersion error" ;
|
||
// restituisco il risultato
|
||
LuaSetParam( L, sVer) ;
|
||
return 1 ;
|
||
}
|
||
|
||
//-------------------------------------------------------------------------------
|
||
static int
|
||
LuaGetVersion( lua_State* L)
|
||
{
|
||
// nessun parametro
|
||
LuaClearStack( L) ;
|
||
// costruisco la stringa con le versioni
|
||
string sVer ;
|
||
if ( ! ExeGetVersionInfo( sVer, "\n"))
|
||
sVer = "VersionInfo error" ;
|
||
// restituisco il risultato
|
||
LuaSetParam( L, sVer) ;
|
||
return 1 ;
|
||
}
|
||
|
||
//-------------------------------------------------------------------------------
|
||
static int
|
||
LuaIs64bit( lua_State* L)
|
||
{
|
||
// nessun parametro
|
||
LuaClearStack( L) ;
|
||
// restituisco il risultato
|
||
#if defined( _WIN64)
|
||
bool bRes = true ;
|
||
#elif defined( _WIN32)
|
||
bool bRes = false ;
|
||
#endif
|
||
LuaSetParam( L, bRes) ;
|
||
return 1 ;
|
||
}
|
||
|
||
//-------------------------------------------------------------------------------
|
||
static int
|
||
LuaGetLanguage( lua_State* L)
|
||
{
|
||
// nessun parametro
|
||
LuaClearStack( L) ;
|
||
// recupero il nome della lingua corrente
|
||
string sLang = ExeGetLanguage() ;
|
||
LuaSetParam( L, sLang) ;
|
||
return 1 ;
|
||
}
|
||
|
||
//-------------------------------------------------------------------------------
|
||
static int
|
||
LuaGetMsg( lua_State* L)
|
||
{
|
||
// 1 parametro : nMsg
|
||
int nMsg ;
|
||
LuaCheckParam( L, 1, nMsg)
|
||
LuaClearStack( L) ;
|
||
// recupero il nome della lingua corrente
|
||
string sMsg = ExeGetMsg( nMsg) ;
|
||
LuaSetParam( L, sMsg) ;
|
||
return 1 ;
|
||
}
|
||
|
||
//-------------------------------------------------------------------------------
|
||
static int
|
||
LuaVerifyKeyOption( lua_State* L)
|
||
{
|
||
// 1 parametro : nOptInd
|
||
int nOptInd ;
|
||
LuaCheckParam( L, 1, nOptInd)
|
||
LuaClearStack( L) ;
|
||
// verifico l'abilitazione dell'opzione (da chiave + licenza)
|
||
bool bOk = ExeVerifyKeyOption( nOptInd) ;
|
||
LuaSetParam( L, bOk) ;
|
||
return 1 ;
|
||
}
|
||
|
||
//-------------------------------------------------------------------------------
|
||
static int
|
||
LuaSetDefaultFont( lua_State* L)
|
||
{
|
||
// 1 parametro : sDefaultFont
|
||
string sDefaultFont ;
|
||
LuaCheckParam( L, 1, sDefaultFont)
|
||
LuaClearStack( L) ;
|
||
// imposta il font di default
|
||
bool bOk = ExeSetFont( "", sDefaultFont) ;
|
||
LuaSetParam( L, bOk) ;
|
||
return 1 ;
|
||
}
|
||
|
||
//-------------------------------------------------------------------------------
|
||
static int
|
||
LuaGetDefaultFont( lua_State* L)
|
||
{
|
||
// nessun parametro
|
||
LuaClearStack( L) ;
|
||
// recupera il font di cefault
|
||
string sDefaultFont ;
|
||
bool bOk = ExeGetDefaultFont( sDefaultFont) ;
|
||
if ( bOk)
|
||
LuaSetParam( L, sDefaultFont) ;
|
||
else
|
||
LuaSetParam( L) ;
|
||
return 1 ;
|
||
}
|
||
|
||
//-------------------------------------------------------------------------------
|
||
static int
|
||
LuaWinExec( lua_State* L)
|
||
{
|
||
// un solo parametro : CmdLine
|
||
string sCmdLine ;
|
||
LuaCheckParam( L, 1, sCmdLine)
|
||
LuaClearStack( L) ;
|
||
// mando in esecuzione la linea di comando
|
||
STARTUPINFO si ;
|
||
PROCESS_INFORMATION pi ;
|
||
ZeroMemory( &si, sizeof( si)) ;
|
||
si.cb = sizeof( si) ;
|
||
ZeroMemory( &pi, sizeof( pi)) ;
|
||
bool bOk = ( CreateProcess( NULL, stringtoW( sCmdLine), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi) != FALSE) ;
|
||
CloseHandle( pi.hProcess) ;
|
||
CloseHandle( pi.hThread) ;
|
||
// restituisco il risultato
|
||
LuaSetParam( L, bOk) ;
|
||
return 1 ;
|
||
}
|
||
|
||
//-------------------------------------------------------------------------------
|
||
static int
|
||
LuaCloseExe( lua_State* L)
|
||
{
|
||
// 1 parametro opzionale : [nExitCode]
|
||
int nExitCode = 0 ;
|
||
LuaGetParam( L, 1, nExitCode) ;
|
||
LuaClearStack( L) ;
|
||
// eseguo chiusura forzata
|
||
if ( ExeOnTerminateProcess( nExitCode))
|
||
TerminateProcess( GetCurrentProcess(), abs( nExitCode)) ;
|
||
// restituisco il risultato (se arrivo qui vuol dire che non è consnetito terminare l'esecuzione)
|
||
LuaSetParam( L, false) ;
|
||
return 1 ;
|
||
}
|
||
|
||
//-------------------------------------------------------------------------------
|
||
static int
|
||
LuaCreateMutex( lua_State* L)
|
||
{
|
||
// un solo parametro : sMutexName
|
||
string sMutexName ;
|
||
LuaCheckParam( L, 1, sMutexName)
|
||
LuaClearStack( L) ;
|
||
// verifico esistenza Mutex con Nome (altrimenti lo creo per bloccare gli altri)
|
||
bool bOk = ExeCreateMutex( sMutexName) ;
|
||
// restituisco il risultato
|
||
LuaSetParam( L, bOk) ;
|
||
return 1 ;
|
||
}
|
||
|
||
//-------------------------------------------------------------------------------
|
||
static int
|
||
LuaReleaseMutex( lua_State* L)
|
||
{
|
||
// nessun parametro
|
||
LuaClearStack( L) ;
|
||
// rilascio l'eventuale Mutex con Nome attivo
|
||
bool bOk = ExeReleaseMutex() ;
|
||
// restituisco il risultato
|
||
LuaSetParam( L, bOk) ;
|
||
return 1 ;
|
||
}
|
||
|
||
//-------------------------------------------------------------------------------
|
||
// =================================== DIALOG ===================================
|
||
// Variabili Globali
|
||
const int OFFS_CTRLS = 40 ;
|
||
enum TYPE_CTRLS { CTRL_NONE = 0, CTRL_CHECK = 1, CTRL_COMBO = 2, CTRL_EDIT = 3, CTRL_COLOR = 4, CTRL_BUTTON = 5} ;
|
||
static COLORREF s_CustomColors[16] = {12632256} ; // 16 colori GRAY
|
||
static bool s_bCustomColorsInit = false ; // flag di inizializzazione colori
|
||
const char* SEC_SCENE = "Scene" ;
|
||
const char* KEY_CUSTOMCOLORS = "CustomColors" ;
|
||
|
||
// Dialogo Modeless
|
||
const int MAX_CTRLS = IDC_TEXT8 - IDC_TEXT1 + 1 ;
|
||
static int s_nCtrls = 0 ;
|
||
static string s_sCaption ;
|
||
static string s_sText[MAX_CTRLS] ;
|
||
static string s_sEdit[MAX_CTRLS] ;
|
||
static int s_nType[MAX_CTRLS] ;
|
||
struct DialogContext {
|
||
bool bDone = false ; // flag per chiusura dialogo (X/Ok/Cancel)
|
||
bool bCancelled = false ; // true se X/Cancel
|
||
bool bSelecting = false ; // true quando un BS + in modalità selezione
|
||
int nLastBS = -1 ; // indice dell'ultimo BS premuto
|
||
STRVECTOR vsResult ; // valori finali da ritornare a Lua
|
||
} ;
|
||
static string s_sIdSel_ML ;
|
||
static bool s_bSelectionMode = false ; // se true allora diventa dialogo "Modeless"
|
||
static int s_nActiveRow = - 1 ; // indice della riga di "BS:" attiva
|
||
|
||
//-------------------------------------------------------------------------------
|
||
// OnClosingDialog
|
||
//
|
||
// Scopo:
|
||
// Gestisce la chiusura del dialogo modeless in modo centralizzato e sicuro.
|
||
// Questa funzione viene chiamata quando l’utente chiude il dialogo tramite:
|
||
// - OK
|
||
// - Cancel
|
||
// - pulsante X
|
||
// - WM_CLOSE
|
||
//
|
||
// Comportamento:
|
||
// - Riabilita la finestra principale (Main Window), che era stata disabilitata durante il funzionamento
|
||
// modale del dialogo.
|
||
//
|
||
// - Distrugge la finestra del dialogo.
|
||
//
|
||
// - Riporta il focus alla finestra principale, garantendo continuità nell’interazione dell’utente.
|
||
//
|
||
// - Deseleziona tutti gli oggetti nella scena e aggiorna la vista, in modo che nessuna selezione residua
|
||
// rimanga attiva dopo la chiusura.
|
||
//-------------------------------------------------------------------------------
|
||
static void
|
||
OnClosingDialog( HWND hwndDlg) {
|
||
// reset stato globale
|
||
s_bSelectionMode = false ;
|
||
s_nActiveRow = -1 ;
|
||
nDlgModelessItem = -1 ;
|
||
// il controllo passa al Main
|
||
HWND hMain = GetParent( hwndDlg) ;
|
||
EnableWindow( hMain, TRUE) ;
|
||
DestroyWindow( hwndDlg) ;
|
||
phDlgModeless = nullptr ;
|
||
SetFocus( hMain) ;
|
||
// deseleziono tutto
|
||
ExeDeselectAll() ;
|
||
ExeDraw() ;
|
||
}
|
||
|
||
//-------------------------------------------------------------------------------
|
||
// StartSelectionMode
|
||
//
|
||
// Scopo:
|
||
// Attiva la modalità di selezione (modeless) del dialogo. Questa modalità permette all’utente di interagire
|
||
// con la scena mentre il dialogo rimane aperto e attivo.
|
||
//
|
||
// Parametri:
|
||
// hDlg → handle del dialogo
|
||
// nEditId → ID dell’edit associato al pulsante BS premuto
|
||
// nActiveRow → indice della riga BS attiva (0..MAX_CTRLS-1)
|
||
//-------------------------------------------------------------------------------
|
||
static void
|
||
StartSelectionMode( HWND hDlg, int nEditId, int nActiveRow)
|
||
{
|
||
// il dialogo torna modeless rispetto alla scena
|
||
HWND hMain = GetParent( hDlg) ;
|
||
EnableWindow( hMain, TRUE) ;
|
||
// resta comunque in primo piano
|
||
SetWindowPos( hDlg, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE) ;
|
||
|
||
// disabilito tutti gli edit associati ai BS tranne che quello attivo
|
||
for ( int i = 0; i < s_nCtrls ; ++ i) {
|
||
if (s_sEdit[i].find( "BS:") == 0) {
|
||
int idEdit = IDC_EDIT1 + i ;
|
||
EnableWindow( GetDlgItem( hDlg, idEdit), ( i == nActiveRow ? TRUE : FALSE)) ;
|
||
}
|
||
}
|
||
|
||
// seleziono solo gli elementi presenti nell'edit corrispondente
|
||
nDlgModelessItem = - 1 ; // !<-- Temporaneo [***]
|
||
ExeDeselectAll() ; // !<-- NB. avendo messo nDlgModelessItem = -1 il testo non viene rimosso
|
||
s_bSelectionMode = true ;
|
||
s_nActiveRow = nActiveRow ;
|
||
nDlgModelessItem = nEditId ; // !<-- Aggiorno [***]
|
||
AtoWEX<128> wsEdit( "") ;
|
||
GetDlgItemText( hDlg, nEditId, LPWSTR( wsEdit), 128) ;
|
||
string sIds = wstrztoA( wsEdit) ;
|
||
STRVECTOR vsIds ;
|
||
Tokenize( sIds, ",", vsIds) ;
|
||
for ( const string& sId : vsIds) {
|
||
int nId = GDB_ID_NULL ;
|
||
if ( FromString( sId, nId) && nId != GDB_ID_NULL)
|
||
ExeSelectObj( nId) ;
|
||
}
|
||
ExeDraw() ;
|
||
}
|
||
|
||
//-------------------------------------------------------------------------------
|
||
// EndSelectionMode
|
||
//
|
||
// Scopo:
|
||
// Termina la modalità di selezione e riporta il dialogo in stato modale.
|
||
//-------------------------------------------------------------------------------
|
||
static void
|
||
EndSelectionMode( HWND hDlg)
|
||
{
|
||
s_bSelectionMode = false ;
|
||
s_nActiveRow = -1 ;
|
||
nDlgModelessItem = -1 ;
|
||
|
||
// disabilito tutti gli edit associati ai BS
|
||
for ( int i = 0; i < s_nCtrls ; ++ i) {
|
||
if ( s_sEdit[i].find( "BS:") == 0) {
|
||
int idEdit = IDC_EDIT1 + i ;
|
||
EnableWindow( GetDlgItem( hDlg, idEdit), FALSE) ;
|
||
SetDlgItemText( hDlg, IDC_BUTTON_SEL1 + i, stringtoW( string{ "-"})) ;
|
||
}
|
||
}
|
||
|
||
// il dialogo torna modale
|
||
HWND hMain = GetParent( hDlg) ;
|
||
EnableWindow( hMain, FALSE) ;
|
||
SetFocus( hDlg) ;
|
||
// deseleziono tutto
|
||
ExeDeselectAll() ; //!<-- NB. avendo messo nDlgModelessItem = -1 il testo non viene rimosso
|
||
ExeDraw() ;
|
||
}
|
||
|
||
//-------------------------------------------------------------------------------
|
||
BOOL
|
||
CALLBACK DialogBoxModelessProc( HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
||
{
|
||
// variabili static locali per mantenere lo stato tra chiamate per selezione colori
|
||
static COLORREF selectedColor[MAX_CTRLS] = {0} ; // BLACK
|
||
static HBRUSH hColorBrush[MAX_CTRLS] = {NULL} ; // non definito
|
||
|
||
switch ( message) {
|
||
case WM_INITDIALOG :
|
||
{
|
||
// imposto il dialogo come modale
|
||
HWND hMain = GetParent( hwndDlg) ;
|
||
EnableWindow( hMain, FALSE) ;
|
||
SetFocus( hwndDlg) ;
|
||
|
||
// imposto il contesto della funzione per recuperalo in futuro (per la funzione di CallBack Lua)
|
||
SetWindowLongPtr( hwndDlg, GWLP_USERDATA, (LONG_PTR)lParam) ;
|
||
|
||
// colore di default
|
||
COLORREF defaultColor = RGB( 255, 0, 0) ;
|
||
// inizializzazione colori e brush
|
||
for ( int i = 0 ; i < MAX_CTRLS ; ++ i) {
|
||
selectedColor[i] = defaultColor ;
|
||
if ( hColorBrush[i] != NULL)
|
||
DeleteObject( hColorBrush[i]) ;
|
||
hColorBrush[i] = CreateSolidBrush( selectedColor[i]) ;
|
||
}
|
||
// dati del dialogo
|
||
HWND hwndOwner = GetParent( hwndDlg) ;
|
||
if ( hwndOwner == nullptr)
|
||
hwndOwner = GetDesktopWindow() ;
|
||
RECT rcOwner, rcDlg ;
|
||
GetWindowRect( hwndOwner, &rcOwner) ;
|
||
GetWindowRect( hwndDlg, &rcDlg) ;
|
||
// determino la posizione dell'ultima riga di dati da visualizzare
|
||
HWND hwndLR = GetDlgItem( hwndDlg, IDC_TEXT1 + Clamp( s_nCtrls, 1, MAX_CTRLS) - 1) ;
|
||
RECT rcLR ;
|
||
GetWindowRect( hwndLR, &rcLR) ;
|
||
POINT ptLR{ rcLR.left, rcLR.top} ;
|
||
ScreenToClient( hwndDlg, &ptLR) ;
|
||
// centro e scalo il dialogo
|
||
int nNewH = rcLR.top - rcOwner.top + 2 * OFFS_CTRLS ; // non chiaro perchè va sottratto rcOwner.top ma funziona sempre
|
||
SetWindowPos( hwndDlg, HWND_TOP,
|
||
( rcOwner.left + rcOwner.right - ( rcDlg.right - rcDlg.left)) / 2,
|
||
( rcOwner.top + rcOwner.bottom - nNewH) / 2,
|
||
( rcDlg.right - rcDlg.left),
|
||
nNewH, 0) ;
|
||
// riposiziono il bottone Ok
|
||
HWND hwndOk = GetDlgItem( hwndDlg, IDOK) ;
|
||
RECT rcOk ;
|
||
GetWindowRect( hwndOk, &rcOk) ;
|
||
POINT ptOk{ rcOk.left, rcOk.top} ;
|
||
ScreenToClient( hwndDlg, &ptOk) ;
|
||
SetWindowPos( hwndOk, hwndDlg, ptOk.x, ptLR.y + OFFS_CTRLS, 0, 0, SWP_NOSIZE | SWP_NOZORDER) ;
|
||
// riposiziono il bottone Cancel
|
||
HWND hwndCl = GetDlgItem( hwndDlg, IDCANCEL) ;
|
||
RECT rcCl ;
|
||
GetWindowRect( hwndCl, &rcCl) ;
|
||
POINT ptCl{ rcCl.left, rcCl.top} ;
|
||
ScreenToClient( hwndDlg, &ptCl) ;
|
||
SetWindowPos( hwndCl, hwndDlg, ptCl.x, ptLR.y + OFFS_CTRLS, 0, 0, SWP_NOSIZE | SWP_NOZORDER) ;
|
||
// stile finestra
|
||
LONG style = GetWindowLong( hwndDlg, GWL_STYLE) ;
|
||
style |= WS_SYSMENU ;
|
||
SetWindowLong( hwndDlg, GWL_STYLE, style) ;
|
||
}
|
||
|
||
// assegno titolo del dialogo
|
||
SetWindowText( hwndDlg, stringtoW( s_sCaption)) ;
|
||
|
||
// assegno testi e valori di default e nascondo linee dei controlli non usati
|
||
for ( int i = 0 ; i < MAX_CTRLS ; ++ i) {
|
||
if ( i < s_nCtrls) {
|
||
|
||
// imposto il testo nella riga corrente
|
||
SetDlgItemText( hwndDlg, IDC_TEXT1 + i, stringtoW( s_sText[i])) ;
|
||
|
||
// --- se CheckBox
|
||
if ( s_sEdit[i].find( "CK:") == 0) {
|
||
bool bChecked = false ;
|
||
FromString( s_sEdit[i].substr( 3), bChecked) ;
|
||
CheckDlgButton( hwndDlg, IDC_CHECK1 + i, ( bChecked ? BST_CHECKED : BST_UNCHECKED)) ;
|
||
ShowWindow( GetDlgItem( hwndDlg, IDC_EDIT1 + i), SW_HIDE) ; // nascondo Edit
|
||
ShowWindow( GetDlgItem( hwndDlg, IDC_COMBO1 + i), SW_HIDE) ; // nascondo Combo
|
||
ShowWindow( GetDlgItem( hwndDlg, IDC_BUTTON_SEL1 + i), SW_HIDE) ; // nascondo Button di selezione
|
||
s_nType[i] = CTRL_CHECK ;
|
||
}
|
||
|
||
// --- se ComboBox
|
||
else if ( s_sEdit[i].find( "CB:") == 0) {
|
||
string sList = s_sEdit[i].substr( 3) ;
|
||
STRVECTOR vsVal ;
|
||
Tokenize( sList, ",", vsVal) ;
|
||
int nSel = 0 ;
|
||
HWND hwndCBox = GetDlgItem( hwndDlg, IDC_COMBO1 + i) ;
|
||
for ( int j = 0 ; j < ssize( vsVal) ; ++ j) {
|
||
string sItem ;
|
||
if ( vsVal[j][0] == '*') {
|
||
nSel = j ;
|
||
sItem = vsVal[j].substr( 1) ;
|
||
}
|
||
else
|
||
sItem = vsVal[j] ;
|
||
ComboBox_AddString( hwndCBox, stringtoW( sItem)) ;
|
||
}
|
||
ComboBox_SetCurSel( hwndCBox, nSel) ;
|
||
int nEditHeight = int( SendMessage( hwndCBox, CB_GETITEMHEIGHT, (WPARAM)-1, 0)) ;
|
||
int nItemHeight = int( SendMessage( hwndCBox, CB_GETITEMHEIGHT, 0, 0)) ;
|
||
int nTotalHeight = nEditHeight + nItemHeight * ( ssize( vsVal) + 1) ;
|
||
RECT rc ; GetWindowRect( hwndCBox, &rc) ;
|
||
HWND parent = GetParent(hwndCBox) ; MapWindowPoints( NULL, parent, (LPPOINT)&rc, 2) ;
|
||
SetWindowPos( hwndCBox, NULL, rc.left, rc.top, rc.right - rc.left, nTotalHeight, SWP_NOZORDER) ;
|
||
ShowWindow( GetDlgItem( hwndDlg, IDC_EDIT1 + i), SW_HIDE) ; // nascondo Edit
|
||
ShowWindow( GetDlgItem( hwndDlg, IDC_CHECK1 + i), SW_HIDE) ; // nascondo CheckBox
|
||
ShowWindow( GetDlgItem( hwndDlg, IDC_BUTTON_SEL1 + i), SW_HIDE) ; // nascondo Button di selezione
|
||
s_nType[i] = CTRL_COMBO ;
|
||
}
|
||
|
||
// --- se ColorPicker
|
||
else if ( s_sEdit[i].find( "CP:") == 0) {
|
||
string sVal = s_sEdit[i].substr( 3) ;
|
||
Color CColor ;
|
||
if ( ! FromString( sVal, CColor))
|
||
CColor = INVISIBLE ;
|
||
selectedColor[i] = RGB( CColor.GetIntRed(), CColor.GetIntGreen(), CColor.GetIntBlue()) ;
|
||
if ( hColorBrush[i] != NULL)
|
||
DeleteObject( hColorBrush[i]) ;
|
||
hColorBrush[i] = CreateSolidBrush( selectedColor[i]) ;
|
||
// recupero i valori dei colori personalizzati dal file .ini
|
||
if ( ! s_bCustomColorsInit) {
|
||
// recupero il file Ini
|
||
string sIniFile = ExeGetIniFile() ;
|
||
if ( ! sIniFile.empty()) {
|
||
string sCustomVals = GetPrivateProfileStringUtf8( SEC_SCENE, KEY_CUSTOMCOLORS, "", sIniFile.c_str()) ;
|
||
STRVECTOR vsWinColors ; Tokenize( sCustomVals, ",", vsWinColors) ;
|
||
for ( int j = 0 ; j < ssize( vsWinColors) && j < 16 ; ++ j) {
|
||
unsigned int unVal ;
|
||
if ( FromString( vsWinColors[j], unVal)) {
|
||
unsigned int unR = unVal & 0xFF ;
|
||
unsigned int unG = ( unVal >> 8) & 0xFF ;
|
||
unsigned int unB = ( unVal >> 16) & 0xFF ;
|
||
s_CustomColors[j] = RGB( unR, unG, unB) ;
|
||
}
|
||
}
|
||
}
|
||
s_bCustomColorsInit = true ;
|
||
}
|
||
// nascondo qualsiasi tipo di componente
|
||
ShowWindow( GetDlgItem( hwndDlg, IDC_EDIT1 + i), SW_HIDE) ; // nascondo Edit
|
||
ShowWindow( GetDlgItem( hwndDlg, IDC_COMBO1 + i), SW_HIDE) ; // nascondo Combo
|
||
ShowWindow( GetDlgItem( hwndDlg, IDC_CHECK1 + i), SW_HIDE) ; // nascondo Check
|
||
ShowWindow( GetDlgItem( hwndDlg, IDC_BUTTON_SEL1 + i), SW_HIDE) ; // nascondo Button di selezione
|
||
|
||
// margini per dimensione del rettangolo preview pickColor
|
||
const int MARGIN_RIGHT = 8 ; // spazio tra preview e bordo destro dialog
|
||
const int PREVIEW_HEIGHT = 20 ; // altezza del rettangolo
|
||
const int PREVIEW_MIN_WIDTH = 40 ; // larghezza minima
|
||
|
||
// creazione della static preview
|
||
HWND hwndPreview = NULL ;
|
||
HWND hwndEdit = GetDlgItem( hwndDlg, IDC_EDIT1 + i) ;
|
||
RECT rcEdit ; GetClientRect( hwndDlg, &rcEdit) ; // coordinate client del dialog
|
||
if ( hwndEdit != nullptr && GetWindowRect( hwndEdit, &rcEdit)) {
|
||
// converti rcLabel in coordinate client
|
||
POINT ptEdit = { rcEdit.left, rcEdit.top } ;
|
||
ScreenToClient( hwndDlg, &ptEdit) ;
|
||
int x = ptEdit.x ;
|
||
int y = ptEdit.y ;
|
||
int width = rcEdit.right - rcEdit.left ;
|
||
if ( width < PREVIEW_MIN_WIDTH)
|
||
width = PREVIEW_MIN_WIDTH ;
|
||
hwndPreview = CreateWindowEx( 0, L"STATIC", NULL,
|
||
WS_CHILD | WS_VISIBLE | SS_NOTIFY | SS_CENTERIMAGE | WS_BORDER,
|
||
x, y, width, PREVIEW_HEIGHT,
|
||
hwndDlg, ( HMENU)( IDC_COLOR1 + i),
|
||
GetModuleHandle( NULL), NULL) ;
|
||
}
|
||
// pulizia elementi testuali
|
||
if ( hwndPreview) {
|
||
SetWindowText( hwndPreview, L"") ;
|
||
SetWindowPos( hwndPreview, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE) ;
|
||
InvalidateRect( hwndPreview, NULL, TRUE) ;
|
||
UpdateWindow( hwndPreview) ;
|
||
}
|
||
s_nType[i] = CTRL_COLOR ;
|
||
}
|
||
|
||
// --- se Button di selezione
|
||
else if ( s_sEdit[i].find( "BS:") == 0) {
|
||
ShowWindow( GetDlgItem( hwndDlg, IDC_COMBO1 + i), SW_HIDE) ; // nascondo la Combo
|
||
ShowWindow( GetDlgItem( hwndDlg, IDC_CHECK1 + i), SW_HIDE) ; // nascondo la Check
|
||
SetDlgItemText( hwndDlg, IDC_BUTTON_SEL1 + i, stringtoW( string{ "-"})) ; // modalità non Selezione
|
||
EnableWindow( GetDlgItem( hwndDlg, IDC_EDIT1 + i), FALSE) ; // disattivo la Edit
|
||
// associo alla casella di testo la funzione di KeyPress su Enter
|
||
HWND hEdit = GetDlgItem( hwndDlg, IDC_EDIT1 + i) ;
|
||
if ( hEdit != nullptr)
|
||
SetWindowSubclass( hEdit, UpdateSelectionModelessDialog, 1, (DWORD_PTR)( IDC_EDIT1 + i)) ;
|
||
s_nType[i] = CTRL_BUTTON ;
|
||
}
|
||
|
||
// --- se Testo
|
||
else {
|
||
SetDlgItemText( hwndDlg, IDC_EDIT1 + i, stringtoW( s_sEdit[i])) ;
|
||
ShowWindow( GetDlgItem( hwndDlg, IDC_COMBO1 + i), SW_HIDE) ; // nascondo Combo
|
||
ShowWindow( GetDlgItem( hwndDlg, IDC_CHECK1 + i), SW_HIDE) ; // nascondo Check
|
||
ShowWindow( GetDlgItem( hwndDlg, IDC_BUTTON_SEL1 + i), SW_HIDE) ; // nascondo Button di selezione
|
||
s_nType[i] = CTRL_EDIT ;
|
||
}
|
||
}
|
||
// se numero di controllo superiore al massimo, non visualizzo nullo ( in questo caso aggiungere elementi a Dialog in .rc)
|
||
else {
|
||
// nascondo tutto
|
||
ShowWindow( GetDlgItem( hwndDlg, IDC_TEXT1 + i), SW_HIDE) ;
|
||
ShowWindow( GetDlgItem( hwndDlg, IDC_EDIT1 + i), SW_HIDE) ;
|
||
ShowWindow( GetDlgItem( hwndDlg, IDC_COMBO1 + i), SW_HIDE) ;
|
||
ShowWindow( GetDlgItem( hwndDlg, IDC_CHECK1 + i), SW_HIDE) ;
|
||
ShowWindow( GetDlgItem( hwndDlg, IDC_BUTTON_SEL1 + i), SW_HIDE) ;
|
||
s_nType[i] = CTRL_NONE ;
|
||
}
|
||
}
|
||
break ;
|
||
|
||
case WM_CTLCOLORSTATIC :
|
||
{
|
||
HDC hdcStatic = ( HDC)wParam ;
|
||
HWND hwndCtrl = ( HWND)lParam ;
|
||
int ctrlId = GetDlgCtrlID( hwndCtrl) ;
|
||
if ( ctrlId >= IDC_COLOR1 && ctrlId <= IDC_COLOR8) {
|
||
int idx = ctrlId - IDC_COLOR1 ;
|
||
if ( hColorBrush[idx] == NULL)
|
||
hColorBrush[idx] = CreateSolidBrush( selectedColor[idx]) ;
|
||
SetBkMode( hdcStatic, OPAQUE) ;
|
||
SetBkColor( hdcStatic, selectedColor[idx]) ;
|
||
return ( INT_PTR)hColorBrush[idx] ;
|
||
}
|
||
}
|
||
break ;
|
||
|
||
case WM_COMMAND : {
|
||
int id = LOWORD( wParam) ;
|
||
int code = HIWORD( wParam) ;
|
||
|
||
// --- se click di un Button di selezione
|
||
if ( id >= IDC_BUTTON_SEL1 && id < IDC_BUTTON_SEL1 + MAX_CTRLS) {
|
||
int nBtnId = id ;
|
||
int nEditId = IDC_EDIT1 + ( id - IDC_BUTTON_SEL1) ;
|
||
int nActiveRow = nEditId - IDC_EDIT1 ;
|
||
// se il bottone premuto è lo stesso
|
||
if ( nDlgModelessItem == nEditId) {
|
||
// se selezione attiva, allora deve terminare
|
||
if ( s_bSelectionMode) {
|
||
SetDlgItemText( hwndDlg, nBtnId, stringtoW( string{ "-"})) ;
|
||
EndSelectionMode( hwndDlg) ;
|
||
}
|
||
// se selezione non attiva, allora viene attivata
|
||
else {
|
||
SetDlgItemText( hwndDlg, nBtnId, stringtoW( string{ "S"})) ;
|
||
StartSelectionMode( hwndDlg, nEditId, nActiveRow) ;
|
||
}
|
||
}
|
||
// se nuovo buttone premuto
|
||
else {
|
||
// se esisteva una selezione precedente, questa viene annullata
|
||
if ( nDlgModelessItem != -1) {
|
||
// recupero il Button di selezione precedente e modifico il suo testo
|
||
int nPrevBtnId = IDC_BUTTON_SEL1 + ( nDlgModelessItem - IDC_EDIT1) ;
|
||
SetDlgItemText( hwndDlg, nPrevBtnId, stringtoW( string{ "-"})) ;
|
||
}
|
||
// la selezione passa al comando corrente
|
||
nDlgModelessItem = nEditId ;
|
||
SetDlgItemText( hwndDlg, nBtnId, stringtoW( string{ "S"})) ;
|
||
// il dialogo diventa "Modeless" temporaneamente
|
||
s_nActiveRow = nEditId - IDC_EDIT1 ;
|
||
StartSelectionMode( hwndDlg, nEditId, nActiveRow) ;
|
||
}
|
||
return TRUE ; // !<-- esco
|
||
}
|
||
// --- se comando di Preview per brush di colori mediante click del mouse
|
||
else if ( code == STN_CLICKED && id >= IDC_COLOR1 && id <= IDC_COLOR8) {
|
||
// se selezione attiva, allora deve terminare
|
||
if ( s_bSelectionMode) {
|
||
// se esisteva una selezione precedente, questa viene annullata
|
||
if ( nDlgModelessItem != -1) {
|
||
// recupero il Button di selezione precedente e modifico il suo testo
|
||
int nPrevBtnId = IDC_BUTTON_SEL1 + ( nDlgModelessItem - IDC_EDIT1) ;
|
||
SetDlgItemText( hwndDlg, nPrevBtnId, stringtoW( string{ "-"})) ;
|
||
}
|
||
EndSelectionMode( hwndDlg) ;
|
||
}
|
||
int idx = id - IDC_COLOR1 ;
|
||
HWND hwndPreview = GetDlgItem( hwndDlg, IDC_COLOR1 + idx) ;
|
||
if ( ! hwndPreview)
|
||
return TRUE ;
|
||
// apertura ChooseColor (usa hwndDlg come owner)
|
||
CHOOSECOLOR cc = {} ;
|
||
cc.lStructSize = sizeof( cc) ;
|
||
cc.hwndOwner = hwndDlg ;
|
||
cc.lpCustColors = s_CustomColors ;
|
||
cc.rgbResult = selectedColor[idx] ;
|
||
cc.Flags = CC_FULLOPEN | CC_RGBINIT ;
|
||
if ( ChooseColor( &cc)) {
|
||
selectedColor[idx] = cc.rgbResult ;
|
||
// salvo nel file Ini i nuovi colori personalizzati
|
||
string sIniFile = ExeGetIniFile() ;
|
||
if ( ! sIniFile.empty()) {
|
||
string sOut = "" ;
|
||
for ( int j = 0 ; j < ssize( s_CustomColors) && j < 16 ; ++ j)
|
||
sOut += ToString( ( unsigned int)s_CustomColors[j]) + "," ;
|
||
sOut.pop_back() ;
|
||
WritePrivateProfileStringUtf8( SEC_SCENE, KEY_CUSTOMCOLORS, sOut.c_str(), sIniFile.c_str()) ;
|
||
}
|
||
if ( hColorBrush[idx] != NULL)
|
||
DeleteObject( hColorBrush[idx]) ;
|
||
hColorBrush[idx] = CreateSolidBrush( selectedColor[idx]) ;
|
||
InvalidateRect(hwndPreview, NULL, TRUE) ;
|
||
UpdateWindow( hwndPreview) ;
|
||
}
|
||
return TRUE ; // !<-- Esco
|
||
}
|
||
|
||
switch ( LOWORD( wParam)) {
|
||
case IDOK : {
|
||
// recupero il contesto impostato alla creazione della finestra (durante esecuzione WM_INITDIALOG)
|
||
DialogContext* ctx = (DialogContext*)GetWindowLongPtr( hwndDlg, GWLP_USERDATA) ;
|
||
if ( ctx != nullptr) {
|
||
// inizializzo i risultati
|
||
ctx->vsResult.clear() ;
|
||
ctx->vsResult.reserve( s_nCtrls) ;
|
||
// recupero i valori degli Item
|
||
for ( int i = 0 ; i < s_nCtrls ; ++ i) {
|
||
AtoWEX<128> wsEdit( "") ;
|
||
s_sEdit[i] = "" ;
|
||
|
||
switch ( s_nType[i]) {
|
||
case CTRL_CHECK :
|
||
s_sEdit[i] = ( IsDlgButtonChecked( hwndDlg, IDC_CHECK1 + i) == BST_CHECKED ? "1" : "0") ;
|
||
break ;
|
||
case CTRL_COMBO :
|
||
if ( GetDlgItemText( hwndDlg, IDC_COMBO1 + i, LPWSTR( wsEdit), 128) > 0)
|
||
s_sEdit[i] = wstrztoA( wsEdit) ;
|
||
break ;
|
||
case CTRL_EDIT :
|
||
if ( GetDlgItemText( hwndDlg, IDC_EDIT1 + i, LPWSTR( wsEdit), 128) > 0)
|
||
s_sEdit[i] = wstrztoA( wsEdit) ;
|
||
break ;
|
||
case CTRL_COLOR :
|
||
{
|
||
COLORREF col = selectedColor[i] ;
|
||
BYTE r = GetRValue( col), g = GetGValue( col), b = GetBValue( col) ;
|
||
char buf[16] ;
|
||
sprintf_s( buf, sizeof( buf), "%u,%u,%u", r, g, b) ;
|
||
s_sEdit[i] = buf ;
|
||
}
|
||
break ;
|
||
case CTRL_BUTTON :
|
||
if ( GetDlgItemText( hwndDlg, IDC_EDIT1 + i, LPWSTR( wsEdit), 128) > 0)
|
||
s_sEdit[i] = wstrztoA( wsEdit) ;
|
||
break ;
|
||
}
|
||
|
||
// inserisco i valori all'interno della tabella Lua
|
||
ctx->vsResult.push_back( s_sEdit[i]) ;
|
||
}
|
||
|
||
ctx->bCancelled = false ;
|
||
ctx->bDone = true ;
|
||
}
|
||
|
||
// chiudo il dialogo
|
||
OnClosingDialog( hwndDlg) ;
|
||
return TRUE ;
|
||
}
|
||
[[fallthrough]] ;
|
||
case IDCANCEL : {
|
||
// pulizia brush colori
|
||
for ( int i = 0 ; i < MAX_CTRLS ; ++ i) {
|
||
if ( hColorBrush[i] != NULL) {
|
||
DeleteObject( hColorBrush[i]) ;
|
||
hColorBrush[i] = NULL ;
|
||
}
|
||
}
|
||
// recupero il contesto impostato alla creazione della finestra ( durante esecuzione WM_INITDIALOG) e se esiste lo rimuovo
|
||
DialogContext* ctx = (DialogContext*)GetWindowLongPtr( hwndDlg, GWLP_USERDATA) ;
|
||
if ( ctx != nullptr) {
|
||
ctx->bCancelled = true ;
|
||
ctx->bDone = true ;
|
||
}
|
||
// chiudo il dialogo
|
||
OnClosingDialog( hwndDlg) ;
|
||
return TRUE ;
|
||
}
|
||
}
|
||
|
||
// se siamo in modalità di Selezione e il comando attivo non si riferisce ad un button di Selezione (BS), il dialogo torna modale
|
||
if ( s_bSelectionMode) {
|
||
bool bIsBS = ( id >= IDC_BUTTON_SEL1 && id < IDC_BUTTON_SEL1 + MAX_CTRLS) ;
|
||
bool bIsActiveEdit = ( id == IDC_EDIT1 + s_nActiveRow) ;
|
||
// il dialogo torna modale
|
||
if ( ! bIsBS && ! bIsActiveEdit)
|
||
EndSelectionMode( hwndDlg) ;
|
||
}
|
||
break ;
|
||
}
|
||
|
||
case WM_CLOSE : {
|
||
// recupero il contesto impostato alla creazione della finestra ( durante esecuzione WM_INITDIALOG) e se esiste lo rimuovo
|
||
DialogContext* ctx = (DialogContext*)GetWindowLongPtr( hwndDlg, GWLP_USERDATA) ;
|
||
if ( ctx != nullptr) {
|
||
ctx->bCancelled = true ;
|
||
ctx->bDone = true ;
|
||
}
|
||
// chiudo il dialogo
|
||
OnClosingDialog( hwndDlg) ;
|
||
return TRUE ;
|
||
}
|
||
}
|
||
|
||
return FALSE ;
|
||
}
|
||
|
||
//-------------------------------------------------------------------------------
|
||
// LuaDialogBox (Modeless)
|
||
//
|
||
// Scopo:
|
||
// ------
|
||
// Questa funzione implementa un dialogo "modale" dal punto di vista del codice Lua, ma "modeless" dal punto di vista della
|
||
// UI Windows quando necessario. L’obiettivo è permettere al codice Lua di rimanere sospeso finché l’utente non chiude il
|
||
// dialogo (OK/Cancel/X), mantenendo però la UI attiva e permettendo selezioni nella scena quando l’utente preme un pulsante
|
||
// BS (Button Selection).
|
||
//
|
||
// Perché serve:
|
||
// -------------
|
||
// - I dialoghi modali standard (DialogBox) bloccano completamente la UI, mentre i dialoghi modeless standard (CreateDialog)
|
||
// NON bloccano il codice Lua.
|
||
// - Le coroutine Lua (lua_yield/lua_resume) non sono utilizzabili in questo contesto perché il thread principale
|
||
// dell’applicazione non può essere sospeso tramite yield: il codice Lua non riprende correttamente e la UI non si
|
||
// aggiorna coerentemente)
|
||
//
|
||
// Come funziona:
|
||
// --------------
|
||
// 1) Il dialogo viene creato con CreateDialogParam(), quindi la UI rimane attiva.
|
||
// 2) La funzione NON ritorna subito: entra in un message loop locale (Esattamente equivalente al loop all'interno di
|
||
// DialogBox()). Il cuore del loop è GetMessage(), che è una chiamata BLOCCANTE. Significa che il thread rimane in
|
||
// attesa senza consumare CPU finché non arriva un messaggio. Non c’è polling, non c’è busy loop. Il comportamento è
|
||
// identico a quello di un dialogo modale nativo.
|
||
// 3) Il ciclo rimane attivo finché:
|
||
// - l’utente non chiude il dialogo (OK/Cancel/X)
|
||
// - oppure la finestra viene distrutta
|
||
// In quel momento ctx->bDone viene impostato a true.
|
||
// 4) Durante la vita del dialogo, se l’utente preme un pulsante BS, il dialogo diventa temporaneamente "modeless":
|
||
// - la main window viene abilitata
|
||
// - il dialogo rimane abilitato ma passa in secondo piano logico
|
||
// - l’utente può selezionare oggetti nella scena
|
||
// Quando la selezione termina, il dialogo torna modale.
|
||
// 5) Quando il dialogo chiude, i valori vengono copiati in ctx->vsResult e ritornati a Lua come risultato della funzione.
|
||
//
|
||
// Vantaggi della soluzione:
|
||
// -------------------------
|
||
// - Lua rimane bloccato come con un dialogo modale tradizionale.
|
||
// - La UI rimane completamente attiva.
|
||
// - Le selezioni BS (mediante Button Selection) funzionano senza bloccare il programma.
|
||
// - Nessun uso di coroutine Lua (che non erano affidabili in questo contesto).
|
||
// - Nessun consumo CPU anomalo.
|
||
// - Comportamento stabile e prevedibile.
|
||
//
|
||
// Nota importante:
|
||
// ----------------
|
||
// Il dialogo NON viene mai disabilitato durante la selezione BS (Button Selection). Solo la main window viene
|
||
// abilitata temporaneamente.
|
||
// Questo è fondamentale: disabilitare il dialogo impedirebbe all’utente di poterlo riselezionare dopo la selezione nella scena.
|
||
//
|
||
static int
|
||
LuaDialogBox( lua_State* L)
|
||
{
|
||
// 1 .. 9 parametri : sCaption, { sText, sDefault}, ...
|
||
LuaCheckParam( L, 1, s_sCaption)
|
||
s_nCtrls = 0 ;
|
||
for ( int i = 0 ; i < MAX_CTRLS ; ++ i) {
|
||
STRVECTOR vData ;
|
||
if ( LuaGetParam( L, 2 + i, vData) && ssize( vData) >= 2) {
|
||
s_sText[i] = Trim( vData[0]) ;
|
||
s_sEdit[i] = Trim( vData[1]) ;
|
||
++ s_nCtrls ;
|
||
}
|
||
else
|
||
break ;
|
||
}
|
||
LuaClearStack( L) ;
|
||
|
||
// se UI disabilitata, esco
|
||
if ( ! ExeGetEnableUI()) {
|
||
LuaSetParam( L) ;
|
||
return 1 ;
|
||
}
|
||
|
||
// se dialogo Modeless già aperto, errore
|
||
if ( phDlgModeless != nullptr) {
|
||
LuaSetParam( L) ;
|
||
return 1 ;
|
||
}
|
||
|
||
// creazione del contesto e della Coroutine da gestire
|
||
DialogContext* ctx = new DialogContext() ;
|
||
if ( ctx == nullptr) {
|
||
LuaSetParam( L) ;
|
||
return 1 ;
|
||
}
|
||
|
||
// creazione di un dialogo Modeless
|
||
HWND hTopWnd = ExeGetMainWindowHandle() ;
|
||
nDlgModelessItem = -1 ;
|
||
phDlgModeless = ( CreateDialogParam( GetModuleIstance(), MAKEINTRESOURCE( IDD_LUADLG), hTopWnd,
|
||
(DLGPROC)DialogBoxModelessProc, (LPARAM)ctx)) ;
|
||
if ( phDlgModeless == nullptr) {
|
||
delete( ctx) ;
|
||
ctx = nullptr ;
|
||
LuaSetParam( L) ;
|
||
return 1 ;
|
||
}
|
||
|
||
// porto la finestra in primo piano
|
||
ShowWindow( phDlgModeless, SW_SHOW) ;
|
||
SetForegroundWindow( phDlgModeless) ;
|
||
|
||
// message Loop Modale (ripresa del Loop come da dialogo modale)
|
||
MSG msg ;
|
||
while ( ! ctx->bDone && IsWindow( phDlgModeless)) {
|
||
if ( GetMessage( &msg, NULL, 0, 0) <= 0)
|
||
break ;
|
||
if ( ! IsDialogMessage( phDlgModeless, &msg)) {
|
||
TranslateMessage( &msg) ;
|
||
DispatchMessage( &msg) ;
|
||
}
|
||
}
|
||
|
||
// ritorno i valori lua
|
||
if ( ctx->bCancelled)
|
||
LuaSetParam( L, false) ;
|
||
else
|
||
LuaSetParam( L, ctx->vsResult) ;
|
||
|
||
// libero la memoria
|
||
delete ctx ;
|
||
ctx = nullptr ;
|
||
return 1 ;
|
||
}
|
||
|
||
//-------------------------------------------------------------------------------
|
||
bool
|
||
LuaInstallGeneral( LuaMgr& luaMgr)
|
||
{
|
||
bool bOk = ( &luaMgr != nullptr) ;
|
||
bOk = bOk && luaMgr.RegisterFunction( "print", MyPrint) ;
|
||
bOk = bOk && luaMgr.RegisterFunction( "EgtEvalNumExpr", LuaEvalNumExpr) ;
|
||
bOk = bOk && luaMgr.RegisterFunction( "EgtPause", LuaPause) ;
|
||
bOk = bOk && luaMgr.RegisterFunction( "EgtGetKeyPressed", LuaGetKeyPressed) ;
|
||
bOk = bOk && luaMgr.RegisterFunction( "EgtStartCounter", LuaStartCounter) ;
|
||
bOk = bOk && luaMgr.RegisterFunction( "EgtStopCounter", LuaStopCounter) ;
|
||
bOk = bOk && luaMgr.RegisterFunction( "EgtNumToString", LuaNumToString) ;
|
||
bOk = bOk && luaMgr.RegisterFunction( "EgtSplitString", LuaSplitString) ;
|
||
bOk = bOk && luaMgr.RegisterFunction( "EgtSplitStringPlus", LuaSplitStringPlus) ;
|
||
bOk = bOk && luaMgr.RegisterFunction( "EgtReplaceString", LuaReplaceString) ;
|
||
bOk = bOk && luaMgr.RegisterFunction( "EgtSetVal", LuaSetVal) ;
|
||
bOk = bOk && luaMgr.RegisterFunction( "EgtGetVal", LuaGetVal) ;
|
||
bOk = bOk && luaMgr.RegisterFunction( "EgtGetUUID", LuaGetUUID) ;
|
||
bOk = bOk && luaMgr.RegisterFunction( "EgtExecTsc", LuaExecTsc) ;
|
||
bOk = bOk && luaMgr.RegisterFunction( "EgtExecTscLine", LuaExecTscLine) ;
|
||
bOk = bOk && luaMgr.RegisterFunction( "EgtSetTscVar", LuaSetTscVar) ;
|
||
bOk = bOk && luaMgr.RegisterFunction( "EgtGetTscVar", LuaGetTscVar) ;
|
||
bOk = bOk && luaMgr.RegisterFunction( "EgtGetDebugLevel", LuaGetDebugLevel) ;
|
||
bOk = bOk && luaMgr.RegisterFunction( "EgtGetUserLevel", LuaGetUserLevel) ;
|
||
bOk = bOk && luaMgr.RegisterFunction( "EgtOutLog", LuaOutLog) ;
|
||
bOk = bOk && luaMgr.RegisterFunction( "EgtGetEnableUI", LuaGetEnableUI) ;
|
||
bOk = bOk && luaMgr.RegisterFunction( "EgtOutBox", LuaOutBox) ;
|
||
bOk = bOk && luaMgr.RegisterFunction( "EgtProcessEvents", LuaProcessEvents) ;
|
||
bOk = bOk && luaMgr.RegisterFunction( "EgtOutText", LuaOutText) ;
|
||
bOk = bOk && luaMgr.RegisterFunction( "EgtFileDialog", LuaFileDialog) ;
|
||
bOk = bOk && luaMgr.RegisterFunction( "EgtExistsFile", LuaExistsFile) ;
|
||
bOk = bOk && luaMgr.RegisterFunction( "EgtCopyFile", LuaCopyFile) ;
|
||
bOk = bOk && luaMgr.RegisterFunction( "EgtRenameFile", LuaRenameFile) ;
|
||
bOk = bOk && luaMgr.RegisterFunction( "EgtEraseFile", LuaEraseFile) ;
|
||
bOk = bOk && luaMgr.RegisterFunction( "EgtFindAllFiles", LuaFindAllFiles) ;
|
||
bOk = bOk && luaMgr.RegisterFunction( "EgtCompareFilesLastWriteTime", LuaCompareFilesLastWriteTime) ;
|
||
bOk = bOk && luaMgr.RegisterFunction( "EgtDirectoryDialog", LuaDirectoryDialog) ;
|
||
bOk = bOk && luaMgr.RegisterFunction( "EgtExistsDirectory", LuaExistsDirectory) ;
|
||
bOk = bOk && luaMgr.RegisterFunction( "EgtCreateDirectory", LuaCreateDirectory) ;
|
||
bOk = bOk && luaMgr.RegisterFunction( "EgtEmptyDirectory", LuaEmptyDirectory) ;
|
||
bOk = bOk && luaMgr.RegisterFunction( "EgtEraseDirectory", LuaEraseDirectory) ;
|
||
bOk = bOk && luaMgr.RegisterFunction( "EgtEraseNonEmptyDirectory", LuaEraseNonEmptyDirectory) ;
|
||
bOk = bOk && luaMgr.RegisterFunction( "EgtTextFileCompare", LuaTextFileCompare) ;
|
||
bOk = bOk && luaMgr.RegisterFunction( "EgtBinaryFileCompare", LuaBinaryFileCompare) ;
|
||
bOk = bOk && luaMgr.RegisterFunction( "EgtGetStringFromIni", LuaGetStringFromIni) ;
|
||
bOk = bOk && luaMgr.RegisterFunction( "EgtWriteStringToIni", LuaWriteStringToIni) ;
|
||
bOk = bOk && luaMgr.RegisterFunction( "EgtGetIniFile", LuaGetIniFile) ;
|
||
bOk = bOk && luaMgr.RegisterFunction( "EgtGetTempDir", LuaGetTempDir) ;
|
||
bOk = bOk && luaMgr.RegisterFunction( "EgtGetExeVersion", LuaGetExeVersion) ;
|
||
bOk = bOk && luaMgr.RegisterFunction( "EgtGetVersion", LuaGetVersion) ;
|
||
bOk = bOk && luaMgr.RegisterFunction( "EgtIs64bit", LuaIs64bit) ;
|
||
bOk = bOk && luaMgr.RegisterFunction( "EgtGetLanguage", LuaGetLanguage) ;
|
||
bOk = bOk && luaMgr.RegisterFunction( "EgtMsg", LuaGetMsg) ;
|
||
bOk = bOk && luaMgr.RegisterFunction( "EgtVerifyKeyOption", LuaVerifyKeyOption) ;
|
||
bOk = bOk && luaMgr.RegisterFunction( "EgtSetDefaultFont", LuaSetDefaultFont) ;
|
||
bOk = bOk && luaMgr.RegisterFunction( "EgtGetDefaultFont", LuaGetDefaultFont) ;
|
||
bOk = bOk && luaMgr.RegisterFunction( "EgtWinExec", LuaWinExec) ;
|
||
bOk = bOk && luaMgr.RegisterFunction( "EgtCloseExe", LuaCloseExe) ;
|
||
bOk = bOk && luaMgr.RegisterFunction( "EgtCreateMutex", LuaCreateMutex) ;
|
||
bOk = bOk && luaMgr.RegisterFunction( "EgtReleaseMutex", LuaReleaseMutex) ;
|
||
bOk = bOk && luaMgr.RegisterFunction( "EgtDialogBox", LuaDialogBox) ;
|
||
return bOk ;
|
||
}
|