Le forum (ô combien francophone) des utilisateurs de Powerbuilder.
Pages: 1 2
Un article très intéressant dans le Powerbuilder Developer's Journal :
Overriding the PowerBuilder MessageBox() Function
$PBExportHeader$messagebox.srf $PBExportComments$Overloaded global MessageBox function global type messagebox from function_object end type forward prototypes global function integer MessageBox( string the_title, string the_message ) global function integer MessageBox( string the_title, string the_message, icon the_icon ) global function integer MessageBox( string the_title, string the_message, icon the_icon, button the_button ) global function integer messagebox (string the_title, string the_message, icon the_icon, button the_button, integer the_default) end prototypes global function integer MessageBox( string the_title, string the_message ) // MessageBox( string the_title, string the_message ) // Put it into the clipboard (and log it) f_msg_box_to_clipboard( the_title, the_message ) // Default to no icon, OK!, button 1 return MessageBox( the_title, the_message, None!, OK!, 1 ) end function global function integer MessageBox( string the_title, string the_message, icon the_icon ) // MessageBox( string the_title, string the_message, icon the_icon ) // Put it into the clipboard (and log it) f_msg_box_to_clipboard( the_title, the_message ) /* The possible values for the_icon: Information! StopSign! Exclamation! Question! None! */ // The icon determines the_buttons if the_icon = Question! then // Default to YesNo!, button 1 -> Yes return MessageBox( the_title, the_message, the_icon, YesNo!, 1 ) else // Default to OK!, button 1 return MessageBox( the_title, the_message, the_icon, OK!, 1 ) end if end function global function integer MessageBox( string the_title, string the_message, icon the_icon, button the_button ) // MessageBox( string the_title, string the_message, icon the_icon, button the_button ) // Put it into the clipboard (and log it) f_msg_box_to_clipboard( the_title, the_message ) /* The possible values for the_button: OK! (Default) OK button OKCancel! OK and Cancel buttons YesNo! Yes and No buttons YesNoCancel! Yes, No, and Cancel buttons RetryCancel! Retry and Cancel buttons AbortRetryIgnore! Abort, Retry, and Ignore buttons */ // The_button determines the default if the_button = OKCancel! or the_button = RetryCancel! then // Default to 2 -> Cancel return MessageBox( the_title, the_message, the_icon, the_button, 2 ) elseif the_button = YesNoCancel! then // Default to 3 -> Cancel return MessageBox( the_title, the_message, the_icon, the_button, 3 ) elseif the_button = OK! or the_button = YesNo! then // Default to 1 -> OK and Yes return MessageBox( the_title, the_message, the_icon, the_button, 1 ) elseif the_button = AbortRetryIgnore! then // Default to 2 -> Retry return MessageBox( the_title, the_message, the_icon, the_button, 2 ) else g.bug( "Unexpected button in MessageBox( 4 arguments )" ) return -1 // Have to return something! end if end function
Hors ligne
pour ce super article.
Néanmoins, je n'utiliserai jamais cette technique de surcharger les fonctions globales du powerScript. On code autant pour des être humains que pour un ordinateur.
Franchement qui n'a jamais fait de la maintenance sur des projets où 3 générations de développeurs se sont succédées ?
Donc là le petit nouveau il se retrouve avec des fonctions qui ne font pas ce que dit la doc.
Je préfére définir mes fonctions of_messagebox dans un objet non visuel et déclarer une variable globale, ce qui me permet de coder
g.of_messageBox("Coucou")
Hors ligne
100% d'accord avec toi Shahin
Hors ligne
L'intérêt dans cette technique pour moi c'est justement de pouvoir prendre le contrôle des MessageBox sur une appli existante de taille importante qui a été modifiée par 3 générations de développeurs...
Pour une appli développée du début, ça me parait préférable aussi de partir d'un objet dédié.
Néanmoins, dans le cadre d'un travail en équipe, il y a malheureusement toujours quelqu'un qui finira par coder à sa façon en utilisant le MessageBox standard, par oubli ou par paresse ponctuelle, et cette technique permet de quand même intercepter la chose et de la traiter comme on veut. Je trouve particulièrement astucieux et pratique aussi le fait de pouvoir reprendre la main (en contexte développement uniquement) sur une boucle infinie qui balance des MessageBox à n'en plus finir, que celui à qui ça n'est jamais arrivé me lance la 1ère pépite !
Là où je procéderais différement que ce qui est évoqué dans cet article, c'est que je ne changerais pas les paramètres par défaut (Yes, No, Retry etc...), histoire justement de rester en phase avec la documentation de PB à ce sujet.
Dernière modification par Steve (12-01-2007 10:40:56)
Hors ligne
En tout cas, merci pour ce tips !
+50
Hors ligne
pick ouic a écrit:
En tout cas, merci pour ce tips !
+50
Pas de quoi !
J'ai vu passer ça dans le fil RSS du PBDJ :
http://pbdj.sys-con.com/index.rss
Hors ligne
Bonjour à tous,
Je déterre un peu ce sujet car il m'intéresse fortement.
J'essaie de surcharger la fonction messagebox pour ne plus avoir ces vieilles fenêtres toutes moches dans une application en cours de relooking.
Il est donc impossible que nous repassions partout pour remplacer l'appel à la fonction par une autre qui ouvrirait une window faite main.
Cependant, je ne comprends absolument rien à l'article.
J'ai tenté de créer une fonction messagebox dans laquelle j'appelle ma nouvelle fenetre msgbox...mais rien n'y fait, je me retrouve tjs avec la vieille messagebox.
J'oublie qq chose, mais je ne comprends pas comment et où le faire.
QQ un peut me mettre sur la piste svp ?
Hors ligne
Sebou au pire tu as PBTools qui peut faire un replace global sur une application
http://myelkovan.codeplex.com/
Ca te permettrait de changer le mot messageBox par une fonction maison dans toute ton application d'un coup.
Hors ligne
Sebou a écrit:
J'ai tenté de créer une fonction messagebox dans laquelle j'appelle ma nouvelle fenetre msgbox...mais rien n'y fait, je me retrouve tjs avec la vieille messagebox.
J'oublie qq chose, mais je ne comprends pas comment et où le faire.
QQ un peut me mettre sur la piste svp ?
Où as-tu créé la nouvelle fonction ? Fonction globale ou méthode d'un objet (ça peut aussi marcher avec ça : si tu nommes une méthode "MessageBox" dans un objet la fonction qui sera appelée sera d'abord la méthode locale, pour appeler explicitement une méthode globale du même nom il faudra faire "::MessageBox()"
Sinon pour que la surcharge d'une méthode système fonctionne et pouvoir l'appeler ensuite (par exemple pour un hook), il faut jouer sur le nombre et le type des paramètres : déclarer une fonction avec le même nom mais une liste de paramètres différente de la fonction système. Si tu usilise exactement le même prototype, la fonction système n'est plus appelable.
Si tu veux "juste" remplacer la fonction système alors il faut déclarer ta fonction avec les mêmes paramètres.
Dans le cas de MessageBox(), il existe 16 prototypes différents de cette fonction ! (mais il suffit de redéfinir ceux que tu utilises réellement)
Dernière modification par seki (16-05-2014 08:46:07)
Hors ligne
Euhhhhhh en effet seki, je ne sais pas ce que j'avais brandouillé jusque maintenant MAIS j'ia refait au propre et là ca fonctionne. J'ai du oublié un morceau ou faire une faute de frappe :x
_francois_ : Merci pour PBTools, ca peut etre utile en effet
Donc, maintenant que ça fonctionne, j'ai quand meme un soucis.
J'ai créé une window de type RESPONSE w_msgbox.
Dans le cas suivant, la RESPONSE ne se comporte pas comme une vraie messagebox :
post event ue_traitement( ) li_ret = messagebox("Question", "Souhaitez-vous enregistrer ?", question!,yesnocancel!) IF li_ret = 1 THEN ib_traitement = true
Dans ce cas précis (evenement post AVANT la messagebox), lors de l'ouverture de ma fenêtre messagebox, l'appli dépile ce qui est en post SANS ATTENDRE la réponse li_ret.
Et comme dans ue_traitement, il y a une condition sur la valeur de ib_traitement....Béh ça merdouille
Une idée ?
Hors ligne
Dans ta fonction messagebox tu fais un open ou un opensheet pour ta response ?
Opening response windows Do not use the OpenSheet function to open a response window.
Hors ligne
Sebou a écrit:
Code: pb
post event ue_traitement( ) li_ret = messagebox("Question", "Souhaitez-vous enregistrer ?", question!,yesnocancel!) IF li_ret = 1 THEN ib_traitement = true
Dans ce cas précis (evenement post AVANT la messagebox), lors de l'ouverture de ma fenêtre messagebox, l'appli dépile ce qui est en post SANS ATTENDRE la réponse li_ret.
Et comme dans ue_traitement, il y a une condition sur la valeur de ib_traitement....Béh ça merdouille
Une idée ?
Gnî ??
Tu POSTe un évènement censé utiliser le résultat de la messagebox, le problème c'est que ce qui est posté ne donne aucune garantie sur le moment où ce sera exécuté, à part que ce sera "plus tard".
Si tu as besoin de li_ret pour ue_traitement(), pourquoi tu ne trigges pas l'évènement après l'appel à Messagebox() ?
J'ai l'impression qu'il y a un problème de design du code...
Hors ligne
seki a écrit:
Sebou a écrit:
Code: pb
post event ue_traitement( ) li_ret = messagebox("Question", "Souhaitez-vous enregistrer ?", question!,yesnocancel!) IF li_ret = 1 THEN ib_traitement = true
Dans ce cas précis (evenement post AVANT la messagebox), lors de l'ouverture de ma fenêtre messagebox, l'appli dépile ce qui est en post SANS ATTENDRE la réponse li_ret.
Et comme dans ue_traitement, il y a une condition sur la valeur de ib_traitement....Béh ça merdouille
Une idée ?Gnî ??
Tu POSTe un évènement censé utiliser le résultat de la messagebox, le problème c'est que ce qui est posté ne donne aucune garantie sur le moment où ce sera exécuté, à part que ce sera "plus tard".
Si tu as besoin de li_ret pour ue_traitement(), pourquoi tu ne trigges pas l'évènement après l'appel à Messagebox() ?
J'ai l'impression qu'il y a un problème de design du code...
Tout à fait d'accord...sauf que ce code a 20 ans et qu'il est impossible de trouver tous les endroits du code qui ont ce problème de design...
En cherchant un peu sur le net, j'ai vu des pistes qui se basent sur :
DS_NOIDLEMSG et SetWindowLong
Mais là, je ne sais pas trop comment m'y prendre
Hors ligne
Il semble que le DS_NOIDLEMSG doit être passé dans la fonction CreateWindow donc le SetWindowLong après coup ça risque de faire trop tard.
Tu as bien vérifié que tu faisais un Open et pas un OpenSheet ?
Dernière modification par _francois_ (16-05-2014 11:44:12)
Hors ligne
Assures-toi aussi qu'il n'y a aucun Yield() qui serait exécuté par ta window et les objets qui la compose.
Hors ligne
_francois_ : je fais des openwithparm pour pouvoir passer le texte à afficher
xlat : pas de Yield(), je confirme
Hors ligne
Oui Open OpenWithParm même principe tant qu'il n'y a pas sheet
quand tu as ta "messagebox" affichée ton application est bien "bloquée" comme ça devrait être le cas avec une response ?
Fonctions externes
function Long SetWindowLong (ulong hWnd, int nIndex, long dwNewLong) library "user32" ALIAS FOR "SetWindowLongA;Ansi" function Long GetWindowLong (ulong hWnd, int nIndex) library "user32" ALIAS FOR "GetWindowLongA;ansi"
Variables
constant integer GWL_STYLE = -16 constant integer DS_NOIDLEMSG = 256 // A vérifier
Dans le open de ta message box
ulong lul_handle long ll_gwl lul_handle = handle(this) ll_gwl = GetWindowLong(lul_handle, GWL_STYLE) ll_gwl = bitwiseand(ll_gwl,DS_NOIDLEMSG) // Fonction dans pbnicw de seki, logiquement on peut faire pareil avec les fastfuncs SetWindowLong(lul_handle, GWL_STYLE, ll_gwl)
Pas testé le code, mais j'ai un truc similaire dans mon appli pour changer l'apparence des fenêtres (par de border pas de title, etc...)
Hors ligne
_francois_ a écrit:
Oui Open OpenWithParm même principe tant qu'il n'y a pas sheet
quand tu as ta "messagebox" affichée ton application est bien "bloquée" comme ça devrait être le cas avec une response ?
Fonctions externesCode: pb
function Long SetWindowLong (ulong hWnd, int nIndex, long dwNewLong) library "user32" ALIAS FOR "SetWindowLongA;Ansi" function Long GetWindowLong (ulong hWnd, int nIndex) library "user32" ALIAS FOR "GetWindowLongA;ansi"
VariablesCode: pb
constant integer GWL_STYLE = -16 constant integer DS_NOIDLEMSG = 256 // A vérifier
Dans le open de ta message boxCode: pb
ulong lul_handle long ll_gwl lul_handle = handle(this) ll_gwl = GetWindowLong(lul_handle, GWL_STYLE) ll_gwl = bitwiseand(ll_gwl,DS_NOIDLEMSG) // Fonction dans pbnicw de seki, logiquement on peut faire pareil avec les fastfuncs SetWindowLong(lul_handle, GWL_STYLE, ll_gwl)
Pas testé le code, mais j'ai un truc similaire dans mon appli pour changer l'apparence des fenêtres (par de border pas de title, etc...)
J'ai vérifié pour le 256, c'est bon.
J'ai déclaré les local external functions Get et SetWindowLong
J'ai ajouté ton code à l'open de ma window response...et ca ne change rien
En fait, j'ai bitwiseand qui retourne 0...
Je pense qu'on est sur la bonne piste mais...
Dernière modification par Sebou (16-05-2014 13:04:15)
Hors ligne
en fait c'est peut être bitwiseor qu'il faut dans ce cas
Dans mon code j'ai des bitwiseand couplé à des bitwisenot pour enlever des choses à mon STYLE dans ton cas il faut y ajouter quelque chose.
Dernière modification par _francois_ (16-05-2014 13:27:54)
Hors ligne
_francois_ a écrit:
Code: pb
lul_handle = handle(this) ll_gwl = GetWindowLong(lul_handle, GWL_STYLE) ll_gwl = bitwiseand(ll_gwl,DS_NOIDLEMSG) // Fonction dans pbnicw de seki, logiquement on peut faire pareil avec les fastfuncs SetWindowLong(lul_handle, GWL_STYLE, ll_gwl)
Pas testé le code, mais j'ai un truc similaire dans mon appli pour changer l'apparence des fenêtres (par de border pas de title, etc...)
Pour ajouter un bit, il faut faire un OU binaire (bitwiseor() donc) pas un ET qui ne conservera que ce bit. Faux ami booleen...
Hors ligne
seki a écrit:
Pour ajouter un bit, il faut faire un OU binaire (bitwiseor() donc) pas un ET qui ne conservera que ce bit. Faux ami booleen...
Oui je m'en suis aperçu plus tard, mon esprit est déjà en weekend
Hors ligne
J'ai ajouté pbnicw.pbd à mon appli (PB12.5) et bien sur, je plante quand je souhaite utiliser bitwiseor car "bad runtime..."
Hors ligne
il te faut aussi pbnicw.pbx accessible
Version que j'ai compilé avec la 12.5 et que j'utilise.
http://www.datafilehost.com/d/89f4d6e5
Dernière modification par _francois_ (16-05-2014 13:55:02)
Hors ligne
_francois_ a écrit:
il te faut aussi pbnicw.pbx accessible
Version que j'ai compilé avec la 12.5 et que j'utilise.
http://www.datafilehost.com/d/89f4d6e5
Euhhhh tu as posté le pbx...Mais j'ai pas le pbd 12.5
Pourrais-tu me le faire parvenir par mail stp ? (car c'est une galere sans nom pour pouvoir accéder au site de partage de fichier avec les regles de sécurité ici)
Désolé du dérangement
Hors ligne
je te fais ça lundi quand je serai de retour au boulot
Hors ligne
Pages: 1 2