目次 Edit

プログラムTips Edit

  • デフォルト引数は使えない。C#4.0から導入されるらしい。
  • unsafe,fixed,stackallocの基礎
  • メモリ配列をそのままクラスや構造体にマッピングする
  • 文字列stringをbyte配列にダイレクトコピー
    stringを特定のアドレスにコピーしたい場合はこんな感じで。
    Encodingを"ASCII"にすれば1バイト配列として扱える。
    // こちらは普通のメモリコピー (memcpyと同じ)
    static public unsafe void Copy(void* src, void* dst, int size)
    {
    	byte* s = (byte*)src;
    	byte* d = (byte*)dst;
    	byte* sentinel = s + size;
    	while (s < sentinel)
    	{
    		d[0] = s[0];
    		s++;
    		d++;
    	}
    }
    
    // srcがstringの場合はこっち
    static public unsafe void Copy(string src, void* dst, int size)
    {
    	byte[] bytes = System.Text.Encoding.ASCII.GetBytes(src);
    	fixed (byte* p = &bytes[0])
    	{
    		Copy(p, dst, bytes.Length + 1);
    	}
    }
  • byte 配列から string への変換
    string s = Encoding.ASCII.GetString(bytes);
    *ASCII byte配列の場合。

dllを別のフォルダに置く Edit

ソリューションエクスプローラのプロジェクト上で右クリック>追加>新しい項目>アプリケーション構成ファイル
で、App.configを追加して、そこにアプリケーションの構成ファイルを記述します。
以下は exe と同階層にある dll フォルダにdllを置く場合の記述です。

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1" >
      <probing privatePath="dll" />
    </assemblyBinding>
  </runtime>
</configuration>

TreeViewで複数ノードの選択 Edit

ドッキングウィンドウ(DockPanel Suite) Edit

VisualStudio風のドッキング可能なウィンドウ(DockingWindow)を作りたい場合、 「DockPanel Suite」を使用すると楽。

  • (メモ)実行中ドッキング時に稀に出るエラー:
    Invalid parent form. When using DockingMdi or SystemMdi document style, the DockPanel control must be the child control of the main MDI container form.
    解决方法:
    dockpanel を配置したフォームの IsMdiContainer=true に。

ウィンドウレイアウトの保存方法 Edit

アプリケーション終了時にウィンドウレイアウトを保存し、次回起動時に復帰させることができます。
ドッキングウィンドウのサイズ、位置などが保存されます。
以下の方法ではメインフォームのレイアウトは保存されないので、別途対処する必要があります。

   const string SAVE_LAYOUT_PATH = @"SaveLayout.xml";
   
   /// <summary>
   /// フォームが読み込まれた時に呼ばれる
   /// </summary>
   /// <param name="sender"></param>
   /// <param name="e"></param>
   private void MainForm_Load(object sender, EventArgs e)
   {
       // フォームの生成
       {
           // プレビュー
           m_previewForm = new PreviewForm();
           // テクスチャ
           m_textureForm = new TextureForm();
           // ノードツリー
           m_nodeForm = new NodeForm();
       }
   
       // ウィンドウレイアウトXMLが存在していたら読み出して適用する
       if (System.IO.File.Exists(SAVE_LAYOUT_PATH))
       {
           WeifenLuo.WinFormsUI.Docking.DeserializeDockContent deserializeDockContent = new WeifenLuo.WinFormsUI.Docking.DeserializeDockContent(GetDockContentFromPersistString);
           this.dockPanel1.LoadFromXml(SAVE_LAYOUT_PATH, deserializeDockContent);
       }
       else
       {
           // XMLがなければデフォルト
           m_previewForm.Show(this.dockPanel1, WeifenLuo.WinFormsUI.Docking.DockState.Document);
           m_textureForm.Show(this.dockPanel1, WeifenLuo.WinFormsUI.Docking.DockState.Float);
           m_nodeForm.Show(this.dockPanel1, WeifenLuo.WinFormsUI.Docking.DockState.DockLeft);
       }
   }
	
   /// <summary>
   /// ウィンドウの名称に対応するDockContentを返す
   /// </summary>
   /// <param name="persistString"></param>
   /// <returns></returns>
   WeifenLuo.WinFormsUI.Docking.IDockContent GetDockContentFromPersistString(string persistString)
   {
       if (persistString == typeof(PreviewForm).FullName)
           return m_previewForm;
       if (persistString == typeof(TextureForm).FullName)
           return m_textureForm;
       if (persistString == typeof(NodeForm).FullName)
           return m_nodeForm;
       return null;
   }
   
   /// <summary>
   /// フォームが閉じられた後に呼ばれる
   /// </summary>
   /// <param name="sender"></param>
   /// <param name="e"></param>
   private void MainForm_FormClosed(object sender, FormClosedEventArgs e)
   {
       this.dockPanel1.SaveAsXml(SAVE_LAYOUT_PATH);
   }

その他のドッキングウィンドウ Edit

描画の更新頻度を上げる Edit

デフォルトのままでは描画の更新が毎フレーム呼ばれないので、
フォームにTimerコントロールを配置して、Tickイベントで Control.Invalidate() を呼んでやる。
プロパティはこんな感じ

Enabletrue
Interval8

別の方法として、

System.Windows.Forms.Application.Idle += delegate { Invalidate(); };

という方法もある。
試してみた限りだと、Timerコントロールでやった方が滑らかに描画できた。
処理負荷等は未検証。

Dictionary の初期値設定 Edit

C# 3.0 から、以下のような感じで初期化(初期値の設定)ができるようになった。

using System.Collections.Generic;

class Hoge
{
  Dictionary<string, string> dict = new Dictionary<string, string>()
  {
    {"txt", "notepad.exe"},
    {"bmp", "paint.exe"},
    {"dib", "paint.exe"},
  };
}

ローカル変数であれば、varキーワードが使える。

public void Method()
{
  var dict = new Dictionary<string, string>()
  {
    {"txt", "notepad.exe"},
    {"bmp", "paint.exe"},
    {"dib", "paint.exe"},
  };
}

PropertyGridコントロール Edit

並び順を制御する Edit

デフォルトの状態では勝手に要素がソートされてしまう為、以下のようにして
並び順を制御してやる。

/// <summary>
/// プロパティグリッドのプロパティの並び順をコントロールする。
/// </summary>
class PropertyGridSortTypeConverter : TypeConverter
{
   public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes)
   {
       // TypeDescriptorを使用してプロパティ一覧を取得する
       PropertyDescriptorCollection pdc = TypeDescriptor.GetProperties(value, attributes);

       // プロパティの並び順を指定する。
       string[] sortOrder = 
       {
           "FormatImageDir",
           "ImageDir",
           "PrintDataDir",
           "ImageNoSettingFLG",
       };

       // ソートする。
       return pdc.Sort(sortOrder);

       // return base.GetProperties(context, value, attributes);
   }

   /// <summary>
   /// GetPropertiesをサポートしていることを表明する。
   /// </summary>
   /// <param name="context"></param>
   /// <returns>常にtrue</returns>
   public override bool GetPropertiesSupported(ITypeDescriptorContext context)
   {
       return true;
   }
}

//-------------------------------------------------------------------------------------------------------------
// プロパティ定義部
[TypeConverter(typeof(PropertyGridSortTypeConverter))]
public class HogeProperty
{
   public int FormatImageDir { get; set; }
   public int ImageDir { get; set; }
   public int PrintDataDir { get; set; }
   public int ImageNoSettingFLG { get; set; }
}

参考 Edit

AutoScroll の位置がリセットされないようにする Edit

スクロールしたあと、別のフォームにフォーカスした後フォーカスを戻すと、
スクロール位置が(0,0)に戻ってしまう。
回避するには、以下のように ScrollToControl() をオーバーライドする。

protected override Point ScrollToControl(Control activeControl)
{
   return this.AutoScrollPosition;
}

色選択コントロール Edit

色選択のカスタムコントロール。カスタムカラーピッカー(Custom color picker control)

以下、WPF ASP.NETなど

自作参考

スライダー/トラックバーコントロール Edit

スライダーslider と トラックバーtrackbar

リストビューコントロール Edit

List View Control

グリッドコントロール Edit

Grid Control

その他コントロール Edit

難読化ツール Edit

トラブルシューティング Edit

  • DllImportしたメソッドを呼び出すタイミングでこんなエラーが出る
    マネージ デバッグ アシスタント 'CallbackOnCollectedDelegate' では
    'D:\project\Hoge\debug\Hoge.exe' に問題を検出しました。
    追加情報: コールバックが、型 'Hoge+Callback::Invoke' の
    ガベージ コレクションされたデリゲートで行われました。
    これは、アプリケーションのクラッシュ、破損、およびデータの損失を発生させる可能性があります。
    デリゲートをアンマネージ コードに渡すとき、デリゲートは 2 度と呼び出されないことが確実になるまで
    マネージ アプリケーションによって維持されなければなりません。
    DllImportでインポートしたメソッドを呼び出す時のdelegateはそのインスタンスを保持しなければならない。
    これはだめで、
    HogeImportMethod(new Callback(CallbackMethod));
    これはOK
    m_delegateをフィールドに配置して、コンストラクタ等で初期化後、
    HogeImportMethod(m_delegate);

リロード   新規 編集 凍結 差分 添付 複製 名前変更   ホーム 一覧 単語検索 最終更新 バックアップ リンク元   ヘルプ   最終更新のRSS
Last-modified: 2014-02-26 (水) 20:19:01 (1241d)