Ru-Board.club
← Вернуться в раздел «Прикладное программирование»

» Вопросы по Delphi

Автор: vshersh
Дата сообщения: 23.03.2006 12:38
Vitus_Bering
IMHO Быстрее чем шелл скопировать врядли удасться (кроме частных случаев)...
Автор: Vitus_Bering
Дата сообщения: 23.03.2006 12:46
ИМХО копирование файлов в Total Commander быстрее, чем с ShFileOperation, а написан ТС, как известно, на Delphi 2!
Автор: Jokerjar
Дата сообщения: 23.03.2006 12:50
procedure CopyFile(file1,file2: string);
var
FromF, ToF: file;
NumRead, NumWritten: Integer;
Buf: array[1..2048] of Char;
begin
begin
AssignFile(FromF, file1);
Reset(FromF, 1);
AssignFile(ToF, File2);
Rewrite(ToF, 1);
repeat
BlockRead(FromF, Buf, SizeOf(Buf), NumRead);
BlockWrite(ToF, Buf, NumRead, NumWritten);
until (NumRead = 0) or (NumWritten <> NumRead);
CloseFile(FromF);
CloseFile(ToF);
end;
end;

Можно увеличить размер буфера, это позволит считывать файл большими кусками. В принципе очень быстро работает, минусы: при копировании большого файла программа будет тормозить (возможно, следует запускать процедуру в отдельном потоке).
Автор: vshersh
Дата сообщения: 23.03.2006 12:53
Vitus_Bering
Коммандер не всегда копирует быстрее.

Насколько я знаю, там используется подход, который указал Jokerjar
Автор: Vitus_Bering
Дата сообщения: 23.03.2006 13:37
DroN_S, vshersh, Jokerjar, спасибо. Получается, что оптимально использовать ShFileOperation.
Автор: vshersh
Дата сообщения: 23.03.2006 14:47
Vitus_Bering
Если будешь копировать большие файлы в небольшом количестве, то метод Jokerjar будет самым продуктивным. А если небольшие файлы в большом количестве - то лучше шэлл.

Автор: Jokerjar
Дата сообщения: 23.03.2006 15:21
Небольшие файлы (меньше 1 мб) можно копировать даже так: немного исправляем вышенаписанную процедуру, размеру буфера присваиваем размер файла-источника (динамический массив - setlength). В итоге избавляемся от цикла.

Автор: DroN_S
Дата сообщения: 23.03.2006 16:38
Vitus_Bering
попробуй вот так

Код:
procedure FastFileCopy(const InfileName, OutFileName: string);
const
BufSize = 3*4*4096; { 48Kbytes дает прекрасный результат }
type
PBuffer = ^TBuffer;
TBuffer = array [1..BufSize] of Byte;
var
Size : integer;
Buffer : PBuffer;
infile, outfile : file;
SizeDone, SizeFile: Longint;
begin
if (InFileName <> OutFileName) then
begin
buffer := nil;
AssignFile(infile, InFileName);
System.Reset(infile, 1);
try
SizeFile := FileSize(infile);
AssignFile(outfile, OutFileName);
System.Rewrite(outfile, 1);
try
SizeDone := 0; New(Buffer);
repeat
BlockRead(infile, Buffer^, BufSize, Size);
Inc(SizeDone, Size);
BlockWrite(outfile,Buffer^, Size)
until
Size < BufSize;
FileSetDate(TFileRec(outfile).Handle,
FileGetDate(TFileRec(infile).Handle));
finally
if Buffer <> nil then
Dispose(Buffer);
System.close(outfile)
end;
finally
System.close(infile);
end;
end
else
raise EInOutError.Create('File cannot be copied into itself');
end;
Автор: Vitus_Bering
Дата сообщения: 23.03.2006 17:31
DroN_S, спасибо за код.
Автор: DroN_S
Дата сообщения: 23.03.2006 17:38
Vitus_Bering
да пожалуйста, лишь бы он был полезеным
а написать, мы ещё напишем
Автор: ShIvADeSt
Дата сообщения: 24.03.2006 01:08
Vitus_Bering

Цитата:
Получается, что оптимально использовать ShFileOperation.

На самом деле естественно нет, по ряду причин. Допустим есть там один файл, который занят в данный момент каким либо процессом, тогда любая операция шела прервется (потому что так реализзован проводник или это как то обходится?). Для правильного копирования папок и подпапок используется рекурсивная процедура для обхода дерева. Код уже не раз давался, вот еще разок.

Цитата:

procedure CopyFolder(Source,Destination:string);
var
FileInfo :TSearchRec;
DosCode :integer;
begin
DosCode := FindFirst(Source+ '\*.*', faAnyFile, FileInfo);
try
while DosCode = 0 do begin
if (FileInfo.Name[1] <> '.') and (FileInfo.Attr <> faVolumeID) then
begin
if (FileInfo.Attr and faDirectory = faDirectory) then begin
MkDir(Destination+'\'+ FileInfo.Name);
CopyFolder(Source+'\'+ FileInfo.Name,Destination+'\'+ FileInfo.Name);
end
else if (FileInfo.Attr and faVolumeID <> faVolumeID) then begin
CopyFile(PChar(Source+'\'+FileInfo.Name),PChar(Destination+'\'+FileInfo.Name),false);
end;
end;
DosCode := FindNext(FileInfo);
end;
finally
FindClose(FileInfo);
end;
// RmDir(FolderDest);
end;

далее

Цитата:
var
FromF, ToF: file;
NumRead, NumWritten: Integer;
Buf: array[1..2048] of Char;
begin
begin
AssignFile(FromF, file1);
Reset(FromF, 1);

а почему бы не использовать стандартные АПИ функции по работе с файлами? Я так думаю, что быстрее АПИ никто не сможет работать по виндой.

Цитата:

F1:=OpenFile(FilePath,OfStr,OF_READWRITE);
if F1=HFILE_ERROR then begin
Status:='Halted. Process is busy.';
Exit;
end;
SetFilePointer(F1,0,nil,FILE_BEGIN);
Res:=ReadFile(F1, A[0], FSize, Bytes,nil) ;
WriteFile(F1,Bt,1,Bytes,nil);

проверял, работает быстрее чем стандартный Assign и последующее чтение запись. Так как если посмотреть код то в итоге все равно так идет вызов этих же функций, так проще сразу работать ими.
Автор: Jokerjar
Дата сообщения: 26.03.2006 05:07
Есть у кого-нибудь ГОТОВАЯ функция, которая бы скрывала папку (не атрибуты)?
Автор: mutmut
Дата сообщения: 27.03.2006 09:55
Есть задача: в свернутом окне приложения(допустим браузера) кликнуть мышкой на определенную область(не кнопку) не разворачивая окно. Даже не знаю с какой стороны за это взяться. Помогите! Если не туда просьба сильно не пинать.
Зарание спасибо.
Автор: dyr farot
Дата сообщения: 27.03.2006 10:18
сначала ищи окно ( FindWindow ) потом шли ему ввод от мыши ( mouse_event )
Автор: ShIvADeSt
Дата сообщения: 27.03.2006 11:13
dyr farot

Цитата:
сначала ищи окно ( FindWindow ) потом шли ему ввод от мыши ( mouse_event )

Ну для начала ознакомься как работает моусе_евент и увидишь, что ему нельзя передать хэндл окна. Так как эта функция эмулирует работу мыши, то она не может сделать событие в свернутом окне (это физически невозможно). Если бы это была не область, а контрол (и то не всякий) можно было бы при помощи sendmessage послать событие, а так только единственный способ это разверннуть окно сделать моусе_евент и опять свернуть.
Автор: Schatz
Дата сообщения: 27.03.2006 11:20
Делфи 7

День добрый.
Проблема в следующем
Есть две переменные
Var Counter,MaxCounter:Integer;

Усть таймер, вот его обработчик
Begin
***
***
***
If Counter<MaxCounter then
Counter:=Counter+1
else
Counter:=0;
end;

Есть код
MaxCounter:=5;
Timer1.Enabled:=True;
// в обработчике таймера все работает нормально, далее пытаюсь сделать так
Timer1.Enabled:=False;
MaxCounter:=10;
Timer1.Enabled:=True;
//Вот тут то и возникает проблема, в обработчике таймера по прежнему выполняется сравнение между Counter и 5!!!! т.е. MaxCounter в обработчике таймера по прежнему равен 5, хотя в дебагере MaxCounter принимает значение 10.

Подскажите как можно правильно оформить сравнение двух переменных "If Counter<MaxCounter then " ???

Добавлено:
Прошу прощение за глупый вопрос, нашел проблему, у меня Counter Принимал значение больше максимального значения своего типа и поэтому автоматически переходил в 0.
Еще раз прошу прощения за глупый вопрос
Автор: mutmut
Дата сообщения: 27.03.2006 11:38
ShIvADeSt
То есть получается, что это не возможно(без разворачивания)? Тогда сама задача теряет смысл. А возможно разворачивать в невидимую область экрана и там сделать клик? Вообще задача в следующем есть flash в браузере, надо нажать на определенную область flash`ки.
Автор: OdesitVadim
Дата сообщения: 27.03.2006 11:51
mutmut

Цитата:
невидимую область экрана и там сделать клик

Вообщето да, но такие действия могут очень плохо работать - за этим следят некоторые антивири и начиная с второго сервиспака Windows явно не равнодушна к подобным фокусам. А с броузером, если конечно в настройках безопасности не полазить, она совсем не даст открывать окна за пределами рабочего пространства. Поэтому фокусы в виде "вылетающих окон" неработают. Да и вообще, ТЗ поставлено заведомо неверно. Надо по другому подходить к задаче. Скрываете вы от нас что-то сударь. А телепаты у нас всё таки есть.
Автор: mutmut
Дата сообщения: 27.03.2006 11:59
OdesitVadim
Абсолютно ничего не скрываю. Есть окно браузера в нем flash надо периодически нажимать на определенную область и всё. И что бы это не мещало работе в текуший момент.
Автор: Jokerjar
Дата сообщения: 27.03.2006 12:13
Ты не интересовался, какой класс имеет эта область? Попробуй узнать ее дескриптор
Автор: mutmut
Дата сообщения: 27.03.2006 14:46
Jokerjar
А можно по подробней, как узнать дескриптор области, какую использовать API функцию?
Автор: Olezka
Дата сообщения: 27.03.2006 15:06
подзкажите где находится объект TFileStream в Delphi 7
Автор: Jokerjar
Дата сообщения: 27.03.2006 15:16
Дескриптор можно узнать либо по имени, либо по классу компонента.
Узнаем класс:

Код: function GetCt(a: hwnd): string; //Узнать имя класса по дескриптору
var
sBuf: array[0..255] of char;
begin
GetClassName(a,sbuf,256);
result := trim(StrPas(sBuf));
end;
................................................
//Эту процедуру в таймер интервалом ~10
var
wnd: hwnd;
begin
wnd := windowfrompoint(mouse.CursorPos);
Label1.Caption := GetCt(wnd);
end; //Наводим мышь на область, в Label1 отобразится ее класс (записываешь на бумажку)
Автор: mutmut
Дата сообщения: 27.03.2006 15:56
Jokerjar
Всё ты умеешь. Только тут такая фигня получается, что узнаем мы класс, а он равен MacroMediaFlashPlayerActiveX родитель его и есть форма Internet Explorer_Server. Но у родителя не один такой потомок, а их несколько. На странице несколько флешек. Как быть, как унифицировать именно этого потомка?
Автор: RostY
Дата сообщения: 27.03.2006 16:05
А вы грузите не страницу, а только флешку хттп/..../....swf
Автор: mutmut
Дата сообщения: 27.03.2006 16:20
RostY
Загружается страница(php) на ней 3 фрейма, в одном из них несколько флешок,где-то 4-5.
Автор: OdesitVadim
Дата сообщения: 27.03.2006 18:07
Olezka

Цитата:
подзкажите где находится объект TFileStream в Delphi 7

Там, где и в 6,и в 2005 - Classes
Автор: ShIvADeSt
Дата сообщения: 27.03.2006 23:55
mutmut
Где то я видел пример работы с виртуальными десктопами, как объяснение быстрого сворачивания всех окон (когда мы нажимаем Win-D) то есть все окна просто меняют свой десктоп, попробуй в инете поискать. Тогда возможно удастся перекинуть свернутое окно на другой десктоп, там нажать (вот только хз где результ отобразится ) и потом обратно перекинуть его на свой десктоп. Насчет поиска окон, как вариант можно эмпиричисеским путем выяснить сколько раз надо сделать FindWindowEx, чтобы получить хэндл именно нашей флэшки и потом посылать ей уже мессагу.
Автор: mutmut
Дата сообщения: 28.03.2006 02:20
ShIvADeSt
Отображение результато совсем не нужно. Главное что бы по нажатию отработала флешка.
Я тут проснулся и подумал а если эмпирическим путем вычислить, но на той флешке 5 разных кликабельных облостей, возможно ли будут послать событие именно на обределенную область, или опять будут проблемы какие то?
Автор: Jokerjar
Дата сообщения: 28.03.2006 06:04

Цитата:
На странице несколько флешек. Как быть, как унифицировать именно этого потомка?

В этом случае ИМХО ищем не по классу а по имени

Код: function Gett(a: hwnd): string; //имя по дескриптору
var
sBuf: array[0..255] of char;
begin
SendMessage(a, wm_gettext, 256, integer(@sBuf));
result := trim(StrPas(sBuf));
end;

Страницы: 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768

Предыдущая тема: Вероятность одинакового CRC32


Форум Ru-Board.club — поднят 15-09-2016 числа. Цель - сохранить наследие старого Ru-Board, истории становления российского интернета. Сделано для людей.