ラベル Windows App の投稿を表示しています。 すべての投稿を表示
ラベル Windows App の投稿を表示しています。 すべての投稿を表示

2015年5月11日月曜日

WPF で横長(Landscape)印刷をする

久しぶりに WPF の内容。
正直、こういった技術系の内容は時間が無いと書けない。

何故か?動くコードを載せたいけど、実業務で動いているコードは載せれないし、それを加工するにも結構時間がかかるから。

だから、技術系の blog 書いている人とか、専門サイトに記事を投稿している人はすごいと思う。
あと、ブログとは関係ないけど、動画を上げている人も同様。

いずれも内容がさらっと読めたり、動画見ている時間があっと言う間に過ぎていく様に仕上げるには相当な時間と経験が必要。
やったことない人にしてみたら、大した作業(内容)でないと思うかもしれないが、実際にやってみると結構大変かつ時間がかかる作業というのがわかると思う。きっといい経験ができるだろう。

前置きが少し長くなったが、今回は WPF で横長の印刷を行う部分で困っていたが、なんとか印刷できるようになったので、雰囲気程度にコードを載せようと思います。
実コードから居る部分だけ残したので、動かないコードだとは思います(さっきと言っている内容が違うのは気にしない)。

    PrintDialog printDialog = new PrintDialog();
    if (printDialog.ShowDialog() == true) {
 
        System.Windows.Documents.FixedDocument fixedDoc = new System.Windows.Documents.FixedDocument();
 
        HogePaper paper = new HogePaper();
        var PageSize = new Size(paper.Height, paper.Width);
        paper.Content = null;
 
        System.Windows.Documents.FixedPage fixedPage = new System.Windows.Documents.FixedPage();
        fixedPage.DataContext = this;
        fixedPage.Children.Add(paper.PrintArea);
 
        fixedPage.Measure(PageSize);
        // Point 1!! XAML の画面幅を指定する。
        fixedPage.Arrange(new Rect(15, 15, PageSize.Height, PageSize.Width));
 
        fixedPage.UpdateLayout();

        // Point 2!! 印字出力範囲を指定する
        fixedPage.Width = 11.69 * 96;
        fixedPage.Height = 8.27 * 96;

        System.Windows.Documents.PageContent pageContent = new System.Windows.Documents.PageContent();
        ((System.Windows.Markup.IAddChild)pageContent).AddChild(fixedPage);
        fixedDoc.Pages.Add(pageContent);
 
        paper.Close();
 
        try {
            // Point 3!! XPS 以外の印刷時に横長にする。
            printDialog.PrintTicket.PageOrientation = System.Printing.PageOrientation.Landscape;
            printDialog.PrintDocument(fixedDoc.DocumentPaginator, "print a hoge");
        } catch (ArgumentException) {
            return;
        }
    }

XAML 側については、Width(29.7cm) と、Height(21cm) の指定をしてしておく必要があります。

Point1, 2 については、印刷の範囲を指定する部分となります。
ここを指定しないと、用紙は横長なのにデータは縦長で印字される状態になります。

Point 3 については、直接プリンタ出力だったり、PDF に出力すると、これまた用紙が横なのに縦印刷になるという状態になるのを防ぐための指定。
ふざけているのかと思うのが、XPS への出力場合はこの指定がなくても良いということ。あっても問題ないので付けておくほうがよいでしょう。

しかし印刷するだけなのにここまで、面倒なのか。。。
最初は組み合わせや、プロパティの指定などが分からず、いくらやっても縦長で表示しかされないので、きっと横長印刷はできないんだと思い込んだぐらい。

調べるにしてもキーワードが分からず、魂が抜けかけたが、stackoverflow に助けられた。
http://stackoverflow.com/questions/2493244/wpf-to-xps-in-landscape-orientation
http://stackoverflow.com/questions/26624838/print-a-usercontrol-to-the-center-of-an-a4-page

本当にありがたい。
この記事が同じように悩んでいる人の助けになればいいがと思って締めたいと思います。

Written with StackEdit.

2014年6月22日日曜日

Windows Live Write を Google の 2 段階認証でも使う方法

ここ最近は、Windows Live Write を使用していなかった。
なぜなら、投稿の際にエラーが出るから。

image

原因がわからず、調べても今ひとつだったので放置していた。
しかし、長文書く時とかは Live Writer の方が使いやすい。
というわけで、原因を探ってみた。

とは言っても、実際問題アプリ側で特に設定は触っていないので、
外部の問題と言う事になる。

最近でやった事と言えば・・・Google の 2 段階認証。。。
どうやらこれらしい。

Google 2段階認証プロセス後、Live Writer/WordからBloggerへ記事を投稿する方法
http://nasunoblog.blogspot.jp/2014/01/google-2live-writerwordblogger.html

Google にログインしてからの設定で、「アカウント」→「セキュリティ」とすすみ
「パスワード」の項目の「アプリパスワード」を設定すればアプリ専用のパスワードを発行できる。
このパスワードを Live Writer のブログの設定部のパスワードにセットすれば良い。

やはり、自分の蒔いた種だった。。。

2014年6月17日火曜日

接続されているキーボードの一覧を表示する

バーコードリーダーを使う仕事で、バーコードリーダーが接続されているか確認する処理を実装するようになった。

この場合、シリアルポート接続で使用するのであれば、COM ポートの一覧を取得してその中から取得したいポートを探せば良い。
この時、SerialPort クラスの GetPortNames() メソッドを使用すれば一覧が取得できる。
しかし、この方法だと接続を外した後に同メソッドを使用しても外された事が取得できない。

こういうときは、WMI を使用すれば良い事が分かった。
既に、実現されている方がおられるので、そちらを参考に

C#でCOMポート番号とシリアル接続機器名を同時に取得する方法
http://truthfullscore.hatenablog.com/entry/2014/01/10/180608

さて、COM ポート接続にした場合はこれで良かったのだが、先方に連絡するとCOMポートではなくキーボード接続として扱うようにと言われた。

デバイスマネージャーで確認すると、HID キーボードデバイスとして認識されていた。
この部分を取得すれば・・・と思ったが、他にキーボード等を接続された場合に判断が付かない。
この内容を伝えると、ひとまず接続確認はしなくて良いとの事になった。

一応、キーボードの一覧を取得する方法も調べたので載せておく。
これもまた WMI を使用すれば取得が可能(詳細の判断も出来るのかしら?)。
今回、Windows フォームアプリでボタンを押したら一覧を表示する内容とした。
参照設定に、「System.Management」を設定する必要がある。

        private void button1_Click(object sender, EventArgs e) {
            ManagementObjectSearcher oMS = new ManagementObjectSearcher();
            ManagementObjectCollection oMC;
            string sMsgStr = "";

            oMS.Query.QueryString = "SELECT * FROM Win32_Keyboard";
            oMC = oMS.Get();

            foreach(ManagementObject oMO in oMC) {
                sMsgStr = sMsgStr + "名前:" + oMO["Description"].ToString() + "\r\n";
            }

            MessageBox.Show(sMsgStr);
        }

WMI は、以下のページを参考にさせて頂いた。

キーボードの種類を取得する: Win32_Keyboard - WMI Sample (VBS)
http://www.wmifun.net/sample/win32_keyboard.htm

2014年6月4日水曜日

C# Dictionary の連結

C# の Dictionary 型のデータの連結方法が分からなかった。
調べてみると、stackoverflow にあった。

How to add 2 Dictionary contents without looping in c#
http://stackoverflow.com/questions/712927/how-to-add-2-dictionary-contents-without-looping-in-c-sharp

サンプルはそのままだけど書いてみた。
class Program {
    static void Main(string[] args) {
        Dictionary dict = new Dictionary();
        dict.Add(0, "test");

        Dictionary addDict = new Dictionary();
        addDict.Add(2, "foo");

        addDict = addDict.Concat(dict).ToDictionary(x => x.Key, x => x.Value);

        Console.WriteLine("Data Count = {0}", addDict.Count);

        foreach(int key in addDict.Keys) {
            Console.WriteLine("{0} : {1}", key, addDict[key]);
        }

        Console.ReadKey();
    }
}    // class End...


上手く動いている。

2014年5月18日日曜日

空き容量が無いドライブへの書き込みについて

C# で、空きディスク容量の少ないドライブに、データを書き込んだ場合にどのようになるかを調べてみました。

ここ最近の HDD や USB メモリなどは非常に大きな容量なので、早々ディスク容量には困らないとは思いますが、古いシステムや数年前の USB メモリを使った場合などには、起こる問題だと思います。

まず、確認する方法について考えてみましたが、ディスクにクォーターなどを設けるなど方法が有るのですが、今回手元に 256M の USB メモリがありましたので(10年前くらいの物ですね)、実際に空き容量を無くした状態で、データを書き込み様子を見る事にしました。

まずは、空き容量を無くす方法ですが、Windows の fsutil.exe コマンドを使用してディスク容量を圧迫します(管理者モードのコマンドプロンプトを使用しないと使えない)。

巨大なサイズのファイルを簡単に作る方法
http://www.atmarkit.co.jp/fwin2k/win2ktips/243largefile/largefile.html

有る程度書き込みが出来る分の容量を残したデータを作りプログラムを作成します。

        static void Main(string[] args) {
            while(true) {
                StreamWriter sw = null;
                try {
                    sw = new StreamWriter(@"E:\testdata.txt", true);
                    // 適当にデータを書き込む(例外が出る)
                    sw.WriteLine("123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890");
                } catch(Exception) {
                    // System.IO.Exception が出る
                } finally {
                    if(sw != null) {
                        sw.Close();  // ここで例外が出る
                    }
                }
                break;
            }
            Console.WriteLine("End...");    // 例外が出るとここには到達しない
        }

そして、実行をすると、、、System.IO.Exception が発生します。


今回 StreamWriter を使用してデータを書き込むようにしていたのですが、この例外は容量を超えて書き続けた時と、容量を超えた状態で Close() をしたときに発生します。

また、問題なのは Close() の際に発生する部分でこの部分で例外が発生するとアプリごと終了してしまいます。

この問題については、以下のページで同様に話題となっています。

クローズ処理で例外は発生するのか?
http://d.hatena.ne.jp/rabbit2go/20101027/1288185258

VB.NETで空き容量がない場合にFileCloseできない。
http://dobon.net/vb/bbs/log3-23/13815.html

例外が発生する理由としては、Close() の際に Flush を行い、つまりバッファに貯まったデータを全て書き出そうとするための様です。

対策としては、上記の URL にありましたが、必要な容量分のダミーデータを作成し、データを書き込む際に、ダミーデータとの容量を確認しながら書き込み判断を行えと言った感じでしょうか?つまり手動で容量管理をすれば良いってことかな?

ロジックを組んでおけば、さして面倒な内容では無いのですが、何故か今ひとつ腑に落ちない。
とは言え、アプリが落ちると困るので、容量を見ながらの書き込みは必要という事になります。

毎回ファイルポインタの操作をする様な関数の場合は、その都度書き込み先の容量をチェックして書き込むのが良いかと思います。
この場合、書き込むデータのサイズにはよりますが、有る程度多めのバッファで見積れば良いかと思っています。

ディスクの空き容量については .Net Framework 2.0 以降であれば、System.IO.DriveInfo を使えば容易に判定ができるので、データ書き込み前に書き込みデータと空き容量を判定し、ダメな場合は書き込みしないような処理を実装すれば良いかと思います(ここらをどうするかは仕様によりますが)。

ドライブの領域サイズと空き容量を調べるには?[2.0のみ、C#、VB]
http://www.atmarkit.co.jp/fdotnet/dotnettips/468availablefreespace/availablefreespace.html

ドライブの全体の容量や空き容量を取得する
http://dobon.net/vb/dotnet/file/freespace.html

ファイルの操作については比較的簡易に書かれていることや、最初にも書いたとおり最近の大容量かなどで軽視しがちですが、この部分で足下をすくわれる事が有ったので、戒めに書いた次第です。

2014年4月16日水曜日

WPF での DoEvents

Windows Form の頃は、時間のかかる処理をしつつ画面の変更(進捗率を表示するとか)する時には DoEvents を使っていた。

今回 WPF で DoEvents があるのか?調べてみると、その物自体はなく、自分で実装して使うようになっているようだ。
この実装を行って使うという内容については、結構な件数が確認できたので、メジャーな方法というか、Microsoft のサイト自信に載っているやり方らしい。

Dispatcher.PushFrame メソッド(Microsoft)
http://msdn.microsoft.com/ja-jp/library/system.windows.threading.dispatcher.pushframe%28VS.80%29.aspx

ひとまず、ViewModel にコピペを行って確認をしてみた。
        public DelegateCommand CalculateCommand {
            get {
                if (this.calculateCommand == null) {
                    this.calculateCommand = new DelegateCommand(CalculateExecute, CanCalculateExecute);
                }
                return this.calculateCommand;
            }
        }

        private void CalculateExecute() {
            this.Message = "test message";
            DoEvents();         // ここで呼ぶ

            // 長い処理のつもり
            for(var i = 0; i < 9999; i++) {
                for(var j = 0; j< 99999; j++) {

                }
                this.Message = i.ToString();
                DoEvents();     // ここで呼ぶ
            }

            var calc = new Calculator();
            this.Answer = calc.Execute(this.Lhs, this.Rhs, this.SelectedCalculateType.CalculateType);
        }

        private bool CanCalculateExecute() {
            return this.SelectedCalculateType.CalculateType != CalculateType.None;
        }

        // ↓ ここからを追加
        public void DoEvents() {
            DispatcherFrame frame = new DispatcherFrame();
            Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background,
                new DispatcherOperationCallback(ExitFrames), frame);
            Dispatcher.PushFrame(frame);
        }

        public object ExitFrames(object f) {
            ((DispatcherFrame)f).Continue = false;
            return null;
        }
        // ↑ ここまで

参考にさせて頂いている様々なソースをそのままコピペの切った貼ったでの確認で、オリジナルの作者の方には申し訳無い気持ちではあるが、なんとか期待通りの動きになる事は確認できた。

わざわざの別実装なので、何か弊害がでのかも知れない点が気がかりと言えば気がかりだったりする。

2014年4月14日月曜日

Adobe Acrobat を使用しての PDF 出力時のエラー

WPF から印刷処理経由で PDF の出力を行う際にファイル出力まで何故か遅い。
この時、フリーの PDF プリンタを使用していました。
まずこのフリーの PDF プリンタに要因があるのかも知れないと思い、
Adobe のサイトから Acrobat の体験版を使用してみる事にしました。

インストールも完了し、PDF の出力処理をすると、ファイルの出力はされずログファイルが出力されます。
そしてログファイルの中身を見ると以下の内容が書かれていました。
    %%[ ProductName: Distiller ]%%
    07kyvr not found, using Courier.
    %%[ Error: typecheck; OffendingCommand: xshow ]%%

    Stack:
    [150 150 150 0]
    ( ト ・ゥ%%[ Flushing: rest of job (to end-of-file) will be ignored ]%%
    %%[ Warning: PostScript error. No PDF file produced. ] %%

・・・よくわからん。。。

途方に暮れそうになりながらも正気を戻し、「ProductName: Distiller」あたりで検索をかけてみました。
すると、同じ内容で困っている方がおられました。

AcrobatでPDFに変換しようとするとログファイルが作成されてしまう
http://plaza.rakuten.co.jp/mscrtf/diary/201302140000/

 まさにドンピシャ!!

どうやらフォントの関係で、上手く出力が出来なかったようです。
ここに書かれているように、Adobe PDF のドキュメントのプロパティの
「Adobe PDF 設定」の「システムのフォントのみを使用し、文書フォントを使用しない」の
チェックを外すと出力されるようになりました。
しかし、このログの内容では普通は解決出来ない気がするが・・・

いずれにせよ、上記で PDF 出力しても結果スピードは変わりませんでした。
XPS で出力すると、もの凄く高速(50倍ぐらい速い)なので今回はこちらで対応をしたいと思います。

2014年2月2日日曜日

WPF テキストボックスの設定色々

ほぼ備忘録。
今回は、テキストボックスの IME の制御や入力禁止の方法と、改行許可・折り返し・スクロールバーの指定、
そしてテキストボックスだけとは限らないけど、タブオーダーについてまとめておきます。

○ IMEの制御について 

入力項目によって、IME の制御をかける場合は、以下のようにプロパティをセットするれば良い。

IME ON
<textbox InputMethod.PreferredImeState="On"
            InputMethod.PreferredImeConversionMode="FullShape,Native"/>
IME ON カタカナ入力
<textbox InputMethod.PreferredImeState="On"
            InputMethod.PreferredImeConversionMode="FullShape,katakana"/>
半角英数字
<textbox InputMethod.PreferredImeState="On"
            InputMethod.PreferredImeConversionMode="Alphanumeric"/>
IME 抑制
<textbox InputMethod.IsInputMethodSuspended="True" />

参考:
[XAML] WPF で IME (かな漢字変換) を切り替えるには (Windows フォームから WPF へ)
http://code.msdn.microsoft.com/windowsdesktop/XAML-WPF-IME-Windows-WPF-9ef457d7

○ 改行許可・折り返し・スクロールバーの指定

<TextBox 
    AcceptsReturn="True" 
    TextWrapping="Wrap"
    VerticalScrollBarVisibility="Auto" />
上から、改行許可、折り返し有り、縦スクロールバー自動表示

○ 入力禁止の設定について

入力禁止は以下のプロパティのセットで行える。
<TextBox 
    FontSize="20"
    Margin="5"
    IsReadOnly="True"
    Text="IsReadOnly" />

○ タブーオーダーについて

普通に TabIndex プロパティを設定しても良いようだが、コントロールの中にコントロールを入れたりした場合などに、
上手く制御が利かない場合が有るようなので、「KeyboardNavigation.TabNavigation」を使った上でプロパティをセットした方が良いようだ。 また、タブで移動したくない項目については、「IsTabStop」を「False」にセットする。
    <StackPanel KeyboardNavigation.TabNavigation ="Local" >
        <TextBox Name="TextBox1" Height="20" TabIndex="1" />
        <TextBox Name="TextBox2" Height="20" IsTabStop="False" />
    </StackPanel>

最後に

WPF の書籍がなくてどうしようかと思っていたけど結局の所、その都度検索をかけて情報を蓄積していくのが良いみたい。
というか、それしかないみたい。

2013年12月21日土曜日

SourceTree の Git で Commit の時に「fatal: unable to auto-detect email address ...」のエラー

Windows 版の SourceTree を使用するが、インストール後の最初の設定をスキップしたためか、Commit 処理の際に以下のエラーが発生する。
$ git commit
*** Please tell me who you are.

Run

git config --global user.email "you@example.com"

git config --global user.name "Your Name"

to set your account's default identity.
Omit --global to set the identity only in this repository.

fatal: unable to auto-detect email address (got 'Obby@ObbyWorkstation.(none)')
アプリの設定ファイルを見るが、特にこれらの設定する箇所が見当たらなかった。
(よく見てないだけかもしれないが) 

この場合は、SourceTree をインストールする際に Git 単体も同時にインストールしているはずなので、そっちを使って設定を行ってやればよい。

自分の環境の場合は、Git に付属している Git Bash を使って、以下のコマンドで設定を行った。

まず、確認
$ git config --global -l ← 確認(設定されていない)
user.name=myname
user.mail=me.myself@gmail.com

または、
$ git config --local -l
でもよい
次に設定
$ git --global user.email "xxxxx@xxxxx.xxx.xxx"
$ git --glocal user.name "xxxxx xxxxxx"
これで、上手く行った。

2013年11月24日日曜日

Windows WPF/Silverlight 用プロトタイピングツール「SketchFlow」を使ってみた

大体どのような言語にしても、今時は提案の際にはプロトタイプという物を作ってプレゼンをするかと思います。

Web 系であれば、HTMLで画面遷移を作って、動きの部分については資料に記載や口頭での説明という事が出来るのですが、Windows のアプリについては HTML ほど手軽に組めず(実際はそれ程でもないかもしれませんが)、結果 Excel に図形でイメージを書いての説明になると言う事も少なくは無いかと思います。

以前から、iPhone 用にはなりますが、「POP」と言う画面イメージを手書きにして、それを写真に取り込みプロトタイプにする方法は知っていましたが、今回改めて Windows 系のアプリでプロトタイプを作成できるツールを探してみたところ、Microsoft 純正で「SketchFlow」と言う物が有る事がわかりました。

ただ、このツールを使うには条件があり、VisualStudio Ultimate が無いとダメ。
価格調べてみたけど、パッケージ版が 160 万円ぐらいするんですけど・・・
個人で購入は出来ないので今回も、試用版で試してみます。

まず、SketchFlow ですが、このツールは VisualStudio に付属している  「Blend for Visual Studio 2013」 からプロジェクトの作成で、選択する事が可能です。



あとは、基本的に Blend の使い方と同じように画面を作っていきます。
左上のアセットのタブから配置したいコントロールを選択し、フォームアプリと同様に配置します。
新しい画面については、「SketchFlow マップ」の領域があるので、そこから新しい画面の作成を選択して作成でき、 

画面の遷移についても、コントロールを右クリックして表示されるコンテキストメニューに「移動」の項目があるので、そこで指定が出来る形となっています。

その他、ボタンを押したときの動作等もコントロールの表示非表示程度なら可能です。
アニメーションも WPF 等と同様に設定出来るようですが、よく分からないため今回は使いませんでした。

ここで作成した画面等は、プロジェクトの実行により、アプリとして実行する事が可能となっています。
これで、画面遷移を確認して貰ったり、イメージを等をつかんで貰う事が出来るというわけです。

また、確認用のアプリとしてエクスポートできたり、仕様書用に WORD に出力できたり、画面のスクリーンショットを取得できたりと、プレゼンのための準備物の作成が非常に簡単にできるようになっています(地味にスクリーンショット機能が便利と思った)。
最終的に、SketchFlow で作成した物は、実プロジェクトへの変換も可能なので、作った資産を無駄にする事も無いと言った様になっています。

実稼動プロジェクトに変換
http://msdn.microsoft.com/ja-jp/library/ee371158%28v=expression.40%29.aspx


取っつきやすいインタフェース(アニメとかよく分かりませんでしたが) なので、直感的に使う事ができると思います。
また、プログラマだけではなくデザイナの方にも使いやすいとは思いますので、分業しやすくなると思います(WPF/SilverLight がその理念らしいので当然と言えば当然か)。

もっと詳しく知りたい方は、以下のリンクを参考にしてください。

SketchFlow によるプロトタイプ作成
http://msdn.microsoft.com/ja-jp/library/ee341458%28v=expression.40%29.aspx


プロトタイピングツールSketchFlowを用いた,Silverlightアプリ開発
http://gihyo.jp/dev/feature/01/silverlight-sketchflow


VS100-092 SketchFlow を活用した開発 by 大西彰(Youtube)
http://www.youtube.com/watch?v=_QBfT6f19s4


非常に素晴らしいツールだと思うのですが、ネックとなるのはやはり動作環境について。

せっかく、素晴らしいツールを開発しているのに、最高のエディションしかこの手のツールが付いていないとか非常に残念です。


OS 自体で設けているなら開発ツールぐらいは手頃になれば嬉しいのですけどね。
(Apple の、開発ソフト無償と比べると厳しいですね)

2013年11月17日日曜日

Visual Studio のコンテキストメニューに「Blend で開く」を追加する

WPF での開発の際に、UI 部分は「Blend」を使うわけだが、どの環境だか忘れたが、右クリックのコンテキストメニューで「Blend で開く」の項目が有った気がしたけど、今の環境では表示されない。

ちなみに、この記事で確認しているのは VS2013 Ultimate(試用版ですけど)。

どうも原因は、プロジェクトの設定によって変わるようで、今の VS の開発モードは WPF を選択しているため、この項目は表示出来ないようだ。

すでに、この件について不便を感じ対応されて居られる方がいた。
SourceChord
[WPF][Blend]VS2012のWPFプロジェクトに、「Blendで開く」メニューを追加する

こちらの方の記事を参考に、追加をしてみた。

1.外部ツールの登録

まずは、各所で使用するために、外部ツールとして Blend を呼び出すように設定する。

メニューバーの「ツール」から「外部ツール」を選択する。
(既に、追加し終わった後の画像で申し訳ない)


外部ツールのウインドウが表示されるので、追加ボタンを押して設定をする。

タイトル:Blend で開く
コマンド:C:\Program Files\Microsoft Visual Studio 12.0\Blend\Blend.exe
引数: $(SolutionDir)$(SolutionFileName)


これで、ツールに設定した「Blend で開く」が追加されます。


2.右クリックのコンテキストメニューに追加する

次に、右クリックに追加をします。
設定は、 ツールバーのカスタマイズから設定していきます。
ツールバーで、右クリックして「カスタマイズ」を選択します。


カスタマイズのダイアログが出るので、「コンテキスト メニュー」のコンボボックスから
「プロジェクトとソリューション コンテキスト メニュー|プロジェクト」を選択します。
次に、「コマンドの追加」をクリックして、コマンドの追加のダイアログを表示して、
カテゴリでツールを選択、コマンドは「外部コマンド n」を選択します。
この n は、外部ツールの所で設定された表示の順番になります。
(なので、今回は「外部ツール5」となる)

これで、ソリューションエクスプローラ部分で右クリックをすると「Blend で開く」が表示されるようになります。

3. XAMLファイルでのコンテキストメニューでも使えるようにする。

次に、XAML ファイルを右クリックしたときにも「Blend で開く」を表示するようにします。
先ほどと同じく、カスタマイズのダイアログが出るので、「コンテキスト メニュー」のコンボボックスから「プロジェクトとソリューション コンテキスト メニュー|項目」を選択します。
次に、これも先ほどと同じで「コマンドの追加」をクリックして、コマンドの追加のダイアログを表示して、カテゴリでツールを選択、コマンド「外部コマンド 5」を選択します。



4.確認

これで、右クリックによる Blend の起動が出来るようになったはずなので、確認を行います。




以上で、設定完了。
些細な事ですが、やはり有ると無いでは、使い心地が変わりますね。

2013年11月14日木曜日

SpecFlow を使ってみた2

前回の続き

前回は、空のテストが動くところまで書いたので、ここからはテスト内容の記述と機能の実装に入ります。

テストの詳細追加
まずは、Customer を確認するためのテストを行います。

まず、テストクラス(Steps.cs)に Customer のクラスを格納する変数を用意します。
(当然この段階では、ビルドエラーとなります。)
    private Customer _customer;
次に、インスタンス化の確認為のテストを記述します。
「a user has entered information about a customer」
への部分へテストコードを追加します。
        [Given(@"a user has entered information about a customer")]
        public void GivenAUserHasEnteredInformationAboutACustomer() {
            _customer = new _customer();
        }
以前記述していた「ScenarioContext.Current.Pending();」は、不要となるため削除します。

当然、ここでもビルドエラーとなります。

テスト対象のプロジェクト作成
次に、テスト対象となるためのプロジェクトを作成します。
ソリューションエクスプローラーのソリューションで
右クリックして、追加 → 新しいプロジェクト とし、
Windows フォームでも WPF アプリケーションでも良いので作成します。

Entity Framework の参照設定を追加
今回の例では、EntityFramework を使ってテストを行うため、
プロジェクトの参照に EntityFramework を追加します。

メニューから、
ツール → ライブラリ パッケージマネージャ → ソリューションの NuGet パッケージの管理...
を選択し、オンラインで、「EntityFramework」を検索してインストールします。

追加対象を聞いてくるので、テストプロジェクトと、テスト対象のプロジェクト両方に追加でをするようにします。

Customer クラスの作成
テスト対象のプロジェクトに、Customer を扱うためのクラスを作成します。
プロジェクトを右クリックし、追加 → 新しい項目 → クラス としてクラスを追加します。

クラス名は Customer とします。

以下のように、クラスの内容を記述します。
    public class Customer {
        public int Id { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
    }
テストクラスからテスト対象クラスが見えるように設定する
Customer クラスが作成できたので、テストプロジェクトへ戻り、
テスト対象のクラスを扱えるように参照設定を追加します。

テストのプロジェクトの参照設定を右クリックして、「参照の追加」を押します。
ソリューションのプロジェクトで、テスト対象のプロジェクトが有るので、
チェックを付け、OK で参照追加します。

これで、テストプロジェクトから、テスト対象プロジェクトが参照できるようになりました。

Customer クラスを使えるようにする
Steps.cs の using に、テスト対象のプロジェクトを設定します。
これで、テストクラスで指定していた Customer クラスのエラーがなくなります。

テストの実施
再度テストを実行します。
AddCustomer.feature ファイルで右クリックし、コンテキストメニューを表示させ
「Run SpecFlow Senarios」を実行します。

ここで、一つ目のテストが通った事が確認できます。
(詳しく確認するのであれば、 Steps ファイルの該当箇所にブレークポイントを設定して、
Debug SpecFlow Senarios で確認するとよく分かります)

以降、失敗 → 実装 → 成功 の繰り返しで機能を完成させていく形となります。
例題には、残り 3 つあるが、その内の 2 つについては簡単に記述しておきます。
        [Given(@"she has provided a first name and a last name as required")]
        public void GivenSheHasProvidedAFirstNameAndALastNameAsRequired() {
            _customer.FirstName = "Julie";
            _customer.LastName = "Lerman";
        }

        [When(@"she completes entering more information")]
        public void WhenSheCompletesEnteringMoreInformation() {
        }
「she has provided a first name and a last name as required」については、
名前のセットを行っています。
「she completes entering more information」については、特にする事無いようです。

EntityFramework の部分のテスト
最後に、データを保存するための機能
「that customer should be stored in the system」の部分を実装します。
まずは、テストのクラスに DB を扱うためのクラスを宣言します。
        private CustomerRepository _repository; 
さっきと同様、今の段階で、CustomerRepository は存在しないので、ビルドエラーとなります。
あと、テスト内容も記述します(本当は細かく見ていくんでしょうが、参考通り一気に書きます)。
        [Then(@"that customer should be stored in the system")]
        public void ThenThatCustomerShouldBeStoredInTheSystem() {
            _repository = new CustomerRepository();
            _repository.Add(_customer);
            _repository.Save();
            Assert.IsNotNull(_repository.FindById(_customer.Id));
        }
と言う事で、テスト対象のクラスに、CustomerRepository のクラスを追加します。
Customer クラスと同様に、追加 → 新しい項目 → クラス で追加します。
    public class CustomerRepository {
        public void Add(Customer customer) { throw new NotImplementedException(); }
        public int Save() { throw new NotImplementedException(); }
        public Customer FindById(int id) { throw new NotImplementedException(); }
    }
この状態で、再度テストを実行して結果を確認します。
すると、
    結果  のメッセージ:   
    テスト メソッド UnitTestProject.Features.Add.AddCustomerFeature.HappyPath が例外をスローしました:
    System.NotImplementedException: メソッドまたは操作は実装されていません。

の内容が表示されます。

これは、最初のインスタンス化の部分はパスして、次の Add メソッドで例外が発生しているため、
テストエラーとなっています。
Add メソッドの内容が「throw new NotImplementedException();」なので当然と言えば当然ですね。

参考 Web の説明がリポジトリメソッドを実装していない云々と言う部分が理解できなかったのですが、EntityFramework の Add メソッド等を使えるように、CustomerRepository に、更に DbContext を継承した CustomerContext のクラスを作成し Add メソッド等を完成させます。
(EntityFrameworkを使うので、using System.Data.Entity; を追加します。)
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;

    using System.Data.Entity;

    namespace WpfApplication1 {
        public class CustomerRepository {
            private CustomerContext _context = new CustomerContext();
            public void Add(Customer customer) {
                _context.Customers.Add(customer); 
                //throw new NotImplementedException();
            }
            public int Save() {
                return _context.SaveChanges(); 
                //throw new NotImplementedException();
            }
            public Customer FindById(int id) {
                return _context.Customers.Find(id);
                //throw new NotImplementedException();
            }
        }

        public class CustomerContext : DbContext {
            public DbSet Customers { get; set; }
        }
    }
この状態で、テストを実行するとエラー無くテストが完了します。
ただ、この状態では Save メソッドの部分で誤検知があるとの事。

誤検知部分の修正
誤検知の内容としては、以前の内容は Customer の ID が存在すれば OK と言う物ですが、
DB に保存に成功しても失敗しても ID には何らかの値が入っているために、
この存在チェックではテストの意味がないと言う事です。

この部分、正当な検査方法(正常に保存できたら 0 より大きな値が返ってくる)に変更します。
        [Then(@"that customer should be stored in the system")]
        public void ThenThatCustomerShouldBeStoredInTheSystem() {
            _repository = new CustomerRepository();
            _repository.Add(_customer);
            _repository.Save();
            //Assert.IsNotNull(_repository.FindById(_customer.Id));
            Assert.IsNotNull(_customer.Id>0);
        }
これで、正常なテストとなりました。


以上が、SpecFlow の使い方等々です。
長々と書き、またこれと言った画像も無いため、分かりにくく申し訳無いです。

数日経ってからの更新なので、アクセス数等を確認してみましたが、
この話題ではあまりアクセス数が有りませんでした。
(他の記事も決して多いわけでは有りませんが。。。)

ひょっとしたら、古い技術なのかも知れませんが、どなたかの参考になれば幸いです。

2013年11月10日日曜日

SpecFlow を使ってみた

前回は、SpecFlow について調べてみたが、今回は使ってみようという話。
あまり、上手く情報を探せなかった。

ひとまず、参考にしたのは、以下のページ。

SpecFlow によるビヘイビア駆動設計 by Julie Lerman
http://msdn.microsoft.com/ja-jp/magazine/dn296508.aspx

日本語の記事で書かれているので、読みやすいが言葉のブレがあるようで、理解するのに時間がかかってしまった。。。

さて、今回の確認には、Express 以外の(?) VisualStudio 2013 が必要となります。
理由としては、Express では、「拡張機能と更新プログラム」が使えないから。
正直この部分は、手動での回避か可能かどうか分かりません。
この拡張機能の部分に価値を感じられるのであれば、パッケージを購入するのも良いかもしれないです。
あと、学生や、起業2年以内のベンチャーには、無料キャンペーンがあるので、それを利用した方が良いと思います。

ひとまず、この回では、「VisualStudio 2013 Ultimate」 の 30日トライアル版を使って試してみました。
前置きはここまでとして、内容を書いていきます。


SpecFlow のインストール

まずは、拡張機能の SpecFlow をインストールします。
これで、ファイル作成時に feature ファイのテンプレートが指定できたり、
コンテキストメニューに SpecFlow の内容が追加されたりします。
VisualStudio を起動して、
ツール → 拡張機能と更新プログラム
と辿り、オンラインで「Specflow」を検索し、インストールします。

 

テストプロジェクトの作成

テスト用のプロジェクトを作成します。
ファイル → 新規作成 → プロジェクト Visual C# の テスト を選択し、「単体テスト プロジェクト」を選択します。
名前、場所、ソリューション名は任意で。

次に、作成されたテストプロジェクトに SpecFlow の参照設定を追加します。
これは、上記の物とは違い、SpecFlow 用の DLL を追加するための作業となります。
これによって、SpecFlow の記述が実行できるようになります。

導入方法は、ツール → ライブラリ パッケージマネージャ → ソリューションの NuGet パッケージの管理... と辿り
オンラインで、SpecFlow を検索し、インストールします。

 

 Feature フォルダの作成

テスト内容を格納していくフォルダを作成します。
ソリューションエクスプローラーのプロジェクトを右クリックして
追加→新しいフォルダで、「Features」フォルダを作成します。 ここに、機能別のフォルダを作成していくことになります。

 

機能別フォルダの作成

機能フォルダの Add を Features フォルダへ追加します。
今回は、単純に名前を「Add」としたフォルダを追加します。
Features フォルダで右クリック 追加 → 新しいフォルダで「Add」とする。

 

シナリオファイルの追加

上記で作成した「Add」フォルダに、今回のテストのシナリオとなるファイルを追加します。
「Add」 フォルダで右クリックして、追加 → 新しい項目でウィザードを起動
Visual C# アイテム にある、「SpecFlow Feature File」を選択する。
名前は、参考の通り「AddCustomer.feature」とする。

 

シナリオ内容の作成。

これは、今回の参考 Web の内容から拝借します。
シナリオを上記で作成した AddCustomer.feature に記述します。
(ウィザードで作成された物は削除します。またコピペの場合は体裁を整えます)
Feature: Add Customer
    Allow users to create and store new customers
    As long as the new customers have a first and last name

Scenario: HappyPath
    Given a user has entered information about a customer
    And she has provided a first name and a last name as required
    When she completes entering more information
    Then that customer should be stored in the system

この内容としては、
1. Customer クラスを作成。
2. 名前をセット。
3. DB への格納。
までをテストする内容となっています。
(「she completes entering more information」は、特にテスト内容は無いらしい)
参考 Web では、2 つのシナリオがありますが、
(「必要なデータが入力されていない場合」)今回はひとまず取り扱いません。

 

ステップファイルの作成

シナリオファイルに対応したテストのコード(ステップファイル)を作成していきます。

ステップファイルの作成には、以下の2つの方法が有ります。
1 つ目は、ステップファイルを作成しない状態でテストを実行させて、SpecFlow から返されるテスト出力を利用する方法。
2 つ目は、拡張機能を利用する方法。
参考 Web では、2 つ目の方法を使用しているので、それに沿っていきます。

AddCustomer.feature のエディタ上で右クリックして、コンテキストメニューを表示します。
その中に、「Generate Step Definitions」(ステップ定義の生成)があるので、それをクリックします。
Generate Step Definition Skeleton のウインドウが表示されるので、 下部にある「Copy methods to clipboard」をクリックします。
これで、Step(テスト為ののコード)がクリップボードに格納されます。
(たぶんコレは、1 つ目の方法を置き換えただけのように思える。。。)

次に、Add フォルダ内に Step ファイルを作成します。
追加 → 新しい項目 → Visual C# アイテム → クラス
名前は、「Steps.cs」とします。
作成されたファイルに SpecFlow が使用できるよう using を追加します。
(下記の Steps.cs のコードを参照)
作成した Steps のクラス定義内に、コピーした内容を貼り付けます。 また、クラスの先頭に「[Binding]」注釈を付けます。

ここで、話が少し変わりますが、SpecFlow の単体テストのデフォルトが Nunit を使用するようになっています。
しかし、参考の Web では MSTest をしようしているので、App.config に設定を変更(追加)します。
<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <section name="specFlow" type="TechTalk.SpecFlow.Configuration.ConfigurationSectionHandler, TechTalk.SpecFlow" />
  </configSections>
  <specFlow>
    <!-- For additional details on SpecFlow configuration options see http://go.specflow.org/doc-config -->
    <unitTestProvider name="MsTest" /> ← ここ
  </specFlow>
</configuration>

そして、using で MSTest の記述を追加する。
(using Microsoft.VisualStudio.TestTools.UnitTesting;)

現段階での Steps.cs ファイルの中身は以下の通り
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using TechTalk.SpecFlow;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace UnitTestProject.Features.Add {
    [Binding]
    class Steps {
        [Given(@"a user has entered information about a customer")]
        public void GivenAUserHasEnteredInformationAboutACustomer() {
            ScenarioContext.Current.Pending();
        }

        [Given(@"she has provided a first name and a last name as required")]
        public void GivenSheHasProvidedAFirstNameAndALastNameAsRequired() {
            ScenarioContext.Current.Pending();
        }

        [When(@"she completes entering more information")]
        public void WhenSheCompletesEnteringMoreInformation() {
            ScenarioContext.Current.Pending();
        }

        [Then(@"that customer should be stored in the system")]
        public void ThenThatCustomerShouldBeStoredInTheSystem() {
            ScenarioContext.Current.Pending();
        }

    }
}

この時点で、一旦テストを走らせてみます。
AddCustomer.feature ファイルで右クリックし、コンテキストメニューを表示させ 「Run SpecFlow Senarios」を実行します。
これでビルドが行われた後に、テストが実行されます。
ここでは、Web の参考通り
...
結果  のメッセージ: 
Assert.Inconclusive に失敗しました。
One or more step definitions are not implemented yet.
  Steps.GivenAUserHasEnteredInformationAboutACustomer()
...
テスト内容が無いと言う失敗が表示されます。

すこし、長くなりそうなので、今回はここまでとします。
次回は、テスト内容を記述していく部分を書きます。

2013年10月31日木曜日

SpecFlow について調べてみた

Windows 系の開発をするに当たって、だいたい使用する開発環境は、 Visual Studio となるが、こういった環境でのテストは何を使うかが気になった。

単体テストの NUnit や、MSTest が有るのは知っていたが、BDD は何を使うのがトレンドか調べると、「SpecFlow」と言う物が良いらしい。

SpecFlow
http://www.specflow.org/

ただ、情報が少ない。
内容的には、Rails 等では有名な Cucumber(Gherkin) 形式でのテスト記述が行えるとの事。

実際に使ってみようと思い、まずは Express 版にインストールと思ったが、どうやら Express 版では、拡張機能としての導入が出来ないため使用できないようだ
(ここら辺の情報がまだ掴めていない)。

NuGet を使えば、SpecFlow をインストールできるが、これは何か違うみたい。
(featureファイルを追加のやり方がよく分からない。)

他のサイトを見ると、「新しいアイテムの追加」から feature ファイルの追加等を行っているので、NuGet でのインストールについては、今のところはハズレなんだと思う。

なので、Express ではないバージョンで試す必要がある。
幸い製品版(Express じゃない)が試用期間(30日)付きで動かせるので、こちらで試してみる。

Visual Studio DownLoad
http://www.microsoft.com/visualstudio/jpn/downloads

また、VS2013 用の SpecFlow は、以下から入手できる。

SpecFlow for Visual Studio 2013
http://visualstudiogallery.msdn.microsoft.com/90ac3587-7466-4155-b591-2cd4cc4401bc

VS2013 がインストールされている状態なら、問題なく導入が可能。

今日は、ひとまずここまで。
結局製品版に踏ん切りを付けるまでに時間がかかった。

Express でゴリゴリ頑張る気はないが、ちょっとした確認やテスト環境の実験ぐらいは出来ると嬉しいのだが。。。

Visual Studio 自体は、非常に良くできた開発環境と思うけど値段が高い。。。
もう少しお安くなりませんかね



[自作 iPhone アプリ紹介]
スマートな電話帳をあなたに!!
「Smart Speed Dialer」
AppStore で、販売開始!
ただ今、PromoBook さんでプロモーションコード配布中!!



2013年9月1日日曜日

Firefox アドオン互換性無視と設定の削除

備忘録。
Firefox のアドオンの互換性を無視する方法

「about:config」で設定画面へ移動する。
設定項目が並ぶ部分で右クリックして「新規作成」→「真偽値」

extentions.checkCompatibility.x.x

として(x.x にバージョンを入れる。e.g バージョン23 なら 23.0 とする)、値を 「False」 にする。

これで、互換性は無視できる。
また、これはバージョンごとの指定となるが、

extensions.minCompatibleAppVersion

の値を4.0 となっているところを 0 にすれば、バージョン関係なく無視できる。

これを戻すときは、バージョン関係無しにする方は、4.0 に戻せばいいが、バージョン指定の方は設定を消した方が良い。

これを消す方法は、消す項目で右クリックして「リセット」を押す。
この時点では、表示が残っている。
ブラウザを再起動することにより、削除される。
(起動時に設定値がない項目については削除するようになっているようだ)

2013年8月1日木曜日

Visio 2013 から古いバージョンの Visio ファイルを開く

タイトルのままだが、Visio 2013から古いバージョン(2012以前)のファイルを開こうとすると、以下のウインドウが表示されファイルが素直に開けない。











最初は Excel 等々で表示されるマクロの警告かと思っていたので、ファイルが開かなかったときは、唖然としてしまった。
(この状態が起こったのは、Visio2013で作成したファイル(数時間かけて作成)を、古い形式で保存して確認しようとした時に発生したため)

この場合の対処法は、ウインドウに書かれているままだが、このウインドウを消してからの作業となるため、記憶力の良い人はいいが、自分のような人間は困る。
方法としては、スクリーンショットを取るとか、紙に書くとかWebで検索するの方法を取れば良いが、文面を読んだ所で結局どうするかわからなかった。

Webで調べてみたのだが、ファイルを安全な場所へ持って行けとか、フォルダの権限を変更しろだとか変な記事ばかりが引っかかり、さらにパニック状態になった。

一時の絶望感を覚えながら、弄り倒した結果、答えは実にシンプルだった。
以下の手順を踏めば良いだろう。

まず、先ほどの説明ウインドウを「OK」 ボタンを押して、ウインドウを閉じ、左上の「ファイル」をクリックする。






メニューが表示されるので、「オプション」をクリックする






オプション画面ウインドウが表示されるので、「セキュリティセンター」をクリックして、「セキュリティセンターの設定」ボタンをクリックする。
















セキュリティセンターが開くので、「ファイル制限機能の設定」をクリック。
ファイルの種類が表示されているので、今回対象となるVisoのバージョンの「開く」のチェックボックスを外す。
















「OK」ボタンを押して、Visio を閉じ、再度対象ファイルを開くと無事表示される。

たったこれだけの事なのだが、文章理解力が乏しいのか、勘が悪いのか知らないが絶望と歓喜の両方を味わったのであった。