Archive : 2009-05
Windows API Code Pack for Microsoft .NET Framework (v0.85)さわってみた。
中身は
- Windows 7 ライブラリを含む Windows Shell 名前空間オブジェクト、既知のフォルダーと非ファイルシステム コンテナ
- Windows Vista と Windows 7 のタスクダイアログ
- WPF と Windows Forms での Windows 7 Explorer Browser Control のサポート
- シェル プロパティ システムのサポート
- Windows 7 タスクバー ジャンプリスト、アイコン オーバーレイ、プログレスバー用のヘルパー
- Windows Vista と Windows 7 コモン ファイル ダイアログのサポート(カスタム ファイル ダイアログを含む)
- Direct3D 11.0とDXGI 1.0/1.1 APIのサポート
- センサー プラットフォーム API
- 拡張言語サービス API
川西 裕幸のブログ : Windows API Code Pack for Microsoft .NET Framework (v0.85)
だそうです。以下では同梱のサンプル(DirectX以外)を動かしてみた際のメモ。
Explorer Browser Control
Explorerのコントロール。使い場所は色々ありそうですね。左がWPF版、右がWin Forms版。もちろんWPF版の主要なプロパティは依存関係プロパティになっていまして、Thumbnail Sizeというスライダーを動かせば、バインドされたサムネイルの大きさがスルスルと変わっていきました。良いですね。
Shell
KnownFoldersBrowser
既知のフォルダ?(knownFolders)の一覧を表示するデモ。一覧はMicrosoft.WindowsAPICodePack.Shell.KnownFoldersクラスで取得しています。knownFoldersはVistaで導入されたものらしい。また、standard foldersとは異なり、ベンダが追加(削除)することができるらしい。knownFoldersについて詳しくはMSDNのknownFoldersについてのページを参照のこと。
PropertyEdit
ファイルのプロパティを操作するデモ
ShellHierarchyTreeDemo
階層ツリーのデモ
ShellObjectCFDBrowser
CommonFileDialogのデモ。表示する場所の初期値として設定できるのはフォルダだけではないのが特徴。Windows 7で追加された「ライブラリ」を初期値として設定出来たり、検索条件を初期値として指定して開くことが出来ます。これはちょっと感動ものでした。二枚目のSSは検索条件として「最近使ったファイル」という条件を付加して開いたCommonFileDialog。
StarBackUp
いまいちよくわからない。フォルダ選択ダイアログのサンプル?
StockIconsDemo
システムのアイコンを取得するのに使えるMicrosoft.WindowsAPICodePack.StockIconsクラスのデモ
TaskBarDemo
Windows7でのタスクバーでの通知を活用するためのデモ。タスクバー上でのプログレス表示や、ジャンプリストの作成のデモなど。
ThumbnailBrowserDemo
選択された要素のサムネイルをMicrosoft.WindowsAPICodePack.Shell.ShellObjectクラスのThumbnailプロパティから取得してPictureBoxに描画するサンプル。
センサー プラットフォーム API
サンプル動かそうとしたら落ちた。まぁ対応するセンサデバイスがないわけだから当然ですね。
拡張言語サービス API
多言語ユーザー インターフェイスのサポートと言語サービス
Windows 7 は、多言語ユーザー インターフェイスのサポートを強化し、アプリケーションから言語サービスを利用できるようにすることで、開発者がスタンダードな手法で国際市場に向けたアプリケーションを作成できるようになっています。
Extended Linguistic Services は、小規模の同じAPI 群を使用して、さまざまな先進の言語機能を有効活用できる、Windows 7 の新機能です。開発者は Extended Linguistic Services の API を使用することにより、任意の Unicode テキストから言語を自動検出し、その情報を元にして適切な言語が選択されるような、世界中のユーザーが快適に利用できるしくみを構築できます。 Extended Linguistic Services には、テキストの書記体系を変換する、組み込みの表記変換機能もサポートされています。たとえば、簡体字中国語と繁体字中国語間でテキストを自動的に変換すれば、言語の境界を越えた相互コミュニケーションを促進することが可能です。 Extended Linguistic Services の API を使用することにより、開発者は、既存の Extended Linguistic Services に加え、将来、新しいサービスが公開されたときには、新たにコードを覚え直すことなく、必要なサービスを選ぶだけで済むようになります。
この機能を利用するためのものみたい。あんまり弄れてないです。
いつの間にかに大学の研究室で先生がGoogle AndroidのDev Phone 1を買っていました。別に自分が使うわけじゃないですが、ちょこちょこ弄らせてもらったり。しかしUI関係の研究室でもないのに、何に使うんだろ。
やっぱいいなぁAndroid。いいなぁいいなぁいいなぁ・・・。Touch Diamond買ってなければ絶対に今度docomoから出るAndroid端末買ってましたよ。はぁ・・・。
まぁいいさ、色々なことに手を出しても仕方ない。自分はWPF/Silverlightを頑張ろう。
ようやくfixしました。商学部時代と較べたらキツ過ぎだわw まぁそれでもゆとりですが。1限が一つしかないのが救いですね。授業とか研究会自体は好きなのだけど、拘束時間が長いと平日の行動の自由度が失われているのが辛い。
| 月 | 火 | 水 | 木 | 金 | |
|---|---|---|---|---|---|
| 1 | Webテキスト処理法 | ||||
| 2 | 英語(Writing) | 近代史 | バイト | インターネット | 体育 |
| 3 | モバイルネットワーク論 | SA | 情報数学1 | ||
| 4 | 情報通信セキュリティとプライバシー | 研究室 | 研究室輪講 | ||
| 5 | SA | ||||
| 6 | 研究室ミーティング |
SAというのは先生の授業の手伝い。一応バイトとしてお金が貰える。
Virtual PCに入れるだけでは飽き足らず、Windows 7 RCをデスクトップPCやラップトップPCにもインストールしている今日この頃。
ただ、入れてみたはいいものの、デュアルブートでUbuntuが入っているPCに後から入れたものだから、MBRが書き換えられてGRUBに入れなくなってしまったのでその対処法メモ。
- UbuntuのLive CDでとりあえず起動
- 今回自分は内蔵光学ドライブが壊れていたのでUSB接続の光学ドライブを使用したのですが、この場合BIOSで外部デバイスからのブートを有効にする必要があったので注意
- GNOMEパーティションエディタなりでUbuntuがインストールされているパーティションを特定。
- 再起動してLive CDの起動オプションをfile=/cdrom/preseed/ubuntu.seed boot=casper initrd=/casper/initrd.gz となっているところで”boot=casper"の部分を”root=/dev/sda1" 等環境に合わせて書き換えて起動。(参考:Goro&Ubuntu GRUBの再インストール)
- 起動できたらGRUB復活の呪文。 sudo grub-install /dev/sda
Linuxややこしいなぁ。
WPF Futuresには、WPF Model-View-ViewModel Toolkitの他にも色々な参考になるサンプルが含まれています。Southridge Hands-on-LabはWPF Ribbon ControlとDataGridを使ったリッチなアプリケーション開発のチュートリアルとなっており、PDCのセッションでも出てきていたものがチュートリアルの形式としてまとめられた物のようですね。結構大きなアプリケーションですが、手取り足取り細かく解説してくれるので、参考になるところが多いのではないでしょうか。
ただ、M-V-VMパターンには則っていないところがあり、ViewModelに書くべきロジックをViewのコードビハインドに書いていたりするのでM-V-VMパターンのサンプルとするには注意が必要です。WPF Ribbon Controlのメニュー等は、CommandとしてExecuteメソッドやCanExecuteメソッド以外にも、LabelTitleプロパティなどを持ったオブジェクトを必要とするため、View側でCommandとしてセットするオブジェクトを用意する必要があります。その制約に引きずられてViewのコードビハインドにCommandの処理ロジックを記述しているようです。
では、Ribbon Controlを使用する場合はM-V-VMパターンが使えないかというとそういう訳でもなく、SouthridgeをM-V-VMパターンに則って書き直したバージョンも存在しているようです。自分は詳しく調べられていないのですが、先ほどの問題はNonRoutedRibbonCommandDelegatorというRibbonCommandと同じインターフェイスを備えたプロキシクラスをはさむことで解決しているようです。
・・・とここまで書いたところで気づいたのですが、Ribbon V1 Roadmapをみたところ、Ribbon関係のCommandに設計変更が入るみたいですね。LabelTitleとかまでRibbonCommandに纏めるのをやめて、通常のコントロールと同じようなスタイルに戻るようです。これは素直に新しいバージョンがリリースされるのを待ったほうが楽かもしれません。
WPF Model-View-ViewModel Toolkitのテンプレートやサンプルに含まれるDelegateCommand.cs、とりあえずコメントを日本語訳しながら読んでみました。DelegateCommandという名前ですが、Composite Application Guidance for WPFのDelegateCommandとは異なります。MSDN MagazineのWPF のための MODEL-VIEW-VIEWMODEL (MVVM) デザイン パターンという記事で使われているRelayCommandに、CommandManagerのRequerySuggestedイベントへの応答の有効/無効の設定プロパティ(IsAutomaticRequeryDisabled)と、CanExecuteChangedイベントを発生させるパブリックメソッド(RaiseCanExecuteChanged)を追加し、メモリリークを防ぐためにCanExecuteChangedイベントへのハンドラを弱参照で持つようにした?感じですね。
// This source code is licensed by Microsoft under Ms-PL license.
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Input;
namespace WpfModelViewApplication1.Commands
{
/// <summary>
/// <para>
/// This class allows delegating the commanding logic to methods passed as parameters,
/// and enables a View to bind commands to objects that are not part of the element tree.
/// </para>
/// <para>
/// このクラスはパラメータとして渡されたメソッドへのコマンドのロジックの委譲を実現します。
/// また、Viewが要素ツリーに含まれないオブジェクトにコマンドをバインドすることを可能にします。
/// </para>
/// </summary>
public class DelegateCommand : ICommand
{
#region Constructors
/// <summary>
/// Constructor
/// </summary>
public DelegateCommand(Action executeMethod)
: this(executeMethod, null, false)
{
}
/// <summary>
/// Constructor
/// </summary>
public DelegateCommand(Action executeMethod, Func<bool> canExecuteMethod)
: this(executeMethod, canExecuteMethod, false)
{
}
/// <summary>
/// Constructor
/// </summary>
public DelegateCommand(Action executeMethod, Func<bool> canExecuteMethod, bool isAutomaticRequeryDisabled)
{
if (executeMethod == null)
{
throw new ArgumentNullException("executeMethod");
}
_executeMethod = executeMethod;
_canExecuteMethod = canExecuteMethod;
_isAutomaticRequeryDisabled = isAutomaticRequeryDisabled;
}
#endregion
#region Public Methods
/// <summary>
/// <para>
/// Method to determine if the command can be executed
/// </para>
/// <para>
/// コマンドが実行可能かを返す
/// </para>
/// </summary>
public bool CanExecute()
{
if (_canExecuteMethod != null)
{
return _canExecuteMethod();
}
return true;
}
/// <summary>
/// <para>
/// Execution of the command
/// </para>
/// <para>
/// コマンドを実行する
/// </para>
/// </summary>
public void Execute()
{
if (_executeMethod != null)
{
_executeMethod();
}
}
/// <summary>
/// <para>
/// Property to enable or disable CommandManager's automatic requery on this command
/// </para>
/// <para>
/// CommandManagerのこのコマンドに対する自動再要求の有効/無効を設定する
/// </para>
/// </summary>
public bool IsAutomaticRequeryDisabled
{
get
{
return _isAutomaticRequeryDisabled;
}
set
{
if (_isAutomaticRequeryDisabled != value)
{
if (value)
{
CommandManagerHelper.RemoveHandlersFromRequerySuggested(_canExecuteChangedHandlers);
}
else
{
CommandManagerHelper.AddHandlersToRequerySuggested(_canExecuteChangedHandlers);
}
_isAutomaticRequeryDisabled = value;
}
}
}
/// <summary>
/// <para>
/// Raises the CanExecuteChaged event
/// </para>
/// <para>
/// CanExecuteChangedイベントを発生させる
/// </para>
/// </summary>
public void RaiseCanExecuteChanged()
{
OnCanExecuteChanged();
}
/// <summary>
/// <para>
/// Protected virtual method to raise CanExecuteChanged event
/// </para>
/// <para>
/// CanExecuteChangedイベントを発生させるprotected virtualメソッド
/// </para>
/// </summary>
protected virtual void OnCanExecuteChanged()
{
CommandManagerHelper.CallWeakReferenceHandlers(_canExecuteChangedHandlers);
}
#endregion
#region ICommand Members
/// <summary>
/// <para>
/// ICommand.CanExecuteChanged implementation
/// </para>
/// <para>
/// ICommand.CanExecuteChangedの実装
/// </para>
/// </summary>
public event EventHandler CanExecuteChanged
{
add
{
if (!_isAutomaticRequeryDisabled)
{
CommandManager.RequerySuggested += value;
}
CommandManagerHelper.AddWeakReferenceHandler(ref _canExecuteChangedHandlers, value, 2);
}
remove
{
if (!_isAutomaticRequeryDisabled)
{
CommandManager.RequerySuggested -= value;
}
CommandManagerHelper.RemoveWeakReferenceHandler(_canExecuteChangedHandlers, value);
}
}
bool ICommand.CanExecute(object parameter)
{
return CanExecute();
}
void ICommand.Execute(object parameter)
{
Execute();
}
#endregion
#region Data
private readonly Action _executeMethod = null;
private readonly Func<bool> _canExecuteMethod = null;
private bool _isAutomaticRequeryDisabled = false;
private List<WeakReference> _canExecuteChangedHandlers;
#endregion
}
/// <summary>
/// <para>
/// This class allows delegating the commanding logic to methods passed as parameters,
/// and enables a View to bind commands to objects that are not part of the element tree.
/// </para>
/// <para>
/// このクラスはパラメータとして渡されたメソッドへのコマンドのロジックの委譲を実現します。
/// また、Viewが要素ツリーに含まれないオブジェクトにコマンドをバインドすることを可能にします。
/// </para>
/// </summary>
/// <typeparam name="T">Type of the parameter passed to the delegates</typeparam>
public class DelegateCommand<T> : ICommand
{
#region Constructors
/// <summary>
/// Constructor
/// </summary>
public DelegateCommand(Action<T> executeMethod)
: this(executeMethod, null, false)
{
}
/// <summary>
/// Constructor
/// </summary>
public DelegateCommand(Action<T> executeMethod, Func<T, bool> canExecuteMethod)
: this(executeMethod, canExecuteMethod, false)
{
}
/// <summary>
/// Constructor
/// </summary>
public DelegateCommand(Action<T> executeMethod, Func<T, bool> canExecuteMethod, bool isAutomaticRequeryDisabled)
{
if (executeMethod == null)
{
throw new ArgumentNullException("executeMethod");
}
_executeMethod = executeMethod;
_canExecuteMethod = canExecuteMethod;
_isAutomaticRequeryDisabled = isAutomaticRequeryDisabled;
}
#endregion
#region Public Methods
/// <summary>
/// <para>
/// Method to determine if the command can be executed
/// </para>
/// <para>
/// コマンドが実行可能かを返す
/// </para>
/// </summary>
public bool CanExecute(T parameter)
{
if (_canExecuteMethod != null)
{
return _canExecuteMethod(parameter);
}
return true;
}
/// <summary>
/// <para>
/// Execution of the command
/// </para>
/// <para>
/// コマンドを実行する
/// </para>
/// </summary>
public void Execute(T parameter)
{
if (_executeMethod != null)
{
_executeMethod(parameter);
}
}
/// <summary>
/// <para>
/// Raises the CanExecuteChaged event
/// </para>
/// <para>
/// CanExecuteChangedイベントを発生させる
/// </para>
/// </summary>
public void RaiseCanExecuteChanged()
{
OnCanExecuteChanged();
}
/// <summary>
/// <para>
/// Protected virtual method to raise CanExecuteChanged event
/// </para>
/// <para>
/// CanExecuteChangedイベントを発生させるprotected virtualメソッド
/// </para>
/// </summary>
protected virtual void OnCanExecuteChanged()
{
CommandManagerHelper.CallWeakReferenceHandlers(_canExecuteChangedHandlers);
}
/// <summary>
/// <para>
/// Property to enable or disable CommandManager's automatic requery on this command
/// </para>
/// <para>
/// CommandManagerのこのコマンドに対する自動再要求の有効/無効を設定する
/// </para>
/// </summary>
public bool IsAutomaticRequeryDisabled
{
get
{
return _isAutomaticRequeryDisabled;
}
set
{
if (_isAutomaticRequeryDisabled != value)
{
if (value)
{
CommandManagerHelper.RemoveHandlersFromRequerySuggested(_canExecuteChangedHandlers);
}
else
{
CommandManagerHelper.AddHandlersToRequerySuggested(_canExecuteChangedHandlers);
}
_isAutomaticRequeryDisabled = value;
}
}
}
#endregion
#region ICommand Members
/// <summary>
/// <para>
/// ICommand.CanExecuteChanged implementation
/// </para>
/// <para>
/// ICommand.CanExecuteChangedの実装
/// </para>
/// </summary>
public event EventHandler CanExecuteChanged
{
add
{
if (!_isAutomaticRequeryDisabled)
{
CommandManager.RequerySuggested += value;
}
CommandManagerHelper.AddWeakReferenceHandler(ref _canExecuteChangedHandlers, value, 2);
}
remove
{
if (!_isAutomaticRequeryDisabled)
{
CommandManager.RequerySuggested -= value;
}
CommandManagerHelper.RemoveWeakReferenceHandler(_canExecuteChangedHandlers, value);
}
}
bool ICommand.CanExecute(object parameter)
{
// if T is of value type and the parameter is not
// set yet, then return false if CanExecute delegate
// exists, else return true
// Tが値型でかつ、parameterがセットされていない場合、
// CanExecuteデリゲートが存在するならfalseを返します。
// そうでなければtrueを返します。
if (parameter == null &&
typeof(T).IsValueType)
{
return (_canExecuteMethod == null);
}
return CanExecute((T)parameter);
}
void ICommand.Execute(object parameter)
{
Execute((T)parameter);
}
#endregion
#region Data
private readonly Action<T> _executeMethod = null;
private readonly Func<T, bool> _canExecuteMethod = null;
private bool _isAutomaticRequeryDisabled = false;
private List<WeakReference> _canExecuteChangedHandlers;
#endregion
}
/// <summary>
/// <para>
/// This class contains methods for the CommandManager that help avoid memory leaks by
/// using weak references.
/// </para>
/// <para>
/// このクラスはCommandManagerに対する、弱参照を使うことでメモリリークを防ぐ助けとなるメソッドを含んでいます。
/// </para>
/// </summary>
internal class CommandManagerHelper
{
internal static void CallWeakReferenceHandlers(List<WeakReference> handlers)
{
if (handlers != null)
{
// Take a snapshot of the handlers before we call out to them since the handlers
// could cause the array to me modified while we are reading it.
// 我々が私への配列を読んでいる間にハンドラはそれの変更を引き起こしうるので、
// それらを呼び出す前にハンドラのスナップショットをとります。
EventHandler[] callees = new EventHandler[handlers.Count];
int count = 0;
for (int i = handlers.Count - 1; i >= 0; i--)
{
WeakReference reference = handlers[i];
EventHandler handler = reference.Target as EventHandler;
if (handler == null)
{
// Clean up old handlers that have been collected
// 収集されたハンドラを削除します
handlers.RemoveAt(i);
}
else
{
callees[count] = handler;
count++;
}
}
// Call the handlers that we snapshotted
// スナップショットをとったハンドラを呼びます
for (int i = 0; i < count; i++)
{
EventHandler handler = callees[i];
handler(null, EventArgs.Empty);
}
}
}
internal static void AddHandlersToRequerySuggested(List<WeakReference> handlers)
{
if (handlers != null)
{
foreach (WeakReference handlerRef in handlers)
{
EventHandler handler = handlerRef.Target as EventHandler;
if (handler != null)
{
CommandManager.RequerySuggested += handler;
}
}
}
}
internal static void RemoveHandlersFromRequerySuggested(List<WeakReference> handlers)
{
if (handlers != null)
{
foreach (WeakReference handlerRef in handlers)
{
EventHandler handler = handlerRef.Target as EventHandler;
if (handler != null)
{
CommandManager.RequerySuggested -= handler;
}
}
}
}
internal static void AddWeakReferenceHandler(ref List<WeakReference> handlers, EventHandler handler)
{
AddWeakReferenceHandler(ref handlers, handler, -1);
}
internal static void AddWeakReferenceHandler(ref List<WeakReference> handlers, EventHandler handler, int defaultListSize)
{
if (handlers == null)
{
handlers = (defaultListSize > 0 ? new List<WeakReference>(defaultListSize) : new List<WeakReference>());
}
handlers.Add(new WeakReference(handler));
}
internal static void RemoveWeakReferenceHandler(List<WeakReference> handlers, EventHandler handler)
{
if (handlers != null)
{
for (int i = handlers.Count - 1; i >= 0; i--)
{
WeakReference reference = handlers[i];
EventHandler existingHandler = reference.Target as EventHandler;
if ((existingHandler == null) || (existingHandler == handler))
{
// Clean up old handlers that have been collected
// in addition to the handler that is to be removed.
// 削除されるハンドラに加えて、収集された古いハンドラ
// を削除します。
handlers.RemoveAt(i);
}
}
}
}
}
}