プログラムの事とか

お約束ですが「掲載内容は私個人の見解です」

WPF ( .NET 5 ) でWindows Runtime API を呼ぶのは超簡単だった

昨日のやつ

WPF ( .NET 5 ) でWindows Runtime API を呼ぶ、前にしなければいけないこと - プログラムの事とか

は大嘘でした、ごめんなさい、この方法ではAPIを呼び出そうとすると何らかのビルドエラーが発生しますね、その先に進めませんね

反省はするけど次回に生かせる可能性は低いです

ということで 2021/01/14現在で最新の環境で .NET 5 WPFWindows Runtime APIを呼ぶ方法を改めて

プロジェクトファイルの編集

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>WinExe</OutputType>
    <TargetFramework>net5.0-windows10.0.19041.0</TargetFramework>
    <UseWPF>true</UseWPF>
  </PropertyGroup>

</Project>

編集後はコンパイルエラーが出るかもしれませんが、その場合は一度クリーンすればだいじょぶだと思います

以上

NuGetパッケージとかいらなかったんや

.NET 5 Preview 8 以降はターゲット フレームワーク モニカー<TargetFramework/>を指定するだけでいいらしいです。ちゃんとドキュメントがありました

github.com

試す

今回はちゃんとためします

blogs.windows.com

ここのコードをコピペして実行

f:id:puni-o:20210114102435p:plain

できました

WPF ( .NET 5 ) でWindows Runtime API を呼ぶ、前にしなければいけないこと

2021/01/13時点でのお話です


2021/01/14追記

今回のブログの通りやっても使えません、翌日のブログ(以下のリンク)が正解

puni-o.hatenablog.com

2021/01/14追記おわり

ここから先は試行錯誤中のログ的な感じで残しておきます


プロジェクトファイルの編集

とりあえずこんな感じ

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>WinExe</OutputType>
    <TargetFramework>net5.0-windows10.0.19041</TargetFramework>
    <UseWPF>true</UseWPF>
  </PropertyGroup>
</Project>

.NET 5と対象のWindowsバージョンをTargetFrameworkに(上の例は20H1かな?)

Microsoft.Windows.SDK.Contracts をゲット

NuGetでとりましょう

Install-Package Microsoft.Windows.SDK.Contracts -Version 10.0.19041.1

ここまではググると簡単に出てくると思います

エラー

この状態でビルドすると

1>C:\Program Files\dotnet\sdk\5.0.102\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.Sdk.targets(934,5): error NETSDK1130: .NETCoreApp,Version=v5.0 をターゲットにする場合、Windows メタデータ コンポーネントの直接参照はサポートされていません。このターゲットには、C#/WinRT プロジェクション ツール (https://aka.ms/cswinrt) または指定されたプロジェクションをご使用ください。

.NETCoreApp,Version=v5.0 をターゲットにする場合、Windows メタデータ コンポーネントの直接参照はサポートされていません。このターゲットには、C#/WinRT プロジェクション ツール (https://aka.ms/cswinrt) または指定されたプロジェクションをご使用ください。

こんな感じでエラーがでるはずです

相変わらず意味が分からん、英語だとわかるのかな?

Microsoft.Windows.CsWinRT をゲット

NuGetでこのパッケージをゲットするとエラーが消えます

Install-Package Microsoft.Windows.CsWinRT -Version 1.1.0

.NET 5でMicrosoft.Windows.SDK.Contracts を参照した場合CsWinRTが必要だよっていう記事は見つけられなかったんですが、必須ではないんですかねー?

Windows Runtime API を呼ばない

今回は呼ぶ前にすることなので呼びません。これで正常に呼び出せるのかも試していません。とりあえずビルドエラーが消えてうれしいです

おしまい

WPFのDynamicなSolidColorBrushとDynamicなColor

WPFネタです。半日くらい悩んでいました

準備

App.xaml抜粋

<Application.Resources>
    <Color x:Key="FillColor">#00ffff</Color>
    <SolidColorBrush x:Key="FillBrush" Color="{DynamicResource FillColor}"/>
</Application.Resources>

MainWindow.xaml

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition/>
        <RowDefinition/>
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition/>
        <ColumnDefinition/>
    </Grid.ColumnDefinitions>
    <Rectangle Fill="{DynamicResource FillBrush}"/>
    <Rectangle Grid.Column="1">
        <Rectangle.Fill>
            <SolidColorBrush Color="{DynamicResource FillColor}"/>
        </Rectangle.Fill>
    </Rectangle>
    <Button Grid.Row="1" Content="Red" Click="RedButton_Click"/>
    <Button Grid.Row="1" Grid.Column="1" Content="Green" Click="GreenButton_Click"/>
</Grid>

MainWindow.xaml.cs

private void RedButton_Click(object sender, RoutedEventArgs e)
{
    Application.Current.Resources["FillColor"] = Colors.Red;
}

private void GreenButton_Click(object sender, RoutedEventArgs e)
{
    Application.Current.Resources["FillColor"] = Colors.Green;
}

やっていること

  • アプリケーションのリソースにFillColorというキーのColorとそのColorをDynamicResourceで参照しているFillBrushを用意します
  • Windowの左側のRectangle.FillにはFillBrushをDynamicResourceで入れておきます
  • 右側のRectangle.FillにはXAMLでSolidColorBrushを書いて、そのColorを{DynamicResource FillColor}とします
  • ボタン二つは押したときにFillColorの色を変えるようにしています

動作結果

これを動かすと

f:id:puni-o:20201215182204g:plain

MainWindow.xaml{DynamicResource FillColor}とした方だけが色が変わります。気持ち的には両方変わってほしいんですけどねぇ

ググるとStackOverflowに

stackoverflow.com

というのが出てきて、SolidColorBrushはFrameworkElementでもFrameworkContentElementでもないからダメ、みたいな解答が書いてあります。サンプルのRectangleが両方色が変わらなかったら納得なんですけどね。ちなみに英語力皆無なので本当にそういうことが書いてあるのかは知りません

おまけ

App.xamlの定義をMainWindow.xamlに持ってきて同じようなことをしてみます

MainWindow.xaml

<Window.Resources>
    <Color x:Key="FillColor">#00ffff</Color>
    <SolidColorBrush x:Key="FillBrush" Color="{DynamicResource FillColor}"/>
</Window.Resources>
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition/>
        <RowDefinition/>
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition/>
        <ColumnDefinition/>
    </Grid.ColumnDefinitions>
    <Rectangle Fill="{DynamicResource FillBrush}"/>
    <Rectangle Grid.Column="1">
        <Rectangle.Fill>
            <SolidColorBrush Color="{DynamicResource FillColor}"/>
        </Rectangle.Fill>
    </Rectangle>
    <Button Grid.Row="1" Content="Red" Click="RedButton_Click"/>
    <Button Grid.Row="1" Grid.Column="1" Content="Green" Click="GreenButton_Click"/>
</Grid>

MainWindow.xaml.cs

private void RedButton_Click(object sender, RoutedEventArgs e)
{
    Resources["FillColor"] = Colors.Red;
}

private void GreenButton_Click(object sender, RoutedEventArgs e)
{
    Resources["FillColor"] = Colors.Green;
}

結果

f:id:puni-o:20201215183219g:plain

両方変わるよぉぉぉ