2010年5月19日水曜日

英字ドキュメント読み支援ツール その4

今回のお題は、メインメニュー、カスタムダイアログ、設定外部ファイル化、ユーザ設定永続化、ユーザ設定のリセット。
まず、設定外部ファイル化から。以下の画面から、



ソリューションエクスプローラのプロジェクトアイコンを右クリック→プロパティでプロジェクトのプロパティを開く。次に、設定タブをクリック。
設定で、
名前/型/スコープ/値を
Splitter1Distance/int/ユーザー/600
Splitter2Distance/int/ユーザー/800
Web1Url/string/ユーザー/PDFファイルパス
Web2Url/string/ユーザー/翻訳ページ1Url
Web3Url/string/ユーザー/翻訳ページ2Url

を設定した後、[Ctrl]+Sで保存(上のタブの*マーク(編集中)を外す。)


で、ユーザー設定が完了。
次はプログラムでこの設定を使います。

Form1の青いタイトルバーをダブルクリックして、Loadイベントハンドラを記述。ここで、ユーザ設定を利用して設定することにします。

private void Form1_Load(object sender, EventArgs e)
{
splitContainer1.SplitterDistance = Properties.Settings.Default.Splitter1Distance;
splitContainer2.SplitterDistance = Properties.Settings.Default.Splitter2Distance;
webBrowser1.Url = new Uri(Properties.Settings.Default.Web1Url);
webBrowser2.Url = new Uri(Properties.Settings.Default.Web2Url);
webBrowser3.Url = new Uri(Properties.Settings.Default.Web3Url);
}

後は、先回デザイナー画面で設定したWebBrower1,2,3のUrlを空にして実行してもそれなりに表示されることを確認。


続いて、メインメニューを追加。


Form1の青いタイトルバーをクリックし、Form1を選択した状態で、
ツールボックス→メニューとツールバー→MenuStripダブルクリック。


もし、WebBrower1の垂直スクロールバーの上の△がメニューに被っていたら、ドキュメントアウトラインを使って、以下の画面のように、SplitContainer2を、menuStrip1の上にくるようにドラッグ&ドロップ操作する。



メニューに「設定」を追加


プロパティウィンドウで、コントロール名(name)が「設定ToolStripMenuItem」と変な感じになっているので、「SettingMenuItem」に変更。



次に、設定ダイアログを作成します。

ソリューションエクスプローラのWindowsフォームプロジェクト(WindowsFormsApplication44)を右クリック→追加→Windowフォームをクリックする。



そのままFowm2.csを追加する。

Form2のウィンドウを引き延ばして、TextBoxを3つボタンを3つつける。
button1.Textを「設定初期化」button2.Textを「保存」、button3.Textを「キャンセル」にする。



Form2の青いタイトルバーをダブルクリックし、以下のコードを追加。

private void Form2_Load(object sender, EventArgs e)
{
textBox1.Text = Properties.Settings.Default.Web1Url;
textBox2.Text = Properties.Settings.Default.Web2Url;
textBox3.Text = Properties.Settings.Default.Web3Url;
}

「設定初期化」ボタンをダブルクリックして、以下のコードを追加。
private void button1_Click(object sender, EventArgs e)
{
Properties.Settings.Default.Reset();
textBox1.Text = Properties.Settings.Default.Web1Url;
textBox2.Text = Properties.Settings.Default.Web2Url;
textBox3.Text = Properties.Settings.Default.Web3Url;
DialogResult = DialogResult.OK;
}

「保存」ボタンをダブルクリックして、以下のコードを追加。
private void button2_Click(object sender, EventArgs e)
{
Properties.Settings.Default.Web1Url = textBox1.Text;
Properties.Settings.Default.Web2Url = textBox2.Text;
Properties.Settings.Default.Web3Url = textBox3.Text;
Properties.Settings.Default.Save();
DialogResult = DialogResult.OK;
}

「キャンセル」ボタンをダブルクリックして、以下のコードを追加。
private void button3_Click(object sender, EventArgs e)
{
DialogResult = DialogResult.Cancel;
}

最後に、form2のパブリックプロパティに、以下のようにテキストボックスの内容を取れるようにします。
(今回は、スレッドを使わないので、スレッドセーフのようにはしません。)
public string GetUrl1
{
get { return textBox1.Text; }
}
public string GetUrl2
{
get { return textBox2.Text; }
}
public string GetUrl3
{
get { return textBox3.Text; }
}


続いて、Form1のメニューの「設定ボタン」を押すことにより、Form2を表示するようにします。
まず、以下のように、Form1のプライベートなインスタンス変数を追加します。
private Form2 form2;

Form1_Load()イベントハンドラに、以下を追加します。

form2=new Form2();


で、メニューの「設定」をダブルクリックして、クリックイベントハンドラを作成。
以下のようにします。
private void SettingMenuItem_Click(object sender, EventArgs e)
{
DialogResult dr = form2.ShowDialog();
if (dr == DialogResult.OK)
{
webBrowser1.Url = new Uri(form2.GetUrl1);
webBrowser2.Url = new Uri(form2.GetUrl2);
webBrowser3.Url = new Uri(form2.GetUrl3);
}
}

最後に、プログラム終了直前に、SplitterContainerの分離帯の位置を保存します。
Form1のプロパティウィンドウで、雷マークをクリックし、FormClosingの文字(以下の画像の反転している部分)をクリックする。


以下のイベントハンドラを追加する。
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
Properties.Settings.Default.Splitter1Distance = splitContainer1.SplitterDistance;
Properties.Settings.Default.Splitter2Distance = splitContainer2.SplitterDistance;
Properties.Settings.Default.Save();
}


今日はここまで。
次回は、大量データ保存に対応したものを使って、翻訳結果の保存を行います。

保存先に、SQL Server データベースファイル(...mdfファイル)を利用します。
感覚的には、SQL Serverというよりも、Accessといった感じの使い方です。
時間があれば、通知領域にアイコン(NotifyIcon)を出して、アイコン右クリックでContentsMenuStripを表示して、翻訳結果保存ページまでつなげてみます。(時間がなければ回を分けるかもしれないけど。)

2010年5月18日火曜日

英字ドキュメント読み支援ツール その3

今回は、ドキュメントアウトラインの使い方。

前回の状態(以下の画面)から開始



ここで、ツールボックスのSplitContainerをダブルクリック。


で、どこのコンテナに張り付いたかが良くわからない。コントロールのドラッグアンドドロップでの配置は、平面上であれば直感的だけど、親子関係があると操作しずらい。こういう場合に、Visual Studioでは、「ドキュメントアウトライン」が用意されています。
「ドキュメントアウトライン」タブが無い場合は、メニューより[表示(V)]→[ドキュメントアウトライン]を選択してください。そうするとウィンドウがこんな感じになります。



ドキュメントアウトラインで、splitContainer1をドラッグアンドドロップで、splitContainer2.Panel1の配下に移動させ、splitContainer2.Panel2に、WebBrowerを配置。

プロパティウィンドウで、
splitContainer2.OrientationをHorizontal
splitContainer2.SplitterDistanceを244
WebBrower3.Urlをhttp://www.microsofttranslator.com/Default.aspx
とするとこんな感じになる。




実行結果はこんな感じ。




今日は、これで終わり。
次回は、.configファイル(設定ファイル)、メインメニュー、カスタムダイアログ、設定外部ファイル化、ユーザ設定永続化、ユーザ設定のリセットを実装します。

2010年5月17日月曜日

英字ドキュメント読み支援ツール その2

今回は、前回作成したものに機能追加します。
最初は、クリップボードにコピーした文字列の文字化け訂正。
self pacedのpdfは、シングルクォート、ダブルクォートの文字があると半角カタカナの”チ”に置き換えてしまうので、都合が悪い。また、practice Testの方は、クォート+1文字を全角の漢字1文字に置き換えてしまう。

なので、クリップボードを見て、テキストが入ってきたら、"チ"などを置換するプログラムを追加します。

定期的(0.5秒毎)にクリップボードを変更する動きを作ってみます。
以下の画面から。


ツールボックスのコンポーネントカテゴリからTimerをダブルクリックして、Timerコンポネントを追加します。


Timerが選ばれている状態でF4を押下し、プロパティウィンドウにフォーカスを移動し、
timer1の設定を以下のように変更します。
EnableをTrueに
Intervalを500に




この後、画面下部のタイマーアイコンをダブルクリックして0.5秒毎に処理するイベントハンドラの記述に移ります。



プライベートのブール型のインスタンス変数 isChangingを追加しつつこんなコードを書きます。



で、実行してみて、箇条書きの文字、シングルクォートがちゃんと変更されていることを確認。




次に、左画面で、[Ctrl]+Cを押したら、右画面にフォーカスが移動するように変更。

デザイン画面から、右側のwebBrowerコントロールをクリック。プロパティウィンドウで、雷アイコンをクリック。



ここで、PreviewKeyDownをダブルクリックし、イベントハンドラを記述。




これで、一回右側のブラウザの左側のテキストボックスにフォーカスを当てれば、左側のブラウザで[Ctrl]+Cを押すたびに、フォーカスが右側のブラウザの左側のテキストボックスに移動する。


次回は、機械翻訳のセカンドオピニオンを得るように作り変えます。
「ドキュメントアウトライン」を駆使しながら、splitContainerをもう一枚加えて、画面上部を現行どおり、画面下部を横長の領域で、マイクロソフトの翻訳ページを表示することにします。

2010年5月16日日曜日

英字ドキュメント読み支援ツール その1

久々のプログラムねた。(いやぁ、最近.netのMCP試験受けたから。。。)

MCPを受けるのに、英語のpdfを読んでたんだけど、これがあったら便利かなって言うツールを作ってみます。

徐々に作りこんでいきますので数回に分けて書きます。

まずは、環境作り。
Self Pacedのpdf,版によっては、コピペ禁止になっているものがあるため、acrobat readerでは全く読み込めないので、別ツールを使います。
私が使ったのは、brava! readerこいつを、ieでも使えるように再設定します。

で、プログラム開始。
visual studioで、メニューより[File]→[新しいプロジェクト]で、以下のダイアログを開いて、

C#のWindows フォーム アプリケーションを選択。

以下の画面から、


ツールボックスのコンテナから、Split Containerをダブルクリックしてform1に適用。
form1の中央よりに縦に境界線ができて、左側にPanel1,右側にPanel2が表示される。
次に、ツールボックスのコモンコントロールから、WebBrowserをドラッグしてPanel1とPanel2のそれぞれにドロップ。こんな感じになる。



F4キーでプロパティウィンドウにフォーカスを移動し、以下のプロパティを変更。
Form1.WindowState → Maximized
splitContainer1.SplitterDistance → 120
(解像度が1400x900ならこれでよさそう。そうでなければ試行錯誤で設定)
webBrower1.Url → pdfファイルパスを指定。(C:にあるのなら、C:\...\...pdfを指定)
webBrower2.Url → http://www.excite.co.jp/world/

で、実行結果はこんな感じ。



あとは、左側で英文を読みながら、難しそうな文章は、範囲選択 → [Ctrl]+C → 右画面のテキストボックスをクリック → [Ctrl]+a → [Del] → [Ctrl]+v → [Ctrl]+[Enter]で翻訳。


機械翻訳について、エキサイトと、googleとマイクロソフトのものを使ってみたんだけど私の感覚では、翻訳性能は、こんな感じ。
エキサイト >> マイクロソフト >>>>> google
翻訳性能ではgoogleは引き離されているような感じです。(※1)


簡単ですが、今回はここまで。次回は、コピペの際にクォート文字の文字化けの修正をすること(ClipBoardWatcherクラスを作るのは大変なので、0.5秒毎にクリップボードの文字を置換する方法を取ります)と、キーボードコピー操作をしたときに、フォーカスを右画面に移すこと(をすることにより、上の操作の)「 右画面のテキストボックスをクリック 」を端折ることを目的とします。



※1:ま、エキサイトでも、下のように奇訳をしてくれますが。。。
The PrintPage event is the main event involved in printing documents. を、「PrintPage出来事は印刷ドキュメントにかかわるメーンエベントです。」とか、
An event is raised.を、「出来事は高くしています。」とか、
Validating XML with XmlReaderを、「XmlReaderとXMLを有効にします。」とか、
9-11を、「9-11テロ」とか、
following,obect,handler,constructorを、たまに「↓この」とか、「物」とか、「操作者」とか、「建設者」とか、
print jobを、「印刷仕事」とか、
A printed documentを、「印刷された記録」とか、
applications run in the intranetを、「アプリケーションはイントラネットに立候補します。」とか、
The MDI parent form を、「MDI原型」とか、

2010年4月15日木曜日

給与改定

去年度と比べて月給2130円アップ。あれ、こんなに少なかったかな?

2010年1月16日土曜日

何のものさしかと思えば

http://careerzine.jp/monosashi/search
上場企業の年収って、情報ソースはどこだろう?

2010年1月10日日曜日

ASP.NETでのstatic変数の初期化と利用

先週、職場でASP.NETについての質問を受けましたが、よく分らなかったので週末調べてみました。
質問内容は、(Webサーバは1台でスケールアウトしないものとして)ASP.NETアプリ全体で利用する変数を使う場合に、static変数を使って、Application_Startで初期化する使い方で問題ないか?というもの。

これを調べるに当たって、「.NET エンタープライズWebアプリケーション開発大全Vol.3」とMSDNを利用しました。

まず、Vol.3のP.131
>プロセスリサイクリングやフェイルオーバ時、システム再起動時、アプリケーションリスタート時などにはデータが消失する。
とあります。「など」という言葉が非常に気持ち悪いので、データが消失するのは上記以外に無いものと仮定します。


で、フェイルオーバ時、システム再起動時は判るとして、プロセスリサイクリングとアプリケーションリスタートっていうのが
それぞれ、P.188と、201に書いてある。
プロセスリサイクルとは、プロセス単位で、新プロセスを立ち上げて次回以降の要求を新プロセス側で処理するもので、旧プロセスは(受付処理が終わるか、直ちに)落とされるというもの。
それに対して、アプリケーションリスタートでは、同じプロセスの中に新たなアプリケーションドメインを立てて旧アプリケーションドメインでは受付しなくなるというもの。

なので、プロセスリサイクルとアプリケーションリスタートの違いは、新プロセスを起すか起こさないかの違いで、新アプリケーションドメインを立てるのは違いが無いと読み取れる。

で、Application_Startはいつ呼ばれるかというと、
http://msdn.microsoft.com/ja-jp/library/ms178473(VS.80).aspx
で、

ASP.NET アプリケーションの最初のリソース (ページなど) が要求されたときに呼び出されます。Application_Start メソッドは、アプリケーションのライフ サイクル中に一度だけ呼び出されます。このメソッドを使用してデータのキャッシュへの読み込み、静的な値の初期化などのスタートアップ タスクを実行できます。

とあります。

で、結論(アプリケーションドメインでアセンブリをロードした段階ではリソースがまだ要求されていないので、)アプリケーションリスタートでもワーカープロセスリサイクリング時でもどちらでもその後のリクエスト1個目のときにApplication_Startは呼ばれていそうです。