2009-06-17 6 views
0

Voici mon XAMLDans WPF, comment pouvez-vous dessiner une ligne sur un WindowsFormsHost?

<Grid 
    Name="grid"> 
    <TextBlock 
     Text="Some Label" /> 
    <WindowsFormsHost 
     Name="winFormsHost"> 

    </WindowsFormsHost> 
</Grid> 

Sur la charge de la forme que j'exécute la méthode suivante

protected void OnLoad(object sender, RoutedEventArgs e) 
{ 
    // Create a line on the fly 
    Line line = new Line(); 

    line.Stroke = Brushes.Red; 
    line.StrokeThickness = 17; 

    line.X1 = 50; 
    line.Y1 = 50; 

    line.X2 = 250; 
    line.Y2 = 50; 

    this.grid.Children.Add(line); 

    System.Windows.Forms.TextBox oldSchoolTextbox = new System.Windows.Forms.TextBox(); 
    oldSchoolTextbox.Text = "A bunch of Random Text will follow. "; 
    oldSchoolTextbox.WordWrap = true; 
    oldSchoolTextbox.Width = 300; 

    for (int i = 0; i < 250; i++) 
    { 
     oldSchoolTextbox.Text += "abc "; 

     if (i % 10 == 0) 
     { 
      oldSchoolTextbox.Text += Environment.NewLine; 
     } 
    } 

    this.winFormsHost.Child = oldSchoolTextbox; 
} 

La ligne ne tire que lorsque je commente la ligne suivante.

this.winFormsHost.Child = oldSchoolTextbox; 

Comment dessiner une ligne sur le contrôle WindowsFormsHost?

Répondre

4

Il y a quelque chose Microsoft a appelé « l'espace aérien » qui empêche que cela se produise, au moins facilement. Voici le WPF Interop page describing airspace. [Il a un focus DX, mais la même chose s'applique exactement à WindowsFormsHost.]

WindowsFormsHost (lorsqu'il a un enfant) crée un HWND distinct, ce qui empêche l'affichage du contexte de rendu WPF dans ce rectangle.

La meilleure option pour contourner cela nécessite 3.5sp1 .NET (au moins pour fonctionner de manière fiable). Vous pouvez contourner ce problème en créant une fenêtre d'arrière-plan entièrement distincte, 100% transparente, et en la plaçant au-dessus du contrôle de l'hôte des formulaires Windows. Vous dessinez ensuite dans cela, et il s'affichera correctement.

Il se sent un peu hacky, mais il fonctionne.

+0

C'est un peu hacky mais ça va marcher. Merci beaucoup! –

+0

note que ce chemin va (dans la plupart des cas) forcer la synchronisation à l'emplacement de la fenêtre - manipuler onDrag onResize etc. – Li3ro

0

La réponse acceptée ne fonctionne pas. Cependant, le seul problème est que la fenêtre transparente serait affichée sur ma fenêtre principale. Je devais également me brancher sur le mouvement pour m'assurer que tout restait synchronisé.

j'ai fait quelque chose de légèrement différent qu'une fenêtre transparente. Cela a fonctionné dans mon cas, mais peut ne pas toujours fonctionner.

J'ai créé un contrôle utilisateur Windows Form. Je mets la zone de texte et le dessin au trait sur le contrôle utilisateur du formulaire Windows. Cela m'a ensuite permis de dessiner dessus et de l'afficher dans une application WPF en utilisant WindowsFormsHost.

2

J'ai eu le même problème, et après avoir cherché dans tout aussi fini par utiliser la fenêtre « overlay » transparente sur le dessus du WindowsFormsHost. Pour garder votre fenêtre principale synchronisé avec la fenêtre de recouvrement vous devez gérer les événements suivants:

événement LocationChanged pour votre MainWindow et événement LayoutUpdated pour votre élément WindowsFormsHost. Ces deux gestionnaires d'événements doivent appeler une fonction qui déplace votre fenêtre de recouvrement transparente au-dessus de la fenêtre WindowsFormsHost (SyncOverlayPosition() dans l'exemple ci-dessous).

private void Window_Loaded(object sender, RoutedEventArgs e) 
{ 
    this.LocationChanged += new EventHandler(MainWindow_LocationChanged); 
    _windowsFormsHost.LayoutUpdated += new EventHandler(_windowsFormsHost_LayoutUpdated); 
} 

void MainWindow_LocationChanged(object sender, EventArgs e) 
{ 
    SyncOverlayPosition(); 
} 

void _windowsFormsHost_LayoutUpdated(object sender, EventArgs e) 
{ 
    SyncOverlayPosition(); 
} 

void SyncOverlayPosition() 
{ 
    Point hostTopLeft = _windowsFormsHost.PointToScreen(new Point(0, 0));  

    _overlayWindow.Left = hostTopLeft.X; 
    _overlayWindow.Top = hostTopLeft.Y; 
    _overlayWindow.Width = _windowsFormsHost.ActualWidth; 
    _overlayWindow.Height = _windowsFormsHost.ActualHeight; 
} 
Questions connexes