2016年8月15日月曜日

C# プログレスダイアログ(進捗ダイアログ)の表示

世の中的にはたくさん情報があるが、備忘録をかねて、書く

プログレスダイアログの表示とはWindowsアプリケーションで、なんか重たい処理をした時に、進捗を表すためのFormである。
今時はWPFでやるべきだと思いつつ、まだ、Formアプリケーションを勉強中。

目標としては、以下を意識した

  • 進捗表示中にアプリケーションがフリーズしない
  • 進捗表示に数値情報を出して、あと、どれくらいで終わるかわかるようにする。
  • 今後も、別のアプリケーションで利用するように汎用性を持たせること



まず、僕が作ったProgressFormクラスをのせておきたいのだが、どうも上手く行かなかった。普通にのせるには容量多い。なんぞ、Gistという方法があるみたいなので、後日頑張ってのせる予定。多分、きっと。ぶっちゃけ、誰も見てないか。見てたら、コメントが無性にほしい。ほしがりさんですいません。どうでもいいか。


以下で、ひとまず、載せてもいないコードについて書く。

自分の作成した関数の中身

  • ポイントはまず表示をShow関数で行うこと。この時に、全ての初期化を行う。
  • 次にMessageプロパディを編集して、プログレスダイアログの表示を更新させる。これはクライアントのコードに記載する。この中で、Invokeも行っているので、更新がされないことは無い。
  • 最後に、Close関数で、プログレスダイアログを閉じる。これはfinallyから、呼び出すようにすると良い。
呼び出し側の重い箇所はTaskクラスで、スレッド化する必要がある。そうしないと、アプリケーションがフリーズしたように見えて、気持ち悪い。書き方は以下の感じ。間違ってたら、ごめん。ラムダ式便利。
Task.Run( () => { Console.WriteLine("test");} );

後、この処理ではプログレスダイアログを呼び出したフォームはEnableプロパディをfalseにすることで、操作できないようにしてある。これも最初はどうしたら良いかと迷った。。。
http://qiita.com/OneK/items/6ca3a71511cfe53caabc

これを作っていて、一番、混乱したのはスレッドの扱い方だった。進捗表示はGUIタスクの中で処理すべきかという話で、最初は別スレッドを作った。でも、結果として、GUI表示はGUIタスクの中にまとめて、重たい処理をTaskクラスで、別スレッドにするのが良いと感じた。今後も、その方針で行こうと決めれたのが良かった。


ひとまず、以上で!


2016年5月1日日曜日

openTKの警告 CS0618 'GL.DrawArrays(BeginMode, int, int)' は旧形式です ('Use PrimitiveType overload instead')解決方法

最近、Windowsで3D描画をしたくて、OpenTKを勉強している。

以下のページが非常に参考になっているが、コードを実行時に警告が出て、戸惑ったので、備忘録を残す。
http://masuqat.net/programming/csharp/OpenTKindex.php


OpenTKで以下のような警告がいっぱい出た。
「警告 CS0618 'GameWindow.Mouse' は旧形式です ('Use MouseMove, MouseDown, MouseUp and MouseWheel events or OpenTK.Input.Mouse, instead.')
とか
「警告 CS0618 'Matrix4.Rotate(Quaternion)' は旧形式です ('Use CreateRotation instead.')」
とか
「警告 CS0618 'GL.DrawArrays(BeginMode, int, int)' は旧形式です ('Use PrimitiveType overload instead')」
え、旧形式を勉強してるの。。。と少し萎えたが、簡単に新形式に置き換えできた。
備忘録として残しておく。

this.Mouse.ButtonDown

this.MouseDown

this.Mouse.ButtonUp

this.MouseUp

this.Mouse.Move

this.MouseMove

this.Mouse.WheelChanged

this.MouseWheel

Matrix4.Rotate

Matrix4.CreateFromQuaternion

if (Keyboard[Key.Escape])
{
this.Exit();
}

KeyDown += (sender, eKey) =>
{
        if (eKey.Keyboard[Key.Escape])
        {
                this.Exit();
        }
}

GL.DrawArrays(BeginMode.Lines, 0, 2);     // 単位表示
GL.DrawArrays(PrimitiveType.Lines, 0, 2);     // 単位表示



分かれば、たいしたことではないが、初心者には中々心理的ハードルが高かった 笑。

基本的にはエラー文を参考にすれば、丁寧に解説してくれているので、簡単に直すことが可能。一瞬大掛かりな形式に変わったのかと身構えてしまうがそんなことは無いので、安心しよう。


壁にめげずに学ぶぞ 笑

参考ページ
http://stackoverflow.com/questions/32503171/how-to-use-gl-drawarrays-to-draw-linestrip-using-opentk








2016年3月13日日曜日

GetBufferの考え方(MFC)

MFCのGetBufferについて、いろいろとはまった。。。

まだまだ確信を持てないことが多いが、自分なりに理解したことを備忘録として残しておく。



GetBufferはMFCでCStringを利用時に、固定メモリ領域を確保するために利用される。

GetBufferを利用時には同時に確保したいメモリ領域長を指定する必要がある。
例: GetUserName(strName.GetBuffer(UNLEN + 1), &dwNameLength)
参考サイトhttp://rui.primasm.com/2012/12/bug_getbugger_string_1/

その際、ReleaseBufferを忘れないようにする。
また、ReleaseBuffer呼び出し前に、CStringの別関数を呼び出すと、メモリの再確保が行われ、GetBufferの確保領域のポインタが無効になるので、呼ぶような書き方はしないほうが良い。



ちなみに、GetBufferは以下のようの呼び出し方でも問題はない。
デバッガを使用して確認した。

strName.GetBuffer(UNLEN + 1);
GetUserName(strName, NameLength)

この場合でも、GetBufferの返り値と同様のメモリポインタ(LPCTSTR)が渡されていることを確認した。
ただ、結局GetBuffer後はReleaseBufferをするまで、別の関数を呼び出すことは出来ないので、このような書き方はしないほうが良い。

自分は仕事がらみで、この書き方をしてしまい、あとから大分悩んだ 笑。デバッガを使用すれば、ポインタを直接見れることに気付いて、問題ないことを確認した。
自分の戒めのためにも、今後のためにもブログに一応残しておく。

その時にGetBuffer絡みで参考になったサイト
http://www.kab-studio.biz/Programing/PragmaTwice/Main/223.html


ぜんぜん違う話だが、Format関数の%sでCStringを直接利用してはいけないことを知らなくて、驚いた。余談なので、リンクのみ残しておく。
http://drumken.blog8.fc2.com/blog-entry-246.html


今日は以上なり。


2016年2月13日土曜日

IFileOperationのCopyItemsについて

こんにちは

最近、windows内で、ファイルをコピーするときに、SHFileOperationより、IFileOperationを利用したほうが良いと知りました。windows XP SP3以降はそうらしいです。

しかし、ネット上にIFileOperationの情報が少なくて、実装に大分時間がかかりました。。。それで、ネット上に備忘録も記載します。

参考になったサイトは以下で、そこを見れば、大体のことはわかると思います。

単体ファイルコピーのCopyItem関数についてはmsdnのサイト、そのままでいけました。その後、の複数ファイルをコピーするCopyItems関数の使い方を調べ出して、時間がかかりました。CopyItemをループで回してる人も多そうですね。もしかすると、そっちの方が、内部処理的に早いかもといまさら思いました 笑

CopyItemsを使う場合は以下のようにすれば、可能です。

int CFileManager::CopySelectedFileToSpecifiedFolder(list<CString>* listCopiedFilePath, CString csImportFolder)
{
if (listCopiedFilePath == NULL || listCopiedFilePath->empty() == true) {
return -1;
}

HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); 
if (!SUCCEEDED(hr))
{
return -1;
}

PIDLIST_ABSOLUTE abSourcePidl = NULL;
SFGAOF attrs;

int srcFileNum = listCopiedFilePath->size();
PIDLIST_ABSOLUTE[] pPidlRawArray = new PIDLIST_ABSOLUTE[srcFileNum]);

int no = 0;
for (list<CString>::iterator it = listCopiedFilePath->begin(); it != listCopiedFilePath->end(); it++)
{
CString strSource = *listCopiedFilePath->begin();
hr = SHParseDisplayName(*it, NULL, &abSourcePidl, 0, &attrs);    
if (FAILED(hr))
{
return -1;
}
pPidlRawArray[no] = abSourcePidl;
no++;
}
    delete[] PIDLIST_ABSOLUTE;

CComPtr<IShellItemArray> pShellItemArr = NULL;
hr = SHCreateShellItemArrayFromIDLists(srcFileNum, (LPCITEMIDLIST*)pPidlRawArray.get(), &pShellItemArr);
if (FAILED(hr))
{
return -1;
}


PIDLIST_ABSOLUTE abDestPidl = NULL;

hr = SHParseDisplayName(csImportFolder, NULL, &abDestPidl, 0, &attrs);
if (FAILED(hr))
{
return -1;
}

CComPtr<IShellItem2> pDestShellItem;

hr = SHCreateItemFromIDList(abDestPidl, IID_IShellItem2, reinterpret_cast<LPVOID*>(&pDestShellItem));
if (FAILED(hr))
{
return -1;
}

CComPtr<IFileOperation> fileOp;
hr = fileOp.CoCreateInstance(CLSID_FileOperation);
if (FAILED(hr))
{
return -1;
}

hr = fileOp->CopyItems(pShellItemArr, pDestShellItem);
if (FAILED(hr))
{
return -1;
}

hr = fileOp->PerformOperations();
if (FAILED(hr))
{
return -1;
}

CoUninitialize();

return 0;
}

std::listを使ってたり、一部コード修正したので、コンパイルは未確認だったりしますが、ほぼ同じコードで動作確認しています。
ご参考までにご利用ください。

ではでは~ 

2015年7月27日月曜日

e2 studioでのテスト駆動開発について

以前より、e2 studio上でテスト駆動開発をしたいと考えていた。visual studioだと、両方の環境を利用する必要があるので、面倒くさい。

以下の方法で、できることを確認したので、備忘録を兼ねて、記載。

動作環境
windows 7 SP1 64bit 
cygwin gcc 4.9.2
e2 studio 4.0.1.007

以下のページをベースにやって、上手く行った。bugdasさんに非常に助けられた。e2 studioだからか、一部、やり方が違うところや、自分がド素人ゆえに詰まった所を追記しておく。
http://qiita.com/bugdasi/items/2e86accdd21e1b60ff6a



1. 初めに、CPPUTESTをwindowsで利用できるようにcygwinでインストールを行う。ここは参考ページのとおりにやれば良いが、最後に、cygwinの環境パスを通す必要がある。わからない方は以下のページを参考にすると良い。
http://rx.tokudenkairo.co.jp/tutorial_cygwin.html#path
後、自分がここでハマったのが、自分のPCにmingwをインストールしてあり、そのパスが優先されてgccを利用したためにコンパイルに失敗した。mingwのパスが通っているのなら、外しておくべき。


2. e2 studioでプロジェクトを新規作成。
 C++プロジェクトで実行可能→Hello World C++ Project を選択
 ツールチェインに cygwin gccを選ぶ。 その後、終了をクリック。

3. デバッグをするために必須とのことで、以下のパスを通す。でも、もしかしたら、いらないかも。。。
ウィンドウ→設定 で 設定ウィンドウを開き、C→デバッグ→ソース検索パス→パス・マッピングに \cygdrive\c\ → C:\を登録
参考ページ https://keitarian.wordpress.com/2013/03/29/cygwin-eclipse-cdt-%E7%92%B0%E5%A2%83%E6%A7%8B%E7%AF%89-windows/


4. その後は、最初に示したページ通りに、設定を行っていく。
一つだけ、注意点としては、C:\を/cygdrive/c/に置き換えると書いてあるが、そうすると、逆にコンパイルエラーが出た。
普通にC*\のままでやれば、コンパイルが通る。
以下に主要な設定ページをさらしておく。




以上で、テストの実行が可能なはず。まあ、基本的には最初の参考ページ通りにやれば、上手くいく。

ちなみに、gccではなく、実行環境と同じルネサスのCC-RXでコンパイルできれば、なお良いが、生成されるmotファイルをPCのみでテスト実行する方法が分からなかった。いずれなんとかしたいなあ。。。

それでは、少しでも快適なテスト生活を送りましょう。

2015年3月19日木曜日

「PRJ0002 : エラーの結果 31 が 'C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin\mt.exe' より返されました。」の対策

突然、Visual Studio 2008でコンパイルできなくなった。
今更、Visual Studio 2008を使っている人はほとんど、いないとは思うけど。。。、2日位かかって、ようやく解決したので備忘録でメモ。


現象
以前まで、コンパイルできていたソースがパソコンを再起動後に、以下のエラーを出力して、コンパイルできなくなった
error PRJ0002 : エラーの結果 31 が 'C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin\mt.exe' より返されました。

環境
Windows7
Visual Studio 2008 Professional
SP1 Update済み

対策
下記のソフトをアンインストール後、VisualStudioを再インストールでコンパイル可能になった
  • Microsoft Windows SDK for Visual Studio 2008 .NET Framework Tools -jpn
  • Microsoft Windows SDK for Visual Studio 2008 Headers and Libraries
  • Microsoft Windows SDK for Visual Studio 2008 SDK Reference Assemblies and IntelliSense
  • Microsoft Windows SDK for Visual Studio 2008 SP1 Tools
  • Microsoft Windows SDK for Visual Studio 2008 SP1 Win32 Tools
  • Microsoft Visual Studio 2008 Professinal Edition - 日本語
アンインストール後、PC、を一度再起動したほうが良さげ。


Visual Studioの再インストールはそれだけで、2,3時間かかるから、解決策を探るのに時間がかかって大変 (泣)

治って良かった。

2014年12月26日金曜日

MVCのモデルについて備忘録を書いておく。

MVCは何度読んでも、分かりにくいが、ちょっとずつ理解は進んでいる気がするので、現状の理解について、記載しておき、後で、また振り返ろう!

以下考察。

MVCモデルについて
※あくまで、以下の話はC#FormでMVCを実現する時の話。
  • 実装構造を考えた時に、Controller(以下con)の存在価値がわからなくなる。
    • C#ではユーザーの操作を基本的にViewで受けざるをえないため。Controllerでユーザーの処理を受けるという基本的な使い方はMVCの構成は使えない。
  • 他の話で、ViewとModelの両方で使用したい関数があった場合に、共用できる関数群が無いと不便。
    • もし、ViewとModel間にConを挟む場合、この不便さはやばい。
  • Viewは表示機能と、入力データチェック、ControllerはModelにデータを渡す時と、Viewの表示統括(表示更新するウィンドウの指定処理)、
  • Modelは表示と無関係なデータを処理すると考える。
    • 切り分けが難しいが、ViewとModelはモジュールとして利用し、モジュール間を結ぶのがControllerとかんがえると良い気がする。

  • 使いドコロ
    • MVCは表示機能を実装する時の、プログラムの一部だと考える。故に、MVC以外にCommon等のフォルダを用意して、MVC全てから、呼び出せるフォルダを作る。
  • 基本データをModelに必ず置くと考えると上手くいかない。
    • Viewを表示する時に、必要とする流動的なデータをModelに置くと考えれば、うまくいくかも。。。
      • 固定値なら、Common等のどこからでも、アクセス可能なフォルダに置く。



  • MVCは表示を移植する時に便利な機能である前提で考えると、うまくいく気がする。


これで上手く実装できたら、嬉しい(*^^*)