Часть [1] - Часть [2]

1. Как сохранить положение и размеры формы, а потом их восстановить ?

2. Почему при выходе из программы не сохраняются данные в Базе Данных ?

3. Каким образом можно обработать нажатия кнопок различных диалогов ?

4. Как отображать подсказки (Hint) в строке состояния StatusBar ?

5. Как можно занести в Базу Данных информацию из текстового файла ?

6. Как создать загрузочный компакт-диск ?

7. Почему в отчете QuickReport отображается только текущая запись ?

8. Как сделать чтобы программа закрывалась при нажатии клавиши Esc ?

9. При вызове файла справки выдается ошибка, что данного раздела не существует ?

10. Как найти нужное место в документе Word ?

11. Как время вида 1:02:45 вывести словами 1ч. 02мин. 45сек. ?

12. Как из Базы Данных удалить записи помеченные на удаление ?

13. Как программно скопировать файл ?

14. Как можно анимировать нажатие кнопки ?

15. Как из своей программы перейти на сайт или на e-mail ?

16. В нескольких программах видел, что при нажатии на пункт меню...

17. Как вывести текст поверх картинки загруженной в Image ?

18. При выполнении большого цикла мое приложение как бы замирает. Как это исправить ?

19. При удалении записи в БД выдается запрос на английском языке, хотя...

20. Как написать свой ScreenSaver ?

21. Во многих программах выдаются диалоги для ввода некоторых значений...

22. При вводе текста в Memo и достижении правого края контрола текст автоматически...

23. Как можно программно управлять открытием и закрытием компонента ComboBox...

24. В программе 1С я заметил, что при редактировании ячейки БД в правой ее части...

25. Как программно создать компонент и навесить на него обработчик события ?

26. Можно ли в процессе выполнения программы узнать какой разделитель...

27. Как установить курсор мыши в определенную позицию экрана ?

28. Хочу при запуске программы сделать кнопку активной, но постоянно выдается ошибка...

29. Как из моей программы некоторый файл сделать скрытым ?

30. Как показать контекстное меню в точке нажатия кнопки мышью ?



Вопрос № 1: Как сохранить положение и размеры формы, а потом их восстановить ?

Ответ: Для этого нужно использовать файл инициализации (.ini). При выходе из программы в событие закрытия или уничтожения формы onCloseQuery (или onDestroy) нужно сохранить положение и размеры формы в файл инициализации, а при ее создании их восстановить:

// Сохранение свойств формы
procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
Var iniFile: TiniFile;
begin
 Try
  // Создаем или перезаписываем файл инициализации в текущей директории
  iniFile:=TIniFile.Create(ExtractFilePath(Application.ExeName)+'File.ini');
  // Сохраняем свойства формы 
  iniFile.WriteString('Pos', 'Top', IntToStr(Top));
  iniFile.WriteString('Pos', 'Left', IntToStr(Left));
  iniFile.WriteString('Pos', 'Height', IntToStr(Height));
  iniFile.WriteString('Pos', 'Width', IntToStr(Width));
 Finally
  iniFile.Free;
 End;
end;
// Восстанавливаем свойства формы первым способом
procedure TForm1.FormCreate(Sender: TObject);
begin
 Try
  // Открываем файл инициализации из текущей директории
  iniFile:=TIniFile.Create(ExtractFilePath(Application.ExeName)+'File.ini');
  // Проверяем, нет ли пустых значений
  If (iniFile.ReadString('Pos', 'Top', IntToStr(Top)) = '')
   OR (iniFile.ReadString('Pos', 'Left', IntToStr(Left)) = '')
    OR (iniFile.ReadString('Pos', 'Height', IntToStr(Height)) = '')
     OR (iniFile.ReadString('Pos', 'Width', IntToStr(Width)) = '')
  // Если пустые значения найдены, то стандартный вывод формы
  Then WindowState:=wsNormal Else
  // Если пустые значения не найдены, то восстанавливаем свойства формы
    Begin
      Top:=StrToInt(iniFile.ReadString('Pos', 'Top', IntToStr(Top)));
      Left:=StrToInt(iniFile.ReadString('Pos', 'Left', IntToStr(Left)));
      Height:=StrToInt(iniFile.ReadString('Pos', 'Height', IntToStr(Height)));
      Width:=StrToInt(iniFile.ReadString('Pos', 'Width', IntToStr(Width)));
    End;
 Finally
   iniFile.Free;
 End;
end;             
// Восстанавливаем свойства формы вторым способом
procedure TForm1.FormCreate(Sender: TObject);
Const NoFind = -1000;
Var iniFile               : TIniFile;
    Not_Left, Not_Top     : Integer;
    Not_Height, Not_Width : Integer;
begin
  iniFile:=TIniFile.Create(ExtractFilePath(Application.Exename) + 'IniFile.ini');
  // Проверяем нет ли пустых значений.
  Not_Left:=iniFile.ReadInteger('Position', 'Left', NoFind);
  Not_Top:=iniFile.ReadInteger('Position', 'Top', NoFind);
  Not_Height:=iniFile.ReadInteger('Position', 'Height', NoFind);
  Not_Width:=iniFile.ReadInteger('Position', 'Width', NoFind);

  // Если пустые значения найдены, то стандартный центрируем форму
  If (Not_Left = NoFind) OR (Not_Top = NoFind) 
    OR (Not_Height = NoFind) OR (Not_Width = NoFind)
      Then Form1.Position:=poScreenCenter
   // Если пустые значения не найдены, то восстанавливаем свойства формы
   Else
     Begin
       Left:=iniFile.ReadInteger('Position', 'Left', Left);
       Top:=iniFile.ReadInteger('Position', 'Top', Top);
       Height:=iniFile.ReadInteger('Position', 'Height', Height);
       Width:=iniFile.ReadInteger('Position', 'Width', Width);
     End;
  iniFile.Free;
end;

// Восстанавливаем свойства формы третьим способом, при помощи реестра
...
Var Reestr: TRegistry;
...

procedure TForm1.FormCreate(Sender: TObject);
begin
 Reestr:=TRegistry.Create;
 Reestr.RootKey:=HKEY_CURRENT_USER;
 If Reestr.OpenKey('\SoftWare\MyProg\', False) Then
   Begin
     Form1.Top:=Reestr.ReadInteger('Top');
     Form1.Left:=Reestr.ReadInteger('Left');
     Form1.Height:=Reestr.ReadInteger('Height');
     Form1.Width:=Reestr.ReadInteger('Width');
     Reestr.CloseKey;
   End;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
 Reestr.RootKey:=HKEY_CURRENT_USER;
 If Reestr.OpenKey('\SoftWare\MyProg\', False) Then
   Begin
     Reestr.WriteInteger('Top', Form1.Top);
     Reestr.WriteInteger('Left', Form1.Left);
     Reestr.WriteInteger('Height', Form1.Height);
     Reestr.WriteInteger('Width', Form1.Width);
     Reestr.CloseKey;
   End;
 Reestr.Free;
end;



Вопрос № 2: Почему при выходе из программы не сохраняются данные в Базе Данных ?

Ответ: Это одна из самых распространненых ошибок, проблема решается следующим образом:

procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
 If Table1.Modified Then Table1.Post;
 If Query1.Modified Then Query1.Post;
end;

Аналогичный код, также лучше вставить куда-нибудь в пункт меню "Сохранить":

procedure TForm1.mnuSave(Sender: TObject);
begin
 If Table1.Modified Then Table1.Post;
 If Query1.Modified Then Query1.Post;
end;



Вопрос № 3: Как можно обработать нажатия кнопок различных диалогов ?

Ответ: Здесь все достаточно просто. См. пример:

// Пример с диалогом MessageBox 
procedure TForm1.Button1Click(Sender: TObject);
Var ModalResult: TModalResult;
begin
 ModalResult:=MessageBox(0, 'Сообщение', 'Заголовок', MB_YESNOCANCEL);
 If ModalResult = idYES Then ShowMessage('Нажата кнопка Да')
   Else
 If ModalResult = idNO Then ShowMessage('Нажата кнопка Нет')
   Else
 If ModalResult = idCANCEL Then ShowMessage('Нажата кнопка Отмена');
end;
// Пример с диалогом MessageDlg
procedure TForm1.Button2Click(Sender: TObject);
Var ModalResult: TModalResult;
begin
 ModalResult:=MessageDlg('Сообщение', mtInformation, mbYesNoCancel, 0);
 If ModalResult = mrYES Then ShowMessage('Нажата кнопка YES')
   Else
 If ModalResult = mrNO Then ShowMessage('Нажата кнопка No')
   Else
 If ModalResult = mrCANCEL Then  ShowMessage('Нажата кнопка Cancel');
end;



Вопрос № 4: Как отображать подсказки (Hint) в строке состояния StatusBar ?

Ответ: Для этого нужно использовать событие приложениея onHint:

// В событие OnHint объекта приложения Application назначаем обработчик
procedure TForm1.FormCreate(Sender: TObject);
begin
 Application.OnHint:=StatusHint;
end;

// Сам обработчик заносит текст подсказки в панель строки состояния
procedure TForm1.StatusHint(Sender: TObject);
Begin
 StatusBar1.Panels[1].Text:=Application.Hint;
End;



Вопрос № 5: Как можно занести в Базу Данных информацию из текстового файла ?

Ответ: Допустим, в Базе Данных имеются два поля - Code и Fam. Нужно отметить, что в первом примере вся информация из файла будет занесена только в одно поле Базы Данных. Для того чтобы информация из файла заносилась сразу в несколько полей нужно использовать, либо типизированные файлы и работать с типом данных Запись (Record), либо использовать файлы инициализации (см. Примеры).

// Пример № 1 - Непосредственное внесение данных в БД
procedure TForm1.Button1Click(Sender: TObject);
Var F : System.Text;
    I : Integer;
    X : String;
begin
  I:=0; // Переходим в конец набора данных и запоминаем максимальный номер записи
  Table1.Last;
  I:=Table1.FieldByName('Code').AsInteger;
  AssignFile(F,'File.txt'); // Открываем файл для чтения
  Reset(F);
    Repeat
      Inc(I);        // Увеличиваем номер записи
      Readln(F, X);  // Считываем строку из файла
      Table1.Append; // Добавляем в конец Базы Данных прочитаную строку
      Table1.FieldByName('Code').AsString:=IntToStr(I);
      Table1.FieldByName('Fam').AsString:=X;
      Table1.Next;
    Until Eof(F);
  CloseFile(F);
end;
// Пример № 2 - Использование Записей (Record)
...

Type Base = Record
     Code : String;
     Fam  : String;
End;     
  
Var
  Form1 : TForm1;
  Rec   : Base;
  F     : System.Text;

...

procedure TForm1.Button1Click(Sender: TObject);
begin
 AssignFile(F, 'File.txt');
 Append(F);
 // Вносим в поля записи значения редакторов
 Rec.Code:=Edit1.Text;
 Rec.Fam:=Edit2.Text;
 // Сохраняем значения записи
 Writeln(F, Rec.Code);
 Writeln(F, Rec.Fam);
 CloseFile(F);
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
 AssignFile(F, 'File.txt');
 Reset(F);
 Table1.First;
   Repeat
     // Считываем значения записи
     Readln(F, Rec.Code);
     Readln(F, Rec.Fam);
     // Заносим значения записи в БД
     Table1.Append;
     Table1.FieldByName('Field1').AsString:=Rec.Code;
     Table1.FieldByName('Field2').AsString:=Rec.Fam;
     Table1.Next;
   Until Eof(F);
 CloseFile(F);
end;
// Пример № 3 - Использование файла инициализации
...

var
  Form1   : TForm1;
  IniFile : TIniFile;
  Code    : Integer;

...

procedure TForm1.Button1Click(Sender: TObject);
begin
 Inc(Code);
 // Сохраняем данные в файл инициализации
 IniFile:=TIniFile.Create(ExtractFilePath(Application.ExeName) + 'IniFile.ini');
 IniFile.WriteInteger('Main', 'Code', Code);
 IniFile.WriteString('Step' + IntToStr(Code), 'Str1', Edit1.Text);
 IniFile.WriteString('Step' + IntToStr(Code), 'Str2', Edit2.Text);
 IniFile.WriteString('Step' + IntToStr(Code), 'Str3', Edit3.Text);
 IniFile.Free;
end;

procedure TForm1.Button2Click(Sender: TObject);
Var I    : Integer;
    Str1 : String;
    Str2 : String;
    Str3 : String;
begin
 IniFile:=TIniFile.Create(ExtractFilePath(Application.ExeName) + 'IniFile.ini');
 Code:=IniFile.ReadInteger('Main', 'Code', Code);
 For I:=1 To Code Do
   Begin
    Table1.Append;
    // Считываем данные из файла инициализации и вносим их в БД
    Str1:=IniFile.ReadString('Step' + IntToStr(I), 'Str1', Edit1.Text);
    Str2:=IniFile.ReadString('Step' + IntToStr(I), 'Str2', Edit2.Text);
    Str3:=IniFile.ReadString('Step' + IntToStr(I), 'Str3', Edit3.Text);

    Table1.FieldByName('Field1').AsString:=Str1;
    Table1.FieldByName('Field2').AsString:=Str2;
    Table1.FieldByName('Field3').AsString:=Str3;
    Table1.Next;
  End; 
 IniFile.Free;
end;



Вопрос № 6: Как создать загрузочный компакт-диск ?

Ответ: Для это на диске необходимо создать файлы:

           1. Autorun.exe - Исполняемая программа;
           2. Autorun.inf - Файл информации для исполняемой программы;
           3. Autorun.ico - Иконка.

Файл Autorun.inf можно записать различными способами:

// Стандартный автозапуск
 а) [Autorun]
    Icon = Autorun.ico
    Open = Autorun.exe

// Автозапуск HTML-страницы     
 б) [Autorun]                       
    Icon = Autorun.ico
    Open = Start Autorun.htm

// Автозапуск с извлечением иконки из исполняемой программы:
 в) [Autorun]
    Icon = Autorun.exe, 0
    Open = Autorun.exe

А вот еще один интересный пример, который я увидел на одном компакт-диске:

[Autorun]
Open = AutoRun.exe 
Icon = AutoRun.ico

Shell\Play = Установить драйвер DivX Mpeg4
Shell\Play\Command = DivX\RunInf.exe DivX.inf

Shell\Play1 = Установить драйвер Microsoft Mpeg4
Shell\Play1\Command = Mpeg4\RunInf.exe Mpeg4fix.inf

Shell\Play2 = Установить Windows Media Player
Shell\Play2\Command = Media\mpie4ful.exe

Shell\Video = Начать просмотр фильма
Shell\Video\Command = FlyVCD.exe VideoCD.mls



Вопрос № 7: Почему в отчете QuickReport отображается только текущая запись ?

Ответ: Это одна из самых распространенных ошибок. Нужно указать свойство DataSet для самого компонента QuickReport. Иначе компоненты TQRDBText как бы принудительно будут отображать содержимое текущей Базы Данных.




Вопрос № 8: Как сделать чтобы программа закрывалась при нажатии клавиши Esc ?

Ответ: Для этого нужно свойство формы KeyPreview установить в True. А в обработчик события нажатия клавиш внести следующий код:

procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char);
begin
 If Key = #27 Then Close;
end;



Вопрос № 9: При вызове файла справки выдается ошибка, что данного раздела не существует. Причем так же не происходит переход в самом файле справки. Как это исправить ?

Ответ: 1) Если у Вас не получается запустить файл справки из Вашей программы, то Вы скорее всего забыли указать свойство HelpContext у формы или у определенного компонента на форме.
2) Если не происходит перехода по ссылкам внутри самого файла справки, то тут скорее всего нужно посмотреть сам файл проекта справки. Единственное что приходит в голову, так это, что возможно Вы при создании текстового файла в формате *.rtf между видимой строкой и контекстом случайно поставили пробел. Ни каких пробелов между строкой и контекстом быть не должно. Может Вы неправильно указываете имя раздела, либо такого раздела действительно не существует.




Вопрос № 10: Как найти нужное место в документе Word ?

Ответ: Для начала нужно создать документ Word и вставить в него так называемые метки, то есть те места в документе на которые будет производиться переход. Эти метки вставляются при помощи пункта меню "Вставка" - "Закладка..." текстового редактора Word. Затем нужно положить на форму компоненты TWordApplication и TWordDocument со страницы Servers Палитры Компонентов.

uses Word2000, OleServer, COMobj;

...

procedure TForm1.Button1Click(Sender: TObject);
Var FileName, NewName : OleVariant;
    A1, A2            : OleVariant;
begin
 // Задаем имя открываемого документа (шаблона)
 FileName:='C:\Мои документы\Шаблон.doc';
 // Задаем имя сохраняемого документа
 NewName:='C:\Копия Шаблона.doc';
 // Соединяемся с Word
 WordApplication1.Connect;
 // Задаем имена меток
 A1:='Num1';
 A2:='Num2';

 // Открываем файл (шаблон)
 WordApplication1.Documents.Open(FileName,
                                 EmptyParam, EmptyParam, EmptyParam,
                                 EmptyParam, EmptyParam, EmptyParam,
                                 EmptyParam, EmptyParam, EmptyParam,
                                 EmptyParam, EmptyParam);

 // Находим первую метку
 WordApplication1.ActiveDocument.Bookmarks.Item(A1).Select;
 WordApplication1.Selection.Text:='Текст_1';

 // Находим вторую метку
 WordApplication1.ActiveDocument.Bookmarks.Item(A2).Select;
 WordApplication1.Selection.Text:='Текст_2';

 // Переход на начало документа
 WordApplication1.Selection.SetRange(0,0);
 WordDocument1.ConnectTo(WordApplication1.ActiveDocument);

 // Сохраняем файл шаблона с изменениями
 WordDocument1.SaveAs(NewName);
 // "Показываем" Word
 WordApplication1.Visible:=True;
 // Разъединяемся с Word
 WordApplication1.Disconnect;
end;



Вопрос № 11: Как время вида 1:02:45 вывести словами 1ч. 02мин. 45сек. ?

Ответ: Для разложения даты и времени нужно воспользоваться функцией для декодирования времени:

procedure TForm1.Button1Click(Sender: TObject);
Var Hour, Min, Sec, MSec : Word;
    D, M, Y              : Word;
begin
 DecodeTime(Time, Hour, Min, Sec, MSec);
 ShowMessage(IntToStr(Hour) + 'ч.' + IntToStr(Min) + 'мин.' +  IntToStr(Sec) + 'сек.');

 DecodeDate(Date, Year, Month, Day);
 ShowMessage(IntToStr(D) + 'число' + IntToStr(M) + 'месяца' +  IntToStr(Y) + 'года');
end;



Вопрос № 12: Как из Базы Данных удалить записи помеченные на удаление ?

Ответ: См. пример:

procedure TForm1.FormCreate(Sender: TObject);
begin
 // Создаем возможность выделения нескольких строк
 DBGrid1.Options:=DBGrid1.Options + [dgMultiSelect];
end;

procedure TForm1.ButtonDeleteClick(Sender: TObject);
begin
 // Проверяем действительно ли выбрано несколько записей БД
 If DBGrid1.SelectedRows.Count <> 0 Then
   Begin
     // Перед удалением выводим запрос
     If MessageDlg('Удалить помеченные записи БД ?', mtWarning,
                   [mbYes, mbNo], 0) = mrYes
       Then DBGrid1.SelectedRows.Delete;
   End
 Else
   Begin
     // Если выбрана всего одна запись, то удаляем только ее одну
     If MessageDlg('Удалить текущую запись БД ?', mtWarning,
                   [mbYes, mbNo], 0) = mrYes 
       Then Table1.Delete;
   End;
end;



Вопрос № 13: Как программно скопировать файл ?

Ответ: Для этого нужно воспользоваться функцией CopyFile:

procedure TForm1.Button1Click(Sender: TObject);
begin
 If OpenDialog1.Execute Then Edit1.Text:=OpenDialog1.FileName;
 If OpenDialog2.Execute Then Edit2.Text:=OpenDialog2.FileName;
 CopyFile(PChar(Edit1.Text), PChar(Edit2.Text), True);
end;



Вопрос № 14: Как можно анимировать нажатие кнопки ?

Ответ: Для анимации кнопки стандартная кнопка TButton не очень подойдет, поэтому удобней будет использовать кнопку быстрого доступа TSpeedButton или кнопку TBitBtn. В обработчик события нажатия на кнопку меняем свойства Font, а затем эти свойства восстанавливаем:

procedure TForm1.SpeedButton1MouseDown(Sender: TObject; Button: TMouseButton;
 Shift: TShiftState; X, Y: Integer);
begin
 SpeedButton1.Font.Color:=clRed;
 SpeedButton1.Font.Size:=10;
 SpeedButton1.Font.Style:=[fsBold]
end;

procedure TForm1.SpeedButton1MouseUp(Sender: TObject; Button: TMouseButton;
 Shift: TShiftState; X, Y: Integer);
begin
 SpeedButton1.Font.Color:=clBlack;
 SpeedButton1.Font.Size:=8;
 SpeedButton1.Font.Style:=[]
end;



Вопрос № 15: Как из своей программы перейти на сайт или на e-mail ?

Ответ: Для этого нужно воспользоваться API-функцией ShellExecute:

procedure TForm1.LabelMailClick(Sender: TObject);
begin
 ShellExecute(Handle,'Open','mailto: satanzone@yandex.ru', NIL, NIL, SW_SHOWNORMAL);
end;

procedure TForm1.LabelURLClick(Sender: TObject);
begin
 ShellExecute(HWND(NIL), NIL, 'IExplore', 'http://icops.narod.ru', NIL, SW_SHOWNORMAL);
end;

procedure TForm1.LabelMailMouseMove(Sender: TObject; Shift: TShiftState;
  X, Y: Integer);
begin
 LabelMail.Font.Style:=LabelMail.Font.Style - [fsUnderLine];
end;

procedure TForm1.LabelMailMouseLeave(Sender: TObject);
begin
 LabelMail.Font.Style:=LabelMail.Font.Style + [fsUnderLine];
end;

procedure TForm1.LabelURLMouseLeave(Sender: TObject);
begin
 LabelURL.Font.Style:=LabelURL.Font.Style + [fsUnderLine];
end;

procedure TForm1.LabelURLMouseMove(Sender: TObject; Shift: TShiftState;
  X, Y: Integer);
begin
 LabelURL.Font.Style:=LabelURL.Font.Style - [fsUnderLine];
end;


Вопрос № 16: В нескольких программах видел, что при нажатии на пункт меню он становился выделенным галочкой, а при повторном нажатии это выделение пропадало. Как мне это сделать в своей программе ?

Ответ: Для этого нужно использовать свойство Check:

procedure TForm1.mnuFileClick(Sender: TObject);
begin
 If mnuFile.Checked = False Then
   Begin
     mnuFile.Checked:=True;
     ShowMessage('Пункт меню отмечен !!!');
   End
 Else
   If mnuFile.Checked = True Then
     Begin
       mnuFile.Checked:=False;
       ShowMessage('Пункт меню не отмечен !!!');
     End;
end;


Вопрос № 17: Как вывести текст поверх картинки загруженной в Image ?

Ответ: См. пример:

procedure TForm1.FormCreate(Sender: TObject);
Var BMP : TBitmap;
begin
 BMP:=TBitmap.Create;
 BMP.LoadFromFile('MyPicture.bmp');
 Image1.Picture.Assign(BMP);
 Image1.Canvas.Brush.Color:=clBlue;
 Image1.Canvas.Font.Name:='Arial';
 Image1.Canvas.Font.Size:=10;
 Image1.Canvas.TextOut(10, 10, 'Некоторый текст !!!');
end;


Вопрос № 18: При выполнении большого цикла мое приложение как бы замирает. Как это исправить ?

Ответ:: Для этого нужно в тело цикла вставить конструкцию Application.ProcessMessages. При этом можно будет нажимать на различные кнопки, пользоваться меню, но нельзя будет закрыть приложение :(.

procedure TForm1.Button1Click(Sender: TObject);
Var I: Integer;
begin
 For I:=1 To 100000 Do
   Begin
     Label1.Caption:=IntToStr(I);
     Application.ProcessMessages;      
   End;
end;


Вопрос № 19: При удалении записи в БД выдается запрос на английском языке, хотя вся моя программа построена на русском языке. Можно ли как-нибудь сделать этот запрос русским ?

Ответ: Я тоже столкнулся с такой неприятной мелочью. Лично мне пришла в голову одна очень простая мысль: я сделал отдельный пункт меню "Удалить запись", в котором я написал свой обработчик удаления записи из набора данных с русским диалоговым запросом. Далее я задал свойству пункта меню ShortCut (быстрый доступ "горячей клавишей") значение Ctrl+Del. Еще можно просто запретить вывод запроса на удаление путем установки значения False подсвойству dgComfirmDelete свойства сетки DBGrig, но это не очень хорошо, потому что можно и не заметить как запись будет удалена. Вот небольшой и понятный пример:

procedure TForm1.mnuDBDelClick(Sender: TObject);
begin
 If Application.MessageBox('Удалить запись ?', 'Удаление:', MB_YESNO) = idYES
   Then Table1.Delete;
end;


Вопрос № 20: Как написать свой ScreenSaver ?

Ответ: Честно говоря, я даже никогда об этом не задумывался :). По сути ScreenSaver - это обычная программа переименованная в расширение .scr. Даже если Вы любую программу переименуете из .exe в .scr, и поместите в каталог Windows или Windows\System, то через установленный промежуток времени переименованная программа сработает как ScreenSaver. Значит нужно написать свою собственную программу и в обработчики нажатия клавиш onKeyPress, onKeyDown и onKeyUp записать код закрытия программы. Аналогичным образом нужно "оформить" обработчики движения мыши. А еще надо проверять, чтобы программа запускалась в одном экземпляре, иначе таких хранителей экрана будет одновременно запущено сразу несколько :).



Вопрос № 21: Во многих программах выдаются диалоги для ввода некоторых значений, например, пароля. А как это делается, неужели создается отдельная форма ?

Ответ: Для этого, безусловно, можно создать отдельную форму, но проще будет воспользоваться функциями InputBox или InputQuery. В своих программах с БД я частенько использую такой прием для перехода к определенной записи. Вот небольшой и понятный пример:

procedure TForm1.mnuDBGotoClick(Sender: TObject);
Var Go: String;
begin
 Go:='1';
 InputQuery('Переход к записи', 'Перейти к записи с номером:', Go);
 Try
   If NOT Table1.Locate('Code', Go, []) Then
     MessageDlg('Запись с номером' + Go + 'не найдена', mtWarning, [mbOK], 0);
 Except
   MessageDlg('Значение' + Go + 'не допустимо', mtWarning, [mbOK], 0); 
 End;
end;


Вопрос № 22: При вводе текста в Memo и достижении правого края контрола текст автоматически переносится на новую строку. Как с этим бороться ?

Ответ: Для этого можно поступить двумя способами:
1) Установить свойству WordWrap значение False.
2) Установить свойству ScrollBars значение ssHorizontal - для появления горизонтальной полосы прокрутки, или ssBoth - для появления обоих полос прокрутки.



Вопрос № 23: Как можно программно управлять открытием и закрытием компонента ComboBox и узнать его состояние в текущий момент ?

Ответ:См. пример:

procedure TForm1.Button1Click(Sender: TObject);
begin
 // Открываем список
 ComboBox1.DroppedDown:=True;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
 // Закрываем список
 ComboBox1.DroppedDown:=False;
end;

procedure TForm1.Bla-Bla-Bla(Sender: TObject);
begin
 If ComboBox1.DroppedDown = True Then ShowMessage('Список открыт')
   Else ShowMessage('Список закрыт')
end;


Вопрос № 24: В программе 1С я заметил, что при редактировании ячейки БД в правой ее части появляется кнопка с тремя точками. Если нажать эту кнопку, то появляется отдельная форма для выбора товара. А можно ли такое сделать в Делфи ?

Ответ: Конечно можно, для этого нужно воспользоваться т.н. статическими полями (о них я рассказывал в одной из статей о БД). Для определенного статического поля нужно установить свойство ButtonStyle в значение cbsEllipsis. А затем обрабатывать событие onEditButtonClick сетки DBDrid.

procedure TForm1.DBGrid1EditButtonClick(Sender: TObject);
begin
 FormAdd2.ShowModal;
end;


Вопрос № 25: Как программно создать компонент и навесить на него какой-нибудь обработчик события ?

Ответ: См. пример:

uses ..., StdCtrls;
...

procedure TForm1.FormCreate(Sender: TObject);
Var Memo1 : TMemo;
begin
 Memo1:=TMemo.Create(Self);
 Memo1.Parent:=Form1;
 Memo1.Top:=10;
 Memo1.Left:=10;
 Memo1.Height:=90;
 Memo1.Width:=150;
 Memo1.OnKeyPress:=MyMemoKeyPress;
end;

procedure TForm1.MyMemoKeyPress(Sender: TObject; var Key: Char);
begin
 If NOT(Key In ['0'..'9', Chr(8), Chr(32)]) Then Key:=Chr(0);
end;


Вопрос № 26: Можно ли в процессе выполнения программы узнать какой разделитель целой и дробной части установлен в системе в данный момент ?

Ответ: Разделитель в своей программе можно задать свой. А так для этого служит DecimalSeparator.

procedure TForm1Main.FormCreate(Sender: TObject);
begin
 DecimalSeparator:='.';
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
 ShowMessage('Текущий разделитель: ' + DecimalSeparator);
 Edit1.Text:='10' + DecimalSeparator + '5';
end;


Вопрос № 27: Как установить курсор мыши в определенную позицию экрана ?

Ответ:См. пример:

procedure TForm1.Button1Click(Sender: TObject);
Var P: TPoint;
begin
 GetCursorPos(P); // Сохраняем позицию курсора
 ...
 // Что-то делаем
 ...
 SetCursorPos(P.X, P.Y); // Восстанавливаем позицию курсора
end;


Вопрос № 28: Хочу при запуске программы сделать кнопку активной, но постоянно выдается ошибка. Как лечить ?

Ответ:Если уже Вы решили сделать кнопку активной в обработчике события создания формы, то нужно просто вставить обработчик исключительной ситуации, которая как раз и генерируется. Но при компиляции проекта это исключение все равно будет возникать, что очень не удобно. Более простым и удобным способом будет использовать событие формы onShow. Тогда уж точно никаких ошибок не возникнет.

procedure TForm1.FormCreate(Sender: TObject);
begin
 Try
   If Button1.CanFocus Then Button1.SetFocus;
 Except
 End;
end;

procedure TForm1.FormShow(Sender: TObject);
begin
 If Button1.CanFocus Then Button1.SetFocus;
end;


Вопрос № 29: Как из моей программы некоторый файл сделать скрытым ?

Ответ:Для этого ему нужно задать атрибут как "скрытый".

procedure TForm1.FormCreate(Sender: TObject);
begin
 SetFileAttributes('File.txt', FILE_ATTRIBUTE_HIDDEN);
end;


Вопрос № 30: Как показать контекстное меню в точке нажатия кнопки мышью ?

Ответ:См. пример:

procedure TForm1.Button1Click(Sender: TObject);
begin
 PopupMenu1.Popup(Mouse.CursorPos.X, Mouse.CursorPos.Y);
end;



Вернуться в оглавление
Вернуться на главную страницу
Hosted by uCoz