・大きなファイルコピー問題が解決!2007/09/19 19:12

VisualBasicで作った自作ツールで大きなファイルをコピーしている間、ツールが無反応になってしまう問題を解決するためにDelphiを導入したわけだが、これが突然解決してしまった。(^_^)/

せっかくなのでどういう経緯で解決に至ったのかを書いてみよう。

(1)別スレッド生成作戦

VB6で解決策を探っていたとき、コピーを別スレッドで行えばよいのではないかと考えたことがある。別スレッドでコピーしていればメインのフォームでは何もしていないことになるのでWindowも動かせるしRedrawも行われるはず。しかし、別スレッドの生成はWin32APIを使えばできるはずなのにどうしてもうまくいかない。Webでいろいろ調べてみると、VB6では別スレッドを使うことは事実上不可能という情報が、、、。(T_T)

というわけでこの段階では別スレッド生成をあきらめざるを得なかった。

(2)Delphiで別スレッド生成作戦

別スレッドが使えないVB6は問題外として、VC++でも別スレッドを使うのは面倒な作業らしい。それがDelphiでは別スレッドを簡単安全に使えるような機能が実装されているのだ!

早速Webで見つけたサンプルなど走らせてみると、電光掲示板のように文字列を表示させた状態でメモの内容を編集をするというように、VB6ではどうやっても実現できなかったことが簡単にできてしまった。

これでもう問題は解決かと思われたのだが、ひとつだけ実現できないことがあった。それはコピー途中でのキャンセルだ。

Windowsでファイルをコピーしているとき、途中でキャンセルすることは普通にできる。しかし自作プログラムの中でそれをやろうとしても、コピーコマンドが実行されてしまったらそれをキャンセルすることはできない。実は別スレッドでコピーすれば、そのスレッドを強制的に破棄することでキャンセルが可能だろうと思っていたのだが、それをするとStackやらなにやらの処理ができないということで、できれば使うなということになっている。

無反応になる問題は解決できたけど、キャンセルできないのはいやだなあ、、、、。

(3)自前でコピールーチンを書く作戦

キャンセルできないという問題はひとつのコマンドでコピーをしようとしているからで、自分でコピールーチンを書いてしまえば途中でキャンセルできるようにするのは簡単だ。しかもこの方法なら別スレッドを使わなくてもすべての問題が解決できるのでVB6でも実現可能だ。「VB6で作ったツールをDelphiで作り直すのはめんどうだなあ、、、」と考えていた酢こんぶにとってこれは最良の解決策かもしれない、、、、

高速なコピールーチンを書くという

ものすごい面倒くささ

がなければね。orz

(4)誰かが書いたコピールーチンを使う作戦

今酢こんぶが必要としているようなものは、過去に誰かが必要とした可能性が非常に高い。ということで奇特な使徒が高速コピールーチンのソースを公開していないかと探してみるもののさすがに簡単には見つからない。しかし、この作業の途中である情報が入手できた。

それはWin32APIに、CopyFileExという関数があって、これを使うとコピー経過の表示ができ、さらに途中キャンセルもできるというものだ。それが本当ならVB6でも有効なはずだが、そんなうまい話があるのだろうか?

(5)CopyFileExを使う作戦(結局これで解決!)

実はかなり前からWin32APIを使えば問題は解決するのではないかと漠然と考えていた。そしてCopyFileExのことも聞いたことがある気がする。じゃあなぜ使わなかったのかというと、この関数を使うとExplorerのコピーで表示される、経過を示すダイアログが出るのだと思っていて、これがいやだったのと、そもそも使い方がよくわからなかったということなのだ。

今回CopyFileExでネット検索してみると使い方のサンプルを載せているサイトが見つかったので

http://www.answers.com/topic/copyfileex?cat=technology

それを参考にしてVB6のツールに組み込んでみた。

すると、出ると思っていたダイアログは出ない、無反応にならない、途中キャンセルもできるという、酢こんぶの要求を全て満たすことができるものだったのだ!


という経緯で問題は解決したのだが、CopyFileExってWinNT4.0のころからあったみたいで、つまりそれって酢こんぶがツールを作り始めたときには既に存在していたわけで、、、、、

俺が悩んでた六年間はなんだったの?(T_T)

って感じですわ。

------------------------------------------
このブログの本店「木全屋かるた堂」もよろしくです。

・ファーストガンダムのかるた売ってます。
・ファイル整理に便利な自作ツール置いてます。
・写真(コスプレ、ポートレート、動物)公開してます。
------------------------------------------

・DelphiでファイルのDrag&Dropをするには、、、2007/09/11 23:59

酢こんぶはファイル処理のツールを作るとき、ファイル指定には必ずDrag&Dropを使うことにしている。その方が直感的で素早く操作できるし、なによりファイル選択のダイアログでディレクトリツリーをたどってファイルを選択するのがまどろっこしくて大嫌いなのだ。

というわけでDelphiを使っていくにあたりDrag&Dropがどのような実装になっているか確認してみると、、、

標準で実装されてねー!

VBではオブジェクトのOLEDropModeというプロパティでファイルのドロップを受け付けるかどうかを制御できるのだが、Delphiのコントロールにはそんなプロパティは見当たらない。調べてみるとDelphiにはエクスプローラからファイルをDrag&Dropで受け付ける機能はなく、必要であればWindowsAPIを使うという仕様になっている。Delphiはマルチプラットフォームの開発環境を提供しているので、Windowsに依存する機能は実装していないということなのかもしれないが、とにかく面倒くさい。

Delphiも世に出てから長い月日が流れているので、不便に思った人たちがDrag&Dropを実現するコンポーネントを開発してたりするわけだが、無料のTurbo Delphi Explorerは外部コンポーネントを取り込むことができないんだなあ。(T_T)

しょーがないのでWeb検索してみると、複数のサイトに

DragAcceptFiles(Handle, True)

という記述でファイルのDrag&Dropを受け付けるようになるとある。

だけどどうしてもうまくいかねえんだなあ、これが。orz

さらにいろいろ探してみると、上記の記述ではうまくいかないことがあるのでCreateParamsをオーバーライドした方がいいという情報を得られた。

情報元はこちら。
http://kazina.seesaa.net/category/1723158-1.html

これでやってみると確かにうまくいくので「めでたしめでたし」かというとそうでもない。上記の方法はどちらもフォーム全体にDrag&Drop可能となってしまうので、二つ以上のコントロールに別々のファイルをDropしたいという要求には応えられず、そして酢こんぶの場合そのような要求が頻繁に発生する。

しょーがないのでまたまたWeb検索したのだが解決策は見つからず、試行錯誤の結果、特定のコントロール内にマウスカーソルが入ったらフラグを立て、ファイルのDropイベントが発生した時のフラグの状態によってどのコントロールにDropされたのかを判断するという方法でなんとか所望の動作を実現したのだが、なんか美しくないなあ、、、。

とりあえずソースはこんな感じ。
-----------------------------------------------------
//ListBox1内にマウスカーソルがあるときだけF1を1にする
procedure TForm1.ListBox1MouseEnter(Sender: TObject);
 begin
  F1:=1;
 end;
procedure TForm1.ListBox1MouseLeave(Sender: TObject);
 begin
  F1:=0;
 end;

//ListView1内にマウスカーソルがあるときだけF2を1にする
procedure TForm1.ListView1MouseEnter(Sender: TObject);
 begin
  F2:=1;
 end;
procedure TForm1.ListView1MouseLeave(Sender: TObject);
 begin
  F2:=0;
 end;

//Dropイベント発生時の処理
procedure TForm1.WMDropFiles(var Msg: TWMDropFiles);
 begin

  if F1=1 then
  begin
   //Listbox1にDropされた時の処理
  end;

  if F2=1 then
  begin
   //Listview1にDropされた時の処理
  end;

  DragFinish(Msg.Drop);

 end;
-----------------------------------------------------

うーん、まあとりあえずできるようになったからよしとしよう。

ところでファイルの受付が許可状態のフォームに対してファイル受付禁止にすることってできるのだろうか?


------------------------------------------
このブログの本店「木全屋かるた堂」もよろしくです。

・ファーストガンダムのかるた売ってます。
・ファイル整理に便利な自作ツール置いてます。
・写真(コスプレ、ポートレート、動物)公開してます。
------------------------------------------

・VC++はあきらめて(^_^;Delphiにしてみました2007/09/05 15:12

VC++のわかりにくさにあっさり挫折したので(^_^;何か他にいいコンパイラはないかと探してみると、BorlandのC++Builderがわかりやすそうな気がしてきた。しかし値段は7万超なのがどうもなあ、、、。誰か学生さんを探してアカデミックパックを買ってもらったとしても3万は出ていくし本当に使いやすいかどうかは使ってみないとわかんないしなあ、、、。

とりあえず近所の電気屋に行ってみるとマイクロソフトのパッケージ以外に開発言語の在庫は無し。仕方なく店の中をうろうろしていると書籍のコーナーでTurbo DelphiのCD-ROM付き入門書を発見。DelphiのことはBorlandの出している開発言語だくらいの知識はあったが中身は良く知らない。

確かVBに似た統合開発環境があったはずと思ってぱらぱら立ち読みしてわかったのは、

(1)言語はPascalを元にしたDelphi言語。
(2)無料で使えるTurbo Delphi Explorerが存在する。
(3)VBに似た開発環境のコンパイラ。

というようなこと。これはVBをかじったサンデープログラマがあまり金をかけずにツールを作ることができるコンパイラが欲しいという酢こんぶの要求をかなり高いレベルで満たすものだ。

Pascalは使ったことないけど、新たに覚えなきゃならんのはC++でも同じことだし問題にはならない。基本的にタダだけど小さなツールを作るための機能は十分そうだし、できたものを商用配布するのも可能らしい。

ということでダウンロードで無料版を手に入れることもできたのだが、少しは取っ掛かりが欲しいのでその入門書を買って帰り早速インストールして使ってみるとVC++よりはかなりVBに近いことがわかった。これなら入門書2400円也の出費も十分元が取れそうな気がする。

あとはコンパイラにしたことで、ツールが無反応になってしまう問題が解決できるかどうかだが、それは追い追い検証していくことにしよう。

------------------------------------------
このブログの本店「木全屋かるた堂」もよろしくです。

・ファーストガンダムのかるた売ってます。
・ファイル整理に便利な自作ツール置いてます。
・写真(コスプレ、ポートレート、動物)公開してます。
------------------------------------------