Home > C# Archive

C# Archive

RFRを更新

久々に更新しておきました。
あんまり需要なさそうだけど、一人でも使ってくれる人がいる限り!(ただし自分を含む)
http://red-treasure.com/main/rfr.htm
内容
・プレビューの日付がずれるバグ修正
・画面からはみ出している状態で自動スクロールするとフォントが崩れるバグ修正
・位置がおかしくなることに若干の対策

以上

C#トリビアルメモ7 (Random)

  • 2008-04-28 (月)
  • C#

Randomおそるべし。前回のrand.Next()で極めたと思っていた。
例えば以下のようなことをやるとはまる。


int[] randomArray = new int[10];
for (int i = 0; i < 10; i++) {
   Random rand = new Random();
   randomArray[i] = rand.Next(100);
}

これはたぶん、randomArrayの要素はすべて同じになる。
なぜかというと、new Random()でインスタンスを作ると時間をシードとして生成されるが、時間がms単位だからだそうだ。
上記のような単純なコードの場合は各ループで1msも経つわけないので全部同じシードで初期化されるという。まあ、上記の例だとrandをforの外で定義してやればいいという話だが、例えば


public void hoge() {
   Random rand = new Random();
   // なんらかの処理
   // でもそんなに時間はかからない
}

public void hogehoge() {
   for (int i = 0; i < 10; i++) {
      hoge();
   }
}

ってな感じにしたとき、hoge()内のrandは何回やっても同じことをやることになるのでぜんぜん意味がない感じになる。
仕方がないので下記のようにした。


class CustomRandom {
   static private Random rand = null;
   static public Random GetRandom() {
      if (rand == null) {
         rand = new Random();
      }
      return rand;
   }
}

------------------------------------------------
public void hoge() {
   Random rand = CustomRandom.GetRandom();
   // おなじみシングルトンということで。
}

同じインスタンスに対してNextしてやれば、まあ問題ないかなと。本当はもっと賢くしたほうがいいかもしれないけど、それは未来に託す。

以上

C#トリビアルメモ6 (雑多な文法メモ)

  • 2008-04-25 (金)
  • C#

とりとめもない、こまごまとしたメモ。しばらく離れてると分からなくなる。

1.インターフェイスにもアクセサ、インデクサは設定できる。


interface IHoge
{
   int Foo
   {
      get;
   }

   string this[int index]
   {
      get;
      set;
   }
}

2.refは参照渡し。オブジェクトの場合は参照の参照渡し。定義でも呼び出しでもrefがいる。


public void hoge(ref int foo)
{
   foo = 1;
}

-------------------------------------
int a = 0;
hoge(ref a);
// a == 1

public void hoge(ref int[] foo)
{
   foo[0] = 4;
}
public void hogehoge(int[] foo)
{
   foo[0] = 5;
}
public void hogehogehoge(int[] foo)
{
   int[] bar = new int[3] {3, 2, 1};
   foo = bar;
}
public void hogehogehogehoge(ref int[] foo)
{
   int[] bar = new int[3] {3, 2, 1};
   foo = bar;
}
-------------------------------------
int[] a = {1, 2, 3};
hoge(ref a);
// a == {4, 2, 3}

hogehoge(a);
// a == {5, 2, 3}

hogehogehoge(a);
// a == {5, 2, 3}

hogehogehogehoge(ref a);
// a == {3, 2, 1}

3.配列の初期化一覧


int[] a = new int[3] {1, 2, 3};
---------------------------------------
int[] b = new int[] {1, 2, 3};
---------------------------------------
int[] c = {1, 2, 3};
---------------------------------------
int[] d;
d = new int[3] {1, 2, 3};
---------------------------------------
int[] e;
e = new int[] {1, 2, 3};
---------------------------------------
int[] f = new int[3];
for (int i = 0; i < f.Length; f++) {
   f[i] = i;
}

4.乱数は未満


Random rand = new Random();
int a = rand.Next(0, 100);
// a == 0~99

以上

LINQメモ

  • 2008-04-18 (金)
  • C#

LINQ関連記事を勝手にブックマーク。

[基礎/サマリ]
特集:C#プログラマーのためのLINQ超入門(前編)
http://www.atmarkit.co.jp/fdotnet/special/cslinq01/cslinq01_01.html

Part4 LINQで変わるデータベース開発
http://itpro.nikkeibp.co.jp/article/COLUMN/20080116/291140/

MSDN
http://www.microsoft.com/japan/msdn/net/bb308959.aspx

MSDNライブラリ
http://msdn2.microsoft.com/ja-jp/library/bb397926.aspx

[SQL]
[雑記] LINQ to SQL 実践編
http://ufcpp.net/study/csharp/sp3_linqtosql.html

[XML]
ジョイ・オブ・プログラミング:LINQ(前編)
http://www.atmarkit.co.jp/fdotnet/joyofprogram/20080418linqtoxml01/linqtoxml01_01.html

以上

マイクロソフトカンファレンス2008 第一日目 [出張報告]

マイクロソフトカンファレンスが本日(4/15)から2日間開催されてます。
第一日目に参加してきたので簡単に報告。

場所:ザ・プリンス パークタワー東京
日時:2008-04-15

1.基調講演
 時間になると突然ドラム音が鳴り響き、なぜかライブが始まった。「あれ?会場間違えた?」などと思いながら最後まで聞いた。そしたらステージのセンターがババーーンと開いて草野仁(ふしぎ発見の)が登場。さすがマイクロソフト。
 今回のカンファレンスのテーマがHEROなので「ヒーローとは」的な話を始める仁くん。なぜか松井(ヤンキースの)の話になり10分くらい延々と松井がいかにヒーローであるかを語る。「まさか松井登場か!?」と誰しもが思ったところで仁くん退場。普通にマイクロソフトのジェフ・レイクスとやらが代わって登場。期待させやがって。
 で、そこからはマイクロソフトの製品やら戦略やらの話。フォースカフェとか言うあるのかないのか私は知らない会社がVisual Studio 2008をうまく使ってプロジェクトを進めるデモが3人のプレゼンターによって行われた。(その間時々仁くんも登場してた。)しかしまあ、Visual Studio 2008とWindows Server 2008とかを使ってなかなか面白いことができるんだなという感じ。ここで強調されていたのはVisual Studio 2008でWebページをお絵かき的に作れるところと、仮想サーバによって負荷コントロールが容易だとか言う話、だった気がする。
 最後に日本のマイクロソフトの樋口さんが出てきてなんか言ってた。(あと伊藤忠の後藤さんが出てきてなんかしゃべってたが、たいしたことは言ってない。と思う。)

2.昼飯
 基調講演が終わると12:20。昼飯時。レストラン込みすぎ。昼食は(Googleとは違い)無料ではなかった。完全にキャパを超えたレストランは30分待ち。疲れた。

3.Visual Studio 2008の概要
 まあ、本当に概要。「VisualStudioは~という3本柱を軸に機能を提供します。しかし今回はこれとはちがった視点で~」お前はあほかと。じゃあ3本柱説明スンナと。
 閑古休題。WPF(Windows Presentation Foundation)っていうのがWebページをグラフィカルに簡単に作成できそうでちょっと興味がわいた。今度調べる。あとはWebアプリケーションとかLINQの話があったが、それは別セッションで個別にやっていたのでそっちで。

4.進化したASP.NETで実現するリッチなWebアプリケーション開発
 実際にコードを書きながらデモが行われた。Visual Studioもいろんなことができるようになったんだなーという感じ。Javascriptのデバッグとか、ドラッグ&ドロップでHTMLのフォームとかを作れたり、作ったフォームにロジックを乗せるのもフォームのプロパティをちょこっといじったりでできるという。ログイン処理をドラッグ&ドロップで作れたり、マスターページを作って全部のページのベースにできたりと、ビジュアル・フレームワークって感じ。ASPで作るならなかなか便利そうではある。MicrosoftAjax.jsなんてものもあるんだね。Silverlightの話も期待したが、名前くらいしか出てこなかった。とりあえず聴講者多すぎ。

5.データアクセスは次の時代へ。LINQを活用した効率的アプリケーション開発術
 結論から言うと、これが一番面白かった。これもコードを書きながらデモが行われた。LINQっていうC#からでもVBからでも使えるSQLっぽい構文で、オブジェクトからもDBからもデータを抽出できるというなかなか面白そうな機能。これは熱い。例えばC#で配列から一部を抽出する場合、


int[] data = {1, 2, 3, 4, 5};

var hoge = from foo in data
             where foo > 3
             orderby foo desending
             select new {
                 foo
             };
hoge.ToList();

って感じにするとhoge.ToList()で[5, 4]ってのが得られる。(コードは記憶だけを頼りに何も見ずに書いているので細かいところは間違っているかもしれないが、まあこんな感じ。)
 データベースからデータを抽出する場合も同じ。LINQオブジェクト(?)にデータソースとしてデータベースを関連付けておいて、あとは同じでよいのだ。これはいい!と思うんだけど、これはいい!と思ったGoogleマップレットもGoogle Gearsもぜんぜん流行らないので私の直感は当てにならない可能性がある。

6.展示会
 マイクロソフトのパートナー企業の展示会。いまいち面白いものはなかった。いや、まじで。あと、なにも説明してないのにアンケートだけ求めるのはどうかと思うよ、キャンペーンガールのねえちゃん。ばかうけが置いてあったのは評価できるが、私がいったときにはすでに弾切れだったため、評価ダウン。

7.休憩
 で、そろそろ疲れたので休憩。しようと思ったけど休憩できる場所がない。廊下にいすが全部で11個ほど確認できたが何千人かいるんじゃなかったっけ?ぜんぜん足りん。カフェっぽいのを見つけたがコーラ700円、ありえん。すごいのどが渇いてて、背に腹は代えられないのでカフェに入って、仕方がないのでチョコレートサンデーを食った。飲み物くらい用意すれ、マイクロソフト。

8.ビジネスを支える新世代サーバーオペレーティングシステム Windows Server 2008概要
 IISが7.0になってがんばりました、って話。Zendと協力してFastCGIでPHPが高速動作するようになったらしい。頑健性も増したとか。

9.おみやげ
 というわけで、とりあえず2つ以上のセッション参加でVisual Studio 2008、Windows Server 2008、SQL Server 2008の製品版がもらえる。もろた。あとVistaの体験版も。まあ、ここは計画通り。

10.エピローグ
 なんと、セッション参加証でXBOX360の抽選が行われとった。結果から言うと外れたわけですが、30人くらいに当たる模様。明日も30人くらいに当たるんではないでしょうか。ただいけてないのは、当選番号を小さいボードで掲示するだけのため、人が殺到。ぜんぜん見えん。そしてぜんぜん人が掃けない。なぜかと思っていたら、番号が見えたときに理解した。表に当選番号が手書きで書いてあるんだが、番号がソートされていない。そして大体の人が参加証を3、4枚持っている。・・・明日は改善されるかも。

11.感想
 まあまあおもしろかった。ただ、初日のためか全体的に手際がいまいち悪かった。

タグ:Microsoft Conference 2008 Day-1

以上

C#トリビアルメモ5 (設定を自前で保存する 私的解決編)

  • 2007-10-07 (日)
  • C#

自前でアプリケーションの設定を保存するとして、以下のような方針があると思います。
1.XMLでファイルに保存⇒XMLファイルをパースして設定を復元
2.設定クラスをシリアル化してファイルに保存⇒デシリアライズして設定を復元

デシリアライズした後は、「⇒各部品の初期化に使う」という流れです。
2の方針をとると設定項目が増えたとき、つまり設定クラスのメンバが増えたとき、古いバージョンの設定クラスをデシリアライズできなくなってしまい拡張性に乏しいところがあります。
そこで、XMLにしとけば万事OKなわけですが、XMLをいちいちパースするのも結構メンドクサイし、なんとなく遅そうって感じもします。
そういうわけで私がとった方針は下記です。
・HashTableをメンバ変数にもつ設定クラスを作成⇒HashTableをシリアライズしてファイルに保存⇒HashTableをデシリアライズして設定を復元

要約すると下記のようなクラスになります。


class MySetting
{
    private Hashtable SettingTable = null;
    private static MySetting _instance = null;

    private MySetting()
    {
        if (System.IO.File.Exists(this.FilePath))
        {
            try
            {
                BinaryFormatter serializer = new BinaryFormatter();
                System.IO.FileStream fstream = new System.IO.FileStream(this.FilePath, System.IO.FileMode.Open);
                this.SettingTable = (Hashtable)serializer.Deserialize(fstream);
                fstream.Close();
            }
            catch
            {
                this.SettingTable = new Hashtable();
            }
        }
        else
        {
            this.SettingTable = new Hashtable();
        }
        
        this.DefaultSetting();
    }

    private void DefaultSetting()
    {
        if (!this.SettingTable.ContainsKey("MyAplSize")) this.SettingTable["MyAplSize"] = new System.Drawing.Size(250, 400);
    }

    public void Save()
    {
        try
        {
            BinaryFormatter serializer = new BinaryFormatter();
            System.IO.FileStream fstream = new System.IO.FileStream(this.FilePath, System.IO.FileMode.Create);
            serializer.Serialize(fstream, this.SettingTable);
            fstream.Close();
        }
        catch
        {
        }
    }

    public static MySetting Values
    {
        get
        {
            if (_instance == null) _instance = new MySetting();
            return _instance;
        }
    }

    public System.Drawing.Size MyAplSize
    {
        get
        {
            return (System.Drawing.Size)this.SettingTable["MyAplSize"];
        }
        set { this.SettingTable["MyAplSize"] = value; }
    }
    
    private string FilePath
    {
        get
        {
            return System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + @"\MySetting.dat";
        }
    }
}

コンストラクタでファイルを読み込み、デシリアライズします。ファイルがない場合はデフォルトの設定を適用します。
デフォルトの設定はDefaultSetting()で行い、デシリアライズしたHashTableに設定がない項目(あるいはファイルがない場合は全項目)はここで値を代入しておきます。
Save()でシリアライズして、バイナリで保存しておきます。上記例では対象アプリケーションが保存されているディレクトリの直下にMySetting.datというファイルを作成します。
設定クラスですので、いくつもこのクラスのインスタンスがあるというのも変ですから、シングルトンパターンを適用します。そのためコンストラクタはprivateにしておき、実際に各部品から設定値を読み込むには以下のようにします。


form1.Size = MySetting.Values.MyAplSize;

「Values」が唯一のインスタンスを返すgetterになっています。
各設定項目の取得はgetter,setterで行い、これがHashTableの値をラッピングしている形です。
設定項目をひとつ作るごとにgetter,setterを作成、DefaultSetting()に追加、しないといけないので面倒といえば面倒ですが、一度仕組みを作ってしまえばどうということはありません。

まあ、このやり方がXML方式に比べて本当に速いのか、本当に簡便なのかは甚だ疑問ですが、こうやって実装しちゃったもんは仕方ない。
あと設定項目が減った場合はどうやってシュリンクするかという問題などもありますが、まあ、こんなもんで。

以上

C#トリビアルメモ5 (設定を自前で保存する 動機編)

  • 2007-10-05 (金)
  • C#

地味に更新してるRFR。よろしくお願いします。

ややすごい勢いでC#化してるこのブログですが、C#で設定を保存します。
簡単に設定を保存するには、VS2005以降の場合、Properties.Settingsクラスを使ってすんげぇ簡単にできます。
ただ、この方法だと保存されるファイルのパスを指定できません。アプリケーションスコープの設定は読み込み専用だし、ユーザースコープの設定は保存ファイルがDocument and Setting/user/Local Setting/Application Data/AppName/xxxxxxxxx/とかに保存されたりします。xxxxxxxxxの部分はアセンブリバージョン(?)が変わると変わっちゃいます。
そういうわけでどこに保存されるかわからんので気持ち悪いし、バージョンアップしたら設定を引き継げないし(まあ、引き継ぐ方法もあるけど)、自前で設定を保存するかぁ!ということになります。

(眠いため次回につづく)

C#トリビアルメモ4 (最大化・最小化などのイベントをフックする)

  • 2007-10-02 (火)
  • C#

なんと、HUNTER×HUNTERの新刊出るんですね。しらんかった。

C#で例えば最大化とかのイベントを取得してみます。
FormBorderStyleをtoolwindowとかにしておけば、最大化・最小化ボタンはなくなりますが、タイトルバーをダブルクリックしたり、右クリックから最大化とかを選択したら最大化されてしまいます。
こういうのを無効にしたいときはFormのWndProc()をオーバーライドします。


protected override void WndProc(ref Message m)
{
    const int WM_SYSCOMMAND = 0x0112;
    const int SC_MASK = 0xFFF0;
    const int SC_MINIMIZE = 0xF020;
    const int SC_MAXIMIZE = 0xF030;

    // フォームの最大化・最小化を捕捉したら以降の制御をカットする
    switch (m.Msg)
    {
        case WM_SYSCOMMAND:
            switch (m.WParam.ToInt32() & SC_MASK)
            {
                case SC_MINIMIZE:
                case SC_MAXIMIZE:
                    return;
                    break;

                default:
                    break;
            }
            break;

        default:
            break;                    
    }

    // 基本クラスのメソッドを実行する
    base.WndProc(ref m);
    
}

まー、この辺は完全にWin32APIの話ですが。
どうようにしてSC_MOVEをとれば移動できないようなものもつくれます。

以上

C#トリビアルメモ3 (Webbrowserで文字列を読み込む)

  • 2007-09-29 (土)
  • C#

しばらく更新サボってRSSリーダー作ってました。そこそこDesktopSidebarをぱくったものが出来上がってきました。そのうち公開したいと思います。

そういうわけでC#の話ですが、WebbrowserでファイルやURLじゃなく、文字列に格納されたHTMLを表示したい場合です。


string html = "<html><body>hoge</body></html>";
webbrowser1.DocumentText = html;

とまあ、こんな簡単な感じに動的なHTMLを表示させることができます。
が、これだと更新できないみたいなんです。
つまり、上記のようにHTMLを表示させた後、


webbrowser1.DocumentText = html2;

とやっても表示されません。
そういうときはDocument.OpenNew(), Document.Write()を使えばいけます。


if (this.webbrowser1.Document != null)
{
   this.webbrowser1.Document.OpenNew(true);
   this.webbrowser1.Document.Write(htmlString);
}
   else
{
   this.webbrowser1.DocumentText = htmlString;
}

注意しないといけないのは、最初Documentプロパティはnullであることです。
なので一発目はDocumentTextに直接入れて、次からはOpenNew(), Write()でやることにしてみました。

以上

C#トリビアルメモ2 (Webbrowserのリンクをクリックしたら既定のブラウザで開くようにする)

  • 2007-09-24 (月)
  • C#

最近WordPressの管理画面がばぐってる。微妙にいじったからかな・・・。

そういうわけでタイトルの通りです。
要は、Webbrowser上でクリックされたリンク先URLをどうやってとるかという話です。
まずはWebbrowser.Documentにリスナーを登録します。Webbrowserそのものに登録してもだめ。


webBrowser1.Document.Click += new HtmlElementEventHandler(Document_Click);

リスナーの中身です。


void Document_Click(object sender, HtmlElementEventArgs e)
{
    HtmlElement clickedElement = webBrowser1.Document.GetElementFromPoint(e.MousePosition);
    string link = null;
    if (clickedElement.TagName == "a" || clickedElement.TagName == "A")
    {
        link = clickedElement.GetAttribute("href");
    }
    else if (clickedElement.Parent != null)
    {
        if (clickedElement.Parent.TagName == "a" || clickedElement.Parent.TagName == "A")
        {
            link = clickedElement.Parent.GetAttribute("href");
        }
    }

    if (link != null && link != "")
    {
        try
        {
            System.Diagnostics.Process.Start(link);
        }
        catch
        {
        }
    }
}

HtmlElementEventArgs にToElementとかFromElementありますが、今回の場合どうもnullみたいで、取れているのはxy座標だけ。
そういうわけでGetElementFromPoint()をつかってHtmlElementを取得します。
で、TagNameで要素を判断してるんですが、デバッガで見てみるとなぜか大文字になっていました。まあ、念のためどっちもみとく。
他にいい方法あるのかもしれませんが、まあ、しらんし。
imgタグをaタグで囲っているときとかもあると思うので、一応親要素までチェック。まじめにやるなら親がnullかなんかになるまでループで探索するのが良いと思われる。
晴れてhref属性が取れた暁にはProcess.Start(link)で既定ブラウザを起動。

以上

Home > C# Archive

Return to page top