変奏現実

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

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

また時計が1時間ズレていた

いますぐログアウトしてくださいって云われた。
あと1時間あるはずなのに、あれれれれ?
Windowsの時計が遅れてる?
掃除をするために電源コンセントを抜いた時にUEFIがデフォルト設定に戻ったせいかな?
SATAもIDEになってて正常に起動せず慌ててAHCIに切り替えた。
time.windows.comで同期を取っているとインターネット時計を同期設定してあると1時間近く遅くなっていた。
時刻を合わせ、再びtime.windows.comで同期を取ろうとすると、
「time.windows.comと同期中にエラーが発生しました。タイムアウト期間が経過したため、この操作は終了しました。
 
時計は****/**/** **:** に同期しました。」
と意味不明な内容。
WEB検索すると、どうやら不安定らしい。
それはそうだろう、全世界のWindowsが同期を取りにいくのだから、たやすくパケットが詰まって当たり前だ。
time.windows.com以外のtime.nist.govに変えたら、ほら、うまくいった。
 
尚、Linuxの時刻は、NTPのコマンドラインから同期を取ってから、クローンで定期的に同期のズレを調整する仕組みになっているが、あまりに同期ズレが酷いとログにエラーを吐きだすだけで同期は取ってくれないから、それを見て手動で同期を取りなおさなければいけない。だからNTPでいつも同期を取っているから大丈夫なんてことはなく、NTPのログを注視しなければいけないのだ。



VS 2013のDBツールからSQL Server 2014のデータがやっと見れるようになった

SQL Server のアップデータが無限ループするバグを回避しようとして SQL Server 2014 Expressをインストすると、バージョンが上がり過ぎてしまい・・・
Visual Studio 2013 のデータベース ツールから テーブルのデータを表示しようとすると「Invalid version」とメッセージが出るようになってしまった。
延々とWeb検索をしても、
「仕方がないさ」という返事しか返ってこないので、「仕方がない」ので、フリーのSQLツールを使っていた。
すぐ解消されていたようだが、無償のVisualStudio 2013 Express でさらに日本語という壁がかなり厚かったらしく。
やっと、その問題が解決したアップデートの通知がやってきた。
VS 2013のメニューから「ツール」⇒「拡張機能と更新プログラム」を開き「更新プログラム」のタグを開くと

  1. 製品の更新プログラムに
  • データベース ツール用のMicrosoft SQL Server 更新プログラム
    • たくさんのSQL Server 2014  Expressへのアップデート コンポーネントをインストール。
  • Visual Studop 2013 Update 3
    • Microsoft SQL Server Data Tool と SSDTに必要なコンポーネントをインストール。

の2つ

  1. Visuak Studio ギャラリーに
  • NuGet Package manager for Visual Studio 2013

が表示されるようになった。
使用するのは先の2つだけだけど、終わってみると、結構な数のパッケージがインストされてしまった。

SSDTインスト後
SSDTインスト後

 
UPDATE3インスト後
UPDATE3インスト後

その後に、重かったオンラインヘルプをダウンロードするMicrosoft ヘルプ ビューアー2.1 のダウンロードの通知が出てきた。
herupu
重要度としてはコッチの方が上。(爆笑



【ハッシュ・ザ・ハーツ】 アン・ネーム・スペース ~前座~

セーブポイントが存在しないオンゲのキャラは死んでも何度でも蘇る。
その死と生還の無限ループはオンゲの性(サガ)と云われている。
だがそれは、プレイヤーが「クソゲー!」と投げ出すまでの間でしかない。
※最短記録:3分。(某氏

しかも、様々な苦難を乗り越えても、
どんな不死性を帯びていようとも、
レベルをカンストしていようが、
全身を究極のレア武器や装備で覆われていようが、
怪しいチート・ツールを使おうが・・・
他のサービスへ移行する術を持っていない。

そんな不憫なキャラ・データとネット・ウォームとバット・ネットワークの奇妙な話。

ps.
続きはそのうちに・・・



今更 サロゲートペア文字とは・・・

検索しても「Windows VISTAでは304文字のサロゲートペアが増えました。」としかヒットしない。
JIS X 0213:2004 対応と新日本語フォント「メイリオ」について では

マイクロソフトでは、従来 JIS 第 1 および第 2 水準漢字 (JIS X 0208 に規定されている 6,355 文字) をベースとした Shift JIS の漢字に加え、1998 年には JIS 補助漢字 (JISX 0212 に規定されている 5,801 文字) を加えた 12,156 文字の漢字を標準フォントとして組み込むなど、最新の日本語情報処理規格に基づいて文字の拡張を継続的に行ってきました。Windows Vista ならびに Windows Server 2008 では、これまでと同様に日本文化に根ざした情報化社会の実現を支援するため、国の国語施策および法令に整合する最新の JIS 漢字「JIS2004」に対応した日本語フォントを搭載しています。
Windows Vista ならびに Windows Server 2008 に標準搭載される全ての日本語 OpenType フォント、「MS ゴシック 3 書体 (MS ゴシック、MS P ゴシック、MS UI Gothic)」、「MS 明朝 2 書体 (MS 明朝、MS P 明朝)」および「メイリオ」が JIS2004 対応となります。
なお、JIS2004 対応に伴い、一部の漢字が正字に修正されていますので、ご留意ください。

簡単にすると

× 「メイリオ・フォントを使うとJIS2004 対応に伴い、一部の漢字が正字に修正されています」

○ 「MS明朝などのフォントもJIS2004 対応に伴い、文字化けしますけど仕様です!」

と云う内容だ。要は、Vista以前のXPからテキストを持ってくると、違った漢字に見えるものもあるハズ。
さらに、リンク切れの激しい資料をUnzipして見ていくと、
2.3.2. 追加された文字の使用による影響 に

CJK extension B に属する文字は特に注意が必要 です。CJK extension B とは Unicode の符号位置で U+20000 から U+2A6DF にマッピングされている文字で、

Windows ではUTF-16 によってサロゲートペア(2 つの 16 ビット符号単位で 1つの文字を表す)としてこれらの文字をサポート します。JIS2004にはCJK Extension Bに属する303文字があり・・・とある。

JIS X 0123:2000/2004 で検索した結果も、303文字。
多分、当初のVISTAでは303文字だったのだろう、しかし、Windows7ではU+29FCE(
 
あー、WordPressは、サロゲートペアは未対応だったらしく、記事が途切れてしまった。
たしかフランス製ですからね。関係ないよね。(大笑
ではやりなおし、
Windows7では、U+29FCEと見分けが付かない、U+29FD7(予鳥みたいな字) が増えて、304文字になってるハズ。
Windows8.1には大量にサロゲートペアが増えてるので、Windows7では未実装の文字も全部埋まっているから、ちゃんとやっておかないと、ボロボロだね。



ZBOX-Cシリーズ

ZONTACの超小型ファンレスPCの中のZBOX Cシリーズ
ZONTACのマザボやPCは高めの値段なので敬遠している。
高いパーツを使っているせいなのだろうけどね。
性能が高ければやはり発熱が多く、やはり注意が必要で、やはり最後にはうっかりダメにしてしまうからだ。
モニターのVESAマウンターでぶら下げっぱなしで使うNUCのような扱いをするとどうなるだろう。
「最近NUCがフーフーとお疲れ気味な様なのでエアーをブシューとしてみるよう!」な大雑把な性格にはファンレスは向かないだろう。
たとえCPUやメモリが高い耐久温度仕様(摂氏100℃)でも、その他のパーツがファンレス仕様でなければどうなるのか判らない。
発熱がフィンやマザーボードを伝達して外に逃げていく仕組みなので中は蒸し暑い。
HDDやSSDさらにUSBポートにつなぎぱなしの無線アダプタも一緒に頑張ってたりすると寿命はそんなに長くない気がする。
マメに分解掃除したりMRTGで経過を監視してみたり気を使う必要がある。
だからファンレスはマメな人向けと云うことになる。
 
付属品を見ると、Windows インストールディスクが無い。
多分、「バックアップメディアを自分で作れ」と云うことなのだろう。
おそらく、バックアップは取れるのだろう。
しかし、バックアップからどう起動するのかは不明だ。
 
スペックを見ると、

Name Intel Celeron N2930 (quad-core, 1.83 GHz) Burst frequency up to 2.16 GHz

Memory Type DDR3L
Memory Speed 1333 MHz
Slots 1 x 204-pin SODIMM
Capacity 2GB (up to 8GB)

となっている。
N2930自体はメモリーチャネル数が2のハズだが、このセットのメモリスロットは1個、しかし最大拡張サイズはN2930のスペックと同じ8GBとなっているので、N2930のスペック表の方が間違っている様な気がする。
安いセットに高価なDDR3L-1333MHzの8GBのSO-DIMMを付け加えるのは無駄な気がするが、最後の手段は残して置いた方がいいだろう。
使うWindowsが日本語版なので、英語版よりメモリは多く使うし、運悪く、ブラウザやウイルス監視ソフトがメモリ食いだったり、観たい動画が重くて仕方がないなど、想像すればするほど困った事態に事欠かない。
それくらい仮装記憶の処理は遅い。昔に比べればはるかに処理は速いのだが、アプリの要求スペック(HD画質の動画をカクカクせずに再生するなど)がはるかに高くなっているので、何かと難しいようだ。
多分、お化けのようなDDR式接続でSSDを直結するようになるまでは解決しないだろう。



ICTに弱い日本

ICT(Information and Communication Technology)は「情報通信技術」の略。
弱い理由は非常に簡単。

  1. 簡単な説明、簡単な操作、簡単な実装 と 簡単が並ぶと面白くないと評価するから。
  2. 苦労したとか、残業が何百時間とか、トータル云千人月かかった とか、無駄でも困難な仕事であったことを、無駄に求めるから。
  3. 1.2.となる理由は人月単価上昇の大きな理由と思われているから。

要は、訴求する結果を全く無視したICTをやって、何も価値なんて生まれない。
例をあげれば、小さい携帯電話の画面に4000文字を詰め込むことは困難だ。しかしこの様なことばかりしてもICTとして負け続ける。
だからICTに弱い。
要するに、
FinalFantasy- XIVの様な根性のひねくれたゲームの様なシステムを作り、
そしてそれを華麗に使いこなし、自ら上級者であることをアピールしても、一般ピープルの心には何も響かない。
なぜなら、一般ピープルがプロ野球を観戦するように眺めているのではなく、
一般ピープル自分自身で、球を投げ、バットを振り、飛んでくる打球をジャンプしてミットに捕えなければならないのだから・・・
ただ使いにくいダケのシステムでしかないのだ。
え?なのにFinalFantasy- XIVを遊んでるのはなぜかって?
『FFは遊びじゃない』という言葉があってね・・・
~証明終了~



【C#】便利なのか不便なのか意味不

VisualStudio でフォームにコントロールを貼れば、プロパティ・ウインドウから色々変更できる。
もしプロパティ・ウインドウが無かったら、
private void InitializeComponent()
{
(デザイナーやプロパティ・ウインドウで色々設定した内容。)
}
【色々設定した内容】の部分を手書きで直さないといけないし、全部コンパイルしないと結果が見えない。
非常に便利なんだけど、設定する方法は実は限られている。
string,intなどデータ型
SizeやFontなど組込まれているクラス
enum型
しか、使えないように見えるが、自作のクラスも使える。
ただ単純に使うと、データのところに 『(クラス名)』と表示されるだけだ。
では、どうすれば良いのか?探してみると、みかみんのプログラミング道場 に良いサンプルコードがあった。
これを使うと、追加したShadowプロパティのデータ欄に、GrayText, 1, ToBottomRight  と ちゃんと表示してくれる。
しかし、Sizeクラスのメンバー(WidthやHeight)の様にSizeの子要素としてメンバーを表示したりしないから、手入力でデータを直すには、気合を入れて No-Missで、GrayText, 1, ToBottomRight を修正しないといけない。
それではやっぱり不便なので、
public class ShadowConverter : TypeConverter

public class ShadowConverter : ExpandableObjectConverter
に置き換えると、Shadowにツリービューの様に [+]印が付き、そのプロパティも配下の要素として表現してくれるので、色や方向を変えやすくなる。
しかし、メンバーを変えてもShadowは知らないのでフォームに貼ったコントロールをイジらないと気が付かない(反映されない)。
そこで、Showにイベントハンドラを追加し、中で何か変わったら、コールバックさせる。
1.イベントハンドラを追加。
public event EventHandler SendEvent;
2.イベントハンドラに丸投げする処理と追加。
 
public void Exec()
{
//親に通知する
if (SendEvent != null)
{
SendEvent.BeginInvoke(null, null, null, null);
}
}
3.Shdawの各メソッドを上書きされたらExec()を呼び出す様に大幅に改定。
public Color Color { get ; set ; }

public Color Color { get { return _Color; } set { _Color = value; Exec(); } }
Color _Color;
に修正、DepthやDirectionも同様に修正。
4.カスタムコントロールのコンストラクタを追加し、イベントハンドラの登録処理を追加。
public カスタムコントロールのコンストラクタ()
{
_shadow.SendEvent += new EventHandler(ChildEventReceived);
}
5.イベントハンドラに登録するメソッドを追加。
void ChildEventReceived(object sender, System.EventArgs e)
{
Invalidate();
}
6.ここで、カスタムコントロールのクラスはソースの一番最初にしてね!と後出しで要求されるので、カスタムコントロールのクラスの部分をnamespace **** の直下に移動。
ま、これでかなり使いやすい感じになった。
 
しかし、コードが多すぎるような気がする。コピペだらけになりそうなConverterの部分を共通化。
public partial class EverybodyConverter : ExpandableObjectConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
if (sourceType == typeof(string))
return true;
else
return base.CanConvertFrom(context, sourceType);
}
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
if (destinationType == typeof(string))
return true;
else
return base.CanConvertTo(context, destinationType);
}
public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
{
string strValue = value as string;
if (strValue == null)
return base.ConvertFrom(context, culture, value);
return StringTo(strValue);
}
public virtual object StringTo(string strValue)
{
throw new Exception(“StringTo 未実装”);
}
public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
{
System.Type typeMe = value.GetType();
System.Type typeValue = value.GetType();
if (typeValue.FullName != typeMe.FullName || destinationType != typeof(string))
{
return base.ConvertTo(context, culture, value, destinationType);
}
string rc = ToString(value);
return rc;
}
public virtual string ToString(Object obj)
{
throw new Exception(“ToString 未実装”);
}
}
で、string と Object を変換するToString()とStringTo()だけ実装した方がいいかもしれない。※一応動く。
public class *****Converter : EverybodyConverter
{
public override object StringTo(string strValue)
{
・・・文字をオブジェクトに変換。
}
public virtual string ToString(Object obj)
{
・・・オブジェクトから文字列を作成。
}
}



新型「LIVA」 LIVA-B3-2G-64G-V

新型が出る。
見た目もケースの色が黒⇒白と大きく変わる。
CPUはCeleron N2806N2807 に変わがCPU自体の性能はほとんど変わらない。

ただ対応メモリが DDR3L-1066 ⇒ DDR3L-1333 になるので

この世界最弱なCeleronのオンボ(Intel® HD Graphics 313 MHz)でゲームをするときには地味に効きそうだ。

ただオンボのグラフィックス・バースト周波数は 756 MHz ⇒ 750 MHzに下がっているので、何とも云えない。

またインテル® クイック・シンク・ビデオがYESになったので動画が見やすくなるかもしれない。

セキュアキーも使えるようになったが、メールやHTTPSで使う様なものかは判らない。

メモリは2GBのまま、増やせばコスト増加に直結するので致しかないだろう。
ストレージのeMMCつまりSSDが、32GB ⇒ 64GB に倍増する。
これでスペック上はここのサーバーとほぼ同じになる。
Intel DCCP847DYE (Celeron 847)+DIMM(4G)1枚+SSD(64GB)+無線LAN
しかし、Celeron 874はクロックが1.1GHzと低い反面、L3キャッシュが2MBとN2807の倍なので意外と性能が高く、DIMMもデュアルチャンネル構成にすれば16GB(8GB×2)まで増やせるしデータ転送速度も21.3 GB/sと2倍になるので、あなどれないのだ。
単純にNUCはLIVAの2倍の体積、性能も2倍、メモリやSDDなどを含めた価格も2倍と考えると、いいのかもしれない。
とりあえず、TVにつなぐならAndroidドングルよりLIVAの方が使い道は多いかもしれないし、経理を除く一般事務なら十分使えそう。ファンレスなのでNUCの様に使いだすとフーフーとか唸らず静かだ、USB3にポータブルなSSDやHDDをつなげば容量不足も解消できる。ただファンレスなので室温の高い仕事場ではジワーと遠赤外線熱源となるので人ともども熱射病にかかるかもしれない。※水分は与えないでください。
 
黒⇒白と来れば次は【赤』ですよね。(期待
黒同様 0円Windowsはバンドルされない見込み。
安いのでせめてDSP版で売上を上乗せしたいんだろうね。
バンドルしたら困るくらい売れると思うんだけどね。※だから困るからやらない?
 
 
 
 



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.




top