変奏現実

パソコンやMMORPGのことなどを思いつくまま・・・記載されている会社名・製品名・システム名などは、各社の商標、または登録商標です。

この画面は、簡易表示です

未分類

WPF.ZAML≒FormXXX.Designer.cs

WindowsFormのFormXXX.Designer.csの
#region Windows フォーム デザイナーで生成されたコード
・・・
#endregion
でやっていることと云えば、
フォームに貼るコントロールを作る。
コントロールの属性を設定する。
イベントハンドラを登録する。
なので、WPFのZAMLとたいして変わらない。
 
しかも、フォーム デザイナーの都合で構成が決まっているので、ちょっと修正をすると、フォーム デザイナーがエラーになってしまい画面を見れなくなることもある。
 
だったら、ZAMLの方がXML風で文法チェックもしやすそうだ。
 
ただ、BindingやTemplateを使いだすと、その場しのぎっぽい作りが目立ってくる。
 
MVPっぽいMVVMを使っても、画面レイアウトを整然と作れる訳ではなく、
画面は君に任せた!と丸投げされるだけで、
結局は
View(画面)⇔ViewModel(DataGrid(ロジックで使うデータリスト)+画面を表示・制御するためのプロパティ)

DataGrid(ロジックで使うデータリスト)⇔ModelObject(ロジックで使うデータ)⇔Model(ロジック)
に別けて考えないと、Modelに渡すデータに編集フラグとか画面でしか使わないハズのデータが混入してしまう。
更にデータ量が多く何ページもつないだ画面だったりすると、データベースに編集中の情報を持っておかないと無理。
そこまでいくと、データベースに編集中の情報のキー情報(対象となるデータの絞り込み条件)だけModelに渡せばよくなってしまうので、非常にスッキリした構成になるし、
テーブル構成も
「編集データのインデックス」

  • キー情報(GUID型)
  • 対象となるインスタンスID(Oracleで云うところのRowID)
  • 最終編集年月日

「編集データの詳細」

  • 編集データのインデックスのキー情報(GUID型)
  • オジェクトのシリアルナンバー(詳細で付加したキー情報)
  • オジェクト(ロジックで使うデータ)

の2つで汎用的に使えるし、
大元のデータベースに編集中なんてフラグを付けるよりマシだし、データベースのレコードをSQLのfor Updateでレコードロックしつつ画面編集するよりは扱いやすい。
ということはわかっているけど、なせか日の目をみることはない。



【間違った.Netのカスタムコントロールの作り方】こんなもんでいいかな?

やらないと寂しいところを変更した。

  1. 縦横のスクロールバーが表示してる時に気になる右下隅の部分をボタンで隠した。
  2. マウスの左ボタンを押しながらドラッグすると画像を掴んだ感じでスクロール。
  3. マウスのホイールを回すとズーム(1~10倍)。

ズームするのはコンテキストメニューを出しスライダーを操作した方が良いのだろうけど・・・
コンテキストメニューはテキストしかだせないので、
スライダーを載せたフレームの無いフォームを作り、
TopLevelプロパティをちょっとごまかして・・・
ToolStripDropDownの中に放り込まないといけないから、
1ソースで作るのは面倒だったから止めた。
 
さてここまで来ると
もうちょっとで自前のPanelユーザコントロールを作れてしまうというオチです。
class  ccPanel : Rectange
{
・・・
}
また、PictureBoxクラスに頼っているのは

  1. 画像の表示

//基底クラスで画像を描画してもらう。
base.OnPaint(e);

の1点のみなので、これもImageクラスを使えば、
//Imageクラスで画像を描画してもらう。
g.DrawImage(base.Image,new Point(0,0));
で十分ですから・・・
class ccPictureBox : PictureBox

class ccPictureBox : Control
と簡単に書き換えられそうです。
 
じゃぁ~なんでPictureBoxなんてVSにあるんでしょうね?
やっぱりVBがまだあるからでしょうかね???(大笑
いやそうではなく
/// <summary>
/// 描画時のイベントハンドラ
/// </summary>
/// <param name=”e”></param>
protected override void OnPaint(PaintEventArgs e)
{
//カスタムコントロールの描画オブジェクトを取得
Graphics g = e.Graphics;
g.DrawImage(base.Image,new Point(0,0));
//ここで借り物の描画オブジェクトをDisposeすると後悔するだろう。
}
・・・
/// <summary>
/// ファイルを読んでみる
/// </summary>
/// <param name=”fileName”></param>
public void  ImageLocation(string fileName)
{
this.Image = Image.FromFile(fileName);
}
まで書き上げ、
参考記事を見ながら
[Browsable(false)]
public override bool AllowDrop { get; set; }
と書いたところ、プロパティウインドウにAllowDrop が出なったので
[DefaultValue(false), Browsable(true), Description(“コントロールが、ユーザがドラッグしたデータを受け入れできるかを示します。”), Category(“動作”)]
と書いたものの
 
多国語対応ができず、
 
結局時間切れでデフォルトの設定に戻ってしまったまま・・・・・・・・・・・
それが原因で
【間違った.Netのカスタムコントロールの作り方】ほぼ完成版までたどり着いた訳です。
 
と、想像すると笑えますね。
ともあれ、簡単にカスタムコントロールが作れれば、色々と便利かと思います。
 
【以下、ほぼ完成版のWindows Form(C#)のPictureBoxのスクロールバーとズーム付きのカスタムコントール】
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
namespace Custom.Control
{
class ccPictureBox : PictureBox
{
/// <summary>
/// 画像の高さがコントロールのそれよりも大きい場合に表示する縦スクロール・コントロール
/// </summary>
private VScrollBar sbV;
/// <summary>
/// 画像の幅がコントロールのそれよりも大きい場合に表示する横スクロール・コントロール
/// </summary>
private HScrollBar sbH;
/// <summary>
/// 縦横スクロール・コントロールが表示している時に右下隅の気になる部分を隠すためのボタン・コントロール
/// </summary>
private Button btnNG;
/// <summary>
///現在の横スクロール量
/// </summary>
private float dx = 0.0f;
/// <summary>
///現在の縦スクロール量
/// </summary>
private float dy = 0.0f;
/// <summary>
///現在の画像の描画倍率
/// (等倍=1.0)
/// </summary>
private float zoom = 1.0f;
//マウスのホィールで倍率を増減する単位
private float dZoom = 0.1f;
//マウスのホィールで倍率を増減の最大値
private float dZoomMax = 10.0f;
//マウスのホィールで倍率を増減の最小値
private float dZoomMin = 1.0f;
/// <summary>
/// コンストラクター
/// </summary>
public ccPictureBox()
{
//縦スクロールバー
sbV = new VScrollBar();
sbV.Parent = this;
sbV.Scroll += sbV_Scroll;
sbV.Visible = false;
//横スクロールバー
sbH = new HScrollBar();
sbH.Parent = this;
sbH.Scroll += sbH_Scroll;
sbH.Visible = false;
//気になる部分を隠すためのボタン
btnNG = new Button();
btnNG.Parent = this;
btnNG.Visible = false;
//各イベントハンドラの登録
this.DragDrop += new System.Windows.Forms.DragEventHandler(myDragDrop);
this.DragEnter += new System.Windows.Forms.DragEventHandler(myDragEnter);
this.ClientSizeChanged += new System.EventHandler(myClientSizeChanged);
this.MouseDown += new System.Windows.Forms.MouseEventHandler(myMouseDown);
this.MouseMove += new System.Windows.Forms.MouseEventHandler(myMouseMove);
this.MouseUp += new System.Windows.Forms.MouseEventHandler(myMouseUp);
this.MouseWheel += new System.Windows.Forms.MouseEventHandler(myMouseWheel);
//全ての設定を終えたのでスクロールバーを改めて再調整する
ChkScrollBar();
}
/// <summary>
/// 横スクロール時のイベントハンドラ
/// </summary>
/// <param name=”sender”></param>
/// <param name=”e”></param>
void sbH_Scroll(object sender, ScrollEventArgs e)
{
dx = e.NewValue;
this.Invalidate();
}
/// <summary>
/// 縦スクロール時のイベントハンドラ
/// </summary>
/// <param name=”sender”></param>
/// <param name=”e”></param>
void sbV_Scroll(object sender, ScrollEventArgs e)
{
dy = e.NewValue;
this.Invalidate();
}
/// <summary>
/// 描画時のイベントハンドラ
/// </summary>
/// <param name=”e”></param>
protected override void OnPaint(PaintEventArgs e)
{
//カスタムコントロールの描画オブジェクトを取得
Graphics g = e.Graphics;
//バックアップ
GraphicsState bk = g.Save();
//座標系の水平移動でスクロール操作と連携する。
g.TranslateTransform(-dx, -dy);
g.ScaleTransform(zoom, zoom);
//基底クラスで画像を描画してもらう。
base.OnPaint(e);
//リストア
g.Restore(bk);
//ここで借り物の描画オブジェクトをDisposeすると後悔するだろう。
}
/// <summary>
/// 基底クラスのPictureBoxのImageプロパティをちょっと改造した個所
/// </summary>
[Bindable(true)]
[Localizable(true)]
public new Image Image
{
get
{
// 基底クラスPictureBoxのImageを返す。
return base.Image;
}
set
{
// 基底クラスPictureBoxのImageを更新。
base.Image = value;
//スクロールバーを調整。
ChkScrollBar();
}
}
/// <summary>
/// 直近のSizeの値
/// </summary>
private Size oldSize;
/// <summary>
/// 基底クラスのPictureBoxのSizeプロパティをちょっと改造した個所
/// </summary>
[Bindable(true)]
[Localizable(true)]
public new Size Size
{
get
{
// 基底クラスPictureBoxのSizeを返す。
return base.Size;
}
set
{
// 基底クラスPictureBoxのSizeを更新。
base.Size = value;
if (oldSize == null || !oldSize.Equals(value))
{
//スクロールバーを調整。
ChkScrollBar();
}
//直近のSizeの値を更新。
oldSize = value;
}
}
[DefaultValue(false), Browsable(true), Description(“コントロールが、ユーザがドラッグしたデータを受け入れできるかを示します。”), Category(“動作”)]
public override bool AllowDrop { get; set; }
/// <summary>
/// ドラッグ処理のイベントハンドラ
/// </summary>
/// <param name=”sender”></param>
/// <param name=”e”></param>
private void myDragEnter(object sender, DragEventArgs e)
{
//ファイルならOKにしておく。
if (e.Data.GetDataPresent(DataFormats.FileDrop))
{
e.Effect = DragDropEffects.Copy;
}
}
/// <summary>
/// ドラッグ処理のイベントハンドラ
/// </summary>
/// <param name=”sender”></param>
/// <param name=”e”></param>
private void myDragDrop(object sender, DragEventArgs e)
{
//ファイルなら
if (e.Data.GetDataPresent(DataFormats.FileDrop))
{
// ドラッグ中のファイルなどを取得
string[] drags = (string[])e.Data.GetData(DataFormats.FileDrop);
string fileName = null;
foreach (string d in drags)
{
if (!System.IO.File.Exists(d))
{
// ファイル以外であれば読み飛ばす。
continue;
}
fileName = d;
//最後のファイルを使うならbreakをコメントアウトする
break;
}
if (fileName != null)
{
try
{
this.Image = Image.FromFile(fileName);
}
catch (Exception ex)
{
//画像ファイルではなかったらしい。
MessageBox.Show(“【” + fileName + “】” + ex.Message);
return;
}
//画像ファイルの読み込みに成功した場合。
e.Effect = DragDropEffects.Copy;
//スクロール位置や倍率は初期化する
dx = sbH.Value = 0;
dy = sbV.Value = 0;
zoom = 1;
ChkScrollBar();
}
}
}
/// <summary>
/// スクロールバーを表示するかどうかチェックし
/// 表示する際には位置や設定範囲を調整する
/// </summary>
/// <returns></returns>
private bool ChkScrollBar()
{
bool rc = false;
if (this.Image != null)
{
//各スクロールバーを表示するかどうかを判定
bool showV = (this.Height < this.Image.Size.Height * zoom);
bool showH = (this.Width < this.Image.Size.Width * zoom);
//判定結果の和を戻り値とする
rc = showH | showH;
//縦スクロールバーを表示する場合は
if (showV)
{
sbV.Top = 0;
sbV.Left = this.ClientSize.Width – sbV.Width;
//両方表示する場合、横スクロールバーの高さ分小さくする
sbV.Height = this.ClientSize.Height – (showH ? sbH.Height : 0);
//大雑把な操作はスクロールバーの高さ分
sbV.LargeChange = sbV.Height;
//範囲の補正
//最大値=(画像の高さ)-(縦スクロールバーの高さ)
//但し、スクロールバーを操作時の最大値はMaximum-LargeChange+1までなので・・・
sbV.Maximum = (int)(this.Image.Size.Height * zoom – sbV.Height + (sbV.LargeChange + 1));
sbV.Visible = true;
}
//縦スクロールバーを表示しない場合は
else
{
sbV.Visible = false;
}
//横スクロールバーを表示する場合は
if (showH)
{
sbH.Top = this.ClientSize.Height – sbH.Height;
sbH.Left = 0;
//両方表示する場合、縦スクロールバーの幅分小さくする
sbH.Width = this.ClientSize.Width – (showV ? sbV.Width : 0);
//大雑把な操作はスクロールバーの幅分
sbH.LargeChange = sbH.Width;
//範囲の補正
//最大値=(画像の幅)-(横スクロールバーの幅)
//但し、スクロールバーを操作時の最大値はMaximum-LargeChange+1までなので・・・
sbH.Maximum = (int)(this.Image.Size.Width * zoom – sbH.Width + (sbH.LargeChange + 1));
//
sbH.Visible = true;
}
//横スクロールバーを表示しない場合は
else
{
sbH.Visible = false;
}
//縦横スクロールバーを両方表示するなら、右下隅の気になる部分にボタンを表示する。
if (showV && showH)
{
btnNG.Left = sbV.Left – 1;
btnNG.Top = sbH.Top – 1;
btnNG.Width = sbV.Width + 2;
btnNG.Height = sbH.Height + 2;
btnNG.Visible = true;
}
//それ以外はボタンを隠しておく。
else
{
btnNG.Visible = false;
}
}
return rc;
}
/// <summary>
/// Sizeが変更された後のイベントハンドラ
/// </summary>
/// <param name=”sender”></param>
/// <param name=”e”></param>
private void myClientSizeChanged(object sender, EventArgs e)
{
ChkScrollBar();
}
/// <summary>
/// MouseDown時のマウス座標
/// </summary>
private Point pointCaptureStartMousePoint;
/// <summary>
/// MouseDown時のスクロール位置
/// </summary>
private Point pointCaptureStartScrollPoint;
/// <summary>
/// マウスをボタンを押した時のイベントハンドラ
/// </summary>
/// <param name=”sender”></param>
/// <param name=”e”></param>
private void myMouseDown(object sender, MouseEventArgs e)
{
switch (e.Button)
{
case MouseButtons.Left:
pointCaptureStartMousePoint = new Point(e.X, e.Y);
pointCaptureStartScrollPoint = new Point(sbH.Value,sbV.Value);
this.Capture = true;
break;
}
}
/// <summary>
/// マウスをボタンを離した時のイベントハンドラ
/// </summary>
/// <param name=”sender”></param>
/// <param name=”e”></param>
private void myMouseUp(object sender, MouseEventArgs e)
{
this.Capture = false;
}
/// <summary>
/// マウスをドラッグ操作時のイベントハンドラ
/// </summary>
/// <param name=”sender”></param>
/// <param name=”e”></param>
private void myMouseMove(object sender, MouseEventArgs e)
{
try
{
switch (e.Button)
{
case MouseButtons.Left:
Point pointMousePoint = new Point(e.X, e.Y);
//マウスダウン時からの相対位置に変換。
Point dMove = new Point(pointMousePoint.X – pointCaptureStartMousePoint.X, pointMousePoint.Y – pointCaptureStartMousePoint.Y);
//スクロール量を計算
Point dScroll = new Point(pointCaptureStartScrollPoint.X – dMove.X, pointCaptureStartScrollPoint.Y – dMove.Y);
//スクロール
//スクロールバーを操作時の最大値はMaximum-LargeChange+1までなので・・・
if (0 <= dScroll.X && dScroll.X <= (sbH.Maximum – sbH.LargeChange + 1))
{
dx = sbH.Value = dScroll.X;
}
//スクロールバーを操作時の最大値はMaximum-LargeChange+1までなので・・・
if (0 <= dScroll.Y && dScroll.Y <= (sbV.Maximum – sbV.LargeChange + 1))
{
dy = sbV.Value = dScroll.Y;
}
this.Invalidate();
break;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
/// <summary>
/// マウスのホィールを回した時のイベントハンドラ
/// </summary>
/// <param name=”sender”></param>
/// <param name=”e”></param>
private void myMouseWheel(object sender, MouseEventArgs e)
{
//ZOOM
int d = e.Delta;
Trace.WriteLine(d.ToString());
if(d <0)
{
if (zoom <= dZoomMax)
{
zoom += dZoom;
ChkScrollBar();
this.Invalidate();
}
}
else
{
if (zoom >= dZoomMin)
{
zoom -= dZoom;
ChkScrollBar();
this.Invalidate();
}
}
}
}
}
 
// EOF.



【.Net手抜きの氾濫】スクロールバーの位置や操作の最大値は手抜き仕様

スクロールバーの位置がおかしい?

スクロールバーの位置 = コントロールの大きさ(Width,Height) - スクロールバーの大きさ

で計算していたので

スクロールバーの位置 = コントロールのクライアント領域の大きさ(ClientSize) - スクロールバーの大きさ

に変更した。
本来なら、デスクトップのデザインが変更になったら、クライアント領域の大きさが変わるので、全コントロールに通知しなければいけないのだが、

Windows 32APIで新設されたデスクトップのデザイン通知メッセージが.Netには無い。

ま、気にしなければいらないかな。(大笑
それでも、まだ最大までスクロールしてもバーの大きさの半分ぐらいスライドできない。
ググって見ると、

.NET FrameworkのSystem.Windows.Forms.ScrollBar.Valueプロパティの値はマウス操作ではMaximum-LargeChange+1までしか行かない

という大笑いネタを発見。
その通りにするとピッタリ。
//但し、スクロールバーを操作時の最大値はMaximum-LargeChange+1までなので・・・
sbH.Maximum = this.Image.Size.Width – sbH.Width + (sbH.LargeChange + 1);
なぜ、そうなのかと云えば、
このLargeChangeを丁度良い感じにすると最後まで増やした時に、最大値を超える問題が発生するので安易な補正をかけたとした思えない。
しかも、ドット単位でスクロールをするか画面上のGridのセルコントロールの配置サイズでスクロールするかで、また考え方を変えなくてはいけない。
気持ちよくスクロールするには、
どうすればよいのか色々

考えて使って直して考えて使って直して考えて使って直して

の繰り返し。
しかもそれは画面の内容次第でコロコロ変わる。

iPhoneの気持ちの良さは

『頑固で偏屈な石頭だらけのプレゼンテーション』を一発で通る内容に終始しているから、

使ってみると「さくっと気持ちの良さが伝わる」が・・・

それは副作用でしかなく、本当に使いやすいかどうかは別腹なのだ。

もちろん、「第一印象」は重要なことだが・・・

閑話休題。
確かに鉄板のGUIなんて存在しない。
しかし、MSやスクエニが云うと
『俺ん家には無理!』
と云っているだけでしかないのもまた事実である。(大笑
【修正後のソース】
using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
namespace Custom.Control
{
class ccPictureBox : PictureBox
{
//画像が大きい時に表示する
VScrollBar sbV;
HScrollBar sbH;
float dx = 0;
float dy = 0;
///
/// コンストラクター
///
public ccPictureBox()
{
sbV = new VScrollBar();
sbV.Parent = this;
sbV.Scroll += sbV_Scroll;
sbV.Visible = false;
sbH = new HScrollBar();
sbH.Parent = this;
sbH.Scroll += sbH_Scroll;
sbH.Visible = false;
this.DragDrop += new System.Windows.Forms.DragEventHandler(myDragDrop);
this.DragEnter += new System.Windows.Forms.DragEventHandler(myDragEnter);
ChkScrollBar();
}
///
/// 横スクロール時
///
//////void sbH_Scroll(object sender, ScrollEventArgs e)
{
dx = e.NewValue;
this.Invalidate();
}
///
/// 縦スクロール時
///
//////void sbV_Scroll(object sender, ScrollEventArgs e)
{
dy = e.NewValue;
this.Invalidate();
}
///
/// 描画時
///
///protected override void OnPaint(PaintEventArgs e)
{
Graphics g = e.Graphics;
g.TranslateTransform(-dx, -dy);
GraphicsState bk = g.Save();
base.OnPaint(e);
g.Restore(bk);
}
///
///
///
[Bindable(true)]
[Localizable(true)]
public new Image Image
{
get
{
return base.Image;
}
set
{
base.Image = value;
ChkScrollBar();
}
}
///
///
///
[Bindable(true)]
[Localizable(true)]
public new Size Size
{
get
{
return base.Size;
}
set
{
base.Size = value;
ChkScrollBar();
}
}
[DefaultValue(false), Browsable(true), Description(“コントロールが、ユーザがドラッグしたデータを受け入れできるかを示します。”), Category(“動作”)]
public override bool AllowDrop { get; set; }
///
/// ドラッグ処理のイベントハンドラー
///
//////private void myDragEnter(object sender, DragEventArgs e)
{
//ファイルならOKにしておく。
if (e.Data.GetDataPresent(DataFormats.FileDrop))
{
e.Effect = DragDropEffects.Copy;
}
}
///
/// ドラッグ処理のイベントハンドラー
///
//////private void myDragDrop(object sender, DragEventArgs e)
{
//ファイルなら
if (e.Data.GetDataPresent(DataFormats.FileDrop))
{
// ドラッグ中のファイルなどを取得
string[] drags = (string[])e.Data.GetData(DataFormats.FileDrop);
string fileName = null;
foreach (string d in drags)
{
if (!System.IO.File.Exists(d))
{
// ファイル以外であれば読み飛ばす。
continue;
}
fileName = d;
}
if (fileName != null)
{
try
{
this.Image = Image.FromFile(fileName);
}
catch (Exception ex)
{
MessageBox.Show(“【” + fileName + “】” + ex.Message);
}
e.Effect = DragDropEffects.Copy;
ChkScrollBar();
}
}
}
///
/// スクロールバーを表示するかどうかチェックし
/// 表示する際には位置や設定範囲を調整する
///
///
private bool ChkScrollBar()
{
bool rc = false;
if (this.Image != null)
{
bool showV = (this.Height < this.Image.Size.Height);
bool showH = (this.Width < this.Image.Size.Width);
rc = showH | showH;
//
if (showV)
{
sbV.Top = 0;
sbV.Left = this.ClientSize.Width – sbV.Width;
//両方表示する場合、横スクロールバーの高さ分小さくする
sbV.Height = this.ClientSize.Height – (showH ? sbH.Height : 0);
//大雑把な操作はスクロールバーの高さ分
sbV.LargeChange = sbV.Height;
//範囲の補正
//最大値=(画像の高さ)-(縦スクロールバーの高さ)
//但し、スクロールバーを操作時の最大値はMaximum-LargeChange+1までなので・・・
sbV.Maximum = this.Image.Size.Height – sbV.Height + (sbV.LargeChange + 1);
sbV.Visible = true;
}
else
{
sbV.Visible = false;
}
if (showH)
{
sbH.Top = this.ClientSize.Height – sbH.Height;
sbH.Left = 0;
//両方表示する場合、縦スクロールバーの幅分小さくする
sbH.Width = this.ClientSize.Width – (showV ? sbV.Width : 0);
//大雑把な操作はスクロールバーの幅分
sbH.LargeChange = sbH.Width;
//範囲の補正
//最大値=(画像の幅)-(横スクロールバーの幅)
//但し、スクロールバーを操作時の最大値はMaximum-LargeChange+1までなので・・・
sbH.Maximum = this.Image.Size.Width – sbH.Width + (sbH.LargeChange + 1);
//
sbH.Visible = true;
}
else
{
sbH.Visible = false;
}
}
return rc;
}
}
}
// EOF.



【間違った実装方法】 Windows Form(C#)のPictureBoxのカスタムコントロールにスクロールバーを付ける

ググってみると、
1.ユーザ・コントロールを作る。
2.中にPanelを追加する。
3.PanelはAutoScroll = true にする。
4.Panelの中にPictureBoxを置く。
と云う方法ばかり。
この方法の大きな利点は、Panelのプロパティやイベントをほぼそのまま継承し、都合の悪い場所だけoverrideしてるだけで手間がかからないこと。
※あえて言えば、Panelで未実装なのはドラッグ&ドロップと印刷ぐらいしかない。
この方法の大きな欠点は、PictureBoxのプロパティやイベントを泣きながら全部追加しなければいけなことだが、幸いなことにPictureBoxはしょぼいので、全くその心配は無い。
 
と云う訳で誰もやってそうもないので、ごく普通にPictureBoxのカスタムコントロールにスクロールバーを付けてみた。
この方法の大きな利点は、PictureBoxのプロパティやイベントをほぼそのまま継承し、都合の悪い場所だけoverrideしてるので、手間がかからないこと。
この方法の大きな欠点は、Panelのプロパティやイベントを泣きながら全部追加しなければいけなことだが、本当に困ったことにPanelは優秀で色々やってくれてるので非常にヤバイ!
※未実装は多数あります。
下記のカスタムコントロールをフォームに貼り、Anchor に Bottom, Right を追加するだけでも、未実装の場所はすぐバレる。
いや、フォームのデザイナー上でccPictireBox1のサイズを変えるだけでも判るくらいだ。(大笑
とは云え、どっちが楽なのかは、使い方次第。
 
一番大切なことはImageメソッドしか独自の機能が無いも同然のPictureBoxだからこそPanelを使う方が正解なのであって、何でもかんでも、スクロールバーを付けるならPanelという訳にはいかないことだ。
例えば、半端なく大量にメソッドやイベントがワンサカとありそうなSpreadSheetコントロールみたいなものでは、

  1. 大量にメソッドやイベントのプロパティやイベントを渡すだけのコードを泣きながらドンドン追加してしなければいけない。
  2. SpreadSheetコントロールのスクロールバーらしい動き(Excelっぽい動き)を誰もが期待するので、Panelのまんまの実装では誰(自分さえ)も納得しないから、ガリガリ書かないといけない。

ということになる。もちろんユーザコントロールにSpreadSheetメソッドを追加するだけで機能的なカスタムは可能だか、プロパティ・ウインドウで、色々いじることができないので、結局使う時に大変な目に遭ってしまう。
どれくらい大変なことになるかは、そんなSpreadSheetを貼り、色々設定した後のフォームのFormXXXX.Designer.csファイルを見れば、多分大量のコードとご対面するだろう。

※FormXXXX.Designer.csファイルにはこんな手書き厳禁の札がかかっている。
/// <summary>
/// デザイナー サポートに必要なメソッドです。このメソッドの内容を
/// コード エディターで変更しないでください。
/// </summary>
private void InitializeComponent()
{

そんな心配をすることは滅多にないだろう、第一そんなものを手掛ける優秀な方々が、ググって実装方法を検討なーんてする訳もないよね。(笑
だから、ここを見てしまった貴方。
素直に、ユーザ・コントロールにして、PanelコントロールにPictureBoxを載せた方が無難ですよ。
次回は、【正しい実装方法】 Windows Form(C#)のPictureBoxのカスタムコントロールに楽にスクロールバーを付ける
というのを書いてみたいな。
【参考にしてはいけない未完成のPictureBoxのスクロールバー付きカスタム・コントロールのソース】

using System;
using System.ComponentModel;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Drawing2D;
namespace Custom.Control
{
 class ccPictureBox : PictureBox {
  //画像が大きい時に表示する
  VScrollBar sbV;
  HScrollBar sbH;
  float dx=0;
  float dy=0;
  /// <summary>
  /// コンストラクター
  /// </summary>
  public ccPictureBox() {
   sbV = new VScrollBar();
   sbV.Parent = this;
   sbV.Scroll += sbV_Scroll;
   sbV.Visible = false;
   sbH = new HScrollBar();
   sbH.Parent = this;
   sbH.Scroll += sbH_Scroll;
   sbH.Visible = false;
   this.DragDrop += new System.Windows.Forms.DragEventHandler(myDragDrop);
   this.DragEnter += new System.Windows.Forms.DragEventHandler(myDragEnter);
   ChkScrollBar();
  }
  /// <summary>
  /// 横スクロール時
  /// </summary>
  /// <param name="sender"></param>
  /// <param name="e"></param>
  void sbH_Scroll(object sender, ScrollEventArgs e) {
   dx = e.NewValue;
   this.Invalidate();
  }
  /// <summary>
  /// 縦スクロール時
  /// </summary>
  /// <param name="sender"></param>
  /// <param name="e"></param>
  void sbV_Scroll(object sender, ScrollEventArgs e) {
   dy = e.NewValue;
   this.Invalidate();
  }
  /// <summary>
  /// 描画時
  /// </summary>
  /// <param name="e"></param>
  protected override void OnPaint(PaintEventArgs e) {
   Graphics g = e.Graphics;
   g.TranslateTransform(-dx, -dy);
   GraphicsState bk = g.Save();
   base.OnPaint(e);
   g.Restore(bk);
  }
  /// <summary>
  ///
  /// </summary>
[Bindable(true)]
[Localizable(true)]
  public new Image Image {
   get {
    return base.Image;
   }
   set {
    base.Image = value;
    ChkScrollBar();
   }
  }
  /// <summary>
  ///
  /// </summary>
[Bindable(true)]
[Localizable(true)]
  public new Size Size {
   get {
    return base.Size;
   }
   set {
    base.Size = value;
    ChkScrollBar();
   }
  }
[DefaultValue(false), Browsable(true), Description("コントロールが、ユーザがドラッグしたデータを受け入れできるかを示します。"), Category("動作")]
  public override bool AllowDrop { get; set; }
  /// <summary>
  /// ドラッグ処理のイベントハンドラー
  /// </summary>
  /// <param name="sender"></param>
  /// <param name="e"></param>
  private void myDragEnter(object sender, DragEventArgs e) {
   //ファイルならOKにしておく。
   if (e.Data.GetDataPresent(DataFormats.FileDrop)) {
    e.Effect = DragDropEffects.Copy;
   }
  }
  /// <summary>
  /// ドラッグ処理のイベントハンドラー
  /// </summary>
  /// <param name="sender"></param>
  /// <param name="e"></param>
  private void myDragDrop(object sender, DragEventArgs e) {
   //ファイルなら
   if (e.Data.GetDataPresent(DataFormats.FileDrop)) {
    // ドラッグ中のファイルなどを取得
    string[] drags = (string[])e.Data.GetData(DataFormats.FileDrop);
    string fileName = null;
    foreach (string d in drags) {
     if (!System.IO.File.Exists(d)) {
      // ファイル以外であれば読み飛ばす。
      continue;
     }
     fileName = d;
    }
    if (fileName != null) {
     try {
      this.Image = Image.FromFile(fileName);
     } catch(Exception ex) {
      MessageBox.Show("【" + fileName + "】" + ex.Message);
     }
     e.Effect = DragDropEffects.Copy;
     ChkScrollBar();
    }
   }
  }
  /// <summary>
  /// スクロールバーを表示するかどうかチェックする
  /// </summary>
  /// <returns></returns>
  private bool ChkScrollBar() {
   bool rc=false;
   if (this.Image != null) {
    bool showV = (this.Height < this.Image.Size.Height);
    bool showH = (this.Width < this.Image.Size.Width);
    rc = showH | showH;
    //
    if (showV) {
     sbV.Top = 0;
     sbV.Left = this.Width - sbV.Width;
     sbV.Height = this.Height;
     //両方表示
     if (showH) {
      sbV.Height = this.Height - sbH.Height;
     }
     //
     sbV.Visible = true;
    } else {
     sbV.Visible = false;
    }
    if (showH) {
     sbH.Top = this.Height - sbH.Height;
     sbH.Left = 0;
     sbH.Width = this.Width;
     //両方表示
     if (showV) {
      sbH.Width = this.Width - sbV.Width;
     }
     //
     sbH.Visible = true;
     } else {
      sbH.Visible = false;
     }
    }
   return rc;
  }
 }
}
/// EOF.


一々めんどくさいのでカスタムコントロールに埋めておく

PictureBoxに画像をドラッグして貼り付けるには
デザイナーのプロパティウインドウでAllowDrag に true を設定し、DragDropとDragEnterのイベントハンドラをフォームごとに書くことになるけど、
いっぱい画面があると、毎回コピペするのも面倒。
Form.Designer.csを見てみると、

this.ccPictureBox1.AllowDrop = true;
this.ccPictureBox1.Image = ((System.Drawing.Image)(resources.GetObject(“ccPictureBox1.Image”)));
this.ccPictureBox1.Location = new System.Drawing.Point(96, 58);
this.ccPictureBox1.Name = “ccPictureBox1”;
this.ccPictureBox1.Size = new System.Drawing.Size(263, 200);
this.ccPictureBox1.TabIndex = 0;
this.ccPictureBox1.TabStop = false;
this.ccPictureBox1.Click += new System.EventHandler(this.ccPictureBox1_Click);
this.ccPictureBox1.DragDrop += new System.Windows.Forms.DragEventHandler(this.ccPictureBox1_DragDrop);
this.ccPictureBox1.DragEnter += new System.Windows.Forms.DragEventHandler(this.ccPictureBox1_DragEnter);

※ccPictureBox1は、前に作ったカスタムコントロール。

と、やっているだけだったので、コピペするだけのイベントハンドラならカスタムコントロールに埋めれてしまえばいい。
どうせAllowDrop = false になっていれば処理されることもない。

using System.ComponentModel;
using System.Windows.Forms;

namespace Custom.Control
{
class ccPictureBox : PictureBox
{
/// <summary>
/// コンストラクター
/// </summary>

public ccPictureBox()
{
this.DragDrop += new System.Windows.Forms.DragEventHandler(myDragDrop);
this.DragEnter += new System.Windows.Forms.DragEventHandler(myDragEnter);
}

[DefaultValue(false), Browsable(true), Description(“コントロールが、ユーザがドラッグしたデータを受け入れできるかを示します。”), Category(“動作”)]

public override bool AllowDrop { get; set; }

/// <summary>
/// ドラッグ処理のイベントハンドラー
/// </summary>
/// <param name=”sender”></param>
/// <param name=”e”></param>

private void myDragEnter(object sender, DragEventArgs e)
{
//ファイルならOKにしておく。
if (e.Data.GetDataPresent(DataFormats.FileDrop))
{
e.Effect = DragDropEffects.Copy;
}
}

/// <summary>
/// ドラッグ処理のイベントハンドラー
/// </summary>
/// <param name=”sender”></param>
/// <param name=”e”></param>

private void myDragDrop(object sender, DragEventArgs e)
{
//ファイルなら
if (e.Data.GetDataPresent(DataFormats.FileDrop))
{
// ドラッグ中のファイルなどを取得
string[] drags = (string[])e.Data.GetData(DataFormats.FileDrop);

string fileName = null;
foreach (string d in drags)
{
if (!System.IO.File.Exists(d))
{
// ファイル以外であれば読み飛ばす。
continue;
}
fileName = d;
}
if (fileName != null)
{
this.ImageLocation = fileName;
e.Effect = DragDropEffects.Copy;
}
}
}
}
}

※DragDrop、DragEnterがevent型で、いくつもイベントハンドラを登録できるコレクションクラスなのでそのままoverrideできないのでイベントハンドラはmyDragDrop、myDragEnterとしている。

※複数ファイルをドラッグすると最後のファイルが貼り付く。



ペンチ用のメモリ

Pentium G3258のメモリは他のPCのモノだったのでUMAX DDR3-1333の4GBセット(2GB×2)を購入。
UEFI(BIOS)ではなぜかDDR3-1600と判定されるが、Pentium G3258が扱えるのはDDR3-1333までなので、
起動してみればCPU-ZではDDRのクロックは667MHzと表示。
FFXIVベンチ(キャラメイク編)をやってみると、Now Loading…が長い。
途中でメモリが足りなくなり中座。
仮想記憶を0GBから自動に切り替え再起動。
※FFXIVやるなら標準品質でも8GBあった方が良さそうだ。しかし最高品質にすれば8GBでも遅い、後は積める積むしかないね。
再チャレンジするもNow Loading…は長い。
しかし、最後まで到達。
標準品質(1920×1080)スコアは2,228で判定は普通。
コメント:標準的な動作が見込めます。
しかしプレイするのはちょっと厳しそう。
ベンチの画面を最小化し、メモリ使用量やCPUの温度を見て戻すとスコアが14,904と馬鹿みたいに跳ね上がっていたのはご愛嬌。
メモリ使用量は3GB、しかし仮想記憶をONにしてあるので、カクカク。音もたまに途切れる。
CPU温度はコアが60度を超え、システムやCPU付近は40度。
 
ASRockのA-TuningのOC TweakerではDRAM周波数は1600.00MHzなので
Auto Tuningをしてみた。
注意書きを読むと
Kシリーズ専用。開始するとそのうち再起動するハズ(アニバーサリーペンティウムを含む。
と書いてある。
3.4GHz⇒3.7GHz⇒3.9GHz⇒4.1GHz⇒4.3GHzで妥協されてしまった。
Pキーを押しながら起動しても上限は4.2GHz。
結局、UEFIで最適化されたOC設定の4.5GHz(赤文字)を選択し元に戻す。



【今更だけど】WPFでLostFocusのなかでFocusでフォーカスを戻すとループする

XXXX_LostFocus(object sender, System.EventArgs e)
{
if(XXXX.Text == “”)
{
MessageBox.Show(“未入力エラー”);
//フォーカスを戻し、再入力を促す。
XXXX.Focus();
return ;
}
}
とやると、メッセージボックスが消えた後にまた同じメッセージボックスが・・・メッセージボックスが・・・メッセージボックス・・・
となる。
//フォーカスを戻し、再入力を促す。
XXXX.Focus();
の代りに
//処理済とし、以後のイベントのルーティングが起きないようにする。
//⇒結果的にLostFocus()の次のGotFocus()の処理がされず、
//LostFocus()をキャンセルしたのと似たような効果を得られる。
e.Handled = true;
ハズだったけど、ダメだった
例えばボタンを押したのなら、ボタンの処理にも似たようなコード(e.Handled = true;)を入れないとダメだった。
こっちはちゃんとうまく処理してくれるので、そっちに任せた方がいいかもしれない。
ただキーボード操作でLostFocusした場合には
PreviewLostKeyboardFocusイベントで、KeyboardFocusChangedEventArgs e に対して同様な処理を入れるとうまく動くらしい。
もっともLostFocusは低レベルなイベントなので使わないようにってどこかに書いてあった気がする。



スケールダウンの目途が立たない半導体集積回路

一つの技術にこだわると、やがて奥がものすごく深くなっていく。
半導体の集積回路を作るには、光学レジスト材を塗布し、パターン焼き付けと現像を経て、レジスト材が消えた部分に酸性物質を浸透させ表面に刻みを付け(エッチング)、さらに様々な物質を重ねては刻んでいく。
光学式にパターンを焼き付ける方法は、広い面積でも一度の照射で済むし照射時間も一定で回路の規模や複雑さに照射時間は左右されることもないため、色々な集積回路を量産するにはピッタりだった。
しかし、集積度が上がると、色々問題が出てきた。

1.単純に集積度をあげると、絶縁体の厚さが足りず、リーク電流が増大する。

2.パターンによって焼き付けた跡にユガミやボケが目立つようになった。

3.小さいなゴミですら巨大な隕石サイズになってきた。

4.回路同士の電荷が干渉し始めた。

絶縁体の材質を変えたり、歪み補正したパターンを使ったり、24時間掃除機をかけっぱなし(クリーンルーム自体が巨大なパック式掃除機である)にしたり・・・と、限界を超えようと力任せに色々やっているようだ。
何でも度を超せば、最初のメリットなんか吹き飛んでしまう。それが今の現状だ。
では、限界が見えてきたらどうするのか?
チップを縦に積層してみる。HBMでやってみたら結構大変だったし単価もバカにならない。
なので何度も何度もエッチングしてもズレにくいパターンを考えました!現状の10倍も100倍もエッチングの回数を増やしてみたいと思います。と、やってみせたがSAMSUNGのV-NANDだ。今の調子ならワンチップで1T-bit(128GB)も作れそうだと云う。
縦に長い棒状のチャネル(電極)の周囲に輪状のゲートを縦にいくつも積み重ねる方法だ。5円玉の穴に金属棒を通した構造。
これなら

1.チャネル(電極)を1階層分作る。

2.チャネルの材質と親和性の高いゲート材料を塗布すると、チャネルに集約する。

3.ゲート材料と親和性の高い絶縁材を塗布、均一に広がる。※この時にチャネルの天辺は露出しているハズ。

を何度も繰り返すとできそうだが、

4.絶縁材料と親和性が低いチャネル(電極)を1階層分 増築する。

2周目以降では下のチャネルの真上にチャネルを重ねることがとても大変そうだが、いい感じの材料の選別ができたら、最初の最初のチャネル(電極)を1階層分作る段階の精度で何階層まで重ねられるかが決まるだろう。
USBメモリの様に中規模で低速でも良いから安価な方がいい場合にはゲート同士がくっ付いて1枚になったゲート層となり絶縁層と一緒にロール巻きしたものをロールケーキの様に裁断し、さらに縦にカットケーキの様に切り出し、最後にレーザーであけた穴にアルミニウムを圧入しコントーラーの上に盛って完成になるかもしれない。これでは、もはや電子回路とは思えないしろものだ。
※しかし、すでに誰かが特許を出願中な気がする。
やはり電気伝導率の高いアルミや銅などでちゃんとつないだ方がいいだろう。



Pentium

発売20年記念でアンロック版が出たが、どんなに頑張ってOC(OverClock)してもL3キャッシュが少な過ぎてWindowsではCore i3の性能に及ばない上に消費電力だけは軽く上回ってしまう。
安かろう、悪かろうを地で行くCPUであるが、それ故に、気楽にOCしたい人には最適で、実用性なんてアウトオブ眼中な漢のロマン(OC)にピッタシな一品である。
古いRISC vs CISC 対決では、RISC勢力がスーパースカラなどの高速化のための高度な回路設計に戸惑っている間に、CISC命令をハードウェアでエミュレートしRISC命令(μOPと呼ばれる)に変換することで、RISCのアイデアをそのまま実装し、中身はRISC、見た目はCISCな折衷案のPentiumを世に出し、それなりの評価を得た。
その後、Pentiumはイタズラに高性能を求めたり旧世代の486のODP(OverDriveProcessor)として差し替え路線を展開したりMMXを積んだりとがんばったりしたが競合するAMDやCylixの方が安かったり速かったりで迷走を続け焦りからか1994年の浮動小数点除算命令バグ話では『滅多に起きない』と強弁したが全量リコールを打ち出し信頼回復を行ったのは有名な話。しかし競合他社と性能面で拮抗、発熱や消費電力で負けの状態が続く。
その後、Pentiumはなにをやっても発熱がひどくなりとん挫。TDPがまだマシな古い設計のコアを新しい生産設備の設計ルールに書き起こしコア面積を小さくすることで発熱や消費電力を下げる荒業を駆使し、さらにWindowsは常時マルチプロセスでCPUは多い方が良いとチップに2個のコアを載せ、Core 2 シリーズと名打ってお得感をアピール(まるで飲み会のホラ話な展開)し復活し、AMDのAthlonにやっと肩を並べ、Core i シリーズで引き離し、今に至る。
そんなこんなでPentium自体に高性能なイメージはあまりなく、Core i シリーズで性能面で引き離すまでは営業努力で凌いでいだ様であり、今ではCore i シリーズとは別の販促系ブランドとして存在する。
ps.
さて、Pentium G3258 + AsRock Z97 Anniversary の組み合わせでやってみました。
マザボのAnniversary Boot では 4.0GHz止まりで、つまり40倍まで、4.2GHz では SSDすら認識できませんでした。
定格3.2GHzですからね。あたり、はずれがあるとは云え、渋い結果となりました。
OC専用なので、気長に色々やってみようかな。



お高いだけが取り柄のハイエンド・グラボ~GeForce GTX TITAN Z~

2,999ドルのハズだけど、日本での販売価格が40万円~。
※円高の頃から「日本の代理店は1ドル130円換算が定説」があるので円安で是正されつつある。(大笑
勿論、高杉るし、その割に性能も見合っていない。
その点は R9 295X2 も同じ。どちらも4K解像度(横4,000×縦2,000前後)でゲームをプレイしたい人向けであり、彼らにとって価格が高いことはあまり問題ではないというより、

「安いと興味を失う高価格モノしか興味がない層」

向けの製品。
次は ×3 や ×4 な製品が出てくるだろう。
それも 製造工程が 10 nm スケールで難航している間だけの話。
ろくに量産できないグラフィックチップを載せたグラボだから高価なだけであって、こんなグラボをターゲットにしてゲームを作っても儲からないので、専用ゲームは4K普及後の話になる。
だから、普通のゲームをヌルヌルに遊べることや 他人より高解像度の画面で遊べる優越感 が購入の主な欲求となる。
例外的なものとしては Master of Epic のルーレットでの目押し生産というものがあるものの、4K解像度で生産をする必要が全く、欲求項目としては過去完了形である。
一方、直接ゲームとは関係ないもののフォトショップの加工素材としてゲーム画面を4K高解像度は適している。普通にプレイしていると自分のキャラはかなり小さめにしているので、HD解像度では自分のキャラを拡大するとドット絵状態になることが多いからだ。
逆にゲームプレイを中継するならエンコード負荷や配信する回線の容量、受信側の回線の容量を考慮し、ゲーム画面の解像度は最小限にした方が良いが、エンコード負荷を下げる目的で高価なグラボを使う分には適しているかもしれない。
ま、
いずれにしても高杉な価格なのでニッチ市場である。
 
 




top