はじめまして、Delphi2年目です。
CopyFile関数を使用して、容量が大きいファイルをコピーする処理があり、
コピー中に画面がフリーズっぽくなる現象を防ぐ為に
Timerを使用して定期的にアニメーションを入れてみたのですが、
コピー中はそのコピーが終了するまでTimerが発生しない為、あまり意味がありません。
コピー中でもTimerイベントを発生させることができる方法はないでしょうか。
Delphi5を使用しています。宜しくお願いします。
別スレッドでやらないといずれにせよ固まりますよ。
中級者に反応した書き込みでしたが、2年目さんですか。
もう少し詳しく書くと、
普通にプログラムを組むとそれはメインスレッドと呼ばれる主流だけの
プログラムになり、その流れの中で重い操作をすると全体が止まります。
そのため、別の流れを作ってメインスレッドはそれを短時間で時々チェックしに行くようにしなくてはなりません。
重いファイル操作や計算、通信なんかはそのようにするのが一般的です。
Delphiではそれ専用のコンポーネントTThreadというのもがあるので、
それを使ってファイル操作を行います。
概念が、感覚的に理解しづらいと思いますが知らないと先に進めない技術なので頑張ってください。
TTimerはわかりやすく言いえば別スレッドではありません。
なるほど、ありがとうございました。
そのやり方で試してみます。
CopyFileEx関数を使う手もあります。
http://cult-drang.com/program/tips/memo/api_copyfileex.html
private
{ Private 宣言 }
F_bCancel: Boolean;
...
//MoveFileWithProgress, CopyFileExから呼ばれるコールバックルーチン
function CopyProgressRoutine(
iTotalFileSize: int64;
iTotalBytesTransferred: int64;
iStreamSize: int64;
iStreamBytesTransferred: int64;
dwStreamNumber: DWORD;
dwCallbackReason: DWORD;
hSourceFile: THandle;
hDestinationFile: THandle;
lpData: Pointer
): DWORD; stdcall;
begin
if (iTotalFileSize > 0) then begin
//0で割るエラーを回避
Form1.Caption := Format('コピーしています %d%%', [Trunc(iTotalBytesTransferred / iTotalFileSize * 100)]);
end else begin
Form1.Caption := 'コピーしています';
end;
Application.ProcessMessages;
Result := PROGRESS_CONTINUE;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
//コピー元ファイルを選択
if (OpenDialog1.Execute) then begin
//コピー先ファイルを指定
SaveDialog1.FileName := OpenDialog1.FileName;
if (SaveDialog1.Execute) then begin
F_bCancel := False;
if (CopyFileEx(
PChar(OpenDialog1.FileName),
PChar(SaveDialog1.FileName),
@CopyProgressRoutine,
nil,
@F_bCancel, //特に必要がなければnilでもOK
0
)) then begin
Caption := 'コピーは成功しました';
end else begin
Caption := 'コピーは失敗しました';
end;
end;
end;
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
F_bCancel := True;
end;
ツイート | ![]() |