Показать полную графическую версию : *Флейм* | Delphi. Синтаксис. Использование WinAPI
DillerInc
увеличится размер выходного файла (при установке Range или Overflow Checking), но будешь узнавать о всех недосмотрах в коде программы
DillerInc
03-01-2005, 22:00
Чего-то я запутался в следующем:
procedure TfmSubRip_Mod.bbOpenClick(Sender: TObject);
{Открываем текстовый файл с титрами}
begin
OpenDialog1.Filter := 'Титры с расширением "srt"|*.srt';
if OpenDialog1.Execute and FileExists(OpenDialog1.FileName) then
mmOutput.Lines.LoadFromFile(OpenDialog1.FileName); // Загружаем в многострочное поле текст из файла
lbOutput.Caption := 'Нажмите "Пуск",чтобы начать исправление символов'; // Добавляем текст в метку
...это всё если OpenDialog1.Execute = True,а мне надо добавить сюда ещё обработчик события OpenDialog1.Execute = False(типа пользователь передумал открывать файл и нажал Cancel),который будет опять добавлять текст в метку,например:
lbOutput := 'Повторите операцию "Открыть файл" ';
В общем,попытка добавить в конец вышеуказанного кода слово else вызывает кучу всяких ошибок.Если добавить ещё один условный оператор if...then,то диалоговое окно открытия файла заставляет по два раза открывать нужный файл...
DillerInc
procedure TfmSubRip_Mod.bbOpenClick(Sender: TObject);
{Открываем текстовый файл с титрами}
begin
OpenDialog1.Filter := 'Титры с расширением "srt"|*.srt';
if OpenDialog1.Execute then begin
if FileExists(OpenDialog1.FileName) then begin
mmOutput.Lines.LoadFromFile(OpenDialog1.FileName); // Загружаем в многострочное поле текст из файла
lbOutput.Caption := 'Нажмите "Пуск",чтобы начать исправление символов'; // Добавляем текст в метку
end else lbOutput.Caption := 'Файл не найден' end else
lbOutput.Caption := 'Повторите операцию "Открыть файл" ';
DillerInc
03-01-2005, 22:37
Savant
Ай да Savant - выручатель мой!Действительно получилось,как я хотел.
Спасибо :) .
DillerInc
20-01-2005, 01:12
Доброго всем времени суток!
Это снова я...со своими вопросами.А именно,имеется вопрос по использованию переменных в подпрограммах.
Код:
unit FileDateU;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, Buttons, StdCtrls, ExtCtrls, Mask;
type
TForm1 = class(TForm)
Panel1: TPanel;
bbOpen: TButton;
OpenDialog1: TOpenDialog;
Panel2: TPanel;
lbOutput2: TLabel;
Panel3: TPanel;
lbOutput1: TLabel;
edMaskInput: TMaskEdit;
bbRun: TBitBtn;
procedure bbOpenClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure bbRunClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
begin
lbOutput2.Caption := 'Нажмите "Открыть",чтобы открыть файл и узнать дату его создания';
end;
procedure TForm1.bbOpenClick(Sender: TObject);
var
FileHandle : Integer;
Date : String;
begin
OpenDialog1.Filter := 'Все файлы|*.*';
if OpenDialog1.Execute then
begin
if FileExists(OpenDialog1.FileName) then
begin
FileHandle := FileOpen(OpenDialog1.FileName, fmOpenWrite or fmShareDenyNone);
Date := DateTimeToStr(FileDateToDateTime(FileGetDate(FileHandle)));
lbOutput1.Caption := Date;
lbOutput2.Caption := 'Теперь введите новую дату в редактируемое поле и нажмите "OK",чтобы установить новую дату создания файла';
edMaskInput.SetFocus;
end else
lbOutput2.Caption := 'Файл не найден'
end else
lbOutput2.Caption := 'Повторите операцию открытия файла';
end;
procedure TForm1.bbRunClick(Sender: TObject);
var
Date2 : String;
begin
Date2 := edMaskInput.Text;
FileSetDate(FileHandle, (DateTimeToFileDate(StrToDateTime(Date2))));
end;
end.
Вот насчёт переменной
var
FileHandle : Integer;
...мне почему-то не удаётся связать практику с теорией.По теории подпрограмме доступны те переменные,которые были уже объявлены и описаны в предшествующих подпрограммах.Получается,что подпрограмма TForm1.bbRunClick должна видеть переменную,объявленную и описанную в подпрограмме TForm1.bbOpenClick,но при прогоне программы компилятор,проверяя функцию FileSetDate,сообщает об ошибке "Undeclared Identifier"(FileHandle).
Подскажите,пожалуйста,что я не так понимаю и как можно поправить ситуацию?
DillerIncПо теории подпрограмме доступны те переменные,которые были уже объявлены и описаны в предшествующих подпрограммахПо теории подпрограмме доступны те переменные, которые объявлены в зоне её видимости. Т.е. глобальные переменные, объявленные вообще вне любой подпрораммы, а также еще в случае, когда одна процедура вложена в другую. Лучше наверно показать на довольно прикольном примере, который ща сочинил:program Project_test;
{$APPTYPE CONSOLE}
var TEST: Integer = 5; // объявляем глобальную переменную
procedure a(SUPER: Integer);
// заметим, что переменная SUPER является объявленной локально,
// т.е. существует только внутри процедуры a; и вложенных в неё
procedure b;
begin
inc( SUPER ); // super = 2+1 = 3
dec( TEST ); // test = 5-1 = 4 <-тут изменяем глобальную переменную TEST
end;
var TEST: Integer; // перекрываем глобальную переменную локальной
procedure c;
begin
dec( SUPER ); // super = 3-1 = 2
inc( TEST ); // test = 2+1 = 3 <- а тут - локальную
end;
begin
TEST := SUPER;
b; WriteLn(TEST,' ',SUPER); // test=2!!! super=3
c; WriteLn(TEST,' ',SUPER); // test=3 super=2
end;
begin
a(2);
WriteLn(TEST); // И наконец в подтверждение выводим глобальную переменную TEST
// уменьшенную в процедуре b; на единицу
ReadLn;
end.
Ах да, еще спрашивалось, как подправить. Ну, думаю, это уже стало понятно - сделать FileHandle глобальной:
...........
implementation
{$R *.dfm}
var
FileHandle : Integer;
procedure TForm1.FormCreate(Sender: TObject);
begin
...........
Правда, она не становится глобальной в общем смысле, а также есть некоторые особенности объявления переменных внутри interface и implementation.
DillerInc
20-01-2005, 17:14
Savant
Спасибо,действительно начинает потихоньку мотаться на ус,только для меня теперь остаётся непонятным использование секции интерфейсных объявлений(interface) и секции реализаций(implementation),т.е. всегда ли можно объявлять глобальные переменные в секции реализаций и какие там есть особенности или можно также использовать т.н. поля класса - объявления переменных в следующем месте:
private
{Private declarations}
...?
1. Переменная, объявленная внутри implementation будет доступна всему коду , расположенному ниже её объявления.
2. Переменная, объявленная внутри interface будет доступна всему коду , расположенному ниже её объявления, а также программе, которая использует данный unit.
3. Переменная, объявленная внутри секции private будет доступна только для внутренних вызовов из данного класса.
DillerInc
20-01-2005, 18:00
Savant
Премного благодарю :) .
Теперь немного о функциях рассмотренного выше кода,а именно функции FileGetDate и FileSetDate - насколько я впоследствии понял,они орудуют датой последней модификации определённого файла.А я хотел,чтобы программка изменяла именно дату создания файла.Так вот вопрос: возможно ли такое "дельфийскими силами" и какие функции тогда использовать?
Можно так (используя WinAPI):
program Project_test;
uses Windows, SysUtils; // Необходимые модули
var
CreateTime, // Дата создания
LastAccess, // Дата последнего доступа
LastWrite // Дата последней записи в файл
: PFileTime;
SystemTime: _SystemTime;
FileHandle: THandle;
begin
New(CreateTime); // Создаем переменную под хранение даты/времени
LastAccess:=nil; // Не изменять эту дату/времени
LastWrite:=nil; // Не изменять эту дату/времени
// Открываем некоторый файл
FileHandle:=FileOpen('Project_test.dpr', fmOpenWrite or fmShareDenyNone);
// Произошла ошибка - выводим диагностическое сообщение
if FileHandle < 1 then MessageBox(0,'Не могу открыть файл','Ошибка',0);
try
GetSystemTime(SystemTime); // Получаем текущее системное время
// Преобразовываем переменную к сжатому виду
SystemTimeToFileTime(SystemTime,CreateTime^);
// Устанавливаем дату и время для файла FileHandle
SetFileTime(FileHandle,CreateTime,LastAccess,LastWrite);
finally
FileClose(FileHandle); // Закрываем дескриптор (файл)
Dispose(LastWrite); // Уничтожаем переменную под хранение даты/времени
end;
end.
DillerInc
20-01-2005, 23:04
Savant
...хм...хм...ну,ничего себе...в любом случае спасибо - попробую :) .
DillerInc
Я тут сижу и думаю: какая идиллия!.. Я помогаю тебе осваивать Obj. Pascal , а frizzn по сути так же хелпает мне с Си/Си++ :)
Нет, ну просто умора :lol:
DillerInc
21-01-2005, 21:07
Savant
Взяв в пример код,приведённый тобой выше(который я,кстати,так и не компилировал,т.к. толку создавать программу,если я не до конца понимаю алгоритма её работы)...в общем,решил я залесть в дебри функций WinAPI(типа те,в модуле Windows.pas)и окончательно потерялся :gigi: .
Во-первых,правильно ли,что...
PFileTime = ^TFileTime
...и можно ли так объявлять эти типизированные указатели,т.е. ...
CreationTime : ^TFileTime;
Во-вторых,как понимать запись:
_SystemTime
...т.е. именно это подчёркивание впереди?
Далее имеется API-функция:
function GetFileTime(hFile: THandle;
lpCreationTime, lpLastAccessTime, lpLastWriteTime: PFileTime): BOOL; stdcall;
Хотелось бы уточнить,что представляют из себя буквы lp,например: lpCreationTime ?
Результатом этой функции является значение логического типа BOOL,спрашивается: как я могу использовать это логиское значение,если я хочу вывести,к примеру,вывести дату создания файла в Label1.Caption?И ведь,по-моему,в модулях SysUtils.pas и Windows.pas нету какой-нибудь функции типа FileTimeToDateTime,или...?
Заранее прошу прощения,если уж очень пристаю со своими вопросами :) .
Во-первых,правильно ли,что...
PFileTime = ^TFileTime
Правильно. PFileType = pointer of variable of type FileTime, а TFileTime = variable of type FileTime.
...и можно ли так объявлять эти типизированные указатели,т.е. ...
CreationTime : ^TFileTime;
Объявлять можно, а вот использовать вместо PFileTime... Теоретически должна вылезти ошибка о несовместимости типов, хотя не пробовал.
Во-вторых,как понимать запись:
_SystemTime
...т.е. именно это подчёркивание впереди?
Просто название типа переменной. Введено в Делфи для избежание путаницы с системными типами SYSTEMTIME, FILETIME. Это в принципе не должно тебя волновать, т.к. меж собой эти типы фактически равны.
Далее имеется API-функция:
function GetFileTime(hFile: THandle; lpCreationTime, lpLastAccessTime, lpLastWriteTime: PFileTime): BOOL; stdcall;
Хотелось бы уточнить,что представляют из себя буквы lp,например: lpCreationTime ?
Опять же, это просто сокращенное для удобства название типа переменной. h*, например, = handle, lp* = long pointer (т.е. "расширенно" можно было написать long_pointer_CreationTime и программисту сразу становится ясно, что требуется передать в функцию указатель на переменную). В си (C/C++) это действительно нужно/полезно, в Делфи - не очень, хотя иногда обращаешь внимание.
Результатом этой функции является значение логического типа BOOL,спрашивается: как я могу использовать это логиское значение,если я хочу вывести,к примеру,вывести дату создания файла в Label1.Caption?
Логическое значение отражает лишь факт выполнения функции (0 или отрицательное значение обычно говорит об ошибке, положительное обычно об успехе, в Делфи это соответствует False и True). Все необходимые значение переменных (в данном случае различные времена файла) записываются в соотв. переменные.
И ведь,по-моему,в модулях SysUtils.pas и Windows.pas нету какой-нибудь функции типа FileTimeToDateTime,или...?
Нету. А что?
Кстати есть FileTimeToSystemTime();
DillerInc
22-01-2005, 17:44
Savant
В общем,насчёт функции GetFileTime - в одном месте подсмотрел :biggrin: :
Procedure A;
var
FileHandle : THandle;
FileTime, LocalFileTime : TFileTime;
SystemTime : TSystemTime;
Date1 : String;
begin
FileHandle := FileOpen(OpenDialog1.FileName, fmOpenWrite or fmShareDenyNone);
GetFileTime(FileHandle, @FileTime,NIL,NIL);
FileTimeToLocalFileTime(FileTime, LocalFileTime);
FileTimeToSystemTime(LocalFileTime, SystemTime);
Date1 := DateTimeToStr(SystemTimeToDateTime(SystemTime));
Label1.Caption := Date1;
На основании этого хочется спросить,насколько в Delphi вообще актуально использование указателей на адреса в динамической памяти?Т.е. здесь(в представленном коде)вместо типа PFileTime используется простой TFileTime;процедура New для выделения памяти динамической переменной не используется;в месте,где необходимо использование lpпеременной используется знак @,который как я понял возвращает адрес данной переменной в памяти.Или всё-таки...?
DillerInc
При использовании маленьких переменных - практически все равно, что использовать - динамическое создание/уничтожение переменных ( New(), Dispose() ) или статическое. Мне просто уже привычно работать с динамическим выделением буфера и поэтому я привёл свой пример в том виде в каком привёл :biggrin: . В данном случае я действительно немного переборщил, можно было обойтись одной "собачкой", которая возвращает адрес элемента, стоящего за ней (причем не только переменной, но также функции). Процедура New необходима, когда используются буферы (переменные) по несколько МБайт.
Savant
Опять же, это просто сокращенное для удобства название типа переменной. h*, например, = handle, lp* = long pointer (т.е. "расширенно" можно было написать long_pointer_CreationTime и программисту сразу становится ясно, что требуется передать в функцию указатель на переменную). В си (C/C++) это действительно нужно/полезно, в Делфи - не очень, хотя иногда обращаешь внимание. В Си ( и в C++) от этих lp*, sz* и dw* имхо пользы не больше, чем в Delphi. :shuffle:
DillerInc
07-02-2005, 13:19
Для начала - с челобитной к ув. Модераторам: с какой стати тему окрестили как Флейм?По-моему,здесь идёт самый настоящий процесс разгрызания гранита науки :biggrin: ,т.е. на мой взгляд точнее было бы назвать тему *Практика*|Delphi. Синтаксис или что-то наподобие.
:pray:
Далее...помогите,господа,пожалуйста по следующему делу:
хочу вставить в программу возможность показа сообщения типа mtConfirmation(ну,если пользователь сделал какие-то изменения в открытом документе и хочет выйти из программы,не сохранив эти изменения.Т.к. подобного компонента-диалога в среде Delphi вроде нету,я написал пробный обработчик события нажатия кнопки:
procedure TfmExample.bbRunClick(Sender: TObject);
const
Msg : String = 'Changes you made are not saved yet.Would you like to save them?';
DlgType : TMsgDlgType = mtConfirmation;
Buttons : TMsgDlgButtons = mbYesNoCancel;
var
d : Integer;
begin
d := CreateMessageDialog(Msg, DlgType, Buttons).ShowModal;
case d of
mrYes : SaveDialog1.Execute;
mrNo : fmExample.Close;
mrCancel : Abort;
end
end;
Проблема же заключается в том,что я почему-то не могу нормально вызвать данный диалог в самой программе,т.е. когда сделаны изменения в файле и когда пользователь выходит,не сохранившись.
Насколько я понимаю,необходимо сделать обработчик события OnCloseQuery основной формы и,применяя условные операторы,вывести в нужный момент на экран диалоговое сообщение...а вот как это сделать логически правильно?
Объяснять долговато, лучше на примере.
Вот, наклепал по-быстрому, но хоть понятно что-то...
© OSzone.net 2001-2012
vBulletin v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.