Shell - DrumMidiEditor/DrumMidiEditorApp GitHub Wiki
https://docs.microsoft.com/ja-jp/windows/apps/design/shell/
Notifications Visualizer
https://docs.microsoft.com/ja-jp/windows/apps/design/shell/tiles-and-notifications/notifications-visualizer
タイルとトースト通知の視覚的なプレビューが行える
ローカル <タイル、バッジ、トースト>
アプリが実行されている間、タイルやバッジを直接更新している間
またはトースト通知を送信している間に通知を送信する API 呼び出しのセットです。
* 音楽アプリでは、タイルを更新して "再生中" の音楽を表示
* ゲーム アプリでは、ユーザーがゲームから離れるとタイルを更新してユーザーのハイ スコアを表示
* グリフでアプリに新しい情報があることが示されたバッジは、アプリがアクティブ化されるとクリア
スケジュール <タイル、トースト>
指定した時間に更新が行われるように事前に通知をスケジュールする API 呼び出しのセットです。
* カレンダー アプリでは、予定されている会議用のトースト通知のアラームを設定
定期的 <タイル、バッジ>
クラウド サービスをポーリングして新しいコンテンツの有無を調べて
タイルとバッジを一定の間隔で定期的に更新する通知です。
* 天気予報アプリでは、予報を表示するタイルを 30 分間隔で更新
* "日替わりセール情報" サイトでは、本日のお買い得品を毎朝更新
* イベントまでの日数を表示するタイルでは、表示される日数のカウントダウンを毎日深夜 0 時に更新
プッシュ <タイル、バッジ、トースト、直接>
アプリが実行されていなくてもクラウド サーバーから送信される通知です。
* ショッピング アプリでは、トースト通知を送信して、ユーザーが注目している商品のセール情報
* ニュース アプリでは、ニュース速報が発生したときにタイルを更新
* スポーツ アプリでは、試合の進行中にタイルを更新
* 通信アプリでは、メッセージや電話の着信をアラートで知らせる

トースト通知は、ユーザーの画面の右下と通知センター (Windows 10のアクション センターと呼ばれます) に表示されるWindows通知
パッケージの追加が必要
トースト通知クリック時に、アプリがアクティブ化されるが
その際に、下記設定をしていないとエラーになる。
- Visual Studio の [ツール]-[GUID の作成]からGUIDを取得
<Guid("013F361C-A05E-4425-9E0F-F9D7EA076E56")>
- Package.appxmanifest を編集
<Package
...
xmlns:com="http://schemas.microsoft.com/appx/manifest/com/windows10"
xmlns:desktop="http://schemas.microsoft.com/appx/manifest/desktop/windows10"
IgnorableNamespaces="... com desktop">
...
<Applications>
<Application>
...
<Extensions>
<!--Specify which CLSID to activate when notification is clicked-->
<desktop:Extension Category="windows.toastNotificationActivation">
<desktop:ToastNotificationActivation ToastActivatorCLSID="013F361C-A05E-4425-9E0F-F9D7EA076E56" />
</desktop:Extension>
<!--Register COM CLSID-->
<com:Extension Category="windows.comServer">
<com:ComServer>
<com:ExeServer Executable="DrumMidiEditorApp\DrumMidiEditorApp.exe" DisplayName="DrumMidiEditorApp" Arguments="----AppNotificationActivated:">
<com:Class Id="013F361C-A05E-4425-9E0F-F9D7EA076E56" />
</com:ExeServer>
</com:ComServer>
</com:Extension>
</Extensions>
</Application>
</Applications>
</Package>


// トーストコンテンツを構成後、通知
new ToastContentBuilder()
// ---------------------------------------------------------
// Launch:ユーザーがトーストをクリックしたときにアプリに渡される引数を定義
// ---------------------------------------------------------
.AddArgument("action", "viewConversation")
.AddArgument("conversationId", 9813)
// ---------------------------------------------------------
// Visual:トーストの視覚的な部分
// ---------------------------------------------------------
// ヘッダー:通知ごとに同じ ID を指定すると通知内でグループ化される
.AddHeader( "6289", "HeaderTitle", "action=openConversation&id=6289")
// テキスト要素は3つまで追加可能。1行目がメインで、2,3行目がサブ情報
.AddText( "トースト テスト通知", hintMaxLines: 2 )
.AddText( "説明要素:歩きスマホは" )
.AddText( "説明要素:止めましょう" )
// インライン画像
.AddInlineImage( new Uri( "https://avatars.githubusercontent.com/u/97685486?v=4" ) )
// アプリ ロゴの上書き:Windows 11では無効?(アプリロゴは Attribute 領域に表示)
//.AddAppLogoOverride(new Uri("ms-appdata:///local/Andrew.jpg"), ToastGenericAppLogoCrop.Circle)
// ヒーロー イメージ:Attribute領域の上にイメージを表示
.AddHeroImage( new Uri( "https://user-images.githubusercontent.com/97685486/182838106-50765a8a-814a-42c6-9714-23a23284b593.png" ) )
/**
* URI指定パターン
* - http:// http/https リモート Web画像 ファイルサイズの制限あり
* - ms-appx:///
* - ms-appdata:///
*/
// カスタム タイムスタンプ:通知時刻をアプリ側から指定可能
.AddCustomTimeStamp( new DateTime( 2017, 04, 15, 19, 45, 00, DateTimeKind.Utc ) )
// 進捗状況バー
.AddVisualChild
(
new AdaptiveProgressBar()
{
Title = "進捗バー",
Value = new BindableProgressBarValue( "progressValue" ),
ValueStringOverride = new BindableString( "progressValueString" ),
Status = new BindableString( "progressStatus" )
}
)
// ---------------------------------------------------------
// Action:トーストの対話的な部分 (入力やアクションなど)
// ---------------------------------------------------------
// テキスト入力
.AddInputTextBox( "tbReply", placeHolderContent: "Type a response" )
// 選択入力
.AddToastInput
(
new ToastSelectionBox( "time" )
{
DefaultSelectionBoxItemId = "lunch",
Items =
{
new ToastSelectionBoxItem( "breakfast" , "Breakfast" ),
new ToastSelectionBoxItem( "lunch" , "Lunch" ),
new ToastSelectionBoxItem( "dinner" , "Dinner" ),
}
}
)
// 再通知時間入力
.AddToastInput
(
new ToastSelectionBox( "snoozeTime" )
{
DefaultSelectionBoxItemId = "15",
Items =
{
new( "5" , "5 minutes" ),
new( "15" , "15 minutes" ),
new( "60" , "1 hour" ),
new( "240" , "4 hours" ),
new( "1440" , "1 day" )
}
})
// ボタン
.AddButton
(
new ToastButton()
.SetContent("Reply")
.SetTextBoxId( "tbReply" )
.AddArgument("action", "reply")
.SetBackgroundActivation()
)
.AddButton
(
new ToastButton()
.SetContent("Like")
.AddArgument("action", "like")
.SetBackgroundActivation()
)
//.AddButton
// (
// new ToastButton()
// .SetContent("View")
// .AddArgument("action", "viewImage")
// .AddArgument("imageUrl", image.ToString() )
// )
// [一時停止(再通知)]ボタン
.AddButton
(
new ToastButtonSnooze()
{
SelectionBoxId = "snoozeTime",
}
)
// [無視]ボタン
.AddButton( new ToastButtonDismiss() )
// シナリオ
.SetToastScenario( ToastScenario.Reminder ) // リマインダー
//.SetToastScenario( ToastScenario.Alarm ) // アラーム:トースト通知に少なくとも 1 つのボタンを指定する必要あり
//.SetToastScenario( ToastScenario.IncomingCall ) // 着信呼び出し
//.SetToastScenario( ToastScenario.******** ) // 重要な通知:未実装
// ---------------------------------------------------------
// Audio:トーストがユーザーに表示されるときに再生されるオーディオ
//
// [既定のサウンド一覧]
// https://docs.microsoft.com/ja-jp/uwp/schemas/tiles/toastschema/element-audio#attributes-and-elements
// ---------------------------------------------------------
.AddAudio( new Uri( "ms-appx:///Sound.mp3" ) )
// ---------------------------------------------------------
// Show
// ---------------------------------------------------------
.Show
(
( toast ) =>
{
toast.Tag = "TagName";
toast.Group = "GroupName";
toast.ExpirationTime = DateTime.Now.AddMinutes( 3 ); // 有効期限
toast.Data = new NotificationData();
toast.Data.Values[ "progressValue" ] = "0.6";
toast.Data.Values[ "progressValueString" ] = "15/26 songs";
toast.Data.Values[ "progressStatus" ] = "Downloading...";
toast.Data.SequenceNumber = 0; // 0(常に更新する)、1-(シーケンス位置指定)
}
);
進捗バーの更新
var data = new NotificationData
{
SequenceNumber = 0, // 0(常に更新する)
};
data.Values[ "progressValue" ] = "1.0";
data.Values[ "progressValueString" ] = "26/26 songs";
data.Values[ "progressStatus" ] = "Finished";
ToastNotificationManager.CreateToastNotifier().Update( data, "TagName", "GroupName" );
// 全てのトースト履歴をクリア
ToastNotificationManagerCompat.History.Clear();
// 対象グループのトースト履歴を削除
ToastNotificationManagerCompat.History.RemoveGroup( "GroupName" );
// 対象タグのトースト履歴を削除
ToastNotificationManagerCompat.History.Remove( "TagName" );
// 対象タグ・グループに一致するトースト履歴を削除
ToastNotificationManagerCompat.History.Remove( "TagName", "GroupName" );
// スケジュール通知
new ToastContentBuilder()
.AddText( "5秒後に通知" )
.Schedule
(
DateTime.Now.AddSeconds( 5 ),
toast =>
{
toast.Tag = "18365";
toast.Group = "ASTR 170B1";
}
);
// スケジュールの削除
var notifier = ToastNotificationManagerCompat.CreateToastNotifier();
var scheduledToasts = notifier.GetScheduledToastNotifications();
var toRemove = scheduledToasts
.FirstOrDefault( toast => toast.Tag == "18365" && toast.Group == "ASTR 170B1" );
if ( toRemove != null )
{
notifier.RemoveFromSchedule( toRemove );
}

同じヘッダーIDを使用して、トースト通知
// ヘッダーテスト
new ToastContentBuilder()
// ---------------------------------------------------------
// Visual:トーストの視覚的な部分
// ---------------------------------------------------------
// ヘッダー
.AddHeader( "6289", "HeaderTitle", "action=openConversation&id=6289")
// テキスト要素は3つまで追加可能。1行目がメインで、2,3行目がサブ情報
.AddText( "222" )
// ---------------------------------------------------------
// Show
// ---------------------------------------------------------
.Show
(
( toast ) =>
{
toast.Tag = "TagName2";
toast.Group = "GroupName";
toast.ExpirationTime = DateTime.Now.AddMinutes( 3 ); // 有効期限
}
);
残
- アダプティブ コンテンツ
- コンテキスト メニューのアクション
- アクティブ化の設定が必要

アプリ特有の概要や状態情報を伝達する
- ネットワーク接続状態
- ユーザーの状態
- 未読メールの数
- ソーシャル メディア アプリでの新しい投稿数
など
通知バッジは、アプリが実行されているかどうかに関係なく
アプリのタスク バーのアイコンとスタート タイルの右下隅に表示される

var badgeXml = BadgeUpdateManager.GetTemplateContent( BadgeTemplateType.BadgeNumber );
// 数値を設定
// 1 ~ 99 の数字。 値 0 はグリフ値 "none" と同じであり、バッジをクリア
// 99 を超える数字は、"99+" 表示
var badgeElement = badgeXml.SelectSingleNode( "/badge" ) as XmlElement;
badgeElement?.SetAttribute( "value", "99" );
// バッジ更新
BadgeUpdateManager.CreateBadgeUpdaterForApplication().Update( new( badgeXml ) );

var badgeXml = BadgeUpdateManager.GetTemplateContent( BadgeTemplateType.BadgeGlyph );
var badgeElement = badgeXml.SelectSingleNode( "/badge" ) as XmlElement;
badgeElement?.SetAttribute( "value", "alert" );
// -----------------------------------------------
// [グリフ設定値]
// -----------------------------------------------
// none : なし
// activity : activity
// alarm : alarm(アラーム)
// alert : アラート
// attention : attention(注意)
// available : 利用可能
// away : away(離席中)
// busy : busy(取り込み中)
// error : error
// newMessage : newMessage(新しいメッセージ)
// paused : paused(一時停止)
// playing : playing(再生)
// unavailable : unavailable(利用不可)
// -----------------------------------------------
// バッジ更新
BadgeUpdateManager.CreateBadgeUpdaterForApplication().Update( new( badgeXml ) );
// バッジをクリア
BadgeUpdateManager.CreateBadgeUpdaterForApplication().Clear();
Windows プッシュ通知サービス (WNS) を利用することで
独自のクラウド サービスからトースト更新、タイル更新、バッジ更新、直接更新を送ることができる
サービスの登録が必要で、試すのはめんどう。
https://docs.microsoft.com/ja-JP/azure/notification-hubs/notification-hubs-windows-store-dotnet-get-started-wns-push-notification
アプリのタスク バーへのピン留めをアプリから促すことができる
// APIサポートチェック
if ( !ApiInformation.IsTypePresent( "Windows.UI.Shell.TaskbarManager" ) )
{
return;
}
// タスク バーが存在し、ピン留めを使用できるかどうかを確認
if ( !TaskbarManager.GetDefault().IsPinningAllowed )
{
return;
}
// アプリが現在タスク バーにピン留めされているかどうかを確認
if ( await TaskbarManager.GetDefault().IsCurrentAppPinnedAsync() )
{
return;
}
// ピン止め確認:
if ( await TaskbarManager.GetDefault().RequestPinCurrentAppAsync() )
{
}
RequestPinCurrentAppAsync でエラーとなる。
(インターフェイスが登録されていません)
タイトルバーを自分でカスタマイズできるよって話かね
タイルとは、[スタート] メニュー上でアプリを表すもの
Package.appxmanifestで設定
URI をポーリングして、タイルの状態を更新したりもできるっぽい。