20201112のC#に関する記事は7件です。

[C#/WPF] ノートPCのバッテリーの充電状況などを取得する

もくじ
https://qiita.com/tera1707/items/4fda73d86eded283ec4f

やりたいこと

C#アプリの中で、バッテリの充電が今どれくらいなのか?を知りたい。

やり方

WinFormのAPIを使うやり方と、UWPのAPIを使うやり方があるっぽい。

UWPのAPI版

Windows.Devices.Power 名前空間のクラスを使う。
WPFで使うには、下記の手順が必要。

  • UWPのAPIを使えるように参照を追加(こちら参照)
  • using Windows.Devices.Power;を追加
UWP版.cs
using System;
using Windows.Devices.Power;

namespace ConsoleApp19
{
    class Program
    {
        static Battery AggBattery = Battery.AggregateBattery;

        static void Main(string[] args)
        {
            AggBattery.ReportUpdated += AggBattery_ReportUpdated;
            Console.ReadLine();
        }

        private static void AggBattery_ReportUpdated(Battery sender, object args)
        {
            var report = Battery.AggregateBattery.GetReport();

            var Maximum = Convert.ToDouble(report.FullChargeCapacityInMilliwattHours);
            var Value = Convert.ToDouble(report.RemainingCapacityInMilliwattHours);
            var Percent = (Value / Maximum) * 100;

            Console.WriteLine("Status is " + report.Status + "  Charge is " + Percent.ToString("F2") + "%  Charge Rate is " + report.ChargeRateInMilliwatts);
            Console.WriteLine("  DesignCapacityInMilliwattHours = " + report.DesignCapacityInMilliwattHours + "  FullChargeCapacityInMilliwattHours = " + report.FullChargeCapacityInMilliwattHours + "  RemainingCapacityInMilliwattHours = " + report.RemainingCapacityInMilliwattHours);
        }
    }
}

WinForm版

System.Windows.Forms名前空間SystemInformation.PowerStatusを使う。

WinForm版.cs
        static void Main(string[] args)
        {
            while (true)
            {
                var chargeStatus = SystemInformation.PowerStatus.BatteryChargeStatus;
                var fullLifetime = SystemInformation.PowerStatus.BatteryFullLifetime;
                var percent = SystemInformation.PowerStatus.BatteryLifePercent;
                var lifeRemaining = SystemInformation.PowerStatus.BatteryLifeRemaining;
                var powerlineStatus = SystemInformation.PowerStatus.PowerLineStatus;

                Console.WriteLine("chargeStatus = " + chargeStatus + "  fullLifetime = " + fullLifetime + "  percent = " + percent + "  lifeRemaining = " + lifeRemaining + "  powerlineStatus = " + powerlineStatus);

                Thread.Sleep(1000);
            }
        }

参考

UWP版

Batteryクラス(バッテリーの情報を扱う)
https://docs.microsoft.com/en-us/uwp/api/windows.devices.power.battery?view=winrt-19041
BatteryReportクラス(バッテリーの状況を入れとくためのクラス)
https://docs.microsoft.com/en-us/uwp/api/Windows.Devices.Power.BatteryReport?redirectedfrom=MSDN&view=winrt-19041

Form版

SystemInformation クラス
https://docs.microsoft.com/ja-jp/dotnet/api/system.windows.forms.systeminformation?view=net-5.0

SystemInformation.PowerStatus
https://docs.microsoft.com/ja-jp/dotnet/api/system.windows.forms.systeminformation.powerstatus?view=net-5.0

※SystemInformation クラスには、システムの設定とかもろもろの情報が何でもかんでもつまってるっぽい。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[C#] もうとにかく今すぐデバッグのためのログを出力したいときのクラス/メソッド

目次
https://qiita.com/tera1707/items/4fda73d86eded283ec4f

やりたいこと

C#でアプリをつくっているときに、もう何でもいいから今すぐ簡単にログを出力させて、それを見たい。
例えば、VisualStudioでデバッグ実行がしたくてもできないけど、どの経路を通ったかを知りたくて、でもMessageBoxは出したくない、というとき。

やり方

下記のような簡単なログ用クラスを貼り付けて使用する。
終わったら、クラスごと消す。

static class LogOnDesktop
{
    public static void WriteLogToDesktopLogFile(string line)
    {
        var logPath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + @"\log.log";

        File.AppendAllText(logPath, DateTime.Now.ToString("hh:mm:ss.fff") + "  " + line);
        File.AppendAllText(logPath, Environment.NewLine);
    }
}

で、このクラスのWriteLogToDesktopLogFile()を実行するとデスクトップにlog.logファイルができるが、そいつを以前書いた「Tailっぽくログを監視できるバッチファイル」を使ってリアルタイムで見てやれば、簡易的にログ監視体制の完成。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[C#/WPF] 自分以外のウインドウを最前面にもってくる

目次
https://qiita.com/tera1707/items/4fda73d86eded283ec4f

やりたいこと

自分以外のアプリのウインドウが、ほかのウインドウの後ろに回っていたら、最前面に表示させたい。

このページに、様々なやり方が書かれているので、そちらを見ればわかってしまうが、自分でもやって試したときのメモ。
https://dobon.net/vb/dotnet/process/appactivate.html

やり方

Microsoft.VisualBasic.Interaction.AppActivate()を使う。

  • 最前面に表示させたいアプリ(プロセス)のプロセス名を調べておく。
  • その名前をProcess.GetProcessesByName()に渡して、プロセス(の配列)を取得
  • 取得したプロセスに対して、Microsoft.VisualBasic.Interaction.AppActivate()を行う。

※他にもやり方はいろいろある様子。上のページを参照。

サンプル

例えば、自分と同じプロセス名を持つプロセス(同じexeを二つ起動してるときなど)を取得してきて、全部を最前面に出す、ということをしようと思うと、下記のようになる。

var current = Process.GetCurrentProcess();
Process.GetProcessesByName(current.ProcessName)
.ToList()
.ForEach(p => Microsoft.VisualBasic.Interaction.AppActivate(p.Id));

取得したプロセスの情報を使って対象を絞ってやれば、同じexeがすでに起動してたら、そっち側を最前面にもってくる、みたいなこともできる。

var current = Process.GetCurrentProcess();
Process.GetProcessesByName(current.ProcessName)
.Where(p => p.Id != current.Id) // ←自分以外を指定(プロセス名は同じでも、プロセスIDはそれぞれ異なる)
.ToList()
.ForEach(p => Microsoft.VisualBasic.Interaction.AppActivate(p.Id));

注意

普通にウインドウを持ってるアプリを普通に起動して、そこから上のようにしてやれば、ほかのプロセスを最前面にもってくる、ということはできるっぽい。

ただし制限事項もあるようで、その辺が下記にまとめられていた。
https://docs.microsoft.com/ja-jp/windows/win32/api/winuser/nf-winuser-setforegroundwindow#remarks
image.png

上に参考であげっせて頂いているdobon.netのページでも、「アクティブ化することができないときのやり方」ということでまとめられているくらいなので、この条件の何かに引っかかってうまくアクティブ化できないことはあるんだろうと思う。

私個人的には、これまで最前面に持ってこれなかったことはあまりなかったが、1回だけ、どうしても最前面に出せないこケースがあった。

具体的には、
Windows10で、アクションセンターの中のトーストを押して起動したアプリのWindowが表示される前(Loadedイベントの中)でAppActivate()をやっても、ほかのウインドウを最前面に出すことができなかった。
(記憶がはっきりしないが、たしかそのケースでも、一度ウインドウがでてきて、ボタンを押したときにAppActivate()をすると、うまくいっていた)

上の制限事項をまとめた備考から考えるに、トーストが押されたことを検知してアプリを呼び出してくれるWindowsの機能が「バックグラウンドプロセス」で、バックグラウンドプロセスから呼んだプロセスの中では「ほかのウインドウをアクティブ化」するような処理はできない、ということなんだろう、と予測した。(本当にそうかどうかは不明...)

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

そこらへんにあるXMLファイルをC#でXElementを使って読み込むときの注意点 ~ xmlns

まえがき

ノードの検索が引っかからなくて調べたら、
xmlns(namespace)の指定(<hogefoobar xmlns="http://example.com">みたいなの)が含まれるXMLファイルの場合、
XElement.Elements(ノード名)などを指定するときの「ノード名」として、ネームスペースを含めた文字列をしてしないと抽出できないということが分かったので、備忘を兼ねて記事を書いておきます。

XElement」とタイトルに書いてますが、XElement使わない場合もxmlnsには気を付けたほうがよさそうな予感。

ソース(雰囲気)

C#
XElement rootNode = XElement.Load("ほげほげ.xml");
XNamespace ns = rootNode.Name.Namespace;

IEnumerable<XElement> items = rootNode.Elements(ns + "ノード名");

参考サイト

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Ignite UI for Blazor データグリッドの豊富な機能を使ってみよう(後編) - Ignite UI for Blazor で始めるSPA開発 - ④

本記事は、インフラジスティックスが2020年10月に新たにリリースした Blazor アプリケーション対応のコンポーネントライブラリーである Ignite UI for Blazor の各種コンポーネントの実装を通してモダンWEBアプリケーションの開発に触れてみようという趣旨で作成しております。

Blazor 及び Ignite UI for Blazor については、以下の弊社ブログ記事も有用ですので是非ご参照ください。

ASP.NET Core Blazor を採用すべきアプリケーションは? Blazor を採用すべきポイントまとめ
https://blogs.jp.infragistics.com/entry/2020/10/12/133447
Ignite UI for Blazor 公式リリース!
https://blogs.jp.infragistics.com/entry/igniteui-blazor-release
ASP.NET Core Blazor - Blazor WebAssembly と Blazor Server の違いは? 5つのポイント
https://blogs.jp.infragistics.com/entry/2020/10/30/152834

本連載の過去記事は以下となります。

第1回
https://qiita.com/MNakae_IG/items/5d89b404257d93742e45
第2回
https://qiita.com/MNakae_IG/items/7a833f7a6bc85fbb125d
第3回
https://qiita.com/MNakae_IG/items/a590126cb520255dbcf8

第4回目の本記事では、前回に引き続き、Ignite UI for Blazor のデータグリッドを触りながら主要な機能について確認していきたいと思います。

列のフィルタリング

列のデータ型に基づいてデータの絞りこみ表示を行うフィルタリング機能が組み込まれています。
陽性者数が500人以上で1000人未満の都道府県のみを表示する機能をグリッドに実装してみます。

まずは新たにボタンを配置して、そのボタンがクリックされた際に指定した関数が実行されるようにします。以下のコードを新たに追加します。

# ファイル名「Grid.razor」を以下のように変更します。
...
<button class="btn btn-primary" @onclick="DataFiltering">
    陽性者数(500~1000)で絞り込む
</button>
...
@code {
    private void DataFiltering()
    {
        Console.WriteLine("ボタンをクリックしました");
    }
}

実行してみると、新たにボタンが表示され、ボタンをクリックすると、コンソールにメッセージが出力されることが確認出来ました。

Image from Gyazo

次にこの関数 DataFiltering() にフィルタリングの処理を加えていきます。
フィルタリング処理を行うための FilterFactory インスタンスを作成したうえで、DataFiltering() の中身を以下のように変更します。

# ファイル名「Grid.razor」を以下のように変更します。
@code {
    ...
    public FilterFactory FilterFactory = new FilterFactory();
    ...
    private void DataFiltering()
    {
        this.DataGridRef.FilterExpressions.Clear();

        //フィルタリング列を指定
        FilterExpression column = this.FilterFactory.Property("Npatients");

        FilterExpression filter = new FilterExpression();

        //フィルタリング条件を指定
        filter = column.IsGreaterThanOrEqualTo(500).And(column.IsLessThan(1000));

        this.DataGridRef.FilterExpressions.Add(filter);

        StateHasChanged();
    }
}

実行してボタンをクリックし結果を確認すると、以下のように指定した条件に当てはまるデータが表示されました。

Image from Gyazo

セルの値による表示スタイルの変更

グリッドを利用する際のよくあるシナリオとして、特定の条件に当てはまる値を持つセルの背景や文字色を変更して目立つようにする、というものがあります。「現在の感染者数」列が500以上の場合は数値を赤字で表示するように調整をおこなっていきます。

まず以下のように「現在の感染者数」列を <TemplateColumn> に置き換えます。

# ファイル名「Grid.razor」を以下のように変更します。
<TemplateColumn Field="Ncurrentpatients" HeaderText="現在の感染者数" CellUpdatingScript="onUpdatingNcurrentpatientsColumn" />

次に、wwwroot ディレクトリに DataGridColumnTypes.js というJSファイルを新規に作成します。このJSファイルの中で、先ほど <TemplateColumn> に置き換えたカラムの中身を設定していきます。以下のように記述します。

# ファイル名「DataGridColumnTypes.js」を以下のように変更します。
function onUpdatingNcurrentpatientsColumn(grid, args) {
    let content = args.content;
    let info = args.cellInfo;
    let currentpatients = info.rowItem.Ncurrentpatients;
    let span = null;

    if (content.childElementCount === 0) {
        span = document.createElement("span");
        content.style.fontFamily = "'Segoe UI', Verdana";
        content.style.fontSize = "13px";
        content.appendChild(span);
    } else {
        span = content.children[0];
    }

    if (currentpatients > 500) {
        span.style.color = "#FF0000";
    } else {
        span.style.color = "#000000";
    }
    span.textContent = currentpatients;
}

// .razor ファイルから上記の関数を呼び出せるように以下の記述が必用
igRegisterScript("onUpdatingNcurrentpatientsColumn", onUpdatingNcurrentpatientsColumn, false);

セルの値を判定して特定のスタイルを与える処理を行っているほか、document.createElement() でHTMLエレメントを作成して「現在の感染者数」の数値を入れ、ゼロからセルの中身を構成し直している点と、
最終行の igRegisterScript() の記述が必要な点に注意してください。

最後に wwwroot/index.html で先ほど作成した DataGridColumnTypes.js ファイルを読みこむように設定し、実行します。

# ファイル名「index.html」を以下のように変更します。
<!DOCTYPE html>
...(略)...
    <script src="_framework/blazor.webassembly.js"></script>
    <script src="_content/IgniteUI.Blazor/app.bundle.js"></script>
    <script src="DataGridColumnTypes.js"></script>
</body>
</html>

Image from Gyazo

このように、指定した条件のセルにスタイルが適用できることが確認できます。

列集計

列集計機能を用いてデータ全体の合計の値などが確認できるようにします。SummaryScope プロパティを使用してグリッド部分に以下のように追記します。

# ファイル名「Grid.razor」を以下のように変更します。
<DataGrid Height="90%" Width="100%" DataSource="@GridData" AutoGenerateColumns="false" SelectionMode="GridSelectionMode.SingleRow" @ref="DataGridRef" SummaryScope="DataSourceSummaryScope.Root">

次に OnDataGridRef() 関数を新たに作成し、各列の集計に関するロジックを記述していきます。

# ファイル名「Grid.razor」を以下のように変更します。
    private void OnDataGridRef()
    {

        var PrefectureCount = new ColumnSummaryDescription()
        {
            Field = "Name_jp",
            Operand = SummaryOperand.Count
        };
        var NpatientsSum = new ColumnSummaryDescription()
        {
            Field = "Npatients",
            Operand = SummaryOperand.Sum
        };
        var NcurrentpatientsSum = new ColumnSummaryDescription()
        {
            Field = "Ncurrentpatients",
            Operand = SummaryOperand.Sum
        };
        var NexitsSum = new ColumnSummaryDescription()
        {
            Field = "Nexits",
            Operand = SummaryOperand.Sum
        };
        var NdeathsSum = new ColumnSummaryDescription()
        {
            Field = "Ndeaths",
            Operand = SummaryOperand.Sum
        };
        var NheavycurrentpatientsSum = new ColumnSummaryDescription()
        {
            Field = "Nheavycurrentpatients",
            Operand = SummaryOperand.Sum
        };
        var NinspectionsSum = new ColumnSummaryDescription()
        {
            Field = "Ninspections",
            Operand = SummaryOperand.Sum
        };
        this.DataGridRef.SummaryDescriptions.Add(PrefectureCount);
        this.DataGridRef.SummaryDescriptions.Add(NpatientsSum);
        this.DataGridRef.SummaryDescriptions.Add(NcurrentpatientsSum);
        this.DataGridRef.SummaryDescriptions.Add(NexitsSum);
        this.DataGridRef.SummaryDescriptions.Add(NdeathsSum);
        this.DataGridRef.SummaryDescriptions.Add(NheavycurrentpatientsSum);
        this.DataGridRef.SummaryDescriptions.Add(NinspectionsSum);
    }

今回は sum と count のみ使用しましたが、最小値や最大値、平均値などの表示も可能です。詳細は以下のドキュメントをご参照ください。

Blazor 列集計

最後に DataGridRef に OnDataGridRef() 関数の呼び出しを記述し、実行します。

# ファイル名「Grid.razor」を以下のように変更します。
    private DataGrid DataGridRef
    {
        get { return grid; }
        set
        {
            grid = value;
            OnGridRefChanged();
            this.OnDataGridRef();
            StateHasChanged();
        }
    }

Image from Gyazo

グリッドの最下部に各列の合計を表示することが出来ました。

グリッドの機能についてはまだまだ紹介しきれていないものや、細かな調整が出来る API 等がありますので詳細はドキュメントを参照ください。次回は Blazor チャートを実装していきたいと思います。

Blazor Data Grid 概要

今回作成したサンプルアプリケーションは以下よりダウンロードいただけます。

Ignite-UI-for-Blazor_4.zip

Ignite UI for Blazor トライアル版を利用するには

Ignite UI for Blazor はトライアル板での試用が可能です。
トライアル版を利用するためには以下のページよりアカウントの作成を行ってください。登録より30日間、弊社のテクニカルサポートをご利用いただくことが出来ますのでお気軽にお問い合わせください。

https://iam.infragistics.com/Account/Register

また、製品をご購入をご検討のお客様は以下のページよりお気軽にお問い合わせください。

https://jp.infragistics.com/about-us/contact-us

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ウィンドウ(フォーム)背景に模様

000.png

App.xaml
<Application
    x:Class="SampleApp.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:SampleApp"
    StartupUri="MainWindow.xaml">
    <Application.Resources>

        <!--  既定のButtonスタイル  -->
        <Style TargetType="Button">
            <Setter Property="Margin" Value="8" />
            <Setter Property="Width" Value="150" />
            <Setter Property="HorizontalAlignment" Value="left" />
        </Style>

        <!--  模様付きBorderスタイル  -->
        <Style x:Key="CheckeredPatternStyle" TargetType="Border">
            <Setter Property="Background">
                <Setter.Value>
                    <DrawingBrush
                        Stretch="None"
                        TileMode="Tile"
                        Viewport="0,0,100,100"
                        ViewportUnits="Absolute">
                        <DrawingBrush.Drawing>
                            <DrawingGroup>
                                <GeometryDrawing Brush="Black">
                                    <GeometryDrawing.Geometry>
                                        <RectangleGeometry Rect="0,0,100,100" />
                                    </GeometryDrawing.Geometry>
                                </GeometryDrawing>
                                <GeometryDrawing Brush="ForestGreen">
                                    <GeometryDrawing.Geometry>
                                        <GeometryGroup RenderOptions.EdgeMode="Aliased">
                                            <RectangleGeometry Rect="0,0,50,50" />
                                            <RectangleGeometry Rect="50,50,50,50" />
                                        </GeometryGroup>
                                    </GeometryDrawing.Geometry>
                                </GeometryDrawing>
                            </DrawingGroup>
                        </DrawingBrush.Drawing>
                    </DrawingBrush>
                </Setter.Value>
            </Setter>
        </Style>

    </Application.Resources>
</Application>
MainWindow.xaml
<Window
    x:Class="SampleApp.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:local="clr-namespace:SampleApp"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    Title="MainWindow"
    Width="600"
    Height="400"
    MinWidth="250"
    MinHeight="200"
    ResizeMode="CanResizeWithGrip"
    mc:Ignorable="d">

    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition Width="0.4*" />
        </Grid.ColumnDefinitions>

        <Border Grid.ColumnSpan="2" Style="{StaticResource CheckeredPatternStyle}" />

        <StackPanel>
            <Button Content="Button" />
            <Button Content="Button" />
            <Button Content="Button" />
        </StackPanel>

        <TextBox
            Grid.Column="1"
            Margin="8"
            Opacity="0.9"
            Text="こんにちは"
            VerticalScrollBarVisibility="Visible" />
    </Grid>
</Window>
csproj
<Project Sdk="Microsoft.NET.Sdk">

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

</Project>
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

文字列に変数を混ぜる方法を言語ごとにまとめてみた

ゆるっと Advent Calender 2020 の初日に参加させていただきましたー。
よろしくお願いします。

初日にふさわしいかわかりませんが、ゆるゆる仕事してたら恥をかいた件を書きますね。

先日先輩にレビューしてもらったとき、文字列の中に変数を足しこむやり方を、+演算子を使ってやっていたら先輩に『ダサい』と一蹴されました。(*'▽')ガフッ

string.js
const word = "hogehoge";
const text = "彼はおもむろにこう言った。\n" + word + " 』、と。";
console.log(text);
彼はおもむろにこう言った。
『 hogehoge 』、と。

勉強不足でごめんなさい。( ;∀;)
あと、ユニク〇ばかり着ててごめんなさい。

反省したので自分の学んだことのある言語での書き方や名称をまとめたい思います。

Javascript, Node.js

Javascript および Node.js ではテンプレートリテラルという名称になっています。

文字列をグレイヴ・アクセント(`)で囲み、変数を入れるときはドル記号と波括弧でくくります。

templateLiterals.js
const word = "hogehoge";
const text = `彼はおもむろにこう言った。\n『 ${word} 』、と。`;
console.log(text);
彼はおもむろにこう言った。
『 hogehoge 』、と。

Python

Python ではフォーマット済み文字列リテラルという名称になっています。

f または F を先頭に書いてから文字列を書いていきます。
変数を入れるときは波括弧で区切ります。

formattedStringLiteral.py
word = "hogehoge";
text = f"彼はおもむろにこう言った。\n{word} 』、と。";
print(text);
彼はおもむろにこう言った。
『 hogehoge 』、と。

Java

ない。

強いて言うなら String.format() を使うとできる。

stringFormat.java
String word = "hogehoge";
String text = "彼はおもむろにこう言った。\n『 %s 』、と。";
String output = String.format(text, word);
System.out.println(output);
彼はおもむろにこう言った。
『 hogehoge 』、と。

C♯

C# では文字列補間という名称になっています。

$ を先頭に書いてから文字列を書いていきます。
変数を入れるときは波括弧で区切ります。

stringInterpolation.cs
string word = "hogehoge";
string text = $"彼はおもむろにこう言った。\n『 {word} 』、と。";
System.Console.WriteLine(text);
彼はおもむろにこう言った。
『 hogehoge 』、と。

おわりに

Java にはなかったもんなー( ゚Д゚)

知らなかったの私だけかもしれませんが、実践に勝る経験はありませんね。

この記事が誰かの助けになれば幸いです。|д゚)

自身のメモ用でもあるので、新しい言語を使うときには更新していきますー。

ではまた!(^^)/

参考にさせていただきましたm(_ _)m

MDN - テンプレートリテラル
Python documentation - フォーマット済み文字列リテラル
.NET documentation - 文字列補間

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む