Passer au contenu principal

dnt91's Blog [MVP SharePoint]

Lancer la recherche
dnt91's Blog [MVP SharePoint]
  

dnt91's Blog [MVP SharePoint] > Catégories
Téléchargez Visual Studio 2010 Beta 2.

Ca se passe tout simplement ici > http://msdn.microsoft.com/en-us/vstudio/dd582936.aspx

Amusez vous bien J

[Windows Forms]Implémentation de l’impression dans vos applications

Implémenter l'impression dans vos applications revient à configurer 4 objets ; ces objets sont :

  • L'objet PrintDocument
  • L'objet PrintDialog
  • L'objet PrintPreviewDialog
  • L'objet PageSetupDialog

Voyons à présent chacun de ces objets et comment les combiner pour obtenir une fonctionnalité d'impression.

Vous pouvez récupérer le projet accompagnant cet article ici.

L'objet PrintDocument.

L'objet PrintDocument représente le document à imprimer ; pour lancer l'impression du document, il suffit d'appeler la méthode Print de l'objet PrintDocument ; cette méthode permet de lancer l'impression de notre document sur l'imprimante par défaut.

void PrintButton_Click(object sender, EventArgs e) {

docToPrint.Print();

}

Cependant, avant d'imprimer le document, il faut définir ce que l'on va imprimer. Pour cela, nous allons définir le contenu à imprimer dans l'événement PrintPage de l'objet PrintDocument.

Par exemple, pour imprimer le texte « Implémentation de l'impression », il nous faut le spécifier dans l'objet graphic récupéré à partir de l'événement PrintPage, comme ceci :

void docToPrint_PrintPage(object sender, PrintPageEventArgs e) {

e.Graphics.DrawString(

"Implémentation de l'impression",

new Font("Arial", 10), Brushes.Black, new PointF());

}

Voici le code complet du formulaire PrintDocumentForm permettant de mettre en œuvre ce mécanisme :

public class PrintDocumentForm : Form {

 

#region Variables & Properties

 

PrintDocument docToPrint;

Button PrintButton;

Panel panel;

 

#endregion

 

#region Création de notre formulaire

 

public PrintDocumentForm() {

this.Load += new EventHandler(PrintDocumentForm_Load);

docToPrint = new PrintDocument();

docToPrint.PrintPage += new PrintPageEventHandler(docToPrint_PrintPage);

PrintButton = new Button();

PrintButton.Text = "Print";

PrintButton.Click += new EventHandler(PrintButton_Click);

panel = new Panel();

}

 

void PrintDocumentForm_Load(object sender, EventArgs e) {

this.Controls.Add(panel);

panel.Controls.Add(PrintButton);

}

 

#endregion

 

#region Gestion de l'impression

 

/// <summary>

/// La méthode Print() permet de déclencher

/// l'impression du document

/// </summary>

/// <param name="sender"></param>

/// <param name="e"></param>

void PrintButton_Click(object sender, EventArgs e) {

docToPrint.Print();

}

 

/// <summary>

/// L'événement PrintPage() permet de spécifier le

/// document à imprimer en travaillant avec l'objet

/// Graphics.

/// </summary>

/// <param name="sender"></param>

/// <param name="e"></param>

void docToPrint_PrintPage(object sender, PrintPageEventArgs e) {

e.Graphics.DrawString(

"Implémentation de l'impression",

new Font("Arial", 10), Brushes.Black, new PointF());

}

 

#endregion

 

}

Et voici le résultat en utilisant comme imprimante par défaut une imprimante XPS

Une des limites de notre méthode d'impression est le fait de ne pas pouvoir choisir notre boite de dialogue ; c'est l'objectif du composant PrintDialog

L'objet PrintDialog

Le composant Printdialog est une boite de dialogue modale donnant la possibilité à nos utilisateurs de sélectionner une imprimante.

Pour utiliser ce composant, il nous suffit d'appeler la méthode ShowDialog et de tester la valeur de retour DialogResult correspondant à l'action de l'utilisateur. Si l'utilisateur a cliqué sur OK, nous lançons l'impression, sinon nous ne faisons rien.

Pour cela, modifions le code la méthode PrintButton_Click afin de refléter tout ceci.

void PrintButton_Click(object sender, EventArgs e) {

if (dialogToShow.ShowDialog() == DialogResult.OK)

docToPrint.Print();

}

(Regardez le listing complet du formulaire PrintDialogForm pour l'exemple complet).

Et voici le résultat.

Maintenant que nous sommes capables de sélectionner l'imprimante à utiliser, voyons comment prévisualiser notre document avec de l'imprimer.

L'objet PrintPreview

L'objet PrintPreview est une boite de dialogue donnant la possibilité de prévisualiser un document tel qu'il sera à l'impression

Pour l'utiliser l'objet PrintPreview, affectez sa propriété Document au PrintDocument à prévisualiser, puis appelez la méthode ShowDialog()

void PreviewButton_Click(object sender, EventArgs e) {

previewToShow.Document = docToPrint;

previewToShow.ShowDialog();

}

(Regardez le listing complet de l'exemple PrintPreviewForm pour l'exemple complet)

Et voici le résultat

L'avantage de prévisualiser avant d'imprimer est que l'on se rend compte d'incohérence avant de gaspiller du papier (pensons à la nature J).

Ici, nous remarquons par exemple que les marges ne sont pas correctes ; il serait donc souhaitable de donner à l'utilisateur la possibilité d'ajuster ce genre de propriété ; l'objet PageSetupDialog en est responsable.

L'objet PageSetupDialog

Cet objet permet à l'utilisateur de modifier les paramètres d'impression liés au document.

Voici un exemple de code (le code complet se trouve dans le listing PageSetupForm) :

void SetupButton_Click(object sender, EventArgs e) {

docSetup.Document = docToPrint;

docSetup.PageSettings = new PageSettings();

docSetup.PrinterSettings = new PrinterSettings();

if (docSetup.ShowDialog() == DialogResult.OK) {

docToPrint.PrinterSettings = docSetup.PrinterSettings;

}

}

Et le résultat

Taches supplémentaires :

Vous pouvez déclencher des événements avant ou après l'impression en implémentant les événements BeginPrint et EndPrint de l'objet PrintDocument.

Par exemple, le code suivant affiche une MessageBox en fin d'impression pour notifier l'utilisateur :

void docToPrint_EndPrint(object sender, PrintEventArgs e) {

MessageBox.Show("Impression terminée !");

}

Vous pouvez également gérer l'impression sur plusieurs pages, en jouant avec les méthodes MeasureString(), DrawString(), SubString() et la propriété HasMorePage comme illustré ci-dessous (formulaire CompleteForm).

void PrintButton_Click(object sender, EventArgs e) {

if (dialogToShow.ShowDialog() == DialogResult.OK) {

//On initialise ici le texte à imprimer car

//la Methode Print_Page est appelée autant de

//fois que nécessaire jusque ca que la propriété

//PrintPageEventArgs.e.HasPage soit égale à false

txtToPrint = richTextBox.Text;

docToPrint.Print();

}

}

 

void docToPrint_PrintPage(object sender, PrintPageEventArgs e) {

var numberOfCharacters = 0;

var numberOfLines = 0;

//Police à utiliser

var fontToUse = richTextBox.Font;

//Rectangle définissant la zone d'impression

var rectangleToUse = e.MarginBounds;

var sizeToUse = rectangleToUse.Size;

 

//ne pas mettre ceci ici txtToPrint = richTextBox.Text;

//car on rentre dans une boucle infinie si le document

//contient plusieurs pages.

 

//On récupère le nombre de ligne grâce à la méthode

//MeasureString

e.Graphics.MeasureString(txtToPrint, fontToUse, sizeToUse,

StringFormat.GenericTypographic, out numberOfCharacters, out numberOfLines);

 

//On imprime une page...

e.Graphics.DrawString(txtToPrint, fontToUse, Brushes.Black, rectangleToUse,

StringFormat.GenericTypographic);

 

//...puis on supprime ce qui vient d'être imprimé.

txtToPrint = txtToPrint.Substring(numberOfCharacters);

 

// On vérifie si il reste du contenu à imprimer ; si oui

//la méthode Print_Page sera relancée.

e.HasMorePages = (txtToPrint.Length > 0);

}

Ca y'est, dorénavant vous avez toutes les bases nécessaires pour implémenter l'impression dans vos applications.

[Windows Forms] Gérer un seul événement pour plusieurs contrôles

Lorsque de diverses formations que j'ai l'occasion d'animer, chaque fois que je traite le sujet des event handlers et le fait que ces handlers peuvent être connectés à plusieurs évènements, une question revient assez souvent : « Comment récupérer la valeur du contrôle qui a déclenché l'évènement ».

Ce billet apporte donc la réponse à cette question, en travaillant sur un projet de type Windows application.

Commençons par créer un projet de type Windows forms et ajoutons-y 2 contrôles, un combo et un button.

Afin d'intercepter l'évènement par défaut du combo à savoir le « SelectedIndexChanged, rajoutons quelques items à notre combo.

A présent, nous allons rajouter les événements par défaut de nos contrôles ; pour cela, double-cliquons sur notre combo et notre button, puis rajoutons une MessageBox nous informant quels sont les évènements interceptés.

   1:  private void comboBox1_SelectedIndexChanged(object sender, EventArgs e) {
   2:    MessageBox.Show("Evenement Combo");
   3:  }
   4:   
   5:  private void button1_Click(object sender, EventArgs e) {
   6:    MessageBox.Show("Evenement Button");
   7:  }

Rajoutons un 3ème handler qui intercepte le KeyPress.

Pour cela, commençons déjà par mettre la propriété KeyPreview à true au niveau de notre formulaire Form1, afin d'activer l'enregistrement des événements du clavier

Puis dans les évènements au niveau du formulaire, double-cliquons sur « KeyPress ».

Cette action crée un gestionnaire pour les évènements clavier « KeyPress » ; de même affichons l'évènement dans un MessageBox.

   1:  private void Form1_KeyPress(object sender, KeyPressEventArgs e)  {
   2:    MessageBox.Show("Evenement Clavier");
   3:  }

Jusqu'ici, pas de problème ; voici les différentes boites de dialogue que j'obtiens en cliquant respectivement sur mon combo, mon bouton et la touche espace :

 

Maintenant, implémentons un même gestionnaire pour tous ces événements ; dans votre code, rajoutez la méthode suivante :

   1:  private void TheSameEvent(object sender, EventArgs e) {
   2:    Type controlType = sender.GetType();
   3:    string control = controlType.ToString();
   4:    string eventType = e.GetType().ToString();
   5:              
   6:    MessageBox.Show(
   7:      string.Format("Evènement {0} déclenché par {1}", 
   8:      eventType, control));
   9:  }

Cette méthode possède la même signature que les méthodes précédentes, et nous utilisons ici les objets passés en paramètre pour récupérer notamment l'objet ayant déclenché l'évènement (le sender). Nous récupérons également le type du contrôle dans la variable controlType.

Pour le KeyPress, rajoutons ceci en plus :

   1:  private void TheSameEvent(object sender, KeyPressEventArgs e) {
   2:    TheSameEvent(sender, (EventArgs)e);
   3:  }

Il ne nous reste plus qu'à modifier dans la fenêtre des évènements le nom de notre méthode et d'y mentionner « TheSameEvent ».

Maintenant, si nous cliquons à nouveau respectivement sur mon combo, mon bouton et la touche espace, voici ce que j'obtiens :

 

Pour finir, si nous souhaitons par exemple travailler au niveau de notre button dans notre méthode commune, voici comment il faut procéder :

   1:  private void TheSameEvent(object sender, EventArgs e) {
   2:    Type controlType = sender.GetType();
   3:    string control = controlType.ToString();
   4:    string eventType = e.GetType().ToString();
   5:              
   6:    MessageBox.Show(
   7:      string.Format("Evènement {0} déclenché par {1}", 
   8:      eventType, control));
   9:              
  10:    switch (controlType.ToString().ToLower()) {
  11:      case "system.windows.forms.button": 
  12:        ((Button)sender).Text = "Clicked"; break;
  13:      case "system.windows.forms.combobox":
  14:        ((ComboBox)sender).Items.Add("a new item"); break;
  15:      case "coforcert.windowsforms.events.form1":
  16:        Label label = new Label();
  17:        label.Text = "un label à rajouter au moment du runtime";
  18:        ((Form)sender).Controls.Add(label); break;
  19:      default: break;
  20:  }

Et voici le résultat après avoir implémenté tous les évènements.

Vous pouvez également récupérer le projet final ici.

[WF] Que voulez vous analyser ?

Je viens de publier un article sur le suivi de workflow à l'aide du SQLTrackingService, qui nous simplifie grandement la vie !

Dans cet article, vous y verrez comment faire du tracking sur votre workflow, mais également comment le monitorer, à l'aide de l'object SQLTrackingQuery entre autre.

L'article est téléchargeable ici.

Bonne lecture.

[WF] Modifier un workflow en cours d’exécution.

WF fournit un certain nombre de fonctionnalités des plus surprenantes. Parmi celles-ci, celle que je vais vous présenter aujourd'hui concerne les modifications de vos workflow en cours d'exécution.

Une fois votre workflow conçu, WF, vous donne encore la possibilité de modifier ce dernier en cours d'exécution, soit depuis l'application hôte hébergeant votre workflow, soit directement depuis le workflow lui-même.

Prenons un exemple de workflow tout simple ; nous allons exécuter une boucle While 10 fois, et dans cette boucle While, nous allons y positionner une CodeActivity qui sera chargée de rajouter une activité Delay à notre workflow en cours d'exécution.

RQ : Souvenez vous qu'une activité While ne peut contenir qu'un seul élément enfant ; étant donné que nous souhaitons rajouter une activité Delay à l'intérieur de notre boucle, il nous faut donc les encapsuler (notre activité Code et notre activité Delay) dans une activité Sequence.

Notre activité While va utiliser une condition de code que nous allons appeler EvaluateCondition qui va se charger de contrôler la valeur de notre variable i et éventuellement l'incrémenter :

int i = 0;

private void EvaluateCondition(object sender, ConditionalEventArgs e) {

if (i != 10) {

i++; e.Result = true;

}

else e.Result = false;

}

 

Notre activité Code quant à elle va implémenter notre modification de workflow via la méthode DoChanges :

private static bool FindDelayActivity(Activity delay) {

return (delay.Name == "delayActivity1");

}

private void DoChanges(object sender, EventArgs e){

//Nos Changements seront stockés dans un objet WorkflowChange

WorkflowChanges changes = new WorkflowChanges(this);

//On clone l'arborescence du workflow et on travaille sur le clone

WhileActivity whileActivity =

(WhileActivity)changes.TransientWorkflow.Activities["whileActivity1"];

SequenceActivity sequenceActivity =

(SequenceActivity)whileActivity.Activities["sequenceActivity1"];

DelayActivity delayActivity = new DelayActivity("delayActivity1");

if (sequenceActivity.Activities.Exists(FindDelayActivity))

sequenceActivity.Activities.Remove(sequenceActivity.Activities["delayActivity1"]);

sequenceActivity.Activities.Add(delayActivity);

delayActivity.TimeoutDuration = new TimeSpan(0, 0, i);

//Une fois nos changements effectués, on lance un processus de validation

ValidationErrorCollection errorCollection = changes.Validate();

if (errorCollection.Count != 0) {

Console.WriteLine("Les modifications ne peuvent être prise en compte car il y'a {0} erreurs.\nCorrigez d'abord les erreurs suivantes : ", errorCollection.Count);

foreach (ValidationError error in errorCollection) {

Console.WriteLine("* {0}", error.ErrorText);

}

}

else {

//Si tout s'est déroulé correctement, on applique nos changments à l'instance en cours.

this.ApplyWorkflowChanges(changes);

Console.WriteLine("Le prochain timeout va durer {0} secondes",

delayActivity.TimeoutDuration.Seconds);

}

}

 

Et voila !

Modification effectué !

Après validation des changements, les intervalles sont de plus en plus longs entre les divers appels à la console.

[WF] Quelles règles faut-il suivre ?

Je viens de publier un article sur WF (le 1er d'une longue série).

Cet article a pour but de présenter l'activité Policy et les RuleSets, ainsi que le chainage avant dans WF.

Vous verrez notamment comment une activité Policy peut avoir différentes sorties en fonction du paramétrage, et vous comprendrez le pourquoi de ces différences.

Cette activité Policy peut générer ce résultat…

…ou celui-ci.

Vous apprendrez également à utiliser le concepteur pour contrôler ce que doit faire votre Policy.

Contrôler le chainage avant en 2 étapes.

Bonne Lecture !