完成にしとく
予想図よりはグラフ用紙風表示とかしてなかったり手は抜いた。見た目を凝るのは別のゲームっぽいアプリで一生懸命やることにしよう。一応マウス位置をあらわす黒い四角だけは描いておいた。以下はMainForm.cs。Win32.csとHook.csは先日のやつから変更ない。
念のために操作をおさらい。
- CTRL+ALT+矢印でマウスカーソルが1ドットずつ動く。
- CTRL+ALT+SHIFT+矢印でマウスカーソルが10ドットずつ動く。
- CTRL+ALT+Cでマウス下画素がColorクラスにあわせて16進8桁の文字列としクリップボードに入る。
出力イメージ:Alpha('FF'固定)+Red(16進2桁)+Green(16進2桁)+Blue(16進2桁)
おっと忘れるところだった。ImageUtilsはjunki氏作の画像処理ライブラリである。→のブックマークのMemoNyanDumから入手ができる。大変便利なライブラリなので皆さんもぜひご活用いただきたい。
using System; using System.Drawing; using System.Drawing.Imaging; using System.Windows.Forms; using System.ComponentModel; using ImageUtils; using garu.Util; namespace garu.ColorPicker { partial class MainForm : Form { KeyboardHook keyHook = new KeyboardHook(); MouseHook mouHook = new MouseHook(); const string MYTITLE = "Color Picker"; const int ZOOM = 16; const int CAP_LEN = 15; // 奇数にすること const int FORM_LEN = ZOOM * CAP_LEN; string clipText; Bitmap screenImage; Bitmap formImage; public MainForm() { InitializeComponent(); FormBorderStyle = FormBorderStyle.FixedToolWindow; Icon = new Icon(GetType(), "ColorPicker.ico"); SetStyle(ControlStyles.Opaque, true); formImage = new Bitmap(FORM_LEN, FORM_LEN, PixelFormat.Format24bppRgb); ClientSize = formImage.Size; screenImage = new Bitmap(CAP_LEN, CAP_LEN, PixelFormat.Format24bppRgb); screenCapture(); keyHook.KeyDown += delegate(object sender, KeyEventArgs e) { if (e.KeyCode == Keys.Escape) Close(); if (e.Control && e.Alt) { int step = e.Shift ? 10 : 1; Point pt = Cursor.Position; switch (e.KeyCode) { case Keys.Left: pt.X -= step; break; case Keys.Right: pt.X += step; break; case Keys.Up: pt.Y -= step; break; case Keys.Down: pt.Y += step; break; case Keys.C: Clipboard.SetText(clipText); break; default: return; } e.Handled = true; Cursor.Position = pt; screenCapture(); Invalidate(); } }; mouHook.MouseMove += delegate(object sender, MouseEventArgs e) { if (Win32.WindowFromPoint(e.Location) == Handle) { // MainForm上にマウスがある } else { // 別アプリ上にマウスがある screenCapture(); Invalidate(); } }; } void screenCapture() { Graphics screenGraphics = Graphics.FromImage(screenImage); screenGraphics.CopyFromScreen( Cursor.Position.X - CAP_LEN / 2, Cursor.Position.Y - CAP_LEN / 2, 0, 0, screenImage.Size, CopyPixelOperation.SourceCopy); screenGraphics.Dispose(); BmpProc24 src = new BmpProc24(screenImage); BmpProc24 dst = new BmpProc24(formImage); src.SetXY(CAP_LEN / 2, CAP_LEN / 2); Text = string.Format("{0} (R={1:X2} G={2:X2} B={3:X2})", MYTITLE, src.R, src.G, src.B); clipText = string.Format("FF{0:X2}{1:X2}{2:X2}", src.R, src.G, src.B); for (int y = 0; y < FORM_LEN; y++) { for (int x = 0; x < FORM_LEN; x++) { src.SetXY(x / ZOOM, y / ZOOM); dst.SetXY(x, y); dst.R = src.R; dst.G = src.G; dst.B = src.B; } } const int center = (CAP_LEN / 2) * ZOOM; drawBox(dst, Color.Black, center, center, ZOOM, ZOOM); ImgUtils.CallDispose(src, dst); } void drawBox(BmpProc24 dst, Color color, int x, int y, int width, int height) { for (int i = 0; i < width - 1; i++) { dst.SetXY(x++, y); dst.R = color.R; dst.G = color.G; dst.B = color.B; } for (int i = 0; i < height - 1; i++) { dst.SetXY(x, y++); dst.R = color.R; dst.G = color.G; dst.B = color.B; } for (int i = 0; i < width - 1; i++) { dst.SetXY(x--, y); dst.R = color.R; dst.G = color.G; dst.B = color.B; } for (int i = 0; i < height - 1; i++) { dst.SetXY(x, y--); dst.R = color.R; dst.G = color.G; dst.B = color.B; } } protected override void OnPaint(PaintEventArgs e) { e.Graphics.DrawImage(formImage, 0, 0); } protected override void OnClosing(CancelEventArgs e) { ImgUtils.CallDispose(keyHook, mouHook, screenImage, formImage); base.OnClosing(e); } } }