Avatar billede kkaen Nybegynder
03. juli 2008 - 15:35 Der er 35 kommentarer og
1 løsning

Køre et program inde i Windows Presentation Foundation

I VS2008 vil jeg gerne lave en WPF-applikation, som har et andet program kørende inde i sig, som derved kan presentere brugeren for noget GUI.
Selve WPF-applikationen kan jeg godt få frem, men det at hoste en anden applikation indeni har jeg nogle problemer med.
Jeg har fundet nogle muligheder og vejledninger:

muligheder:
-Windows Forms WebBrowser control
-DSO framer control
-activeX control to host application

http://www.ddj.com/windows/197003872?pgno=5

Walkthrough: Hosting an ActiveX Control in Windows Presentation Foundation:
http://msdn.microsoft.com/en-us/library/ms742735.aspx

men jeg kan ikke rigtig få nogle af dem til at virke. Er det muligt, at nogle herinde kan gennemskue løsningen?
Avatar billede kkaen Nybegynder
10. juli 2008 - 13:16 #1
Nu har jeg fået selve renderingen til at virke i en WindowsForm, som er lavet i et projekt for sig selv. Nu skal jeg gerne have vist den form/projekt inde i mit wpf-projekt.
Jeg har fundet nogle forskellige vejledninger online, men jeg kan ikke rigtig få dem til at virke. Hvordan får jeg importeret min WindowsForm i wpf, og efterfølgende vist det?
Avatar billede aaberg Nybegynder
10. juli 2008 - 13:26 #2
I WPF har du en Control som hedder WindowsFormHost. Den kan du bruge til at have Windows Forms Controls embedded i dit WPF projekt.

Jeg tror for øvrigt du ville have fået mange flere svar på dette spørgsmål, hvis du havde postet det i .NET kategorien.
Avatar billede kkaen Nybegynder
10. juli 2008 - 14:04 #3
Jeg tror/håber også, at det ville have givet flere svar under .NET-kategorien.
Tror du det er bedre, hvis jeg lukker dette spørgsmål, og genopretter det under den anden kategori?

Men jeg har sat en WindowsFormsHost-kontrol ind, men jeg kan ikke rigtig få den løsning til at virke. Jeg har forsøgt at sætte en "source" derpå, men en sådan findes ikke. Det er så her, hvor jeg har forsøgt, at følge diverse gennemgange online, men dette har heller ikke løst problemmet, da jeg ikke kan følge eksemplerne helt igennem, da jeg mangler nogle flere detaljerede trin i vejledningerne.
Men det er så dét, jeg håber på at kunne få her ;-)
Avatar billede aaberg Nybegynder
10. juli 2008 - 14:29 #4
I din XAML kode skriver du:

<my:WindowsFormsHost Height="100" Name="windowsFormsHost1" Width="200" xmlns:my="clr-namespace:System.Windows.Forms.Integration;assembly=WindowsFormsIntegration">
            <usc:UserControl1 x:Name="userControl1" xmlns:usc="clr-namespace:WpfApplication1" />
        </my:WindowsFormsHost>


Skrift UserControl1 ud med navnet på din Windows forms control, og skrift WpfApplication1 ud med namespacet på din Windows forms control.
Avatar billede kkaen Nybegynder
10. juli 2008 - 18:52 #5
Jeg er ikke sikker på, at jeg har eksporteret WindowsFormen rigtigt. Jeg har blot oprettet en reference til den genererede exe-fil i WindowsForm-applicationen.
Navnet på min WindowsForm er "form1". Namespacet skulle være rigtigt nok, med mindre man skal dot'e sig ind på det (?).

Her er hvad jeg har skrevet:

<my:WindowsFormsHost Height="100" Name="windowsFormsHost1" Width="200" xmlns:my="clr-namespace:System.Windows.Forms.Integration;assembly=WindowsFormsIntegration">
      <usc:form1 x:Name="form1" xmlns:usc="clr-namespace:WindowsFormsApplication1" />
</my:WindowsFormsHost>

Det giver kompileringsfejlene:
-"The type or namespace name 'form1' does not exist in the namespace 'WindowsFormsApplication1'(are you missing an assemblyreference?)"
-"The tag 'form1' does not exist in XML namespace 'clr-namespace:WindowsFormsApplication1'"
Avatar billede aaberg Nybegynder
11. juli 2008 - 08:34 #6
Nu prøvede jeg at gøre det samme som du gør, og jeg får samme problem. Jeg fandt dog en workarround. I xaml koden opretter du din WindowsFormsHost uden indhold:

<my:WindowsFormsHost Height="100" Name="windowsFormsHost1" Width="200" xmlns:my="clr-namespace:System.Windows.Forms.Integration;assembly=WindowsFormsIntegration">
</my:WindowsFormsHost>

I codebehind filen i konstruktøren opretter du referencen til projektet.
this.windowsFormsHost1.Child = new WindowsFormsApplication1.MyUserControl();

Men du kan ikke hoste en form i en WindowsFormsHost, kun controls. En form er jo et vindue i sig selv! Hvis du ønsker at åbne en form i et nyt vindue, gør du som du ville gøre i et WindowsForms program: myForm.Show();
Avatar billede kkaen Nybegynder
11. juli 2008 - 09:01 #7
Nu har jeg sat den nye kode ind, men det giver 2 fejl. Jeg har dog rettet den ene. Linien skulle blot ændres til:

this.windowsFormsHost1.Child = new WindowsFormsApplication1.Form1();

så giver højre side ikke fejl. Men venstre side peger ikke på noget korrekt. Den skriver: "The name 'windowFormHost1' does not exist in the current context".
Skal der står "my:" foran WindowsFormsHost-kontrollen i xaml'en?
Avatar billede kkaen Nybegynder
11. juli 2008 - 09:05 #8
Avatar billede aaberg Nybegynder
11. juli 2008 - 09:35 #9
Nu har jeg ikke nærlæst linkene du opgiver, men i det første link snakker de (så vidt jeg lige kan overskue) kun om Windows Forms Controls! Han embedder PropertyGrid kontrollen, som en er control. En form er jo et vindue, som kan minimeres og maksimeres og flyttes på osv, det kan man jo ikke uden videre embedde ind på et andet vindue, som man f.eks. ville embedde en tekstboks.

Uanset, nu har jeg testet det. Bruger jeg en control virker det fint. Bruger jeg en form, får jeg fejlmeddelelsen: "Den underordnede kontrollen kan ikke være et skjema på øverste nivå." Hvis du sætter dine klasser til at nedarve fra UserControl i stedet for Form, bør det virke.

Og, ja, der skal stå "my:" for WindowsFormsHost i XAML koden. "my:" kommer fra følgende namespace: xmlns:my="clr-namespace:System.Windows.Forms.Integration;assembly=WindowsFormsIntegration". Dette forteller at den skal se efter kontrollen i WindowsFormsIntegration namespacet i WindowsFormsIntegration assemblien. Hvis du copy/paster nedenstående kode ind i din XAML, bør det virke:

<my:WindowsFormsHost Height="100" Name="windowsFormsHost1" Width="200" xmlns:my="clr-namespace:System.Windows.Forms.Integration;assembly=WindowsFormsIntegration">
</my:WindowsFormsHost>

Sørg for at du staver navnet på kontrollen ens i XAML filen og Code behind filen.
Avatar billede aaberg Nybegynder
11. juli 2008 - 09:37 #10
Jeg kan lige tilføje, at jeg sidder med en norsk version af Windows, det er derfor fejlmeddelelsen jeg beskriver, er lidt mærkeligt skrevet :-)
Avatar billede kkaen Nybegynder
11. juli 2008 - 10:21 #11
Nu har jeg nedarvet fra "System.Windows.Forms.UserControl". Før var det "Window".
Men jeg får stadig samme fejl. Er det fordi, jeg benytter den forkerte metode i codebehind'en? Jeg benytter nemlig: private void Window_Loaded(object sender, RoutedEventArgs e)
Inde i metoden skriver jeg:
this.windowsFormsHost1.Child = new WindowsFormsApplication1.Form1();

Det er "windowsFormsHost1", den ikke kan finde. Jeg går ud fra, at "windowsFormsHost1" blot skal tages fra Name-taget i Window1.xaml's kode for <my:WindowsFormHost ...> ? (som du beskrev i "Sørg for at du staver navnet på kontrollen ens i XAML filen og Code behind filen.")
Avatar billede aaberg Nybegynder
11. juli 2008 - 10:59 #12
<<Nu har jeg nedarvet fra "System.Windows.Forms.UserControl". Før var det "Window".>>
Jeg går ud fra at du mener: "Før var det "Form""!? Der er ingen klasse i Windows Forms Frameworket som hedder Window. Window er en klasse i WPF frameworket. I dit WPF projekt skal alle vinduerne nedarve fra Window. I dit Windows forms projekt, skal alle UserControls nedarve fra UserControl (Hvor den før nedarvede fra Form).

Window_Loaded() metoden bør virke fint. Uanset hvilken metode du placere koden i, skal kompileren ikke komme med fejl, fejlen skal komme runtime hvis du placere den forkert. Men jeg kan ikke lige overskue hvad du gør forkert. Men jeg har lige flækket et lille meget simpelt testprojekt sammen, download det her:
http://www.aaberg.cc/TestWindowsFormsHost.zip

I dette projekt har jeg lagt WindowForms projektet og WPF projektet i samme solution. I stedet for at referere til exe-filen på Windows forms projektet, refererer jeg til projektet (Dette kan man kun gøre når de ligger i samme solution). Så virker det at gøre det hele direkte fra XAML filen.

Se om kan få det til at virke, og om du forstår det. Ellers bare spørger du bare. :-)
Avatar billede kkaen Nybegynder
11. juli 2008 - 12:50 #13
Du har ret i "Før var det "Form".
I min version er der dog ikke tale om en UserControl (jeg kan vist ikke engang oprette sådan en...?). Jeg benytter en Form, som skal vises i en WPF-app. Men er der mulighed for, at jeg kan oploade projekterne til din server, så du nøjagtig kan se, hvad jeg gør forkert?
Avatar billede aaberg Nybegynder
11. juli 2008 - 13:39 #14
Upload det på følgende link, og post linket til filen her.
http://zupload.com/

Jeg kan desværre ikke på en simpel måde give dig tilgang til min server.
Avatar billede kkaen Nybegynder
11. juli 2008 - 19:31 #15
Nu har jeg uploaded en 3-4 gange både i IE og Firefox, men jeg får ikke noget link bagefter. Findes der andre måder, hvorpå jeg kan uploade filen til dig?
Avatar billede kkaen Nybegynder
12. juli 2008 - 11:53 #16
Nu har jeg fundet et andet sted:

http://www.gratisupload.dk/show.php?fileId=13951

Jeg håber, at filerne virker. Ellers spørg her ;-)
Avatar billede kkaen Nybegynder
12. juli 2008 - 14:44 #17
Nu har jeg fundet ud af, hvordan man starter applikationen manuelt. Den åbnes bare i et nyt vindue, hvilket jo ikke er så interessant. En mulighed ud over "UserControl/Form"-løsningen kunne være, at benytte "HwndHost" til at hoste applikationen inde i wpf-vinduet. Men jeg kan ikke finde nogle eksempler, som forklarer fremgangsmåden detaljeret nok...?
Avatar billede aaberg Nybegynder
12. juli 2008 - 22:35 #18
I dit WPF projekt skal du fjerne referencen til en usercontrol inde i din WindowsFormsHost tag i XAML koden, så der bare står:

<my:WindowsFormsHost Height="100" Name="windowsFormsHost1" Width="200" xmlns:my="clr-namespace:System.Windows.Forms.Integration;assembly=WindowsFormsIntegration">
           
</my:WindowsFormsHost>

Og så skal du fjerne referencen til det eksterne namespace i toppen af XAML filen. Og så fandt jeg ud af at koden aldrig kommer til Window_Loaded() metoden, så jeg flyttede følgende kodelinje op i konstruktøren.
this.windowsFormsHost1.Child = new WindowsFormsApplication1.Form1();

Det virker dog stadig ikke, da man ikke kan hoste en form i en WindowsFormsHost kontrol, men så vil det virker med controls.

Hvorfor er det, at du er så ivrig for at bruge forme? Hvad er vitsen med det? Det er da mere logisk at bruge UserControls! Hvis du laver din form i det eksterne projekt om til en UserControl, da vil det virke.
Avatar billede kkaen Nybegynder
13. juli 2008 - 14:23 #19
Hvis det ikke virker i den form, det har nu, så må vi jo finde en anden løsning ;-)
(hvad med "HwndHost"? Den tror jeg har en reel change...)

Grunden til jeg gerne vil bruge forms er, at jeg har indtryk af, at det kun er forms, som kan hoste et activeX-objekt. Og activeX-objektet er nemlig hele humlen her (activeX-objektet står for at hoste en medieafspiller, som kan rendere en filtype, som Microsoft Mediaplayer ikke kan). Jeg har nogle dll-filer, som står for importen af activeX-delen. Jeg har prøvet at tilføje dll-filen i toolboxen i de forskellige projekttyper, men det er tilsyneladende kun i et forms-projekt, hvor der rent faktisk også kommer et ikon frem for funktionalitetten i toolboxen.
Inde i projektet er der en AxInterop.ANIMALib. Dette er vel et udtryk for, at det er kommunikation mellem 2 programmer. Derfor vil "HwndHost" igen være ideelt. Jeg ved ikke, om UserControls kan yde denne funktionalittet (?).

Da dette er et nyt område for mig, har jeg ikke den store viden om det. Så jeg er naturlilgvis åben for input og gode forslag ;-)
Avatar billede kkaen Nybegynder
13. juli 2008 - 19:08 #20
...udover ActiveX-løsningen, så har jeg også fundet:

-Windows Forms WebBrowser control
-DSO framer control

Men jeg har dog ikke sat mig ind i noget om de teknologier endnu.
Avatar billede aaberg Nybegynder
14. juli 2008 - 08:33 #21
Nu har jeg googlet lidt, og det ser ud som om at du kan embedde en ActiveX controls direkte i en WindowsFormsHost control i WPF. Se denne artikkel for et eksempel:
http://www.ddj.com/architect/197003872?pgno=7

Ellers har jeg set eksempler på det gjort i en WebBrowser control, som du også selv foreslår. Hvis du bruger windows handles (hwnd) for at embedde en form i en anden form, bliver du nød til at bruge pinvoke laget i .NET, og dette bliver hurtigt indviklet. Jeg tror også, at så længe du bruger forme, vil du kunne flytte rundt på din child form selv om den er embedded i en parent, lidt ligesom MDI (Jeg ved ikke om man kan overstyre dette).
Avatar billede kkaen Nybegynder
14. juli 2008 - 10:08 #22
Det er 1 af de artikler, som jeg har prøvet at følge. Hvis jeg har forstået det rigtigt, så giver denne artikkel udtryk for, at man kan vise outputtet fra en activeX-fil direkte i WPF; altså behøver man IKKE, at hoste activeX'en i en form, for så at importere formen i WPF?
Modsat viser denne artikkel, at man SKAL benytte en form.
Avatar billede aaberg Nybegynder
14. juli 2008 - 11:25 #23
Nu har jeg prøvet at følge eksemplet, og jeg får det til at virke uden problemer, og uden at bruge en Form. Jeg skal uploade et projekt lidt senere i dag, hvor det virker.
Avatar billede kkaen Nybegynder
14. juli 2008 - 11:30 #24
Ah, dejligt. Mange tak ;-)
Avatar billede aaberg Nybegynder
14. juli 2008 - 12:31 #25
http://www.aaberg.cc/ActiveXInWPF.zip

I eksemplet embedder jeg Windows Media Player activeX kontrollen. Det eneste der er lidt tricky, er at oprette referencer til activeX kontrollen. Jeg brugte følgende opskrift:

1. Højreklik et sted på toolboxen og tryk "Choose items...". Under "COM components", vælg activeX kontrollen og tryk "OK".
2. Opret en Windows Forms UserControl(eller Form :-))
3. Fra toolboksen, drag/drop activeX kontrollen ind på UserControl'en (eller formen). Nu bliver alle nødvendige referencer oprettet.
4. Slet UserControl'en (eller formen).
Avatar billede kkaen Nybegynder
15. juli 2008 - 10:04 #26
Det ser jo "let og lige til" ud.
Jeg har dog problemer med at opnå det samme i mit eget projekt. Jeg har oprettet et helt nyt projekt, hvor jeg har højreklikket på toolboxen, og valgt den aktuelle activeX-control (her fandt jeg også UserControllen, så nu er dét mysterium løst). Så trykker jeg på "ok", men så kommer der ikke noget ikon for controllen frem i toolboxen. Jeg har prøvet at genstarte VS, men dette ændrede ikke på det.
Så hvordan kan jeg tvinge API'et til at vise ikonet? Og hvorfor kommer det ikke automatisk frem, som jeg ber den om?
Avatar billede aaberg Nybegynder
15. juli 2008 - 10:08 #27
Den kommer kun frem i toolboxen hvis du har en Windows Forms UserControl eller Form åben. Den kommer ikke frem i toolboxen hvis du har et WPF vindue eller UserControl åben.
Avatar billede kkaen Nybegynder
15. juli 2008 - 11:05 #28
Åh ja.
Men når jeg studerer dit projekt, så ser det ud som om, at det er et WPF-projekt. Men du opretter kontrollen deri alligevel. Er det bare fordi, selve ikonet ikke kommer frem i toolboxen, at man kan komme om ved problemet således?

Jeg har lavet et nyt namespace, som indeholder 2 projekter. Et FORMprojekt og et WPFprojekt. I formen har jeg fulgt din vejledning om oprettelse af activeX-kontrollen. Denne form (selve formen er slettet som du har beskrevet i vejledningen) skal så vises i wpf-projektet. Men her har jeg problemer med initialiseringen.
Jeg har oprettet en reference til FORMprojektet, og prøver så at initialisere der fra.
Dette er hvad jeg har forsøgt:

public partial class Window1 : Window
{
    WindowsFormsFinally.Form1 formen;
    public Window1()
    {
        InitializeComponent();
        formen = new WindowsFormsFinally.Form1();
        this.windowsFormsHost1.Child = formen;//linien fra dit eksempel
    }
}

Men det virker ikke. Jeg tror, jeg har mistet overblikket...?
Avatar billede aaberg Nybegynder
15. juli 2008 - 11:49 #29
Ikke opret 2 projekter! Opret èt WPF projekt. På Solution Exploreren højreklikker du på projektet, og trykker "Add" og "New Item...". Nu får du en liste over "Visual Studio Installed Templates". Her vælger du en "Windows Form" eller en "User Control" (Ikke den der hedder "User Control (WPF)"). Nu kan du tilføje ActiveX kontrollen til toolboxen og drag/droppe den ind på den netop oprettede UserControl eller Form. Når du gør dette, bliver alle nødvendige referencer til ActiveX kontrollen automatisk oprettet. Derefter kan du slette din Form/UserControl igen. Dette kan godt gøres uden at tilføje/fjerne en Widnows Forms control, men så bliver du nød til at bruge nogle kommandolinje værktøjer. Da synes jeg alligevel dette er nemmere (Selvom det er lidt af en work arround).

Nu har du et WPF projekt med et par ekstra referencer i "References" mappen. Når jeg gør dette med Windows Media Player, får jeg 2 ekstra referencer som hedder "AxMSTSCLib" og "MSTSCLib". Du kan se disse referencer ved at folde ud "References" i Solution Exploreren.

I dit WPF vindue (Window1.xaml) tilføjer du en WindowsFormsHost control. Brug drag/drop fra toolboxen frem for at redigere i xaml koden direkte, fordi designeren da automatisk tilføjer referencer til System.Windows.Forms og System.Windows.Forms.Integration.

Højreklik et sted på WPF vinduet i designeren, og tryk "View Code". I konstruktøren tilføjer du kode til at sætte Child Propertien på WindowsFormsHost kontrollen:
public Window1()
{
    this.windowsFormsHost1.Child = new AxWMPLib.AxWindowsMediaPlayer();
}

Og så skal det virke.
Avatar billede kkaen Nybegynder
15. juli 2008 - 13:13 #30
Det var dejlig med en skridt-for-skridt forklaring. Det påskønner jeg.

Jeg har dog stadig nogle problemer med projektet. Jeg fik det først til at virke, men blev i tvivl om jeg havde gjort det korrekt, da der stod "Form1" i titellinien på det ekserkverede (prøvede først med UserControl, men dette virkede slet ikke). Derfor lavede jeg det forfra. Og nu ender jeg hver gang med:

"Unable to get the window handle for the 'AxAnima' control. Windowless ActiveX controls are not supported."

Og jeg har implementeret referencer til renderingsobjektet som i det formprojekt, hvor jeg har fået det til at virke i.

Jeg har uploaded det seneste projekt til:
http://www.gratisupload.dk/show.php?fileId=14030

Har jeg overset noget et sted? (ja, det har jeg vel)
Er det fordi, jeg sletter WindowsFormen efter activeX-objektet er tilføjet, og der dermed kommer nogle referencer, som ikke peger på noget?
Avatar billede aaberg Nybegynder
15. juli 2008 - 13:30 #31
Det lyder ikke som om din ActiveX kontrol har et brugergrænsesnit! Prøv først at få det til at virke med Windows Media Player, den har vi jo set virker. Gør derefter det samme med AxAnima.

Hvad er det for en ActiveX kontrol. Er den tilgængelig på internettet et sted?
Avatar billede kkaen Nybegynder
15. juli 2008 - 16:29 #32
Som det står her, så burde den kunne inkluderes i et .Net-projekt:

http://www.octaga.com/community/viewtopic.php?f=2&t=11

Den kan også downloades fra det site.
Avatar billede aaberg Nybegynder
15. juli 2008 - 22:28 #33
Nu har jeg lavet et eksempel med Octaga playeren. Er det den kontrol du mener? Så vidt jeg kan se, er dere flere ting man kan downloade fra siden.

http://www.aaberg.cc/WpfFinallyX3d.zip
Avatar billede kkaen Nybegynder
16. juli 2008 - 09:44 #34
Wau, tak!
Det var lige dét, jeg var interesseret i. Så vidt jeg kan se, så er humlen, at der kaldes den rigtige metode på Octage-objektet. Og den metode kendte jeg ikke. Når den benyttes, så virker projektet udfra de indstillinger, som du hele tiden har angivet. Har du fundet en oversigt over octage-frameworket inde på sitet? Er det dét, du primært mener, når du siger, at man kan downloade en masse ting inde fra sitet (udover diverse software)?

Jeg kunne nu godt tænke mig, at få noget mere indsigt i de andre valgmuligheder, jeg også nævnte:
-Windows Forms WebBrowser control
-DSO framer control
Men det må jeg jo nok tage i et andet spørgsmål.

Lægger du lige et svar, så du kan få nogle point?
Avatar billede aaberg Nybegynder
16. juli 2008 - 10:45 #35
Det jeg mente med at man kan downloade flere ting fra octaga websiden er, at jeg ser de har flere produkter (Player, Professional, Enterprise, Panorama, Exporter, Modeller). Men jeg er glad for at vi fik det til at virke nu :-)

en "DSO framer control" ved jeg ikke hvad er. En Windows Form WebBrowser control er egentlig bare internet exploren embedded i din applikation. For at få en ActiveX control til at vises i internet exploren, angiver man et <object> tag i html koden. Jeg husker ikke den præcise syntax, men det er ikke inviklet, og der findes masse dokumentation om det på nettet.
Avatar billede kkaen Nybegynder
16. juli 2008 - 12:11 #36
Cool - tak for det ;-)
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester