Aide pour l'enregistrement des propriétées
Bonjour,
je suis en train de dévelloper une extension mais je me heurte à un problème:
Lorsque j'édite un élément des propriétées de l'objet, MMF2 plante.
J'utilise la syntaxe deja donnée dans SetPropValue, sachant qu'une valeur DWORD s'enregistre et se charge très bien.
Petit bout de code:
<div class="ubbcode-block"><div class="ubbcode-header">Code:</div><div class="ubbcode-body ubbcode-pre"><pre> case PROPID_USER:
{
// Saissisez la chaine de caractères
LPSTR pStr = (LPSTR)((CPropDataValue*)pValue)->m_pData;
// Vous pouvez simplement pousser la chaine si votre structure d'EDITDATA a une taille fixe,
// ou ayant une taille adaptative de structure comme ci-dessous
// Si la longeur est différente
if (strlen(pStr)!=strlen(edPtr->user))
{
// Demande a MMF de réapproprier la structure avec la nouvelle taille
LPEDATA pNewPtr = (LPEDATA)mvReAllocEditData(mV, edPtr, sizeof(EDITDATA)+strlen(pStr));
// Si la réallocation est terminé
if (pNewPtr!=NULL)
{
// Copie la chaine
edPtr=pNewPtr;
strcpy(edPtr->user, pStr);
}
}
else
{
// Même taille : copie simple
strcpy(edPtr->user, pStr);
}
}
break;</pre></div></div>
edPtr->user étant une variable "LPSTR user" déclarée dans la structure tagEDATA_V1 (normalement quoi)
Donc, en gros.
Lorsque j'édite un LPSTR -> Bug
Lorsque j'édite un DWORD -> Ok
Aucuns autres bugs à signaler
Je pense que l'érreur se trouve dans ce bout de code mais je sait pas plus.
Merci de votre aide [img]/epicentre/images/%%GRAEMLIN_URL%%/smile.gif[/img] .
Re: Aide pour l'enregistrement des propriétées
L'exemple donné dans le SDK ne marche pas avec un LPSTR mais avec un tableau de char de longueur 1 se trouvant à la fin de la structure EDITDATA:
<div class="ubbcode-block"><div class="ubbcode-header">Code:</div><div class="ubbcode-body ubbcode-pre"><pre>
typedef struct tagEDATA_V1
{
// Header - required
extHeader eHeader;
// Object's data
char user[1];
} EDITDATA;
</pre></div></div>
En gros seule la fin de la structure change. La structure EDITDATA ne peut pas contenir de LPSTR car elle est enregistrée telle qu'elle sur disque.
Si plusieurs éléments sont de taille variable, et pas seulement une seule chaîne, alors une solution pour gérer ça c'est de créer un objet C++ avec des fonctions LoadFromEditData et SaveToEditData, le LoadFromEditData permettant d'initialiser l'objet à partir de la structure EDITDATA et le SaveToEditData permettant de recréer la structure EDITDATA à partir des données de l'objet. Mais en général peu d'objets sont suffisamment complexes pour avoir besoin de ce système.
Yves.
Re: Aide pour l'enregistrement des propriétées
J'utilise effectivement plusieurs objets de taille variables (utilisateur, pass...)
Mon objet est effectivement assez complexe car il fait deja 525ko à cause des libs, plus une dll de 225ko encore environ.
J'ai remplacé les LPSTR par des chars[1] et ca marche, enfin ca plante plus ^^.
J'imagine que je vait avoir besoin d'utiliser cette technique de SaveToEditData/LoadFromEditData (que j'avoue ne pas avoir très bien compris :> ), en gros, il faudrait créer une nouvelle classe d'objets?
Merci
Re: Aide pour l'enregistrement des propriétées
Houlla, c'est quoi comme objet? Il fait vraiment 525 Ko en mode release? Il utilise les MFCs peut-être?
Si tu as plusieurs LPSTR, alors tu ne peux pas les remplacer tous par les chars[1] sinon ils vont s'écraser les uns les autres. [img]/epicentre/images/%%GRAEMLIN_URL%%/smile.gif[/img]
Exemple d'objet C++ avec les fonctions dont je parlais :
Par exemple une structure EDITDATA avec 2 chaînes de taille variable, nom utilisateur et mot de passe :
<div class="ubbcode-block"><div class="ubbcode-header">Code:</div><div class="ubbcode-body ubbcode-pre"><pre>
typedef struct tagEDATA_V1
{
// Header
extHeader eHeader;
// Object's data
DWORD userOffset;
DWORD passwordOffset;
} EDITDATA;
typedef EDITDATA * LPEDATA;
</pre></div></div>
userOffset et passwordOffset sont les adresses des textes relatives au démarrage de la structure EDITDATA, les textes étant stockés après la structure EDITDATA.
L'objet C++ dont je parlais pourrait être écritcomme ceci :
<div class="ubbcode-block"><div class="ubbcode-header">Code:</div><div class="ubbcode-body ubbcode-pre"><pre>
class CEditObject
{
public:
CEditObject();
CEditObject(LPCSTR pName, LPCSTR pPassword);
~CEditObject();
void LoadFromEditData(mV* pMV, LPEDATA edPtr);
LPEDATA SaveToEditData(mV* pMV, LPEDATA edPtr);
public:
LPSTR m_pUserName;
LPSTR m_pPassword;
};
CEditObject::CEditObject()
{
m_pUserName = _strdup("");
m_pPassword = _strdup("");
}
CEditObject::CEditObject(LPCSTR pName, LPCSTR pPassword)
{
m_pUserName = _strdup(pName);
m_pPassword = _strdup(pPassword);
}
CEditObject::~CEditObject()
{
free(m_pUserName);
free(m_pPassword);
}
void CEditObject::LoadFromEditData(mV* pMV, LPEDATA edPtr)
{
// Free current strings
free(m_pUserName);
free(m_pPassword);
// Load strings from edPtr
m_pUserName = _strdup((LPSTR)((LPBYTE)edPtr + edPtr->userOffset);
m_pPassword = _strdup((LPSTR)((LPBYTE)edPtr + edPtr->passwordOffset);
}
void CEditObject::SaveToEditData(mV* pMV, LPEDATA edPtr)
{
// Calculate size of EDITDATA
int lsize = sizeof(EDITDATA) +
strlen(m_pUserName) + 1 +
strlen(m_pPassword) + 1;
// Re-allocate edPtr
LPEDATA pNewPtr = (LPEDATA)mvReAllocEditData(mV, edPtr, lsize);
// OK?
if ( pNewPtr != NULL )
{
// Update EDITDATA members
pNewPtr->userOffset = sizeof(EDITDATA);
pNewPtr->passwordOffset = pNewPtr->userOffset + strlen(m_pUserName) + 1;
// Add strings
LPSTR pText = (LPSTR)((LPBYTE)pNewPtr + sizeof(EDITDATA));
strcpy(pText, m_pUserName);
pText += strlen(pText) + 1;
strcpy(pText, m_pPassword);
}
return pNewPtr;
}
</pre></div></div>
Et son utilisation par exemple dans la fonction CreateObject:
<div class="ubbcode-block"><div class="ubbcode-header">Code:</div><div class="ubbcode-body ubbcode-pre"><pre>
int WINAPI DLLExport CreateObject(mv _far *mV, fpLevObj loPtr, LPEDATA edPtr)
{
#ifndef RUN_ONLY
// Check compatibility
if ( IS_COMPATIBLE(mV) )
{
CEditObject edo("Albert", "");
edPtr = edo.SaveToEditData(mV, edPtr);
if ( edPtr != NULL )
return 0; // OK
}
#endif // !defined(RUN_ONLY)
// Error
return -1;
}
</pre></div></div>
ou dans ta fonction SetProp :
<div class="ubbcode-block"><div class="ubbcode-header">Code:</div><div class="ubbcode-body ubbcode-pre"><pre>
case PROPID_USER:
{
CEditObject edo;
edo.LoadFromEditData(mV, edPtr);
LPSTR pStr = (LPSTR)((CPropDataValue*)pValue)->m_pData;
free(edo.m_pUserName);
edo.m_pUserName = _strdup(pStr);
LPEDATA pNewPtr = edo.SaveToEditData(mV, edPtr);
}
break;
</pre></div></div>
Attention, je ne garantis pas que ça compile et que ça marche, j'ai juste tapé ça à vue de nez comme exemple. [img]/epicentre/images/%%GRAEMLIN_URL%%/wink.gif[/img] Mais il ne devrait pas y avoir d'erreur majeure. Enfin j'espère...
Re: Aide pour l'enregistrement des propriétées
Houla! Ca as l'air bien compliqué (pour moi ^^)
Je pense que je ferait cette modification après...
Etant donné que je développe une extension qui pourra se connecter a MySQL (voila le pourquoi des 500ko), j'utilise plus que 2 variables char, notamment {serveur, user, pass, db} (je croit que c'est tout ^^)
Pour l'instant mon extension a l'air de se connecter correctement mais je n'en suis pas sur...
J'ai actuellement deux problèmes:
-Impossible d'appeler la fonction callRuntimeFunction pour un RFUNCTION_GENERATEEVENT
-Le débuggeur affiche "Utilisateur: " pour wsprintf(pBuffer, temp, rdPtr->user), alors qu'il devrait afficher "Utilisateur: abcd"
Pour le 2ème probème je vait essayer de voir si un problème ne survient pas lors du transfers de editdata à rundata...
Re: Aide pour l'enregistrement des propriétées
<div class="ubbcode-block"><div class="ubbcode-header">En réponse à:</div><div class="ubbcode-body">Houla! Ca as l'air bien compliqué (pour moi ^^)
Je pense que je ferait cette modification après...</div></div>
Ca n'a rien de compliqué mais il faut connaître le C++ et pas seulement le C. Une bonne occasion de s'y mettre? [img]/epicentre/images/%%GRAEMLIN_URL%%/smile.gif[/img]
Sinon il est aussi possible de tout faire en C pur et dur, mais le C++ est plus élégant et plus facile à modifier si on ajoute d'autres chaînes. Je recommande la solution que j'ai indiquée. De toute façon si tu utilises plusieurs chaînes de taille variable, alors tu es obligé de passer par une solution dans le genre de celle que j'ai donnée, en C++ ou en C. Essaye de vraiment comprendre comment ça marche, c'est pas très compliqué et ça utilise uniquement le B-A-BA du C++, rien de sophistiqué. [img]/epicentre/images/%%GRAEMLIN_URL%%/smile.gif[/img]
Tu peux poster ta structure EDITDATA?
Pour les problèmes, le mieux c'est de tracer le code avec le débuggeur de Visual C.
Re: Aide pour l'enregistrement des propriétées
Pour l'instant mon editdata c'est:
<div class="ubbcode-block"><div class="ubbcode-header">Code:</div><div class="ubbcode-body ubbcode-pre"><pre>typedef struct tagEDATA_V1
{
// Header - Obligatoire
extHeader eHeader;
char sql_server[256];
char sql_user[256];
char sql_password[256];
char sql_db[256];
DWORD sql_port;
} EDITDATA;</pre></div></div>
Je risque d'avoir encore besoin d'ajouter des variables char mais uniquement dans le RunData...
EDIT: J'ai réglé le bug du débuggeur mais je risque de ne pas vous répondre avant dimanche-lundi... au revoir )^_^(
Re: Aide pour l'enregistrement des propriétées
OK, comme ça ça va, pas besoin d'utiliser le système que j'ai indiqué car les chaînes ont une taille fixe. Tu aurais besoin du système seulement si tu voulais optimiser la taille de la zone.
Par contre il faut faire attention à ne pas dépasser la taille des buffers.
Re: Aide pour l'enregistrement des propriétées
<div class="ubbcode-block"><div class="ubbcode-header">Posté à l'origine par: Tyrael</div><div class="ubbcode-body">-Impossible d'appeler la fonction callRuntimeFunction pour un RFUNCTION_GENERATEEVENT</div></div>
J'ai eu le même problème tantôt. La solution est d'appeler la macro
<div class="ubbcode-block"><div class="ubbcode-header">Code:</div><div class="ubbcode-body ubbcode-pre"><pre>
GenerateEvent(LPRDATA rdPtr, int EventID);
</pre></div></div>
Re: Aide pour l'enregistrement des propriétées
callRuntimeFunction c'est simplement parcequ'il y a une faute de syntaxe dans l'aide je crois que c'est : callRunTimeFunction