2011年2月27日

My Tool Made Myself

Vectorとかを探しても自分の欲しいツールが見つからない。
見つかっても操作性が自分に合わなかったり
なによりインストールを求められたりするのがイヤ

て、場合はやっぱりセルフメイドが一番ですな
欲しい機能を自分が使いやすいようにデザイン
あーでもないこーでもないと試行錯誤している時間が実は楽しかったり('-'*)エヘ

そういうわけで今回作ったのはこちら
てってれてってって~んてて~ん♪
指定フォルダの中にあるファイルをそのファイルの名前のフォルダを作って移動するツール~♪

まとめるなら:ファイル名でフォルダを作って移動するソフトです、( ̄▽ ̄)V


機能としてはこんなの
・フォルダを指定(内部にフォルダがないこと)
・指定したフォルダ内のファイルチェックしてファイル名を自動リスト化
・作ったリストからフォルダを作成(拡張子は自動で除去)
・ファイル名と同じ名前のフォルダにそのファイルを移動
・当然インストール不要、レジストリなど一切ノータッチ
・以上!

何に使うの?って言われると困るんですが(;´▽`A``
大量の大きな動画ファイルを分割転送する必要に迫られて作ったのです
フォルダに分けてしまえば、あとは分割ツールでフォルダごとに分割コマンドを実行すればいいので
というか詳しくは聞かないで(*/∇\*)キャ

使い方は人それぞれですので、どうぞ自由に使ってください。
メイン部分のソースコードを載せときます。
載ってないのはデザインとフォルダを開く部分だけっす、改変も引用も好きにして(*^-゜)v♪

string[] files = System.IO.Directory.GetFiles(textBox1.Text, "*", System.IO.SearchOption.AllDirectories);
if (files.Length != 0)
{
 for(int i = 0; i< files.Length;i++)
 {
  System.IO.FileInfo fi = new System.IO.FileInfo(files[i]);
  string name = files[i].Split('.')[0];
  if (name.EndsWith(" "))
  {
   name = name.Substring(0, name.Length - 1);
  }
  System.IO.Directory.CreateDirectory(name);
  textBox2.Text = textBox2.Text + "\n" + "Create:" + textBox1.Text + "\\" + name;
  fi.MoveTo(name + "\\" + fi.Name);
  textBox2.Text = textBox2.Text + "\n" + "Move:" + files[i];
  }
 }
textBox2.Text = textBox2.Text + "\n" + "Finish!";
自分の環境で動くことを確認しただけですので、 もしバグっても大目に見てください(*_ _)人


というか、このツール欲しい人っています?
周りに載ってるであろうソフトのほうが高性能だろうから
ま、いらないだろうな・・・。。。ρ(-ω- ) イジイジ・・・


追記:ツール公開しました。知恵袋の方、気付くの遅くてSorry

2011年2月19日

ボタンは目立ったイカでいい♪

というのは冗談で。
プログラムのお仕事をしていると、レイアウトだとかデザインといったものが後回しにされがちです。


ですが、実際に仕事で使う人(エンドユーザですね)にしてみれば
「中でどう動こうが知ったこっちゃない!それよりこのごちゃごちゃした画面何とかしてくれ!」


ってのが大半だったりします。(いやいや、内部の動きも知ってほしいんですけど(^_^;))もっとも、作るほうもごちゃごちゃした画面はキライです
時間はかかるしバグはできやすいしテスト項目多いし・・・
機能はシンプルに!ロジックは安定性を!ソースコードのコメントでケンカするな!(最後のはスルーで)

で、愚痴はここまで。
小さな画面で小さなプログラムを作っていると、どうしてもひとつのボタンに複数の機能を割り振らないと
スペース的にどうにもならん!ってことがあります
(アイコン画像+説明がセットで一個のボタン。みたいな)

でもそれ、一個一個手でグラフィック作ってたら気が遠くなりますし
画像ファイルの総数もバカバカ増えていき、
アイコン部分と文字部分を分けて作っても今度はプログラムがごちゃごちゃしていくという・・・

で、おいら自身ひどい仕様書のせいで死亡寸前な目にあったので
CompactFrameworkで動的にボタンに文字を描画するコントロールを作りました

イメージとしてはこんな感じです(貰った仕様書は文字のみの手書きでもっと難読化済み・・・)







左側の□はアイコン画像で、右側に文字を動的に描画します。
背景の黒部分が全体のサイズとなるので、アイコン部分、文字部分共に一個のボタンとして動作可能です。
通常のFrameworkならこんなことしなくても比較的楽にできますが、
CompactなのでPaint部分をオーバーライドして、ええ、コンパクトなもんで・・・

using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;
using System.Windows.Forms;

namespace TestButton
{
 //文字表示機能付きボタンコントロール
 public class Button2 : System.Windows.Forms.Control
 {

 // プライベート メンバ
 private Image image; //表示したい画像を設定
 private Point point; //画像の表示位置を設定
 private Color color; //文字色を設定
 private bool bPushed; // ボタンが押されたかどうかの状態を示すフラグ
 private Bitmap m_bmpOffscreen; //描画用のBitmap

 public Image Image
 {
  get
  {
   return image;
   }
  set
  {
   image = value;
  }
 }

 public Point Point
 {
  get
  {
   return point;
  }
  set
  {
   point = value;
  }
 }

 public Color Color
 {
  get
  {
   return color;
  }
  set
  {
   color = value;
  }
 }

 public Button2()
 {
  bPushed = false;
  // 既定の最小サイズ(あまり小さいとデザイン画面で行方不明に・・・)
  this.Size = new Size(21, 21);
 }

 protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
 {
  Graphics gxOff; // 画面上に表示されない画像
  Rectangle imgRect; // 画像用の四角形
  Brush backBrush; // 背景を設定するためのブラシ

  if (m_bmpOffscreen == null) // Dバッファリング用のビットマップ
  {
   m_bmpOffscreen = new Bitmap(ClientSize.Width, ClientSize.Height);
  }

  gxOff = Graphics.FromImage(m_bmpOffscreen);
  gxOff.Clear(this.BackColor);

  if (bPushed) //ボタンプッシュの判定
  {
   // ボタンが押されたときも背景はそのまま。
   backBrush = new SolidBrush(Color.Black);
  }
  else
  {
   backBrush = new SolidBrush(Parent.BackColor);
  }

  gxOff.FillRectangle(backBrush, this.ClientRectangle);

  if (image != null)
  {
   // コントロールの中央に画像を設定します。
   int imageLeft = (this.Width - image.Width) / 2;
   int imageTop = (this.Height - image.Height) / 2;
   if (bPushed)
   {
    // ボタンが押された場合。
    // 画像を 2 ピクセル移動します。
    imgRect = new Rectangle(imageLeft + 2, imageTop + 2, image.Width, image.Height);
   }
   else
   {
    imgRect = new Rectangle(imageLeft, imageTop, image.Width, image.Height);
   }
   // 透過キーを設定します。
   //フォーム自体の背景色が可変になっていたり、ボタンとしての背景色が一定でなかったりすると
   //四角い枠がそのまま出てきます。もっとも、そう表示したいのであれば透過は不要です
   ImageAttributes imageAttr = new ImageAttributes();
   imageAttr.SetColorKey(BackgroundImageColor(image), BackgroundImageColor(image));

   // 画像を描画します。
   gxOff.DrawImage(image, imgRect, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, imageAttr);
  }

  if (bPushed) // ボタンが押された場合。押したという枠を出す
  {
   // 四角形を準備します。
   Rectangle rc = this.ClientRectangle;
   rc.Width--;
   rc.Height--;
   // 四角形を描画します。
   gxOff.DrawRectangle(new Pen(Color.Black), rc);
  }

  // メモリ内にあるビットマップから描画します。
  e.Graphics.DrawImage(m_bmpOffscreen, 0, 0);

  Brush bBrush = new SolidBrush(Color);
  float x = Point.X;
  float y = Point.Y;
  if (bPushed) // ボタンが押された場合。
  {
   x = x + 2;
   y = y + 2;
  }
  e.Graphics.DrawString(this.Text, this.Font, bBrush, x, y);

  base.OnPaint(e);
 }

 protected override void OnPaintBackground(System.Windows.Forms.PaintEventArgs e)
 {
  base.OnPaintBackground(e);
 }

 private Color BackgroundImageColor(Image image)
 {
  //透過色を左上ピクセルとしています
  Bitmap bmp = new Bitmap(image);
  return bmp.GetPixel(0, 0);
 }

 protected override void OnMouseDown(System.Windows.Forms.MouseEventArgs e)
 {
  bPushed = true;
  this.Invalidate();
 }

 protected override void OnMouseUp(System.Windows.Forms.MouseEventArgs e)
 {
  bPushed = false;
  this.Invalidate();
 }

 }
}

描画の順番としては
最上:文字
中間:イメージ画像
最下:背景色


になっているので、グラフィックツール等で立体的なボタンイメージを作り
その上に動的に文字を描画するという使い方が一番メインでないかと


改めて見直すと、もうちょっとシンプルに作れるような気もしますが
ま、いっかъ( ゜ー^)♪


このへん参考です
http://msdn.microsoft.com/ja-jp/library/aa446518.aspx