qshinoの日記

Powershell関係と徒然なこと

wpf webbrowser class

wpf webbrowser class

class : System.Windows.Controls.WebBrowser

<Window    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  Title="hdoc" Height="300" Width="300">
  <StackPanel>
    <WebBrowser Name="ax"
      Source="c:¥poi.html" />
  </StackPanel>
</Window>

コード

ソース変更

$ax = $win.FindName("ax")
$ax.Source=uri("c:¥qwe.html")

<!-- Web Browser Control -->
<WebBrowser Name="browser" Source="http://msdn.com" 
  Width="600" Height="600"  />

xaml

<StackPanel>
    <StackPanel Orientation="Horizontal">
        <TextBox Name="address" Width="200" />
        <Button Name="go" Content="Go"/>
    </StackPanel>
    <WebBrowser Name="browser" />
</StackPanel>

C-sharpサンプル

public MainWindow()
{
    InitializeComponent();

    var serviceProvider = (IServiceProvider)webBrowser1.Document;
    if (serviceProvider != null)
    {
        Guid serviceGuid = new Guid("0002DF05-0000-0000-C000-000000000046");
        Guid iid = typeof(SHDocVw.WebBrowser).GUID;
        var webBrowserPtr = (SHDocVw.WebBrowser)serviceProvider
            .QueryService(ref serviceGuid, ref iid);
        if (webBrowserPtr != null)
        {
            webBrowserPtr.NewWindow2 += webBrowser1_NewWindow2;
        }
    }
}

private void webBrowser1_NewWindow2(ref object ppDisp, ref bool Cancel)
{
    // Handle the event.
}

[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("6d5140c1-7436-11ce-8034-00aa006009fa")]
internal interface IServiceProvider
{
    [return: MarshalAs(UnmanagedType.IUnknown)]
    object QueryService(ref Guid guidService, ref Guid riid);
}

参考

https://msdn.microsoft.com/ja-jp/library/system.windows.controls.webbrowser(v=vs.110).aspx

http://www.atmarkit.co.jp/fdotnet/dotnettips/814wpfwebbrowser/wpfwebbrowser.html

WPF背景色

wpf背景色

WPFでコントロールに背景色を付ける。

気合いでやるなら、このぐらい。

<Window x:Class="BackgroundColorChange.MainWindow"
 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 Title="Keypad" Height="500" Width="500">
 <Grid Height="306" ButtonBase.Click="button_Click" UIElement.GotFocus="textBox1_GotFocus">
  <TextBox Height="23" HorizontalAlignment="Left" Margin="24,27,0,0" Name="textBox1" VerticalAlignment="Top" Width="120" Text="0" Background="AliceBlue">
   <TextBox.Style>
    <Style TargetType="{x:Type TextBox}">
     <Style.Triggers>
      <Trigger Property="IsFocused" Value="true">
       <strong><Setter Property="Background"></strong>
        <Setter.Value>
         <LinearGradientBrush>
          <GradientStop Color="Red"/>
         </LinearGradientBrush>
        </Setter.Value>
       </Setter>
      </Trigger>
     </Style.Triggers>
    </Style>
   </TextBox.Style>
  </TextBox>
  <TextBox Height="23" HorizontalAlignment="Left" Margin="24,56,0,0" Name="textBox2" Text="0" VerticalAlignment="Top" Width="120" Background="AliceBlue" />
  <TextBox Height="23" HorizontalAlignment="Left" Margin="24,85,0,0" Name="textBox3" Text="0" VerticalAlignment="Top" Width="120" Background="AliceBlue" />
  <Button Focusable="False" Content="1" Height="25" HorizontalAlignment="Left" Margin="303,24,0,0" Name="button2" VerticalAlignment="Top" Width="32" />
  <Button Focusable="False" Content="2" Height="25" HorizontalAlignment="Left" Margin="303,55,0,0" Name="button5" VerticalAlignment="Top" Width="32" />
  <Button Focusable="False" Content="3" Height="25" HorizontalAlignment="Left" Margin="303,86,0,0" Name="button8" VerticalAlignment="Top" Width="32" />
  <Button Focusable="False" Content="4" Height="25" HorizontalAlignment="Left" Margin="351,24,0,0" Name="button1" VerticalAlignment="Top" Width="32" />
  <Button Focusable="False" Content="5" Height="25" HorizontalAlignment="Left" Margin="351,55,0,0" Name="button3" VerticalAlignment="Top" Width="32" />
  <Button Focusable="False" Content="6" Height="25" HorizontalAlignment="Left" Margin="351,86,0,0" Name="button4" VerticalAlignment="Top" Width="32" />
  <Button Focusable="False" Content="7" Height="25" HorizontalAlignment="Left" Margin="401,24,0,0" Name="button7" VerticalAlignment="Top" Width="32" />
  <Button Focusable="False" Content="8" Height="25" HorizontalAlignment="Left" Margin="401,55,0,0" Name="button9" VerticalAlignment="Top" Width="32" />
  <Button Focusable="False" Content="9" Height="25" HorizontalAlignment="Left" Margin="401,86,0,0" Name="button10" VerticalAlignment="Top" Width="32" />
  <Button Focusable="False" Content="0" Height="25" HorizontalAlignment="Left" Margin="351,117,0,0" Name="button6" VerticalAlignment="Top" 

参考

https://social.msdn.microsoft.com/Forums/vstudio/en-US/a8c18880-f21c-40e5-a8bc-f1a9aaae7635/how-to-change-textbox-background-color-on-xaml?forum=wpf

http://stackoverflow.com/questions/1441059/changing-background-color-of-container-when-textbox-is-in-focus

http://stackoverflow.com/questions/15399622/accessing-background-color-of-textblock

WPF ShowDialog()中の非同期イベント

ShowDialog()中に非同期イベントを処理できない。

PowershellWPFのShowDialog()を処理中に非同期イベントが発生しても処理されない件、原因不明ながら回避策にて対応。

なお、イベントの発生と処理は別物。発生時刻をイベントのプロパティTimeGeneratedで確認。処理時刻をハンドラでの(Get-Date)で確認する。

まずは問題

$win = xxx でWindow生成 $win.ShowDialog()

UI内のイベントで Start-Process のExited EventをRegister-ObjectEventで登録。これはUIスレッドで発生しないため、非同期イベント。

プロセスが終了してもUIスレッドで処理されない。

但し、UIスレッド内でGet-Eventした時に前記イベント発生。

イベントの生成時刻プロパティを見ると、UIスレッドで処理された時刻よりかなり前に発生していた。

  • 対策1 UIのボタンなどの処理で、Get-Eventする。
  • 対策2 DispatcherTimerで定期的にイベント処理を発生させる。

対策1

単純にボタンでGet-Event。ボタン名が"kita", Windowが$winとすると、

$kita = $win.FindName("kita")
$kita.add_click( {Get-Event})

kitaボタンを押すと、非同期イベントがあれば処理してくれる。

対策2

タイマーイベントの副作用で、非同期イベントを処理。ある意味、前記のkitaボタンをタイマーが自動で押してくれる様なもの。

$proc = Start-Process cmd -Passthru

$timer = New-Object System.Windows.Threading.DispatcherTimer
$timer.interval = New-Object TimeSpan(0,0,1)
$timer.add_tick({
  Write-Host "tick" 
  if ( $this.tag ){
    # イベント発生済み
    # イベントジョブ削除
    $this.Stop()
    Remove-Job -id ($this.tag).id
    $this.tag = $null
})
$timer.IsEnabled = $true
$timer.Start()
$timer.tag = $null

$ev = Register-ObjectEvent $proc -EventName Exited -Messagedata @{timer=$timer;ev=$ev;dispatcher=[System.Windows.Threading.Dispatcher]::CurrentDispatcher } $timer -Action { 
  $data = $event.MessageData
  $timer = $data.timer
  $timer.tag = $data.ev
  Unregister-Event -SourceIdentifier $EventSubscriber.Name
  # 何らかの後処理。
  # 本処理PSEventJobがJobとして残っているので、どこかで削除する必要あり。
  # UIスレッド処理: $eventは引数
  $data.dispatcher.BeginInvoke({
    # uiスレッド処理
  }, @($event))
}

参考

http://d.hatena.ne.jp/omoisan/touch/20090711/1249783732

http://main.tinyjoker.net/Tech/CSharp/WPF/�̥����åɤ������Ǥ������.html

http://www.atmarkit.co.jp/ait/spv/1411/04/news133.html

http://ari-it.doorblog.jp/archives/30059088.html

Dispatcher class

https://msdn.microsoft.com/ja-jp/library/system.windows.threading.dispatcher(v=vs.110).aspx#メソッド

Peocess Exited event

https://msdn.microsoft.com/ja-jp/library/system.diagnostics.process.exited(v=vs.90).aspx

WPF timer使用例

https://code.msdn.microsoft.com/windowsdesktop/XAMLCVB-WPF-Windows-WPF-2aab6085

DispatcherTimer

https://msdn.microsoft.com/ja-jp/library/ms615945.aspx#継承階層

IsEnabled

https://msdn.microsoft.com/ja-jp/library/system.windows.threading.dispatchertimer.isenabled.aspx

tag property

https://msdn.microsoft.com/ja-jp/library/system.windows.threading.dispatchertimer.tag.aspx

TimeSpan

https://msdn.microsoft.com/ja-jp/library/system.timespan(v=vs.110).aspx

コンストラクター

https://msdn.microsoft.com/ja-jp/library/bk8a3558(v=vs.110).aspx

Application.Run()

Applucation.Run()

何をしているのか?

MSDN/wpfだとあっさりと、

Run()

Starts a Windows Presentation Foundation (WPF) application.

Run(Window)

Starts a Windows Presentation Foundation (WPF) application and opens the specified window.

さて

Application classの記述を見ると、スタンドアローンの場合、Applicationオブジェクトが必要ではないらしい。

とは言え、何をするものか?

A standalone application does not require an Application object; it is possible to implement a custom static entry point method (Main) that opens a window without creating an instance of Application. However, XAML browser applications (XBAPs) require an Application object.

参考

wpf application

https://msdn.microsoft.com/ja-jp/library/system.windows.application(v=vs.110).aspx

wpf Applucation.Run

https://msdn.microsoft.com/ja-jp/library/ms597010(v=vs.110).aspx

https://social.msdn.microsoft.com/Search/ja-jp/?Query=Application.Run+メソッド

http://dobon.net/vb/dotnet/form/runvsshowdialog.html

Event powershell

https://blogs.technet.microsoft.com/heyscriptingguy/2011/06/16/use-asynchronous-event-handling-in-powershell/

application.run() vs ShowDialog()

http://dobon.net/vb/dotnet/form/runvsshowdialog.html

application.run()

https://msdn.microsoft.com/ja-jp/library/ms597010(v=vs.110).aspx

application class

https://msdn.microsoft.com/ja-jp/library/system.windows.application(v=vs.110).aspx#メソッド

application exit event

https://msdn.microsoft.com/ja-jp/library/system.windows.application.exit(v=vs.110).aspx

application shutdownmode

https://msdn.microsoft.com/ja-jp/library/system.windows.application.shutdownmode(v=vs.110).aspx

AppDomain

AppDomain

.Netの実行環境階層構造

Process – AppDomain —- RunSpace

かな?

  • Process メモリ空間を共有する。
  • AppDomain : アセンブリ空間共有
  • RunSpace : コンテキスト共有

一つのAppDomainに最大1つのアプリケーションクラスを持てる。

コード例/msdn

using System;
using System.Reflection;
using System.Threading;

class Module1
{
    public static void Main()
    {
        // Get and display the friendly name of the default AppDomain.
        string callingDomainName = Thread.GetDomain().FriendlyName;
        Console.WriteLine(callingDomainName);

        // Get and display the full name of the EXE assembly.
        string exeAssembly = Assembly.GetEntryAssembly().FullName;
        Console.WriteLine(exeAssembly);

        // Construct and initialize settings for a second AppDomain.
        AppDomainSetup ads = new AppDomainSetup();
        ads.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory;

        ads.DisallowBindingRedirects = false;
        ads.DisallowCodeDownload = true;
        ads.ConfigurationFile = 
            AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;

        // Create the second AppDomain.
        AppDomain ad2 = AppDomain.CreateDomain("AD #2", null, ads);

        // Create an instance of MarshalbyRefType in the second AppDomain. 
        // A proxy to the object is returned.
        MarshalByRefType mbrt = 
            (MarshalByRefType) ad2.CreateInstanceAndUnwrap(
                exeAssembly, 
                typeof(MarshalByRefType).FullName
            );

        // Call a method on the object via the proxy, passing the 
        // default AppDomain's friendly name in as a parameter.
        mbrt.SomeMethod(callingDomainName);

        // Unload the second AppDomain. This deletes its object and 
        // invalidates the proxy object.
        AppDomain.Unload(ad2);
        try
        {
            // Call the method again. Note that this time it fails 
            // because the second AppDomain was unloaded.
            mbrt.SomeMethod(callingDomainName);
            Console.WriteLine("Sucessful call.");
        }
        catch(AppDomainUnloadedException)
        {
            Console.WriteLine("Failed call; this is expected.");
        }
    }
}

// Because this class is derived from MarshalByRefObject, a proxy 
// to a MarshalByRefType object can be returned across an AppDomain 
// boundary.
public class MarshalByRefType : MarshalByRefObject
{
    //  Call this method via a proxy.
    public void SomeMethod(string callingDomainName)
    {
        // Get this AppDomain's settings and display some of them.
        AppDomainSetup ads = AppDomain.CurrentDomain.SetupInformation;
        Console.WriteLine("AppName={0}, AppBase={1}, ConfigFile={2}", 
            ads.ApplicationName, 
            ads.ApplicationBase, 
            ads.ConfigurationFile
        );

        // Display the name of the calling AppDomain and the name 
        // of the second domain.
        // NOTE: The application's thread has transitioned between 
        // AppDomains.
        Console.WriteLine("Calling from '{0}' to '{1}'.", 
            callingDomainName, 
            Thread.GetDomain().FriendlyName
        );
    }
}

/* This code produces output similar to the following: 

AppDomainX.exe
AppDomainX, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
AppName=, AppBase=C:\AppDomain\bin, ConfigFile=C:\AppDomain\bin\AppDomainX.exe.config
Calling from 'AppDomainX.exe' to 'AD #2'.
Failed call; this is expected.
 */

参考

http://www.atmarkit.co.jp/fdotnet/technology/glossary01/glossary01_02.html

http://d.hatena.ne.jp/junjun777/touch/20110907/csharp_compiler_csharp_class

https://msdn.microsoft.com/ja-jp/library/system.appdomain.docallback(v=vs.110).aspx?cs-save-lang=1&cs-lang=csharp#code-snippet-2

AppDomain class

https://msdn.microsoft.com/ja-jp/library/system.appdomain(v=vs.110).aspx#継承階層

別AppDomainで実行

http://devlights.hatenablog.com/entry/20120808/p1