📖 wpf-window-practice - Git Hub に上げたもの
📖 wpf-mutex-practice - Git Hub に上げたもの
<Button Name="btn0" HorizontalAlignment="Center"
VerticalAlignment="Center" Width="100" Height="50">
別のウィンドウを開く
</Button>
<Window x:Class="WpfWindowPractice.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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfWindowPractice"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<Button Name="btn0" HorizontalAlignment="Center"
VerticalAlignment="Center" Width="100" Height="50">
別のウィンドウを開く
</Button>
</Grid>
</Window>
<Button Name="btn0" HorizontalAlignment="Center"
VerticalAlignment="Center" Width="100" Height="50">
閉じる
</Button>
ramen-tabero-futsu2.png
「 👆 Gridタグの間に こう書くらしいぜ」
「 レイアウトを作っただけで ボタンを押したときとかの 働きのロジックは まだ書いてないな」
「 👆 プロパティ ウィンドウのテキストボックスを ダブルクリックしろだぜ」
「 しかし テキストボックスをダブルクリックするとか、そんな ふだんしないようなことを
ユーザーに求めるUIデザインは ダメだと思うぜ。
こんなUIデザインが いっぱいある。 わたしは悲しい」
「 👆 一応説明しておくと、 Buttonタグに Click属性が増えてるぜ」
var win = new Window1();
win.Show();
「 👆 戻って、2行だけかきたせば サブ ウィンドウが開くようだぜ」
「 Window を new して .Show() するだけじゃないか。簡単だろ」
「 ウィンドウが2つになったり、片方が閉じられたら もう片方も閉じたいとか、
やること増えると どんどん 複雑になっていくのよ」
「 👆 サブ ウィンドウのボタンには 閉じるためのコードを1行だけ書くぜ」
「 👆 メイン ウィンドウの [別のウィンドウを開く]
ボタンをクリックすれば、
サブ ウィンドウ が開くぜ」
「 👆 Mutex(ミューテックス;2重起動防止)付いてないんで、
ボタン連打して PCが潰れるまで 窓増やせるぜ」
📖 C#のMutexとは?2つの種類と使用方法を理解しよう!
「 👆 Mutex(ミューテックス;2重起動防止)のことは、この記事を参考にしようぜ。
WPFの機能じゃなくて、C#言語が備えてる Windowsプログラミングという感じのものだぜ」
「 説明が WPF じゃなくて Windows フォーム のものじゃない?」
「 そう! Microsoft Windows のプログラミングに関わると
B で X を使う方法を知りたいのに、A で X を使う方法の記事が 山ほどヒットする!
そして
A で X を使う方法は C だし、 B で X を使う方法は D だぜ!
D が知りたいのに C の記事が出てくる!
Web上の検索は 意味を考えて拾ってくるのではなく 文字で当てて拾ってくるし、
現代の Google は よく検索されているだろう文字列の方を優先して 見つけてくるから D が出てくる!
Microsoft も Google も それを解決できていないところを見ると
インターネット上に大量の情報を 増やすことだけして それを整理することは できてないんだぜ。
だから わたしが 人力で記事を書いて整理している。
わたしは Microsoft や Google の AI技術にはできない 価値の高い記事を書くことを 人力でやっている」
📖 WPF:Mainメソッドを書き変えるには?[C#/VB]
「 👆 プログラムが最初に実行されるところのことを エントリーポイント というが、
WPF では App.xaml のところに 自動生成 されるらしく、プログラマーは エントリーポイントに プログラムを書けないぜ」
「 👆 App.xaml のビルドアクションが アプリケーション定義
になってるから Main 関数が自動生成で上書きされてしまうそうで、
ビルドアクションを ページ
にすれば Main 関数の自動生成を止めさせることができるそうだぜ」
📖 Application Management Overview
「 👆 アプリケーション クラスを作るのが アプリケーション定義
のようだぜ。
App.xaml を Page にしていいのか、わたしには判断つきかねるぜ。真似せんとこ」
「 Microsoft のドキュメントを読んでも 分からないことが分かるようになることが 少ない。
既に分かってるやつが 答え合わせをするために読むドキュメントだぜ」
📖 Replacing the WPF entry point
「 👆 定番の Stack Overflow も見てみようぜ」
「 Application Definition
を Page
に変える方法は たくさんの記事が出回っているが 望まない結果を得るから
別の方法にしろ、と書いてくれている人がいるぜ」
「 1秒で 分るよな そんなことは。 不具合の発見も考慮して コントロールできていないものを使わないという 考えができてるやつだぜ。
こうやったら できた、で うまく行った、とか やってるやつは 誰にもすくわれない流しそうめんのように 海に流れ出ていってほしい」
「 👆 真のプログラマーは こうやって使ってほしいと用意されている方法を使う。 App.xaml の Startup メソッドを実装するのが正解。
テキストボックスを ダブルクリックするという奇行をしろだぜ」
「 👆 すると Startup
という属性が付いていて、Application_Startup
を呼び出します、という紐づけが行われたな。
ここで、 StartupUri
という属性ではないことに 気を付けてくれだぜ」
「 隠しテクニックみたいなことをやらせる上に さらに まぎらわし!」
「 👆 だから WPFアプリケーションでは Main 関数から始めるのではなく、 App.xaml の Startup 属性に紐づいているメソッドから
始めるのが、 Microsoft から見て そうやってほしい使われ方なのだろう」
「 そんなこと Microsoft のドキュメントの どこに書いてるんだぜ?」
using System.Threading;
using System.Windows;
namespace WpfMutexPractice
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
/// <summary>
/// アプリケーションのエントリーポイントです
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Application_Startup(object sender, StartupEventArgs e)
{
// Mutexの初期所有権が呼び出し元のスレッドに付与されたかどうか
bool createdNew;
// Mutex作成
Mutex mutex = new Mutex(true, "MySampleApplication", out createdNew);
if (!createdNew)
{
// Mutexの初期所有権が付与されなかった場合は、多重起動と判断して終了します
MessageBox.Show("すでに起動しています。2つ以上同時に起動できません。");
// Mutex解放
mutex.Close();
return;
}
try
{
// メイン ウィンドウ表示
var window = new MainWindow();
window.Show();
}
finally
{
// Mutex解放
mutex.ReleaseMutex();
mutex.Close();
}
}
}
}
📖 C#のMutexとは?2つの種類と使用方法を理解しよう!
「 それだと App.xaml に StartupUri="MainWindow.xaml"
と書いてあるから、2つのコードで ウィンドウを起動しようとしない?」
「 👆 StartupUri="MainWindow.xaml"
を消すぜ」
「 👆 それより こっちのページを見ろだぜ。 WPF で 二重起動を防止する方法が書いてるぜ」
「 👆 しかし まだ気になることがあったので もっと記事を読むぜ」
「 既に起動していたら 2つ目は起動しないだけでなく、
既に起動しているウィンドウを最前面に出すコードかだぜ! ケアが すげえ!」
「 でも C# 使ってるのに 32bit Windows の Win32API ネイティブ メソッド呼び出してるの いけてなくない?」
「 ウィンドウのハンドル A を取得して、そのハンドル A がウィンドウを指すか確認して、
そのウィンドウ A の子ウィンドウまで含めて最後に利用していたウィンドウのハンドル B を取得して、
そのウィンドウ B が可視状態であるかまで確認して、可視であれば、
ウィンドウ B を最大化ウィンドウでも 最小化ウィンドウでもなく ノーマルに表示し、
そして ウィンドウ B を最前面に出す、
ということを やればいいわけだぜ」
「 👆 プログラマーの実践を知ってほしい。 分からなかったら調べろということだぜ。
C# でも ウィンドウのハンドルを取得することはできるらしいぜ。
Win32API とは おさらば しようぜ?」
「 お父んに おさらば する権限があるかどうかは プログラミング スキルとは関係ないよな」
「 プログラマーの足を引っ張っているのは 味方のプログラマーですからね。
プログラマーの最大の親友は 敵プログラマーなのよ」
📖 [C#][.NET] .NET アプリケーション (WPF/Windows フォーム) で多重起動を禁止し、単一のプロセスで動作させる
「 👆 これは いけそうだが、 バグを盛り込まずに実装できる気がしね」
「 ウィンドウ A を起動したとき、二重起動したら困るんで、
既に起動していた同じプログラムのウィンドウ B が起動しているときは A は起動せず、
既に起動しているウィンドウ B を最前面に出してちょうだいよ。
そのウィンドウが子ウィンドウ C を出していて、最後に触っていたのがそのウィンドウ C だったら、
B ではなく C を最前面に出してよ。
どんなアプリでもよく見かける機能だし、WPFのプログラマーなら、さくっとやってちょうだいよ
Win32API無しで」
「 クリボーを超える高さにジャンプできないチビ マリオの気分だぜ。
これは やばいな」
<Application x:Class="WpfMutexPractice.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfMutexPractice"
StartupUri="MainWindow.xaml"
Startup="Application_Startup" Exit="Application_Exit">
<Application.Resources>
</Application.Resources>
</Application>
「 👆 ひとまず、単に 二重起動しない ミューテックスを使ったアプリのソースを公開するぜ。まず xaml」
using System.Threading;
using System.Windows;
namespace WpfMutexPractice
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
/// <summary>
/// ミューテックス(二重起動防止)作成
/// </summary>
private Mutex _mutex = new System.Threading.Mutex(false, "Muzudho's WPF mutex practice");
/// <summary>
/// アプリケーションのエントリーポイントです
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Application_Startup(object sender, StartupEventArgs e)
{
if (!_mutex.WaitOne(0, false))
{
// TODO 既に起動しているウィンドウをアクティブ(最前面に表示)します。この機能は難しいので、今回は実装しません
// 既に起動しているので終了させます
_mutex.Close();
_mutex = null;
this.Shutdown();
}
}
private void Application_Exit(object sender, ExitEventArgs e)
{
if (_mutex != null)
{
_mutex.ReleaseMutex();
_mutex.Close();
}
}
}
}
「 👆 プロジェクトを右クリックから、ファイル エクスプローラーを開いてくれだぜ」
「 👆 そしたら 📂./bin/Debug/netcoreapp3.1 とフォルダーを下りていってくれだぜ」
「 👆 WpfMutexPractice.exe
を2回ほど ダブルクリックしても、二重起動しないことを確かめてくれだぜ。
ひとまず そこまで」
「 👆 ウィンドウの後ろに回っている、既に起動しているウィンドウが 最前面にこないでしょ。
これじゃ 製品の品質としては ダメなのよ」
「 👆 説明を読むと、ローカルPCのどこかにある クラスのインスタンスをバイナリにして投げ込んでおける送信先の住所のようなものが
あるらしいぜ。 URLの書き方は上記の通り」
「 チャンネル名は任意だぜ。受け取る相手が知ってる名前にしろだぜ。
例えば .exe ファイルを右クリックしてプロパティを見れば書いているような 製品名 でも入れとけだぜ。
まあ 製品名 が被ってることもあるだろうから、間違って混線することはあるだろうな。
製品名が被ったら それ以外の見分け方の手段も講じなければいけないかもしれないが、今は 良しとしようぜ」
「 アイテム名は任意だぜ。受け取る相手が知ってる名前にしろだぜ。
例えば Move とかいう名前にして、将棋の指し手でも 送り付ければいいんじゃないかな」
namespace WpfIpcPracticeAlice
{
using System;
/// <summary>
/// 名前と本文
///
/// プロセス間通信(IPC) によって複数のプロセスで共有します
/// </summary>
public class MessageCard : MarshalByRefObject
{
/// <summary>
/// 名前
/// </summary>
public string Name { get; private set; }
/// <summary>
/// メッセージ
/// </summary>
public string Message { get; private set; }
}
}
「 👆 試しに 名前と本文だけ持つクラスを作って、チャンネルに送れるか試してみようぜ?」
「 System.MarshalByRefObject
って型を気にしないオブジェクトだろ。難しいの使ってんな」
「 👆 げえっ! レガシー技術かだぜ! 覚える気なくなったぜ」
「 調べたら .NET core では廃止されてた。
どうすっかな 仕事で使うが プライベートの時間を使ってまで 覚えたくないぜ」
Crieitは個人で開発中です。
興味がある方は是非記事の投稿をお願いします! どんな軽い内容でも嬉しいです。
なぜCrieitを作ろうと思ったか
また、「こんな記事が読みたいけど見つからない!」という方は是非記事投稿リクエストボードへ!
こじんまりと作業ログやメモ、進捗を書き残しておきたい方はボード機能をご利用ください!