2008年12月30日火曜日

[.NET]Control.Updateの活用

たとえば100回ループする処理を実行中に状況を画面に表示したい場合、ループ内で単純にControl.Text属性を変更しても画面は更新されません。以下のbutton1_Clickがその例です。

回避方法としてすぐに思いつくのがDoEventsを使う方法です。以下のbutton2_Clickがその例です。しかしDoEventsは副作用があり、他の処理に影響を及ぼしてしまう場合があります。そのため、利用をできるだけ控えてきましたが、こういう処理の場合泣く泣くDoEventsを書いてきました。

しかし、button3_ClickのようにControl.Updateを使用する方法があること今日知りました。ということで確認の実装してみました。Control.Updateでも目的は達成できますね。

/// <summary>
/// 画面更新されない例
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button1_Click(object senderEventArgs e)
{
    for (int i = 0i < 100i++)
    {
        Thread.Sleep(100);
        // textBox1に値を設定しているけど、ループ中画面は更新されない。
        textBox1.Text = i.ToString();
    }
    textBox1.Text = "Finish!!";

}

/// <summary>
/// Application.DoEventsで画面を更新する例
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button2_Click(object senderEventArgs e)
{
    for (int i = 0i < 100i++)
    {
        Thread.Sleep(100);
        textBox1.Text = i.ToString();
        // DoEventsでメッセージQueueを処理する。
        Application.DoEvents();
    }
    textBox1.Text = "Finish!!";
}

/// <summary>
/// Control.Updateで画面を更新する例
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button3_Click(object senderEventArgs e)
{
    for (int i = 0i < 100i++)
    {
        Thread.Sleep(100);
        textBox1.Text = i.ToString();
        // Control.Updateで処理する。
        textBox1.Update();
    }
    textBox1.Text = "Finish!!";
}

2008年12月28日日曜日

[.NET]VB.NETの三項演算子

C#では、三項演算子を以下のように書きます。

int result = arg == null ? 0 : arg.Length;


しかし、VB.NETにはコレ相当の演算子はありません。が、新しいバージョンでは、Ifなる演算子が追加されていたようです。コードはこんなかんじ

Dim result As Integer = IIf(arg = Nothing0arg.Length'実行時エラーになる
Dim result2 As Integer = If(arg = Nothing0arg.Length)

2008年12月24日水曜日

[.NET]画像処理グレースケール化(4)

以前、Unsafeを使わずに配列処理の処理をし画像をグレースケール化するGDD Blog: [.NET]画像処理グレースケール化(1)
GDD Blog: [.NET]画像処理グレースケール化(2) GDD Blog: [.NET]画像処理グレースケール化(3) という記事を書きましたが、パフォーマンスの比較をするためにあえてUnsafeを使ってパフォーマンスを計測してみました。コードはこんな感じ。


//以下の構造体を別途定義
//private struct RGB
//{
//    public byte b;
//    public byte g;
//    public byte r;
//}

Bitmap bmp = new Bitmap(ctlPicture.Image);

//bitmapをメモリ上にロックします
Rectangle rect = new Rectangle(00bmp.Widthbmp.Height);
BitmapData bmpData = bmp.LockBits(rectImageLockMode.ReadWrite,
                                          PixelFormat.Format24bppRgb);

int stride = bmpData.Stride;
int size = stride * bmp.Height;

unsafe
{
    RGBpRGB = (RGB*)bmpData.Scan0.ToPointer();
    for (int j = 0j < sizej = j + sizeof(RGB))
    {
        byte val = (byte)Math.Round((pRGB->r + pRGB->g + pRGB->b) / 3.0d);
        pRGB->r = val//r
        pRGB->g = val//g
        pRGB->b = val//b
        pRGB++;
    }
}

bmp.UnlockBits(bmpData);
ctlPicture.Image = bmp;


5回の計測の平均値で20.2msでした。Unsafeを使った割にはアレですね。

2008年12月21日日曜日

[他]SQLServer2008 Express用 SMS

以前、VS2008 Express Editionを入れたときに、SQLServer2005から2008にバージョンアップしました。しかし、2005用のSMS(SQLServe Management Studio)ではSQLServer2008にはつながらないようです。

で、しらべてみると、Microsoft® SQL Server® 2008 Express with Toolsというのがありました。備忘録としてメモ。

ダウンロードしたツールの、「インストール」→「SQL Serverの新規スタンドアロン インストールまたは既存のインストールへの機能追加」を選択。あとはウィザードに従って次へボタンを押下。チェックボックスで何を入れるかを選択する画面があります。ここで管理ツールっぽいものをチェックすればOK。

しかし、PowerShellをインストールしていないと先に進めません。コレがまた面倒(個人的見解)なんです。
PowerShellを入れたくない人は入れれないことになりますね。

2008年12月15日月曜日

[.NET][Java]単体テストツール

現在、短期のJavaプロジェクトに携わっています。画面の無いサービス的なアプリケーション開発ということもあり、JUnitで単体テストを組むことにしました。
で、カバレッジ計測をしたかったため、JUnitと連動する計測ツールを探したところ、djUnitにたどり着きました。ツールをEclipseに導入して単体テストを動作させると、未通過のロジックにはしるしが付いたり、レポートが表示されたりと、至れり尽くせり。さらにこのdjUnitはMockとしての機能があり、特定のメソッドの戻り値を強引に書き換えたり、例外を発生させたりすることができます。
もう自分でMockを書かなくても大半はカバーできたりします。最近みたツールの中では最高かもしれません。

で、.NET系でも同じようなツールはないかと思い検索したところ、Typemockというツールがヒットしました。実際に使っていませんが、MSDNマガジン2008/6月号に記事が載っていました。
次回、機会があったら使ってみようと思います。

2008年12月10日水曜日

[.NET]FileSystemWatcher

VS2005以降だと思いますが、FileSystemWatcherというコンポーネントが存在します。
興味があったのでちょっと使ってみました。

FileSystemWatcherではEnableRaisingEventsというプロパティにて、イベント処理型と、変更待機のいずれかを選択することができます。
以下の例では、サブフォルダ配下も含め、ファイルの生成・更新・リネーム・削除を監視し何かあったら画面に表示するというサンプルです。イベント処理のタイプで実装しています。


public partial class Dust28Form : Form
{
    public Dust28Form()
    {
        InitializeComponent();
    }


    private void Dust27Form_Load(object senderEventArgs e)
    {
        //デザイナで以下のプロパティが設定してある

        ////サブディレクトリを含めるかどうか
        //fileSystemWatcher.IncludeSubdirectories = true;
        ////ファイル名のフィルタリング(ぜんぶ)
        //fileSystemWatcher.Filter = true;
        ////監視対象フォルダ
        //fileSystemWatcher.Path = "c:\temp";
        ////監視対象のイベント
        //fileSystemWatcher.NotifyFilter = NotifyFilters.FileName | NotifyFilters.LastWrite | NotifyFilters.DirectoryName;


        //イベント ハンドラ呼び出しをマーシャリングするために使用するオブジェクト
        fileSystemWatcher.SynchronizingObject = this;
        //初期状態は機能を無効にする
        fileSystemWatcher.EnableRaisingEvents = false;
    }

    private void btnMonitor_Click(object senderEventArgs e)
    {
        //ボタン押下イベント。機能の有効無効を排他的に切り替えている

        //今のステータスと入れ替える
        fileSystemWatcher.EnableRaisingEvents = !fileSystemWatcher.EnableRaisingEvents;
        //ボタンのキャプションを変更する
        btnMonitor.Text = fileSystemWatcher.EnableRaisingEvents ? "監視停止" : "監視開始";
    }

    private void fileSystemWatcher_Changed(object senderSystem.IO.FileSystemEventArgs e)
    {
        //更新
        AddLog("Changed"e);
    }

    private void fileSystemWatcher_Created(object senderSystem.IO.FileSystemEventArgs e)
    {
        //生成
        AddLog("Created"e);
    }

    private void fileSystemWatcher_Deleted(object senderSystem.IO.FileSystemEventArgs e)
    {
        //削除
        AddLog("Deleted"e);
    }

    private void fileSystemWatcher_Renamed(object senderSystem.IO.RenamedEventArgs e)
    {
        //名前変更
        AddLog("Renamed"e);
    }

    private void AddLog(String evtSystem.IO.RenamedEventArgs e)
    {
        //画面への出力(ファイル名変更)
        textLog.AppendText(String.Format("{0} Event={1} File={2} OldFile={3}\n"evte.ChangeTypee.FullPath,e.OldFullPath));
    }

    private void AddLog(String evtSystem.IO.FileSystemEventArgs e)
    {
        //画面への出力(更新・削除・作成)
        textLog.AppendText(String.Format("{0} Event={1} File={2}\n"evte.ChangeTypee.FullPath));
    }

}

2008年12月7日日曜日

[.NET]log4netのPatternにTabを含める

先日@itの掲示板を見ていると「【Log4net】エラーログをタブ区切りにしたい」という話題が挙がりました。

私も興味があったので調べてみましたが、結局わからず、PatternConverterを使ってがんばれば。という結論に達しました。しかし、そのレスを見ると、xml的な解決策を提示していました。
目からうろこです。すばらしい発想の転換ですね。しかし、当然といえば当然なんですけどね。

2008年12月5日金曜日

[.NET]埋め込みリソース

VS.NET2003以前はよく知りませんが、VS2005以降では、プロジェクトの中に好きなリソースを埋め込むことができます。画像やHTMLをアセンブリの中に埋め込むイメージです。

作業としては、以下のとおりです。
  1. 該当のリソースを右クリックし、「ビルドアクション」を「埋め込まれたりソース」にする
  2. Assembly.GetManifestResourceStreamを使用し情報を取り出す


コードのほうはこんな感じ。以下の例ではプロジェクト内にhtmlというフォルダがある前提。
(ネームスペース+フォルダ+ファイル名というところがアレ)

string result = string.Empty;

//タイプからリソース名を組み立てる(namespace + フォルダ名 + ファイル名)
//プロジェクトに「html」というフォルダがある
string resName = GetType().Namespace + ".html." + name;

try
{
    Assembly asm = Assembly.GetExecutingAssembly();
    using (StreamReader rd = new StreamReader(asm.GetManifestResourceStream(resName)))
    {
        result = rd.ReadToEnd();
    }
}
catch
{
    //特にないもしない
}

2008年12月1日月曜日

[.NET]MenuStripで左の余白を消す方法

ContextMenuStripでは、AutoSizeとShowImageMargine属性を使うことにより、左側のイメージが表示されている余白を削除することができます。しかしどういうわけかMenuStripにはShowImageMargine属性が無いため、左の余白を消すことができないみたいなのです。

コレに対し、MenuStripからContextMenuStripを表示する方法が紹介されていました。結構強引なやり方だと思いますが、ありはありですね。

方法 : ContextMenuStrip コントロールでチェックの余白とイメージの余白を有効にする

2008年11月28日金曜日

[.NET]デフォルトコンストラクタは自動で呼び出される

普段あまり意識していなかったのですが、デフォルトコンストラクタは勝手に呼ばれるらしい。ということで実験してみました。

■コード
public class Kihon
{
    public Kihon()
    {
        System.Diagnostics.Debug.WriteLine(" kihon()");
    }

    public Kihon(string text)
    {
        System.Diagnostics.Debug.WriteLine(" kihon(string text)");
    }
}

public class Hasei : Kihon
{
    public Hasei()
    {
        System.Diagnostics.Debug.WriteLine(" hasei()");
    }

    public Hasei(string text)
    {
        System.Diagnostics.Debug.WriteLine(" hasei(string text)");
    }
}

public class HaseiHasei : Hasei
{

    public HaseiHasei()
        : this("x")
    {
        System.Diagnostics.Debug.WriteLine(" HaseiHasei()");
    }

    public HaseiHasei(string text)
//            : base(text)
    {
        System.Diagnostics.Debug.WriteLine(" HaseiHasei(string text)");
    }
}


■実行例
System.Diagnostics.Debug.WriteLine(@"1.new Hasei(""text"")-----------------------------");
Hasei a = new Hasei("text");

System.Diagnostics.Debug.WriteLine(@"2.new HaseiHasei(""text"")------------------------");
HaseiHasei b = new HaseiHasei("text");

System.Diagnostics.Debug.WriteLine(@"3.new HaseiHasei()--------------------------------");
HaseiHasei c = new HaseiHasei();


■実行結果
1.new Hasei("text")-----------------------------
 kihon()
 hasei(string text)
2.new HaseiHasei("text")------------------------
 kihon()
 hasei()
 HaseiHasei(string text)
3.new HaseiHasei()--------------------------------
 kihon()
 hasei()
 HaseiHasei(string text)
 HaseiHasei()

2008年11月27日木曜日

[.NET]場合によりRadioButtonの変更を拒否する

先日、WindowsFormの仕事をしていました。画面にRadioButtonがあるのですが、とある状態のときチェックを変更させたくない。という要件がありました。納品ギリギリだったので、調べるまもなくClickChangedの中で処理しました。後日、本来あるべきか手法を調べようと思っており、今日思い立ちましたので調査してみました。

すると、Validatingというイベントがあり、このイベント引数を操作することによりキャンセルできることがわかりました。コードはこんな感じ(現在秒が2で割り切れない場合キャンセルします)。

private void radioButton1_Validating(object sender, CancelEventArgs e)
{
    e.Cancel = DateTime.Now.Second % 2 == 0;
}



・・・こんな簡単なら調査に時間割けばよかった。とほほ。

2008年11月26日水曜日

[他]大規模データ処理の極意?

先日CodeZineに、はてな流大規模データ処理の極意という記事が載っていました。じっくり読んでしまいました。その中で私自身の考えも及んでいなかったこと・知らなかったこと(Linuxちょっと弱い)がいくつか書かれていることがありました。抜粋すると以下のような感じ。
  • メモリ(キャッシュ)で処理ができなくなりディスクI/Oが発生した時点で負け
  • Linuxではメモリが空いていれば秋メモリはすべてキャッシュにまわる(キャッシュの制限はない)
  • OSが起動したら、データベースのファイルを全部catして「/dev/null」に投げる→メモリにキャッシュが構築される
  • SQL文でJOINを使わない(複数のSQLに分離して実行→テーブル単位でDBサーバを分けたりできる)

できればこのセミナーに参加したかったです。しかし、CodeZineに限らず、このような記事をタダで読めるとは。いい時代になりました。

2008年11月25日火曜日

[.NET]ASP.NETで特定のパスの未認証で利用する

先日@itの掲示板を眺めていると、IISフォーム認証で、外部サイトからrequest→responseする方法という話題が挙がりました。
システム連携かなにかで、特定のパスのみ、未認証で利用したいということらしい。

私自身ASP.NETをあまりやっていないので、どのように解決するのかわかりませんでしたが、特定のASPXでも特定のパスでも、Web.configのみで背低可能なようです。

いやー勉強になりますねぇ。

2008年11月18日火曜日

[.NET]Exception.StackTraceプロパティ

ちょっとしたコードの書き方の違い何ですが、以下のTest1とTest2メソッドでは、Exception.StackTraceの結果が変わってしまうのです。
Test1ではコールスタックが更新されず、Test2ではコールスタックが初期化されます。

private void Form1_Load(object senderEventArgs e)
{
    try
    {
        Test1();
    }
    catch (Exception ex)
    {
        System.Diagnostics.Debug.WriteLine("-----------Test1");
        System.Diagnostics.Debug.WriteLine(ex.StackTrace);
    }
    try
    {
        Test2();
    }
    catch (Exception ex)
    {
        System.Diagnostics.Debug.WriteLine("-----------Test2");
        System.Diagnostics.Debug.WriteLine(ex.StackTrace);
    }
}

private void Test1()
{
    try
    {
        ExceptionThrow();
    }
    catch (Exception e)
    {
        throw;
    }
}

private void Test2()
{
    try
    {
        ExceptionThrow();
    }
    catch (Exception e)
    {
        throw e;
    }
}
private void ExceptionThrow()
{
    throw new NotImplementedException();
}


実行結果はこんな感じ。

-----------Test1
   場所 WindowsFormsApplication1.Form1.ExceptionThrow() 場所 C:\Users\hoge\AppData\Local\Temporary Projects\WindowsFormsApplication1\Form1.cs: 66
   場所 WindowsFormsApplication1.Form1.Test1() 場所 C:\Users\hoge\AppData\Local\Temporary Projects\WindowsFormsApplication1\Form1.cs: 49
   場所 WindowsFormsApplication1.Form1.Form1_Load(Object senderEventArgs e場所 C:\Users\hoge\AppData\Local\Temporary Projects\WindowsFormsApplication1\Form1.cs: 23

-----------Test2
   場所 WindowsFormsApplication1.Form1.Test2() 場所 C:\Users\hoge\AppData\Local\Temporary Projects\WindowsFormsApplication1\Form1.cs: 61
   場所 WindowsFormsApplication1.Form1.Form1_Load(Object senderEventArgs e場所 C:\Users\hoge\AppData\Local\Temporary Projects\WindowsFormsApplication1\Form1.cs: 32

2008年11月16日日曜日

[.NET]URLを組み立てる

ASP.NETなどで、画面遷移をするURLを組み立てるとき、現在のGET引数を元にパラメータを変更したURLを組み立てたい。といったときに.NET FrameworkではUriBuilderというクラスがあります。

このクラスにQueryというプロパティがあります。名前のとおりQueryを操作するのですが、名前ではなく、インデックスでしかアクセスができないうえ、URLエンコードもしてくれないという、かゆいところに手はが届かないアレなクラスですが、何も無いよりはいいかも。

文字コードの問題はありますが、この辺まとめて日本向けにユーティリティ的なクラスを作ると意外と便利かも。

2008年11月11日火曜日

[.NET]プロセス間の排他制御

以前Log4netにて、複数のプロセスから同じファイルに出力すると言う処理を実装したことがあります。
プロトタイプだったので、良しとしましたが、本来ファイル出力時に他のプロセスが書いていないことを確認してから出力するという処理が必要でしたが、時間もあまり無くそのままにしていました。

その後、正式にプロジェクトはスタートしたのですが、私はプロジェクトを離れたため、その後どうなったのかは不明です。正式版ではなんらか排他制御していると思いますが、当初Mutexを使う予定でした。

以下の例では、同じプログラムを複数実行しても、ロックボタンを押せるのは1つという条件をMutexを使って実装してみました。すごく簡単なので、プロトタイプ作るときにも入れ込んでおけばよかった。。。

public partial class DustCS25Form : Form
{
    private Mutex mutex = null;

    public DustCS25Form()
    {
        InitializeComponent();
    }

    /// <summary>
    /// 初期化
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void DustCS25Form_Load(object senderEventArgs e)
    {
        btnLock.Enabled = true;
        btnRelease.Enabled = !btnLock.Enabled;
        textBox1.Text = "初期状態";
    }

    /// <summary>
    /// ロックボタン押下
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void btnLock_Click(object senderEventArgs e)
    {
        //2つ目の引数をOS上でユニークにする。
        mutex = new Mutex(falsetextID.Text);

        textBox1.Text = "ロック取得開始";
        //ロックする
        mutex.WaitOne();
        textBox1.Text = "ロック中";

        btnLock.Enabled = false;
        btnRelease.Enabled = !btnLock.Enabled;
    }

    /// <summary>
    /// 解除ボタン押下
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void btnRelease_Click(object senderEventArgs e)
    {

        //ロックを解除する
        mutex.ReleaseMutex();
        textBox1.Text = "初期状態";

        btnLock.Enabled = true;
        btnRelease.Enabled = !btnLock.Enabled;
    }

}

2008年11月8日土曜日

[.NET]WebBrowserのShift+リンク押下

System.Windows.Forms.WebBrowserを使うとそのままHTMLをコントロール上に表示可能です。さらに、ボタンやリンクなども動作します。内部的にはIEのコンポーネントということらしいです。
ソレが理由かはわかりませんが、操作系のがIEに依存してしまします。たとえば、Shift+リンク押下。
コレをやると、ブラウザが起動するのです。これを抑止する方法があったので紹介します。

これは、NewWindowイベントをインプリメントする必要があります。コードはこんな感じ。

private void webBrowser1_NewWindow(object senderCancelEventArgs e)
{
    e.Cancel = true;
    webBrowser1.DocumentText = "こらー!!";
}

2008年11月5日水曜日

[.NET]テキストファイルを読み込みstringにセットする

テキストファイルを読み込み、string型にセットする処理を実装しようと思い、StreamReaderのReadLineで読み込み、StringBuilderにセットすると言うループを組んでいました。
その直後くらいに、たまたまMSDNのStreamReaderを見ると、ReadToEndなるメソッドがあることを知りました。
コレ使うとループ不要の一発で。。。コードはこんな感じ。

string result;
using (StreamReader rd = new StreamReader(new StreamReader("TestFile.txt")))
{
    result = rd.ReadToEnd();
}

2008年11月1日土曜日

[他]VS2008ショートカット集

以前から無いかなぁと思っていたのですが、Visual Studio 2008 ショートカット キー というのがありました。
備忘録としてメモ。

2008年10月31日金曜日

[他]VS2005/2008のトレースポイント機能

今日、@itの記事を読んでいると、ブレークポイントならぬ、トレースポイントについて紹介されていました。機能的には、そのポイントを通過するとDebug.WriteLineのようにアウトプットに好きな文字列を出力することができます。で調べてみると、MSDNにも記事がありました。例により備忘録としてメモ。


トレースポイントを設定すると、●ではなく◆が表示されます。また、通常のブレイクポイントの設定を変更することにより、同様の機能を実現できるみたいですね。

コンパイルが不要なので、結構便利かもしれません。コード的には100%修正ミスが無いことが保障できますし。

しかし、残念ながら、ExpressEditionではサポートされていません・・・。

また、この機能はコンテキストメニューからのみ利用できるようで、ツールボタンやメニューからは利用できません。何でなんでしょう?

2008年10月28日火曜日

[.NET]WindowsFormでリサイズ時の最小値を制御する

ちょっと前にかかわったWindowsFormを使ったシステムの案件で、リサイズ時に特定のサイズより小さくできないようしてほしいとの依頼がありました。
でとりあえず、サイズ変更系のイベント(Resize,ReseBegin,ResizEnd)あたりで実現できるかなぁ。と思い、ソレらしく実装しようと考えました。
「どうせイベントの引数でキャンセルする」みたいなパターンだろうと思い、インプリメントしようとすると、それらしいプロパティが無いのです。

で調べてみると、FormにMinmumSizeというプロパティがあり、ここに値を設定するだけでした。最大値の場合はMaximumSizeというプロパティがあります。

いやー簡単に実現できたので、テストが楽にできて助かりました。

2008年10月25日土曜日

[.NET]アクティブなWindowにキー入力?

先日MSDNを斜め読みしていると、アクティブなWindowにキーストロークを送信するクラスとして、System.Windows.Forms.SendKeysというのが存在することを知りました。

用途としては、たとえばWindowsFormのテストの自動化っぽい事が可能ですね。また、何らかの都合でボタン押下相当の処理では問題場ある場合、本当にキー入力っぽく処理することも可能ですね。

Googleさんで検索してみると、VBスクリプトでも同様の機能が提供されているようですね。知りませんでした。

2008年10月22日水曜日

[.NET]カラーデータを保存する

先日、XMLに表示色(RGB)を保存するという処理を実装しました。
とりえあえず、Color.ToArgb()とColor.FromArgb()で実装したものの、人が見やすい形式であるXMLにふさわしくないなぁと思っていました。で、考えたのがHTMLの#RRGGBBの形式です。
アノ形式に簡単に落とせないかなぁと思って調べてみると、ColorTranslatorというクラスがあることがわかりました。

  • #RRGGBBからColorに変換 → ColorTranslator.FromHtml ()
  • Colorから#RRGGBBに変換 → ColorTranslator.ToHtml()

いやー便利なクラスがあるものですねぇ。

2008年10月20日月曜日

[.NET]ダブルクリックとクリックのイベントをインプリメントすると、ダブルクリック時にクリックが先に発生する

ちょっと長いタイトルですが、.NET WindowsFormアプリでマウスクリック系のイベントで困ったことが発生しました。というのは、ダブルクリックとクリックをインプリメントすると、ダブルクリック時にクリックも発生してしますのです。

処理の特性上、通常のクリック・ダブルクリックでは問題は発生しないのですが、 キーボードとの組み合わせで、


  • Ctrl+クリック:選択状態を排他的に変更

  • Ctrl+ダブルクリック:編集状態に遷移

という処理をします。この場合ダブルクリックの処理が「選択状態にを排他的に変更+編集状態に遷移」に*見えて*しまうのです。

とりあえず、クリックが排他的な処理であったため、ダブルクリックのときにクリック相当の処理を実行するようにしちゃいました。一瞬ちらつきますが、処理的にはそれらしく動作しているように*見えます*。

もうひとつの対応方法としては、


  1. クリック時にタイマー起動。タイムアウトの設定は、SystemInformation.DoubleClickTimeより取得

  2. ダブルクリックイベントが発生した場合、タイマーを停止する

  3. タイマーのイベントが発生したらクリックの処理をする


です。

しかし、コレを実装するとクリックの処理のパフォーマンスが悪く*見えて*しまいます。対処方法としてはどっちもどっち。しかし、仕組み上どうしようもないことに気がつきました。クリック時にダブルクリックかどうかは予測できませんからねぇ。

もっとよい方法はないものか考えてみたものの、よい解決案は見つかりませんでした。ということで、こんな設計するなよ!って事にしておこう。

2008年10月14日火曜日

[.NET]Excelの印刷ページ数の算出

先日COM Interopを使ったExcelを使う機会がありました。テンプレートから値をはめ込んだ後、印刷ページ数を算出し、目次を作るという処理を組んだのですが、どうもページ数が合わない。
で、いろいろ調べてみると非推奨ながらマクロを使った方法があるようなので紹介します。

//本当はコレで算出できるはずなんですが。。。
//    int hCount = getHPageBreaks(sheet) + 1;
//    int vCount = getVPageBreaks(sheet) + 1;
//
//    return hCount * vCount;


//代替の方法
    return Convert.ToInt32(sheet.Application.ExecuteExcel4Macro"Get.Document(50,\"" + sheet.Name + "\")" ));

2008年10月8日水曜日

[他]インテリセンスが英語に?

先日、C#.NET 2008 Express Edition SP1に入れ替えました。
簡単なサンプルを作っていると違和感が。。。そうなんです。インテリセンスの説明が英語になっているではないですか。なんだそりゃ。

ディベロッパー製品開発統括部 Blogによると、「また、Visual Studio の開発環境中に表示される Intellisense ですが、現在一部英語で表示される箇所があります」だそうです。っていうかほとんど英語のように感じました。

また、同じマシンにインストールしてあるC#.NET 2005 Express Editionを何気に開いてみると、なんとこっちのインテリセンスも英語になっちゃってます。2008に巻きこまれたようです。いつ直ることやら。。。

2008年10月7日火曜日

[他]ソケットのエラー コード

Socketで発生するエラーコードについてまとめられているURLが紹介されていました。備忘録としてメモ。
Windows ソケットのエラー コード、値、および意味

2008年10月5日日曜日

[他]定義に移動(G)(VS2005,2008)

先日@itの掲示板を見ていると、「ctrl + shift + F2 で戻れない」という話題がありました。

コレは、コンテキストメニューの「定義に移動(G)」など、ジャンプ系の機能を実行した後、呼び出し元に戻るという昨日をショートカットで呼び出すというものなのですが、私この「定義に移動(G)」を結構使います。そのため「ウホ、ソレ便利かも」と思って実際にやってみました。が、動作しませんでした。

で、キーボードの反応が悪かったのか?と思い、偶然F2を押してみると、なんと「リファクタリング」の「名前の変更(G)」が動くではないですか!!コレは、エクスプローラやExcelの選択したオブジェクトの名前(データ)変更と同じのなで、一発で記憶することができました。

私、結構メソッド名変更するタイプなので、いいショートカットを覚えられました。

該当のスレッドを追っていくとヒントがありますが、「ctrl + shift + F2 」はVB系のキーバインドらしく、VS標準はCTRL+[-]ということでした。ちなみに「定義に移動(G)」はF12です。この組み合わせも結構便利かも。

2008年10月1日水曜日

[他]SQLで最小値の一覧を取得する

先日@itを見ていると、「キー値が同一のとき、キー以外の値が最小のデータを効率よく取得するには」という話題が挙がりました。

で、私が思いつく方法といえば、サブクエリで最小値の一覧を取得しその値の一覧を連結するという方法です。コードはこんなかんじ(手打ち未検証)。

SELECT 
     key
    ,code
    ,value1
    ,value2 
FROM table1
WHERE
(key,codeIN (SELECT key ,MIN(codeFROM table1 GROUP BY key,code)


このほかにINNER JOINする方法を思いつきました。
しかし、このスレッドでは私が思いついた方法以外の方法が紹介されていました。おそらく私の思いついた方法はコストが高いと思います。集計関数を使わずにできるとは。。。いやー勉強になりますねぇ。

2008年9月30日火曜日

[.NET]普通のボタンにショートカットキーを割り当てる(その2)

先日ダミーのメニューを使ったボタンのショートカット機能ですが、別の方法として、ErrorProviderっぽい実装ができないか考えてみました。実装してみるとそれらしく動作しました。

コンポーネントなので、デザイナーのFormにドロップすればよいのですが、TargetForm(ComponetからFormを取得す方法がわからない)とKeyPreviewプロパティをそれらしく設定する必要があります。
FormのKeyPreviewの代わりに、このコンポーネントのKeyPreviewをTrueにすると、初期化時にTargetFormのTargetFormをそれらしく設定します。

/// <summary>
/// ショートカットキー機能を付加するExtenderProvide
/// </summary>
[ProvideProperty("ShortcutKeys"typeof(Control))]
public partial class ShortcutKeyProvider : ComponentIExtenderProviderISupportInitialize
{
    /// <summary>
    /// 情報格納エリア
    /// </summary>
    private Dictionary<KeysControlextInfo = new Dictionary<KeysControl>();
    
    private Form targetForm = null;
    /// <summary>
    /// 対象のForm
    /// </summary>
    [Description("ショートカットを有効にする対象のform")]
    public Form TargetForm
    {
        get { return targetForm; }
        set { targetForm = value; }
    }

    private bool keyPreview = true;
    /// <summary>
    /// キーイベントの設定
    /// </summary>
    /// <remarks>FormのKeyPreviewがFalseの場合、この値をFormのKeyPreviewに設定します</remarks>
    [Description("キーボードイベントがフォームとともに登録されるかを決定します")]
    public bool KeyPreview
    {
        get { return keyPreview; }
        set { keyPreview = value; }
    }

    /// <summary>
    /// コンストラクタ
    /// </summary>
    public ShortcutKeyProvider()
    {
        InitializeComponent();
    }

    /// <summary>
    /// コンテナ指定付コンストラクタ
    /// </summary>
    /// <param name="container">コンテナ</param>
    public ShortcutKeyProvider(IContainer container)
    {
        container.Add(this);

        InitializeComponent();
    }

    #region ISupportInitialize メンバ

    /// <summary>
    /// 初期化の開始
    /// </summary>
    public void BeginInit()
    {
    }

    /// <summary>
    /// 初期化の終了
    /// </summary>
    public void EndInit()
    {
        //キー押下イベントを設定
        if (TargetForm != null)
        {
            TargetForm.KeyDown += new KeyEventHandler(TargetForm_KeyDown);
            if (TargetForm.KeyPreview == false)
            {
                System.Diagnostics.Debug.WriteLine("****FORMのKeyPreviewを変更します!! ==> " + KeyPreview);
                TargetForm.KeyPreview = KeyPreview;
            }
        }
    }

    #endregion



    #region IExtenderProvider メンバ

    bool IExtenderProvider.CanExtend(object extendee)
    {
        //ボタンのみ対応する.対応するコントロールを増やすならここに追加
        return extendee is Button;
    }

    #endregion

    /// <summary>
    /// ショートカットキーの取得
    /// </summary>
    /// <param name="ctrl">該当のコントロール</param>
    /// <returns>キー</returns>
    [Description("このコントロールに割り当てたいショートカットキーを設定・取得します")]
    [DefaultValue(typeof(Keys), "None")]
    public Keys GetShortcutKeys(Control control)
    {
        return GetKeysByControl(control);
    }

    /// <summary>
    /// ショートカットキーの設定
    /// </summary>
    /// <param name="ctrl">該当のコントロール</param>
    /// <param name="value">割り当てられたキー</param>
    [Description("このコントロールに割り当てたいショートカットキーを設定・取得します")]
    public void SetShortcutKeys(Control controlKeys shortcutKey)
    {
        //キーがほかに割り当て済みの場合、例外とする
        Control checkCtrl;
        if (extInfo.TryGetValue(shortcutKeyout checkCtrl))
        {
            if (checkCtrl != control)
            {
                throw new ArgumentException("ショートカットキー重複 " + checkCtrl.ToString());
            }
        }
        
        //登録済みの場合削除
        Keys key = GetKeysByControl(control);
        if (key != Keys.None)
        {
            //MAPより削除する
            extInfo.Remove(key);
        }

        //指定されたキーがNone以外の場合、MAPに格納する
        if (shortcutKey != Keys.None)
        {
            extInfo.Add(shortcutKeycontrol);
        }

    }

    /// <summary>
    /// キーとコントロールの変換
    /// </summary>
    /// <param name="key">コントロール</param>
    /// <returns>対応付けられたショートカットキー</returns>
    private Keys GetKeysByControl(Control control)
    {
        Keys result = Keys.None;
        foreach (Keys key in extInfo.Keys)
        {
            //コントロールからショートカットキーを割り出す
            if (extInfo[key] == control)
            {
                result = key;
                break;
            }
        }

        return result;
    }

    /// <summary>
    /// キー押下イベント
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void TargetForm_KeyDown(object senderKeyEventArgs e)
    {
        Control control = null;
        if (extInfo.TryGetValue(e.KeyDataout control))
        {
            if (control != null && control.Enabled == true)
            {
                ((Button)control).PerformClick();
            }
        }
        
    }

}


partial class ShortcutKeyProvider
{
    /// <summary>
    /// 必要なデザイナ変数です。
    /// </summary>
    private System.ComponentModel.IContainer components = null;

    /// <summary> 
    /// 使用中のリソースをすべてクリーンアップします。
    /// </summary>
    /// <param name="disposing">マネージ リソースが破棄される場合 true、破棄されない場合は false です。</param>
    protected override void Dispose(bool disposing)
    {
        if (disposing && (components != null))
        {
            components.Dispose();
        }
        base.Dispose(disposing);
    }

    #region コンポーネント デザイナで生成されたコード

    /// <summary>
    /// デザイナ サポートに必要なメソッドです。このメソッドの内容を
    /// コード エディタで変更しないでください。
    /// </summary>
    private void InitializeComponent()
    {
        components = new System.ComponentModel.Container();
    }

    #endregion
}

2008年9月29日月曜日

[.NET]普通のボタンにショートカットキーを割り当てる

「とあるFormのメニューにある項目をボタンに変更したい。ただしショートカットは使用したい。」

という仕様変更を言い渡されました。まぁ単純に考えると、FormのKeyPreview=Trueに変更して、キーイベントをアレして実装すればよいのですが、ほかに方法がないかと調査してみました。


調べてみたものの、ショートカットのみっていう機能みつからず、あきらめてメニューから項目削除しようとしたところ、Visibleプロパティがあるではないですが。そこで、
  1. 該当のメニューの制御(Enableプロパティの制御)そのままのこす
  2. 該当のメニューのVisible=Falseにする
  3. ボタンのクリックイベントを該当のメニューのクリックイベントに同じメソッドを指定する
  4. ボタンのEnable制御は1.のタイミングで実施する

ということを実装してみました。というかほとんど実装していません。そしてToolTipにそれらしいショートカットーを表示すると、ショートカットの機能する(しているようにみえる)ボタンが完成しちゃいました。
いいやり方とはいえませんが、こんな使い方もできちゃうんですねぇ。

2008年9月27日土曜日

[.NET]クラッシックASP/ASP.NETで情報共有

レガシーASPとASP.NETを共存させたい。または移行などで共存せざるを得ない場合があります。
基本的に両者は別のサービスであるため、情報の共有も簡単ではありません。しかしStateServerというSQLServerを使ったデータ連携を使うと意外と簡単に実現することができます。

従来の ASP と ASP.NET でセッション状態を共有する方法

何かあった場合に備えてメモ。

2008年9月24日水曜日

[他]VSで#region(折りたたまれた部分)も含んで検索する

VS.NET2003/VS2005・2008では、エディタ上の#region~#endregionを折りたたんで表示することができます。
自動生成や修正が少なく目に入れたくない部分を折りたたんでおくことにより、必要な部分のみに集中してコードを見ることができます。しかし、ソースを検索するときはヒットしてほしいのですが折りたたんでいると該当部分がヒットせずイラっとくる時があります。
そのため、折りたたまれたソースをあえて展開してから修正をする。という面倒なことをしていました。

私の場合、検索はインクリメンタル検索またはF3系の機能を使うため、ほとんど検索ダイアログを出しません。ところがある日、たまたま検索ダイアログを出して検索しようとすると、

  • 非表示のテキストを検索する(VS.NET2003)
  • 検索オプション→非表示のテキストを検索(VS2005,2008)

というオプションがあるではないですか!

・・・これまでの苦労は。。。なんだったんだろう。

2008年9月19日金曜日

[.NET]プロパティ変数の直接参照(DeepCopy的な処理)

強引なやり方としてはリフレクションがありますが、通常privateフィールドは、該当のクラスからしかアクセスできません。ということから、同一クラスでも別インスタンスからはアクセスできないと信じきっていました。しかし、コピーコンストラクタを書いていると、そんなことはないってことがわかりました。
たとえば、とあるフィールドを変更するとフラグが立つといった処理系ではこういったやり方もあるというのに今日気づきました。いやー頭が固くなってますねぇ。コード例はこんなかんじ

public class DataClass
{
    private bool udate = false;
    /// <summary>
    /// 更新フラグ
    /// </summary>
    public bool IsUpdate
    {
        get { return udate; }
    }

    private int intData = 0;
    /// <summary>
    /// 数値のプロパティ
    /// </summary>
    public int IntData
    {
        get { return intData; }
        set { intData = valueudate = true; }
    }

    private String strData = String.Empty;
    /// <summary>
    /// 文字列のプロパティ
    /// </summary>
    public String StrData
    {
        get { return strData; }
        set { strData = valueudate = true; }
    }

    /// <summary>
    /// コンストラクタ
    /// </summary>
    public DataClass()
    {
    }

    /// <summary>
    /// コピーコンストラクタ
    /// </summary>
    /// <param name="src">コピー元</param>
    public DataClass(DataClass src)
    {
        intData = src.intData;
        strData = src.strData;
        udate = src.udate;
    }
}

2008年9月13日土曜日

[.NET] システム情報の取得(SystemInformation)

.NETアプリケーションを組む際に、システム的な情報を取得したい場合があります。そういった情報を集めたクラスがSystemInformationです。たとえば以下のような情報が取得できます。
  • HorizontalScrollBarHeight 水平スクロールバーの既定の高さ
  • VerticalScrollBarWidth 垂直スクロール バーの既定の幅
  • MonitorCount モニタの数
  • MouseWheelPresent マウスホイールの有無
  • PowerStatus 電源ステータス
  • TerminalServerSession リモートデスクトップ接続かどうか(未確認)

ほかにもたくさんシステム情報が取得できます。
P/Invokeを使わなくてもここまで取得できるとは。。。

2008年9月11日木曜日

[他]いまさらVB5

とある見積もりをするために、VB5のソースを解析する必要がありました。
とりあえず、エディタ(秀丸)でソース見てたのですが、画面の雰囲気などよくわからず、「んーどうした物だろう」と考えていました。会社にVB5のライセンスはあると思いますが、ライセンス借りたりするのが異常にメンドクサイ。そこで、昔フリーで使えたVB5のエディションがあった事を思い出しました。

しかし検索してもダウンロードできるサイトにたどり着かない。で、直リンクでダウンロードできるURLを発見したので備忘録としてメモ。

Visual Basic 5.0 Control Creation Edition

しかし、いつリンク切れするかわかりませんので、その際はご容赦を。

2008年9月9日火曜日

[.NET]SqlParameter にIsNull?

先日、@itの掲示板を見ていると、Where句にSqlParameterを使用しているものの条件としてNullを指定したくて困っているとのスレがありました。私のわかる範囲では、パラメータを使用せず

 Where xxx is null;

という方式しか思いつきませんでしたが、その解決案として

 Where (xxx = @param OR (xxx IS NULL AND @param IS NULL));

というのが紹介されていました。
Orになっちゃうのでパフォーマンスが気になるところですが、すばらしい発想ですね。

2008年9月3日水曜日

[.NET]ファイル属性の取得

先日、とあるコードを見ていると、なぜかファイルを追加モードでオープンすることで、ファイルの存在チェックおよび、出力可能かを検査しているコードが書かれていました。
そしてファイルを実際に出力しているのは別のメソッドで実施。っていうかチェックすることでファイルのタイムスタンプ変わっちゃうし。。。

見ただけでイラっときてしまいましたので、Fileクラスのメソッドで置き換えました。コードはこんな感じ

if (!File.Exists(dlg.FileName))
{
    //ファイルがないときの処理
}else if ((File.GetAttributes(dlg.FileName) & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
{
    //ファイルが読み取り専用のとき
}

2008年9月1日月曜日

[.NET]コントロールのフォーカス枠描画

ちょっと前に携わったプロジェクトでWindowsFormの仕事をしました。標準のコントロールではニーズに合わなかったため、なくなく独自のコントロールをいくつか作成しました。
描画は独自なのですが、フォーカス枠はボタンなどの通常のコントロールと同じ表示でよいということで、それらしく描画していたのですが、調べてみると、ControlPaintというクラスで簡単に書けることがわかりました。コードはこんな感じ。


Rectangle rect = new Rectangle(2, 2, Width - 4, Height - 4);
ControlPaint.DrawFocusRectangle(e.Graphics, rect);


ちなみにこの処理は、OnPaintの中で実施しています。

2008年8月31日日曜日

[.NET]ActiveX(COM)ラッパークラスのGAC登録

ちょっと前に、.NETアセンブリからActiveX(COM)を呼び出すようなことをやっていました。
しかしそのときは、参照設定の追加→COMのタブから該当のCOMコンポーネントを選択する。というやり方をとっていました。この方法では、自動的にCOM呼び出し用のinteropアセンブリが生成されます。

GDD Blog: [.NET]ActiveX(com)呼び出し(その2)などでいろいろ試していましたが、今回はちょっと要件が違っており、関連するアセンブリと一緒にGACに登録する必要がありました。

で、関連するアセンブリのAssemblyInfo.csにkeyファイルを指定しコンパイルすると、コンパイルエラーが発生しました。調べてみるとinteropアセンブリが署名されていないことが原因ということがわかりました。

その後タイプ ライブラリ インポータ (Tlbimp.exe)の説明にたどり着きました。よく説明を見るとパラメータにkeyファイルが指定できることがわかりました。keyファイルを指定してアセンブリを生成し、そのアセンブリを参照することによりコンパイルは通過。そして、GACに両方を登録することにより正しく動作しました。

原因の糸口がつかめず「ActiveX(COM)の処理を.NETに移植するか?」なんて話も出ましたが、とりあえずギリギリセーフでした。

2008年8月28日木曜日

[.NET]ToolStripMenuItemのショートカット割り当て(その2)

GDD Blog: [.NET]ToolStripMenuItemのショートカット割り当て」で、ショートカットに「CTRL+Enter」を割り当てる方法を書きましたが、今回は「Enter」のみなどキー1つをショートカットに割り当て(いるように見え)る方法についてメモ。

いろいろ調べみても、やはり修飾(Ctrl/Altなど)なしでショットカットを割り当てることはできないことがわかりました。そこで、画面をそれらしく表現するには、以下のようにすればよいことがわかりました。コードはこんな感じ。


//コンストラクタ
public Form1()
{
    InitializeComponent();
    // メニューのショートカットキーに「↓」って表示される(デザイナから設定可能)
    toolStripMenuItem1.ShortcutKeyDisplayString = "↓";
    // 特殊なキーの押下をハンドリグするイベントをインプリメント(デザイナから設定可能)
    this.PreviewKeyDown += new PreviewKeyDownEventHandler(Form1_PreviewKeyDown);
}

void Form1_PreviewKeyDown(object senderPreviewKeyDownEventArgs e)
{
    //↓矢印押下ならメニュー押下相当の処理
    if (e.KeyCode == Keys.Down)
    {
        toolStripMenuItem1.PerformClick();
    }
}

private void toolStripMenuItem1_Click(object senderEventArgs e)
{
    MessageBox.Show(this"「↓」おされたよ");
}

2008年8月26日火曜日

[.NET]ToolStripMenuItemのショートカット割り当て

とあるお客様向けのシステムで、「コントロール+リターン」のショートカットキーを割り当ててほしい。との依頼がありました。機能はコンテキストメニューにあるので、その機能にキー割り当てをするだけ。というわけで、該当のメニュを選択し、プロパティ「ShortCutKeys」にリターンキーを設定。しようとしたのですが、プルダウンに出てこないのです!!!

あぁ「Return」じゃなくて「Enter」だきっとそうに違いないと思い、プルダウンを探しましたが見つからない。こうなったらローラー作戦。ということで上から下まで1つづつチェック。しかしプルダウンに存在しないのです。

仕方がないので、コード上でShortCutKeysを設定問題なく動作しました。「リターンキーは推奨されていないんだ。きっと。」と思いあきらめようとしたのです、なんとなくプロパティを見てみると、なんとテキスト編集できるではないですか。で、「Ctrl+Enter」とテキストを入力すると、設定できました。
そして正しく?動作しています。なんで「Enter」が選択できないのかは不明です。

同じ設定をVS2005/VS2008の両方で試しましたが同じようにプルダウンからは選択できないようです。
不思議ですねぇ。

あと、単に「Enter」と入力するとエラーになります。当たり前といえば当たり前ですね。

2008年8月25日月曜日

[他]AnkhSVN 2.0(その2)

GDD Blog: [他]AnkhSVN 2.0で外部diffが動かない。と書きましたが、今日試してみると普通に動作していました。

んーよくわかりませんが、VSまたはマシン再起動で反映された感じでしょうか。

2008年8月21日木曜日

[他]AnkhSVN 2.0

久しぶりにAnkhSVNのサイトを除いてみると、なんとバージョンアップして2.0になっていました。
UIがだいぶ変わています。ちょっと使いやすくなった気がします。

しかし、外部のDiffプログラムを設定しても正しく動作しないんです。何ででしょう。。。

後は日本語化を誰かがやってくれればたすかるんですけどねぇ。

2008年8月15日金曜日

[.NET]??演算子(その2)

先日??演算子についてBlogに書きましたが、その説明ページにもっと衝撃的なことが。
なんと、int型でもnull値を許容させることができるようなのです。
null 許容型 (C# プログラミング ガイド)に詳しい説明が。で、こんな感じ。

intnum = null;


型の後ろに?って書くだけでnullをセットすることができるようなのです。でサンプル書いてみました。

inthoge = null;
System.Diagnostics.Debug.WriteLine("1. hoge == null " + (hoge == null));
System.Diagnostics.Debug.WriteLine("2. hoge.HasValue " + hoge.HasValue);
System.Diagnostics.Debug.WriteLine("3. hoge= " + hoge);
hoge = 1;
System.Diagnostics.Debug.WriteLine("4. hoge.HasValue " + hoge.HasValue);
System.Diagnostics.Debug.WriteLine("5. hoge= " + hoge);


で、実行結果は以下のとおり。
1hoge == null True
2hoge.HasValue False
3hoge
4hoge.HasValue True
5hoge1


DAOっぽいクラスのインタフェースなど、意外と用途はあるかもしれません。

2008年8月14日木曜日

[.NET]??演算子

先日、コードレビューをしていると、不思議な記述を見つけました。コードはこんな感じ。

string hoge = null;
string hage = hoge ?? "hogehoge";


左辺がnullの場合右辺の結果を返す演算子のようです。三項演算子を用いる場合の特定条件で使えそうですね。

2008年8月9日土曜日

[.NET]MouseWheelイベントのインプリメント(つづき)

GDD Blog: [.NET]MouseWheelイベントのインプリメントでは、イベントのインプリメントの仕方を書きましたが、今回はその引数である、MouseEventArgsについて書きます。

先日実装した機能では、コントロール+ホイールで表示している画面の縮小拡大をし、コントロールを押していない場合は、スクロールさせるという機能を実現する必要がありました。
しかし、コントロール+ホイールで縮小拡大するのですが、同時に画面がスクロールしてしまうのです。

キー押下イベントでは、Handledというプロパティにtrueを設定すると上位コンテナ?にイベントがわたらないのですが、残念ながらMouseEventArgsにはHandledプロパティはありません。
で、MouseWheelの引数の型をよく見ると、HandledMouseEventArgsというクラスでした。プロパティには、Handledがありました。

キャストしてHandledにtrueを設定するとキーイベント同様に上位コンテナ?にイベントは通知されませんでした。めでたくコントロール押下+ホイールで拡大のみを実現できました。

わかってみると1行のコードなんですが、ここにたどり着くまでに3日費やしました。重たい1行でした。

2008年8月5日火曜日

[.NET]MouseWheelイベントのインプリメント

VB.NETでは違うのかもしれませんが、C#ではMouseWheelイベントをGUI(プロパティのイベント(イナズマボタンのアレ))からスケルトン?を作ることができません。理由はよくわかりません。

でも、コードエディタ上で、「panel1.MouseWheel +=」まで書けば、後はタブキーを2回押下することによりイベントのスケルトンを作ることができます。実装はこんな感じ

private void Form1_Load(object senderEventArgs e)
{
    panel1.MouseWheel += new MouseEventHandler(panel1_MouseWheel);
}

void panel1_MouseWheel(object senderMouseEventArgs e)
{
    //ホイールの処理
}