eTill
Messages postés16Date d'inscriptionjeudi 11 janvier 2007StatutMembreDernière intervention 4 août 2008
-
25 juil. 2008 à 17:42
cs_eldim
Messages postés956Date d'inscriptionlundi 30 mai 2005StatutMembreDernière intervention21 août 2014
-
4 août 2008 à 17:32
Bonjour,
j'ai besoin de créer une classe dans une Dll qui peut ouvrir une Windows Form. Cette classe peut aussi bien être appelée d'une application en mode console que d'une Windows Form. Pour les besoins de l'exemple, nous appellerons cette classe 'CalledForm'.
Pour l'instant, voici les options autour desquelles j'ai prospecté:
1/ la Form est ouverte avec Application.Run(CalledForm):
a. mode Console: il faut que CalledForm soit fermée pour que ce qui est envoyé à la console soit lu.
b. mode Form: plein de problèmes, soit des exceptions, soit CalledForm s'affiche à la place de l'autre Form, etc.
2/ la Form est ouvert avec CalledForm.Show()
a. mode Console: CalledForm s'ouvre, mais ne se dessine pas, et le curseur se met en sablier (la Form se bloque)
b. mode Form: tout va bien. Ca semble bien la méthode idoine.
après investigation sur le net, j'ai mis en place une solution tierce, qui consiste à 'threader' l'appel à Application.Run, dont voici les bases:
public partial class CalledForm: Form , ----
{ , ----
private Thread m_localThread = new Thread(Run); , ----
private static void Run(Object frm) , ----
{ , ----
Application.EnableVisualStyles(); , ----
Application.Run((Form)frm); , ----
} , ----
public void ThreadedShow() , ----
{ , ----
if (!m_localThread.IsAlive) , ----
m_localThread.Start(this); , ----
} , ----
}
3/ dans ce cas là, si la Form est ouverte avec CalledForm.ThreadedShow()
a. mode Console. Tout va bien. C'est clairement la méthode recommandée.
b. mode Form: ça marche, mais ce n'est pas optimale (CalledForm est clairement plus lente) et elle n'est pas fermée quand on quitte l'appli principale.
Ma question est donc, comment puis-je, par programmation, savoir dans quel mode je suis, pour pouvoir appeler la bonne méthode (Show() ouThreadedShow()) ?
A savoir:
j'ai essayé Application.OpenForms, qui s'avère peu fiable, on peut se trouver dans des cas ou ça renvoie 0 alors que des formes sont en construction.
j'ai égalemet essayé GetStdHandle et GetConsoleModemais ce n'est pas plus fiable non plus.
cs_eldim
Messages postés956Date d'inscriptionlundi 30 mai 2005StatutMembreDernière intervention21 août 20141 30 juil. 2008 à 12:24
Bonjour,
je ne vois pas bien la subtilité... sur mes applis, que l'appelle se fasse sous DOS ou Windows les form s'affichent pareil...
sans passer par un intermédiaire... suffit d'avoir winodws form en référence et de commencer ton programme par un static void main
-- Pourquoi faire simple quand on peut faire compliquer --
eTill
Messages postés16Date d'inscriptionjeudi 11 janvier 2007StatutMembreDernière intervention 4 août 2008 30 juil. 2008 à 18:57
Bonjour eldim.
De mon côté, les Forms ne réagissent pas pareilles, justement, c'est bien là le problème.
J'ai essayé de décrire les problèmes que je rencontre, et pour quelles raisons.
Attention, il ne s'agit pas d'un appelle d'une même Application à partir de la console (écrire le chemin de l'exe dans une fenêtre .cmd) vs son appel GUI (double click sur l'icône ou autre). Là, effectivement, c'est simple.
Le problème survient quand deux appli qui ont un mode d'exécution différents (CUI vs GUI) s'appuient sur une même DLL avec Form. Quelle méthode cette Dll doit offrir à l'application appellante pour que la fenêtre s'ouvre proprement Application.Run(CalledForm) ? CalledForm.Show() ? CalledForm.ThreadedShow() ?
C'est effectivement compliqué, et je m'en serais bien passé...
cs_eldim
Messages postés956Date d'inscriptionlundi 30 mai 2005StatutMembreDernière intervention21 août 20141 31 juil. 2008 à 07:56
je dois être mal réveillé car j'ai aussi une appli (par contre en vb.net mais c'est pareil)dont le corps est dans une dll et qui est appelée de plusieurs façon y compris en DOS et windows et en mettant le show directement dans la dll et non dans l'application et j'ai aucun souci
j'appel juste une procedure de la dll qui fait elle même le show
-- Pourquoi faire simple quand on peut faire compliquer --
Vous n’avez pas trouvé la réponse que vous recherchez ?
eTill
Messages postés16Date d'inscriptionjeudi 11 janvier 2007StatutMembreDernière intervention 4 août 2008 31 juil. 2008 à 10:24
Ce dont je parle est assez facilement reproduisible:
Créer une nouvelle solution
Créer un premier projet de type ClassLibrairy avec juste une Form nommée 'CalledForm' dedans.
C'est plus flagrant si la Form a au moins un contrôle dedans (un simple Label suffit).
Créer un deuxième projet de type ConsoleApplication, avec ce code dedans:
class
Program
{
static
void Main(
string[] args)
{
CalledForm calledForm =
new
CalledForm();
calledForm.Show();
eTill
Messages postés16Date d'inscriptionjeudi 11 janvier 2007StatutMembreDernière intervention 4 août 2008 31 juil. 2008 à 11:22
C'est bien un Show() que je veux faire.
Un ShowDialog() rend la fenêtre modale, à savoir que la fenêtre doit être fermée pour que le programme principal continue de tourner, ce qui n'est pas ce dont j'ai besoin.
Effectivement, avec un ShowDialog (ou Application.Run(CalledForm)) la form s'ouvre. Mais fenêtre et console ne peuvent interagir.
Et c'est de façon certaine ce que je ne veux pas dans le cas où le module appelant est une Form.
eTill
Messages postés16Date d'inscriptionjeudi 11 janvier 2007StatutMembreDernière intervention 4 août 2008 31 juil. 2008 à 11:46
Oui,
d'où la mise en place du 'ThreadShow'.
Mais l'utiliser systématiquement n'est pas efficace, en tout cas il dessert mes besoins dans le cas où le module appelant possède une Form.
Voilà où j'en suis arrivé et pourquoi je poste ce sujet.
cs_eldim
Messages postés956Date d'inscriptionlundi 30 mai 2005StatutMembreDernière intervention21 août 20141 31 juil. 2008 à 12:05
je connais pas le threadshow
c'est juste que je l'aurais fait comme ça:
Threading.Thread TH=new threading.thread( AdresseDeTaProcQui lance ta form)
TH.Start
et dans ta proc qui lance ta form ou dans le load de ta form
le sleep qui rend la main à ta procedure dos (ce qui fait que tu as deux procedures en parallèle)
-- Pourquoi faire simple quand on peut faire compliquer --
eTill
Messages postés16Date d'inscriptionjeudi 11 janvier 2007StatutMembreDernière intervention 4 août 2008 31 juil. 2008 à 12:21
Je n'ai pas essayé directement avec MainWindowHandle, mais avec Application.OpenForms(). Malheureusement, ce n'est pas un test fiable, entre autre au moment des differentes initialisations, où les fenêtres ne sont pas toutes forcément ouvertes. Je soupçonne que le pb risque d'être le même, mais je vais essayer.
cs_eldim
Messages postés956Date d'inscriptionlundi 30 mai 2005StatutMembreDernière intervention21 août 20141 31 juil. 2008 à 13:50
c'est du bricolage mais tu peux essayer de vérifier si une référence à windowsform est présente avec ça
system.Reflection.Assembly.GetCallingAssembly.GetReferencedAssemblies
-- Pourquoi faire simple quand on peut faire compliquer --
eTill
Messages postés16Date d'inscriptionjeudi 11 janvier 2007StatutMembreDernière intervention 4 août 2008 31 juil. 2008 à 14:21
Hmm, c'est très risqué, car cette info est très peu représentative de la réalité.
Je peux imaginer d'ores et déjà plein de cas de figure où une référence à une WindowsForm existe mais où je suis dans le cas d'un appel 'Console'.
Encore moins fiable que Application.OpenForms().
J'aimerais trouver un jeu de tests totalement fiables.
Merci tout de même.
cs_eldim
Messages postés956Date d'inscriptionlundi 30 mai 2005StatutMembreDernière intervention21 août 20141 31 juil. 2008 à 14:30
essai de regarder du coté des flux
lorsque l'appli est en mode console les flux de sortie sont redirigé par une api (je ne sais plus laquelle)
le tout c'est de trouver comment j'ai pas trop de temps cet aprem... mais je vai chercher
-- Pourquoi faire simple quand on peut faire compliquer --