From b89d334147c609472103baa3bd25ac3ee00e9627 Mon Sep 17 00:00:00 2001 From: Nikita Tsukanov Date: Tue, 23 Aug 2016 01:30:06 +0300 Subject: [PATCH] Implemented embedding to WPF and WinForms --- Avalonia.sln | 46 +++++ samples/ControlCatalog/ControlCatalog.csproj | 12 +- .../ControlCatalog/ControlCatalogControl.xaml | 24 +++ .../ControlCatalogControl.xaml.cs | 19 ++ samples/ControlCatalog/MainWindow.xaml | 28 +-- samples/interop/WindowsInteropTest/App.config | 6 + .../EmbedToWinFormsDemo.Designer.cs | 119 +++++++++++ .../WindowsInteropTest/EmbedToWinFormsDemo.cs | 26 +++ .../EmbedToWinFormsDemo.resx | 120 +++++++++++ .../WindowsInteropTest/EmbedToWpfDemo.xaml | 21 ++ .../WindowsInteropTest/EmbedToWpfDemo.xaml.cs | 31 +++ samples/interop/WindowsInteropTest/Program.cs | 22 +++ .../Properties/AssemblyInfo.cs | 36 ++++ .../Properties/Resources.Designer.cs | 71 +++++++ .../Properties/Resources.resx | 117 +++++++++++ .../Properties/Settings.Designer.cs | 30 +++ .../Properties/Settings.settings | 7 + .../SelectorForm.Designer.cs | 76 +++++++ .../WindowsInteropTest/SelectorForm.cs | 30 +++ .../WindowsInteropTest/SelectorForm.resx | 120 +++++++++++ .../WindowsInteropTest.csproj | 186 ++++++++++++++++++ .../Avalonia.Controls.csproj | 1 + src/Avalonia.Controls/EmbeddableControl.cs | 66 +++++++ .../Platform/PlatformManager.cs | 8 + .../Avalonia.Themes.Default.csproj | 5 + src/Avalonia.Themes.Default/DefaultTheme.xaml | 1 + .../EmbeddableControl.xaml | 17 ++ .../Avalonia.Win32/Avalonia.Win32.csproj | 9 + .../Embedding/EmbeddedWindowImpl.cs | 4 +- .../Embedding/WinFormsAvaloniaControlHost.cs | 63 ++++++ .../Embedding/WpfAvaloniaControlHost.cs | 52 +++++ .../Avalonia.Win32/Input/KeyInterop.cs | 2 +- .../Input/WindowsKeyboardDevice.cs | 2 +- .../Input/WindowsMouseDevice.cs | 2 +- .../Interop/UnmanagedMethods.cs | 3 +- .../Avalonia.Win32/PlatformConstants.cs | 2 +- src/Windows/Avalonia.Win32/PopupImpl.cs | 2 +- src/Windows/Avalonia.Win32/Win32Platform.cs | 2 +- src/Windows/Avalonia.Win32/WindowImpl.cs | 2 +- 39 files changed, 1356 insertions(+), 34 deletions(-) create mode 100644 samples/ControlCatalog/ControlCatalogControl.xaml create mode 100644 samples/ControlCatalog/ControlCatalogControl.xaml.cs create mode 100644 samples/interop/WindowsInteropTest/App.config create mode 100644 samples/interop/WindowsInteropTest/EmbedToWinFormsDemo.Designer.cs create mode 100644 samples/interop/WindowsInteropTest/EmbedToWinFormsDemo.cs create mode 100644 samples/interop/WindowsInteropTest/EmbedToWinFormsDemo.resx create mode 100644 samples/interop/WindowsInteropTest/EmbedToWpfDemo.xaml create mode 100644 samples/interop/WindowsInteropTest/EmbedToWpfDemo.xaml.cs create mode 100644 samples/interop/WindowsInteropTest/Program.cs create mode 100644 samples/interop/WindowsInteropTest/Properties/AssemblyInfo.cs create mode 100644 samples/interop/WindowsInteropTest/Properties/Resources.Designer.cs create mode 100644 samples/interop/WindowsInteropTest/Properties/Resources.resx create mode 100644 samples/interop/WindowsInteropTest/Properties/Settings.Designer.cs create mode 100644 samples/interop/WindowsInteropTest/Properties/Settings.settings create mode 100644 samples/interop/WindowsInteropTest/SelectorForm.Designer.cs create mode 100644 samples/interop/WindowsInteropTest/SelectorForm.cs create mode 100644 samples/interop/WindowsInteropTest/SelectorForm.resx create mode 100644 samples/interop/WindowsInteropTest/WindowsInteropTest.csproj create mode 100644 src/Avalonia.Controls/EmbeddableControl.cs create mode 100644 src/Avalonia.Themes.Default/EmbeddableControl.xaml create mode 100644 src/Windows/Avalonia.Win32/Embedding/WinFormsAvaloniaControlHost.cs create mode 100644 src/Windows/Avalonia.Win32/Embedding/WpfAvaloniaControlHost.cs diff --git a/Avalonia.sln b/Avalonia.sln index a67f75991a..abbeeab2fa 100644 --- a/Avalonia.sln +++ b/Avalonia.sln @@ -163,6 +163,10 @@ Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Avalonia.RenderTests", "tes EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VirtualizationTest", "samples\VirtualizationTest\VirtualizationTest.csproj", "{FBCAF3D0-2808-4934-8E96-3F607594517B}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Interop", "Interop", "{A0CC0258-D18C-4AB3-854F-7101680FC3F9}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WindowsInteropTest", "samples\interop\WindowsInteropTest\WindowsInteropTest.csproj", "{C7A69145-60B6-4882-97D6-A3921DD43978}" +EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution src\Skia\Avalonia.Skia\Avalonia.Skia.projitems*{2f59f3d0-748d-4652-b01e-e0d954756308}*SharedItemsImports = 13 @@ -2242,6 +2246,46 @@ Global {FBCAF3D0-2808-4934-8E96-3F607594517B}.Release|Mono.Build.0 = Release|Any CPU {FBCAF3D0-2808-4934-8E96-3F607594517B}.Release|x86.ActiveCfg = Release|Any CPU {FBCAF3D0-2808-4934-8E96-3F607594517B}.Release|x86.Build.0 = Release|Any CPU + {C7A69145-60B6-4882-97D6-A3921DD43978}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU + {C7A69145-60B6-4882-97D6-A3921DD43978}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU + {C7A69145-60B6-4882-97D6-A3921DD43978}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU + {C7A69145-60B6-4882-97D6-A3921DD43978}.Ad-Hoc|iPhone.Build.0 = Release|Any CPU + {C7A69145-60B6-4882-97D6-A3921DD43978}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU + {C7A69145-60B6-4882-97D6-A3921DD43978}.Ad-Hoc|iPhoneSimulator.Build.0 = Release|Any CPU + {C7A69145-60B6-4882-97D6-A3921DD43978}.Ad-Hoc|Mono.ActiveCfg = Release|Any CPU + {C7A69145-60B6-4882-97D6-A3921DD43978}.Ad-Hoc|Mono.Build.0 = Release|Any CPU + {C7A69145-60B6-4882-97D6-A3921DD43978}.Ad-Hoc|x86.ActiveCfg = Release|Any CPU + {C7A69145-60B6-4882-97D6-A3921DD43978}.Ad-Hoc|x86.Build.0 = Release|Any CPU + {C7A69145-60B6-4882-97D6-A3921DD43978}.AppStore|Any CPU.ActiveCfg = Release|Any CPU + {C7A69145-60B6-4882-97D6-A3921DD43978}.AppStore|Any CPU.Build.0 = Release|Any CPU + {C7A69145-60B6-4882-97D6-A3921DD43978}.AppStore|iPhone.ActiveCfg = Release|Any CPU + {C7A69145-60B6-4882-97D6-A3921DD43978}.AppStore|iPhone.Build.0 = Release|Any CPU + {C7A69145-60B6-4882-97D6-A3921DD43978}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU + {C7A69145-60B6-4882-97D6-A3921DD43978}.AppStore|iPhoneSimulator.Build.0 = Release|Any CPU + {C7A69145-60B6-4882-97D6-A3921DD43978}.AppStore|Mono.ActiveCfg = Release|Any CPU + {C7A69145-60B6-4882-97D6-A3921DD43978}.AppStore|Mono.Build.0 = Release|Any CPU + {C7A69145-60B6-4882-97D6-A3921DD43978}.AppStore|x86.ActiveCfg = Release|Any CPU + {C7A69145-60B6-4882-97D6-A3921DD43978}.AppStore|x86.Build.0 = Release|Any CPU + {C7A69145-60B6-4882-97D6-A3921DD43978}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C7A69145-60B6-4882-97D6-A3921DD43978}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C7A69145-60B6-4882-97D6-A3921DD43978}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {C7A69145-60B6-4882-97D6-A3921DD43978}.Debug|iPhone.Build.0 = Debug|Any CPU + {C7A69145-60B6-4882-97D6-A3921DD43978}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {C7A69145-60B6-4882-97D6-A3921DD43978}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {C7A69145-60B6-4882-97D6-A3921DD43978}.Debug|Mono.ActiveCfg = Debug|Any CPU + {C7A69145-60B6-4882-97D6-A3921DD43978}.Debug|Mono.Build.0 = Debug|Any CPU + {C7A69145-60B6-4882-97D6-A3921DD43978}.Debug|x86.ActiveCfg = Debug|Any CPU + {C7A69145-60B6-4882-97D6-A3921DD43978}.Debug|x86.Build.0 = Debug|Any CPU + {C7A69145-60B6-4882-97D6-A3921DD43978}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C7A69145-60B6-4882-97D6-A3921DD43978}.Release|Any CPU.Build.0 = Release|Any CPU + {C7A69145-60B6-4882-97D6-A3921DD43978}.Release|iPhone.ActiveCfg = Release|Any CPU + {C7A69145-60B6-4882-97D6-A3921DD43978}.Release|iPhone.Build.0 = Release|Any CPU + {C7A69145-60B6-4882-97D6-A3921DD43978}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {C7A69145-60B6-4882-97D6-A3921DD43978}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {C7A69145-60B6-4882-97D6-A3921DD43978}.Release|Mono.ActiveCfg = Release|Any CPU + {C7A69145-60B6-4882-97D6-A3921DD43978}.Release|Mono.Build.0 = Release|Any CPU + {C7A69145-60B6-4882-97D6-A3921DD43978}.Release|x86.ActiveCfg = Release|Any CPU + {C7A69145-60B6-4882-97D6-A3921DD43978}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -2294,5 +2338,7 @@ Global {F1381F98-4D24-409A-A6C5-1C5B1E08BB08} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B} {48840EDD-24BF-495D-911E-2EB12AE75D3B} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B} {FBCAF3D0-2808-4934-8E96-3F607594517B} = {9B9E3891-2366-4253-A952-D08BCEB71098} + {A0CC0258-D18C-4AB3-854F-7101680FC3F9} = {9B9E3891-2366-4253-A952-D08BCEB71098} + {C7A69145-60B6-4882-97D6-A3921DD43978} = {A0CC0258-D18C-4AB3-854F-7101680FC3F9} EndGlobalSection EndGlobal diff --git a/samples/ControlCatalog/ControlCatalog.csproj b/samples/ControlCatalog/ControlCatalog.csproj index daa8b0901a..7761d792ad 100644 --- a/samples/ControlCatalog/ControlCatalog.csproj +++ b/samples/ControlCatalog/ControlCatalog.csproj @@ -38,7 +38,7 @@ Designer - + Designer @@ -88,6 +88,9 @@ App.xaml + + ControlCatalogControl.xaml + MainWindow.xaml @@ -215,6 +218,13 @@ Designer + + + MSBuild:Compile + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/samples/interop/WindowsInteropTest/EmbedToWpfDemo.xaml b/samples/interop/WindowsInteropTest/EmbedToWpfDemo.xaml new file mode 100644 index 0000000000..1115cf5768 --- /dev/null +++ b/samples/interop/WindowsInteropTest/EmbedToWpfDemo.xaml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + diff --git a/samples/interop/WindowsInteropTest/EmbedToWpfDemo.xaml.cs b/samples/interop/WindowsInteropTest/EmbedToWpfDemo.xaml.cs new file mode 100644 index 0000000000..75d6f4f5d2 --- /dev/null +++ b/samples/interop/WindowsInteropTest/EmbedToWpfDemo.xaml.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; +using Avalonia.Controls; +using ControlCatalog; +using Window = System.Windows.Window; + +namespace WindowsInteropTest +{ + /// + /// Interaction logic for EmbedToWpfDemo.xaml + /// + public partial class EmbedToWpfDemo : Window + { + public EmbedToWpfDemo() + { + InitializeComponent(); + Host.Child = new EmbeddableControl {Content = new ControlCatalogControl()}; + } + } +} diff --git a/samples/interop/WindowsInteropTest/Program.cs b/samples/interop/WindowsInteropTest/Program.cs new file mode 100644 index 0000000000..4770688ecf --- /dev/null +++ b/samples/interop/WindowsInteropTest/Program.cs @@ -0,0 +1,22 @@ +using System; +using Avalonia.Controls; +using ControlCatalog; +using Avalonia; + +namespace WindowsInteropTest +{ + static class Program + { + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main() + { + System.Windows.Forms.Application.EnableVisualStyles(); + System.Windows.Forms.Application.SetCompatibleTextRenderingDefault(false); + AppBuilder.Configure().UseWin32().UseSkia().SetupWithoutStarting(); + System.Windows.Forms.Application.Run(new SelectorForm()); + } + } +} diff --git a/samples/interop/WindowsInteropTest/Properties/AssemblyInfo.cs b/samples/interop/WindowsInteropTest/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..087fdfe991 --- /dev/null +++ b/samples/interop/WindowsInteropTest/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("WindowsInteropTest")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("WindowsInteropTest")] +[assembly: AssemblyCopyright("Copyright © 2016")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("c7a69145-60b6-4882-97d6-a3921dd43978")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/samples/interop/WindowsInteropTest/Properties/Resources.Designer.cs b/samples/interop/WindowsInteropTest/Properties/Resources.Designer.cs new file mode 100644 index 0000000000..c3223efc62 --- /dev/null +++ b/samples/interop/WindowsInteropTest/Properties/Resources.Designer.cs @@ -0,0 +1,71 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace WindowsInteropTest.Properties +{ + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources + { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() + { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager + { + get + { + if ((resourceMan == null)) + { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("WindowsInteropTest.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture + { + get + { + return resourceCulture; + } + set + { + resourceCulture = value; + } + } + } +} diff --git a/samples/interop/WindowsInteropTest/Properties/Resources.resx b/samples/interop/WindowsInteropTest/Properties/Resources.resx new file mode 100644 index 0000000000..af7dbebbac --- /dev/null +++ b/samples/interop/WindowsInteropTest/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/samples/interop/WindowsInteropTest/Properties/Settings.Designer.cs b/samples/interop/WindowsInteropTest/Properties/Settings.Designer.cs new file mode 100644 index 0000000000..4b768fb74f --- /dev/null +++ b/samples/interop/WindowsInteropTest/Properties/Settings.Designer.cs @@ -0,0 +1,30 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace WindowsInteropTest.Properties +{ + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase + { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default + { + get + { + return defaultInstance; + } + } + } +} diff --git a/samples/interop/WindowsInteropTest/Properties/Settings.settings b/samples/interop/WindowsInteropTest/Properties/Settings.settings new file mode 100644 index 0000000000..39645652af --- /dev/null +++ b/samples/interop/WindowsInteropTest/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/samples/interop/WindowsInteropTest/SelectorForm.Designer.cs b/samples/interop/WindowsInteropTest/SelectorForm.Designer.cs new file mode 100644 index 0000000000..7cf402913e --- /dev/null +++ b/samples/interop/WindowsInteropTest/SelectorForm.Designer.cs @@ -0,0 +1,76 @@ +namespace WindowsInteropTest +{ + partial class SelectorForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.btnEmbedToWinForms = new System.Windows.Forms.Button(); + this.btnEmbedToWpf = new System.Windows.Forms.Button(); + this.SuspendLayout(); + // + // btnEmbedToWinForms + // + this.btnEmbedToWinForms.Location = new System.Drawing.Point(12, 12); + this.btnEmbedToWinForms.Name = "btnEmbedToWinForms"; + this.btnEmbedToWinForms.Size = new System.Drawing.Size(201, 86); + this.btnEmbedToWinForms.TabIndex = 0; + this.btnEmbedToWinForms.Text = "Embed to WinForms"; + this.btnEmbedToWinForms.UseVisualStyleBackColor = true; + this.btnEmbedToWinForms.Click += new System.EventHandler(this.btnEmbedToWinForms_Click); + // + // btnEmbedToWpf + // + this.btnEmbedToWpf.Location = new System.Drawing.Point(219, 12); + this.btnEmbedToWpf.Name = "btnEmbedToWpf"; + this.btnEmbedToWpf.Size = new System.Drawing.Size(201, 86); + this.btnEmbedToWpf.TabIndex = 1; + this.btnEmbedToWpf.Text = "Embed to WPF"; + this.btnEmbedToWpf.UseVisualStyleBackColor = true; + this.btnEmbedToWpf.Click += new System.EventHandler(this.btnEmbedToWpf_Click); + // + // SelectorForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(432, 284); + this.Controls.Add(this.btnEmbedToWpf); + this.Controls.Add(this.btnEmbedToWinForms); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.MaximizeBox = false; + this.Name = "SelectorForm"; + this.Text = "Interop"; + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.Button btnEmbedToWinForms; + private System.Windows.Forms.Button btnEmbedToWpf; + } +} + diff --git a/samples/interop/WindowsInteropTest/SelectorForm.cs b/samples/interop/WindowsInteropTest/SelectorForm.cs new file mode 100644 index 0000000000..6430694f79 --- /dev/null +++ b/samples/interop/WindowsInteropTest/SelectorForm.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace WindowsInteropTest +{ + public partial class SelectorForm : Form + { + public SelectorForm() + { + InitializeComponent(); + } + + private void btnEmbedToWinForms_Click(object sender, EventArgs e) + { + new EmbedToWinFormsDemo().ShowDialog(this); + } + + private void btnEmbedToWpf_Click(object sender, EventArgs e) + { + new EmbedToWpfDemo().ShowDialog(); + } + } +} diff --git a/samples/interop/WindowsInteropTest/SelectorForm.resx b/samples/interop/WindowsInteropTest/SelectorForm.resx new file mode 100644 index 0000000000..1af7de150c --- /dev/null +++ b/samples/interop/WindowsInteropTest/SelectorForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/samples/interop/WindowsInteropTest/WindowsInteropTest.csproj b/samples/interop/WindowsInteropTest/WindowsInteropTest.csproj new file mode 100644 index 0000000000..24f090a545 --- /dev/null +++ b/samples/interop/WindowsInteropTest/WindowsInteropTest.csproj @@ -0,0 +1,186 @@ + + + + + Debug + AnyCPU + {C7A69145-60B6-4882-97D6-A3921DD43978} + WinExe + Properties + WindowsInteropTest + WindowsInteropTest + v4.6 + 512 + true + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + + + Form + + + EmbedToWinFormsDemo.cs + + + EmbedToWpfDemo.xaml + + + Form + + + SelectorForm.cs + + + + + EmbedToWinFormsDemo.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + + + SelectorForm.cs + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + + + + {d211e587-d8bc-45b9-95a4-f297c8fa5200} + Avalonia.Animation + + + {b09b78d8-9b26-48b0-9149-d64a2f120f3f} + Avalonia.Base + + + {d2221c82-4a25-4583-9b43-d791e3f6820c} + Avalonia.Controls + + + {799a7bb5-3c2c-48b6-85a7-406a12c420da} + Avalonia.DesignerSupport + + + {7062ae20-5dcc-4442-9645-8195bdece63e} + Avalonia.Diagnostics + + + {62024b2d-53eb-4638-b26b-85eeaa54866e} + Avalonia.Input + + + {6b0ed19d-a08b-461c-a9d9-a9ee40b0c06b} + Avalonia.Interactivity + + + {42472427-4774-4c81-8aff-9f27b8e31721} + Avalonia.Layout + + + {6417b24e-49c2-4985-8db2-3ab9d898ec91} + Avalonia.ReactiveUI + + + {eb582467-6abb-43a1-b052-e981ba910e3a} + Avalonia.SceneGraph + + + {f1baa01a-f176-4c6a-b39d-5b40bb1b148f} + Avalonia.Styling + + + {3e10a5fa-e8da-48b1-ad44-6a5b6cb7750f} + Avalonia.Themes.Default + + + {3e53a01a-b331-47f3-b828-4a5717e77a24} + Avalonia.Markup.Xaml + + + {6417e941-21bc-467b-a771-0de389353ce6} + Avalonia.Markup + + + {925dd807-b651-475f-9f7c-cbeb974ce43d} + Avalonia.Skia.Desktop + + + {3e908f67-5543-4879-a1dc-08eace79b3cd} + Avalonia.Direct2D1 + + + {811a76cf-1cf6-440f-963b-bbe31bd72a82} + Avalonia.Win32 + + + {d0a739b9-3c68-4ba6-a328-41606954b6bd} + ControlCatalog + + + + + Designer + MSBuild:Compile + + + + + \ No newline at end of file diff --git a/src/Avalonia.Controls/Avalonia.Controls.csproj b/src/Avalonia.Controls/Avalonia.Controls.csproj index d6e5926727..339af5adca 100644 --- a/src/Avalonia.Controls/Avalonia.Controls.csproj +++ b/src/Avalonia.Controls/Avalonia.Controls.csproj @@ -56,6 +56,7 @@ + diff --git a/src/Avalonia.Controls/EmbeddableControl.cs b/src/Avalonia.Controls/EmbeddableControl.cs new file mode 100644 index 0000000000..a1c4fc9ed8 --- /dev/null +++ b/src/Avalonia.Controls/EmbeddableControl.cs @@ -0,0 +1,66 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Avalonia.Controls.Platform; +using Avalonia.Input; +using Avalonia.Layout; +using Avalonia.Platform; +using Avalonia.Styling; + +namespace Avalonia.Controls +{ + public class EmbeddableControl : TopLevel, IStyleable, IFocusScope, ILayoutRoot, INameScope + { + public EmbeddableControl() : base(PlatformManager.CreateEmbeddableWindow()) + { + PlatformImpl.Show(); + } + + public void Prepare() + { + EnsureInitialized(); + ApplyTemplate(); + LayoutManager.Instance.ExecuteInitialLayoutPass(this); + PlatformImpl.Show(); + } + + + private void EnsureInitialized() + { + if (!this.IsInitialized) + { + var init = (ISupportInitialize)this; + init.BeginInit(); + init.EndInit(); + } + } + + protected override Size MeasureOverride(Size availableSize) + { + return PlatformImpl.ClientSize; + } + + private readonly NameScope _nameScope = new NameScope(); + public event EventHandler Registered + { + add { _nameScope.Registered += value; } + remove { _nameScope.Registered -= value; } + } + + public event EventHandler Unregistered + { + add { _nameScope.Unregistered += value; } + remove { _nameScope.Unregistered -= value; } + } + + public void Register(string name, object element) => _nameScope.Register(name, element); + + public object Find(string name) => _nameScope.Find(name); + + public void Unregister(string name) => _nameScope.Unregister(name); + + Type IStyleable.StyleKey => typeof(EmbeddableControl); + } +} diff --git a/src/Avalonia.Controls/Platform/PlatformManager.cs b/src/Avalonia.Controls/Platform/PlatformManager.cs index e75f3c162b..339b2356f3 100644 --- a/src/Avalonia.Controls/Platform/PlatformManager.cs +++ b/src/Avalonia.Controls/Platform/PlatformManager.cs @@ -43,6 +43,14 @@ namespace Avalonia.Controls.Platform return s_designerMode ? platform.CreateEmbeddableWindow() : platform.CreateWindow(); } + public static IWindowImpl CreateEmbeddableWindow() + { + var platform = AvaloniaLocator.Current.GetService(); + if (platform == null) + throw new Exception("Could not CreateEmbeddableWindow(): IWindowingPlatform is not registered."); + return platform.CreateEmbeddableWindow(); + } + public static IPopupImpl CreatePopup() { return AvaloniaLocator.Current.GetService().CreatePopup(); diff --git a/src/Avalonia.Themes.Default/Avalonia.Themes.Default.csproj b/src/Avalonia.Themes.Default/Avalonia.Themes.Default.csproj index f3f1714e2d..93b258d3f1 100644 --- a/src/Avalonia.Themes.Default/Avalonia.Themes.Default.csproj +++ b/src/Avalonia.Themes.Default/Avalonia.Themes.Default.csproj @@ -208,6 +208,11 @@ True + + + Designer + +