Windows API Code Packのインストール

Windows7以降に追加された機能を使用するには追加ライブラリを入れると簡単です。
以前はMicrosoftのコードギャラリーから入手できましたが消滅してしまいました。
現在ではNuGetから入手・インストールします。

NuGetの画面
f:id:kitunechan:20150730134815p:plain

  • Core
  • Shell
  • ShellExtensions
  • DirectX
  • ExtendedLinguisticServices
  • Sensors


Windows API Code Packで何ができるのかは参考リンクを参照で。。。


ちなみにCoreとShellをインストールした状態では、参照設定で以下のものが必要でした。

  • PresentationCore
  • PresentationFramework
  • System.Xaml
  • WindowsBase


参考リンク:Windows API Code Pack連載 第1回~第10回の一覧 - 田中達彦のブログ - Site Home - MSDN Blogs
Windows API Code Pack連載 第1回~第10回の一覧 | 田中達彦のブログ


Windows API Code PackのソースはGithubで公開されています。
github.com

オブジェクトをファイルに保存する

自分で作成したクラスをファイルに保存する方法です。
DataContractSerializerを使用してXML形式で保存します。

DataContractSerializer は System.Runtime.Serialization を使います。
多分初期設定では参照設定がないので追加して下さいね。


早速ですが、読み書き用のクラスにまとめました。 ジェネリック仕様になります。

using System;
using System.IO;
using System.Runtime.Serialization;
using System.Xml;
public class FileXML {
  /// <summary>
  /// XMLファイルに保存
  /// </summary>
  static public bool Save<T>( T obj, string FilePath ) {
    try {
      // XmlSerializerを使ってファイルに保存(T型オブジェクトの内容を書き込む)
      var serializer = new DataContractSerializer(typeof(T));

      using( var fs = new FileStream(FilePath, FileMode.Create) )
      using( var xw = XmlWriter.Create(fs, new XmlWriterSettings {
        Indent = true,
        IndentChars = "\t"
      }) ) {
        // オブジェクトをシリアル化してXMLファイルに書き込む
        serializer.WriteObject(xw, obj);
      }

    } catch( Exception ) {
      return false;
    }
    return true;
  }

  /// <summary>
  /// XMLファイルを読み込み
  /// </summary>
  static public T Load<T>( string FilePath ) where T: new() {
    try {
      using( var sr = new StreamReader(FilePath) )
      using( var xr = XmlReader.Create(sr, new XmlReaderSettings() )) {
        // XMLをオブジェクトに読み込む
        var serializer = new DataContractSerializer(typeof(T));

        // XMLファイルを読み込み、逆シリアル化(復元)する
        return (T)serializer.ReadObject(xr);
      }
    } catch( Exception ) {
      return default(T);
    }
  }
}


保存するオブジェクトのクラスを作成します。

public class 保存クラス {
	public int PublicNum1;

	private int PrivateNum2;
	public void SetNumber(int num) {
		this.PrivateNum2 = num;
	}

	public int PublicProperty3 { get; set; }

	private int PrivateProperty4 { get; set; }
	public void SetNumberProperty( int num ) {
		this.PrivateProperty4 = num;
	}
}

実際に使うとこんな感じ

// 保存
var Save = new 保存クラス();
  Save.PublicNum1 = 100;
  Save.SetNumber(200);
  Save.PublicProperty3 = 300;
  Save.SetNumberProperty(400);

FileXML.Save<保存クラス>(Save, "./保存.xml");


// 読込
var Load = FileXML.Load<保存クラス>("./保存.xml");
// Load
//   PublicNum1      100
//   PrivateNum2       0
//   PublicProperty3   300
//   PrivateProperty4    0

出力されるファイルの中身がこちら
読込したデータからわかるようにPublicのものが全て保存されます

<?xml version="1.0" encoding="utf-8"?>
<保存クラス xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/%E3%82%B7%E3%83%AA%E3%82%A2%E3%83%AB">
	<PublicNum1>100</PublicNum1>
	<PublicProperty3>300</PublicProperty3>
</保存クラス>

Privateや保存したいデータを指定する場合は[DataContract]属性をクラスにつけて、保存したいフィールドやプロパティに[DataMember]属性を付けます。

using System.Runtime.Serialization;

[DataContract]
public class 保存クラス {
	[DataMember]
	public int PublicNum1;

	[DataMember]
	private int PrivateNum2;
	public void SetNumber(int num) {
		this.PrivateNum2 = num;
	}

	//[DataMember] ← 付けないと保存されない
	public int PublicProperty3 { get; set; }

	[DataMember]
	private int PrivateProperty4 { get; set; }
	public void SetNumberProperty( int num ) {
		this.PrivateProperty4 = num;
	}
}

PublicProperty3 は Public ですが [DataMember]をつけていないので保存されません。

<?xml version="1.0" encoding="utf-8"?>
<保存クラス xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/%E3%82%B7%E3%83%AA%E3%82%A2%E3%83%AB">
	<PublicNum1>100</PublicNum1>
	<PrivateNum2>200</PrivateNum2>
	<PrivateProperty4>400</PrivateProperty4>
</保存クラス>


ちなみにオブジェクトなら何でも保存できるので、こんなのもできます

var tuple = Tuple.Create(10, 20, 30, "string");
FileXML.Save<Tuple<int,int,int,string>>(tuple, "./保存.xml");
<?xml version="1.0" encoding="utf-8"?>
<TupleOfintintintstring xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/System">
	<m_Item1>10</m_Item1>
	<m_Item2>20</m_Item2>
	<m_Item3>30</m_Item3>
	<m_Item4>string</m_Item4>
</TupleOfintintintstring>


こんな感じで好き放題保存してやりましょう!


参考:
DataContractSerializerを使って、オブジェクトのXMLシリアル化、逆シリアル化を行う: .NET Tips: C#, VB.NET
neue cc - .NETの標準シリアライザ(XML/JSON)の使い分けまとめ

[Windows Form] データバインドのやり方

テキストボックスの内容をいちいち変数に入れる処理を書くのはめんどくさいですね。
データバインドを使いましょう。

Visual Studioのデザイナーで設定すると簡単にできます。
スクリーンショットではアドイン画面がいくつか含まれています

適当にフォームを作りました。
テキストボックスが3つあるだけです。
f:id:kitunechan:20150416114723p:plain

続きを読む

ComboBoxの見た目と中身を別にする

コンボボックスの見た目と欲しいデータが別なんてことはよくあることですね。
簡単な物だったら匿名クラスを使ってちょいちょいです。

this.comboBox1.ValueMember = "value";
this.comboBox1.DisplayMember = "display";
this.comboBox1.DataSource = new[]{
	new { value="1", display="でーた1" },
	new { value="2", display="でーた2"},
	new { value="3", display="でーた3"},
	new { value="4", display="でーた4"},
	new { value="5", display="でーた5"},
};
//ValueMember と DisplayMember はデザイナーの方で指定したほうがスッキリすると思うます

DisplayMember が見た目に使うプロパティ名
ValueMember が実際のデータのプロパティ名 になります。

this.comboBox1.SelectedValueにデータバインドをしておけばvalueが勝手に取得できて楽になります。

ユーザーコントロールのスナップを自作する

ユーザーコントロールを作成してテキストボックスなんか置いたりすると、スナップ(ピンクの線)が消えてしまって配置するのがめんどくさくなります。
そこで、ユーザーコントロールにもスナップを追加します。

とりあえずUserControlを継承したクラスを作成します。
この後作成するスナップ付きのユーザーコントロールにこのクラスを使います。

[Designer(typeof(UserControlSnapLineDesigner))]
public class UserControlBase: UserControl {
	protected virtual Control SnapLineControl { get { return null; } }

	private class UserControlSnapLineDesigner: ControlDesigner {
		public override IList SnapLines {
			get {
				IList snapLines = base.SnapLines;

				Control targetControl = ( this.Control as UserControlBase ).SnapLineControl;

				if( targetControl == null )
					return snapLines;

				using( ControlDesigner controlDesigner = TypeDescriptor.CreateDesigner(targetControl,
					typeof(IDesigner)) as ControlDesigner ) {
					if( controlDesigner == null )
						return snapLines;

					controlDesigner.Initialize(targetControl);

					foreach( SnapLine line in controlDesigner.SnapLines ) {
						if( line.SnapLineType == SnapLineType.Baseline ) {
							snapLines.Add(new SnapLine(SnapLineType.Baseline, line.Offset + targetControl.Top,
								line.Filter, line.Priority));
							break;
						}
					}
				}
				return snapLines;
			}
		}
	}
}

先ほど作ったクラスを使用してユーザーコントロールを作成します。
作成するユーザーコントロールにはテキストボックスが配置してあり、このテキストボックスのスナップを持ってきます。

UserControlBase で作成したSnapLineControlをオーバーライドでコントロールを指定します。

public partial class ユーザーコントロール: UserControlBase {
	
	// ~ 細かいところは省略します ~
	
	//ここで指定するだけ↓
	protected override Control SnapLineControl {
		get {
			return this.textBox1;
		}
	}
}

これでテキストボックスのピンクの線がユーザーコントロールにもつくようになりました。

引用:.net - Baseline snaplines in custom Winforms controls - Stack Overflow

自作プロパティを(DataBindings)に追加する方法

Visual Studioで自作プロパティをデザイナー内の(DataBindings)に追加する方法

System.ComponentModel.Bindable(true)をプロパティに付けましょう

[System.ComponentModel.Bindable(true)]
public int プロパティ{ get;set; }

デザイナーから直接いじれるのは便利です。

キーが押されているか調べる

Control.MouseButtons とか Control.ModifierKeysを使うだけ

2つのキー同時押しはビット演算を使いましょう。

if( ( Control.MouseButtons & MouseButtons.Right ) == MouseButtons.Right ) {
	if( ( Control.ModifierKeys & ( Keys.Control | Keys.Shift ) ) == ( Keys.Shift | Keys.Control ) ) {
		// キー押されてます
	}
}

はてなブログのソースコード記述

はてな記法で、csは小文字じゃないとダメなのね・・・

>|cs|
// C#
/// <summary>
/// MainWindow の ViewModel です。
/// </summary>
class MainWindowViewModel {
    /// <summary>
    /// Hoge を取得または設定します。
    /// </summary>
    public String Hoge { get; set; }
}
 ||<
↑ここのスペースを消すべし!