Skip to content

Instantly share code, notes, and snippets.

@stinos
Created October 5, 2014 16:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save stinos/fdd62bcdb4cb3ea10476 to your computer and use it in GitHub Desktop.
Save stinos/fdd62bcdb4cb3ea10476 to your computer and use it in GitHub Desktop.
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="460">
<StackPanel Orientation="Horizontal">
<StackPanel Orientation="Vertical" Width="160">
<Button x:Name="StartButton" Content="Start Python"/>
<TextBlock x:Name="Status"/>
</StackPanel>
<ContentControl Grid.Column="1" x:Name="PythonWinHost" Width="300"/>
</StackPanel>
</Window>
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows;
using System.Windows.Interop;
using System.Windows.Threading;
using IronPython.Hosting;
namespace WpfApplication1
{
public static class User32
{
public const int WS_CHILD = 0x40000000;
public const int WS_CAPTION = 0x00C00000;
public const int WS_THICKFRAME = 0x00040000;
public const int GWL_STYLE = -16;
[DllImport( "user32.dll" )]
public static extern int GetWindowLong( IntPtr hWnd, int nIndex );
[DllImport( "user32.dll" )]
public static extern int SetWindowLong( IntPtr hWnd, int nIndex, int dwNewLong );
[DllImport( "user32" )]
public static extern IntPtr SetParent( IntPtr hWnd, IntPtr hWndParent );
}
public class WpfHwndEmbedHost : HwndHost
{
private readonly IntPtr childWin;
public WpfHwndEmbedHost( IntPtr childWin )
{
this.childWin = childWin;
}
protected override HandleRef BuildWindowCore( HandleRef hwndParent )
{
int style = User32.GetWindowLong( childWin, User32.GWL_STYLE );
style = style & ~User32.WS_CAPTION & ~User32.WS_THICKFRAME;
style |= User32.WS_CHILD;
User32.SetWindowLong( childWin, User32.GWL_STYLE, style );
User32.SetParent( childWin, hwndParent.Handle );
this.InvalidateVisual();
return new HandleRef( this, childWin );
}
protected override void DestroyWindowCore( HandleRef hwnd )
{
}
}
public partial class MainWindow : Window
{
private const bool hostedWin = true;
private readonly Dispatcher mainDispatcher;
private Dispatcher pyDispatcher;
private Thread procThread;
public MainWindow()
{
InitializeComponent();
DataContext = this;
mainDispatcher = Application.Current.Dispatcher;
Status.Text = "Ready";
StartButton.Click += ( sender, args ) => StartPythonThread();
}
private void StartPythonThread()
{
var thr = new Thread( PythonThread ) { IsBackground = true, Name = "Python" };
thr.SetApartmentState( ApartmentState.STA );
thr.Start();
}
private Window CreateWindow()
{
var win = new Window();
win.Show();
if( hostedWin )
{
var hostedWinHandle = new WindowInteropHelper( win ).Handle;
mainDispatcher.Invoke( () => { PythonWinHost.Content = new WpfHwndEmbedHost( hostedWinHandle ); } );
}
return win;
}
private void StartProcessThread()
{
procThread = new Thread( ProcessThread ) { Name = "Process" };
procThread.Start();
}
private bool ProcessRunning()
{
return procThread != null && procThread.IsAlive;
}
private void ProcessThread()
{
mainDispatcher.Invoke( () => { Status.Text = "Process start"; } );
Thread.Sleep( 5000 );
mainDispatcher.Invoke( () => { Status.Text = "Process done"; } );
}
private void PythonThread()
{
pyDispatcher = Dispatcher.CurrentDispatcher;
Debug.Assert( !ReferenceEquals( pyDispatcher, Application.Current.Dispatcher ) );
SynchronizationContext.SetSynchronizationContext( new DispatcherSynchronizationContext( pyDispatcher ) );
var py = Python.CreateEngine();
var scope = py.CreateScope();
( (dynamic) scope ).createWindow = new Func<Window>( CreateWindow );
( (dynamic) scope ).startProcess = new Action( StartProcessThread );
( (dynamic) scope ).processRunning = new Func<bool>( ProcessRunning );
( (dynamic) scope ).runDispatcher = new Action( Dispatcher.Run );
py.Execute( script, scope );
}
private const string script =
@"
import time
import clr
clr.AddReference( 'PresentationFramework' )
clr.AddReference( 'PresentationCore' )
from System.Windows.Controls import Button
def RunIt( s, e ):
startProcess()
time.sleep( 1.5 ) #make sure proc thread started...
while processRunning():
time.sleep( 0.5 )
b = Button()
b.Content = 'Start Process'
b.Click += RunIt
win = createWindow()
win.Content = b
runDispatcher()
";
}
}
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{F3304AF0-F1E8-45EB-A6E0-C480D2909B30}</ProjectGuid>
<OutputType>WinExe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>WpfApplication1</RootNamespace>
<AssemblyName>WpfApplication1</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="IronPython, Version=2.7.0.40, Culture=neutral, PublicKeyToken=7f709c5b713576e1, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>packages\IronPython.2.7.4\lib\Net45\IronPython.dll</HintPath>
</Reference>
<Reference Include="IronPython.Modules, Version=2.7.0.40, Culture=neutral, PublicKeyToken=7f709c5b713576e1, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>packages\IronPython.2.7.4\lib\Net45\IronPython.Modules.dll</HintPath>
</Reference>
<Reference Include="IronPython.SQLite">
<HintPath>packages\IronPython.2.7.4\lib\Net45\IronPython.SQLite.dll</HintPath>
</Reference>
<Reference Include="IronPython.Wpf">
<HintPath>packages\IronPython.2.7.4\lib\Net45\IronPython.Wpf.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Dynamic, Version=1.1.0.20, Culture=neutral, PublicKeyToken=7f709c5b713576e1, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>packages\IronPython.2.7.4\lib\Net45\Microsoft.Dynamic.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Scripting, Version=1.1.0.20, Culture=neutral, PublicKeyToken=7f709c5b713576e1, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>packages\IronPython.2.7.4\lib\Net45\Microsoft.Scripting.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Scripting.AspNet">
<HintPath>packages\IronPython.2.7.4\lib\Net45\Microsoft.Scripting.AspNet.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Scripting.Metadata, Version=1.1.0.20, Culture=neutral, PublicKeyToken=7f709c5b713576e1, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>packages\IronPython.2.7.4\lib\Net45\Microsoft.Scripting.Metadata.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Xaml">
<RequiredTargetFramework>4.0</RequiredTargetFramework>
</Reference>
<Reference Include="WindowsBase" />
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
</ItemGroup>
<ItemGroup>
<ApplicationDefinition Include="App.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</ApplicationDefinition>
<Page Include="MainWindow.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Compile Include="App.xaml.cs">
<DependentUpon>App.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="MainWindow.xaml.cs">
<DependentUpon>MainWindow.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
</ItemGroup>
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
<None Include="packages.config" />
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
<AppDesigner Include="Properties\" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment