Отправляет email-рассылки с помощью сервиса Sendsay

Программирование на Delphi

  Все выпуски  

Программирование на Delphi #19


Информационный Канал Subscribe.Ru

Программирование на Delphi. Выпуск №19: 06.02.05.


Приветствую Вас, уважаемые читатели!

Письмо...

Вот я раз ответил на чей-то вопрос, и мне в ответ пришло письмо с Subject: Re: Answer_41
В котором было написано : 41 - 5, 5.
Что это значит???

Ведущий: Вы невнимательно читаете нашу рассылку. Уже неоднократно говорилось, что подобные письма - уведомления о начисленных баллах. Каждый читатель имеет свой собственный "счёт". За каждый ответ начисляются баллы (от 1 до 5). Данное письмо означает, что за ваш ответ на 41-ый вопрос вам начислено 5 баллов и на вашем счету всего 5 баллов.

Добавлено на http://www.delphi-faq.fatal.ru/faq.htm.


А теперь повторю правила подачи вопросов: вопросы нужно присылать на НАШ ящик с темой 'Question'. Присылать свои вопросы читателям НЕ НУЖНО! Господин 'it', надеюсь, понял, что о нём речь.

Количество подписчиков: 1812.

Через несколько дней будет открыт новый конкурс.

Пожалуйста, не забывайте дублировать свои вопросы на нашем форуме.

Top-10 Readers:

Место
Имя
Кол-во баллов
Место
Имя
Кол-во баллов
1.
148 баллов
6.
50 баллов
2.
137 баллов
7.
38 баллов
3.
112 баллов
8.

Den

36 баллов
4.
93 балла
9.
33 балла
5.
62 балла
10.
30 баллов

Правила нашей рассылки:
1. Не присылайте ответов на вопросы вроде "да я не знаю" или "да/нет". Такие ответы не публикуются.
2. Вопросы, не касающиеся Delphi, не принимаются (для этого существуют другие рассылки).
3. Запрещено присылать вложенные файлы, размером более 100 Кб, без предварительной связи с администратором.
4. Не изменяйте тем присылаемых писем. Письма с "неправильными" темами не публикуются! Используйте текстовый формат писем.


Новые вопросы.

63. День добрый ! Прошу помощи, кто знает как к Делфе (7) пристроить самописный плагин, или кто знает где взять плагин к D-7, чтоб как в D-8 в редакторе кода можно было сворачивать текст процедур и отдельных блоков кода ?. Первый вариант желательнее ... [Ответить].

64. Прошу ответить на вопрос. Можно ли в Delphi в исходнике использовать верхние и нижние индексы? Если можно, как? [Ответить].

65. Уважаемые коллеги, подскажите, как к обьекту можно прицепить обработчики cm_MouseWheelUp, cm_mouseWheelDown? cm_mouseWheel я приклеил без проблем, но отследить, куда вхилилось не получилось. [Ответить].

66. Подскажите пожалуйста, как мне преобразовать 24-ную картинку в 16-ти битную? [Ответить].

67. Хотелось бы научиться работать с системным реестром. Где можно найти подробный учебник (кроме встроенного HELPа)? [Ответить].

68. Как считать плотность расположения секторов на сидюке, используя Delphi, для формирования уникального номера CD? Стоят стандартные драйвера из набора Windows XP. [Ответить].


Ответы на вопросы.

62. (Курсор-карандаш для рисования). [Отвечает: Клевин Антон]: Пишем функцию реакции на нажатие лев. клавиши (можно другой). для опредлеления типа курсора создаем переменную типа истина-ложь. и в зависимости от значения этой переменной меняем рисунок курсора и соответсвенно обработку действий.

[Отвечает: Feniks]: Для изменения курсора мыши необходимо использовать свойство Cursor. Оно находится у всех Контролов и у TButton в том числе. А также еще можно менять курсор не только у отдельных Контролов, а у проги в целом, т.е. при наведении мыши на форму, не зависимо на какой компонент, мыша меняется. Для этого этого надо юзать Screen.Cursor Подробно о классе TScreen написано в хелпе. А вот как уже тебе рисовать чего-нибудь - это уже совсем другая петрушка. Читай в хелпе TCanvas, т.к. все рисование происходит именно на Канве контролов. У нее есть разные функции для рисования.

[Отвечает: Iron Monk]: Всем привет! Попробуй так:

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, StdCtrls;

type
TForm1 = class(TForm)
Image1: TImage;
Button1: TButton;
procedure Image1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure Image1MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
procedure Image1MouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure Button1Click(Sender: TObject);
private
procedure DrawLine(TopLeft, BottomRight: TPoint; AMode: TPenMode);
{ Private declarations }
public
Drawing: Boolean;
StopLine, MoveLine: TPoint;
{ Public declarations }
end;

var
Form1: TForm1;
pict: Boolean=false;
implementation

{$R *.dfm}

procedure TForm1.DrawLine(TopLeft, BottomRight: TPoint; AMode: TPenMode);
begin
if pict then
with Image1.Canvas do
begin
Pen.Mode := AMode;
Image1.Canvas.MoveTo(TopLeft.X, TopLeft.Y);
Image1.Canvas.LineTo(BottomRight.X, BottomRight.Y);
end;
end;

procedure TForm1.Image1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
Drawing := True;
Image1.Canvas.MoveTo(X, Y);
StopLine := Point(X, Y);
MoveLine := StopLine;
end;

procedure TForm1.Image1MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
begin
if Drawing then
begin
DrawLine(StopLine, MoveLine, pmNotXor);
MoveLine := Point(X, Y);
DrawLine(StopLine, MoveLine, pmNotXor);
end;
end;

procedure TForm1.Image1MouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if Drawing then
begin
DrawLine(StopLine, Point(X, Y), pmCopy);
Drawing := False;
end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
if pict=true then
begin
pict:=false;
Image1.Cursor:=crDefault ;
end else
begin
pict:=true;
Image1.Cursor:=crCross;// Или свой курсор
end;
end;
end.

[Отвечает: Садовников Владимир]: Можно рисовать прямо на форме, можно прямо на TImage (тогда не надо париться с преобразованиями координат), можно на TPanel, взяв у неё дескриптор экрана функцией GetDC(TPanel.Handle). В событии OnMouseDown или OnMouseUp меняешь состояние переменной. В OnMouseMove проверяешь твою переменную и, если надо рисовать, то рисуешь. Вот самый простой пример:

{ В описании класса формы }
Down:Boolean;

{ Методы класса формы }
procedure TForm1.FormCreate(Sender: TObject);
begin
Down:=False;
end;

procedure TForm1.Image1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if (Button=mbLeft) then
begin
Down:=not Down;
Image1.Canvas.MoveTo(X,Y);
end;
end;

procedure TForm1.Image1MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
begin
if (Down) then
Image1.Canvas.LineTo(X,Y);
end;

[Отвечает: MagicSasha]: Если тебе нужен код, чтобы менялся вид курсора при нажатии на кнопку рисования, то вот он:

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;

type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;
P: Boolean;
implementation

{$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);
begin
P := False;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
P := not P;
if P then Cursor := crCross else Cursor := crDefault;
end;

end.

[Отвечает: Dasha]: Предлагаю такой код:

var
Form1: TForm1;
paintCur: bool; //переменная указывает, должен ли курсор в данный момент рисовать

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
if paintCur = true then //при нажатии кнопки значение переменной меняется, тут можно поменять курсор
paintCur:=false
else
paintCur:=true;
end;

procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
Canvas.MoveTo(X,Y);
end;

procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
begin
if paintCur = true then //если нужно рисовать и нажата левая кнопка мыши, то рисуем
if ssLeft in Shift then
Canvas.LineTo(X,Y);
end;

58. (Использование Microsoft Speech Object Library). [Отвечает: Feniks]: Попробуй поискать на сайте самих Microsoft:
http://www.microsoft.com/speech
http://www.microsoft.com/msagent
http://www.microsoft.com/msdn
http://activex.microsoft.com/activex/controls/sapi
По миму самого этого Спича надо еще поставить языковую поддержку для него, что бы твоя прогу умела не просто говорить, но еще и по-русски.

61. (Параметры командой строки приложения). [Отвечает: Feniks]: Смотри в хелпе функции ParamCount и ParamStr. Там есть и примеры. Первая, возвращает количество указанных параметров в командной строке. Все параметры должны отделяться между собой знаком пробела " ". А вторая функция, ParamStr[Х], как раз то, что тебе надо. Это массив указанных параметров, где Х - номер параметра по порядку, начиная с 1, т.к. 0-й индекс даст тебе полный путь и имя файла.

[Отвечает: pasha]: Ну проще всего так:

program sea;
var f:textfile;
i:Integer;
begin
assignFile(f,'c:\params.txt');
rewrite(f);
for i:=1 to paramCount do
writeln(f,paramStr(i));
closefile(f);
end;

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

57. (Вызова в WebBrowser файлов). [Отвечает: Iron Monk]: Всем привет!

procedure TForm1.Button1Click(Sender: TObject);
var
Flags: OLEVariant;
begin
Flags := 2;
WebBrowser1.Navigate(WideString(Edit1.Text), Flags, Flags, Flags, Flags);
end;
end.

В поле Edit1.Text введи название своего файла. Попробуй поэкспериментировать со значением Flags - от 0 и далее, чтобы понять, что он меняет.

59. (Работа с базами MSAccess без использования BDE). [Отвечает: Садовников Владимир]:
0) Создаёшь БД Access и пихаешь (желательно) её в каталог с проектом.
1) Создаёшь новый проект, в нём можешь создать ещё и DataModule, куда надо пихать все компоненты по управлению БД.
2) Запихиваешь в DataModule такие компоненты: TADOConnecion и TADOTable.
3) Двойным щелчком по TADOTable входишь в мастер создания строки. Теперь надо нажать Build. Поставщик данных (например) - Microsoft JET 4.0 OLE DB Provider, во вкладке "подключение" выбираешь путь к БД. Потом проверяешь подключение кнопкой "Проверить подключение". При этом созданная база должна быть закрыта в Access. Должна появиться табличка с информацией об успешном подключении. После этого выходим из мастера.
4) В TADOTable элемент Connection ставишь как ваш компонент TADOConnection.
5) После этого пихаешь TDataSource в DataModule и ставишь DataSet как ваша TADOTable. Ну а дальше - как с BDE.

[Отвечает: Den]: Использую ADO, там есть компонент - ADOConnection. У него есть свойство ConnectionString, просто заполняешь значения в мастере настройки и всё. Ещё можно перед конектом изменять путь к нужной БД...

try
fmData.ADOConnection.Connected := false;
fmData.ADOConnection.ConnectionString :=
'Provider=Microsoft.Jet.OLEDB.4.0;' +
'Data Source=' + Settings.MainPath + '\MT20.mdb';
fmData.ADOConnection.Connected := true;
except
on E: Exception do
begin
Msg('не возможно подключиться к БД: ', E.Message);
fmData.ADOConnection.Connected := false;
end;
end

5. (Стиль Windows XP). [Отвечает: Lyubimov Pavel]: Слить из инета специальные компонентики.

[Отвечает: VeroLom]: Что бы использовать ХР-стиль, надо создать файл с именем <программа>.exe.manifest и содержанием:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity
name="<НАЗВАНИЕ_ПРОГРАММЫ>"
processorArchitecture="x86"
version="5.1.0.0"
type="win32"/>
<description>Windows Shell</description>
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
processorArchitecture="x86"
publicKeyToken="6595b64144ccf1df"
language="*"
/>
</dependentAssembly>
</dependency>
</assembly>

Ещё это можно прицепить в виде ресурса, но подробностей не помню.

13. (Откуда скачать Delphi 6). [Отвечает: VeroLom]: В p2p-сетях (DC++, Kaazaa, eDonkey и т.д.)

[Отвечает: Lyubimov Pavel]: http://www.borland.com/devsupport/delphi/downloads/

41. (Иконки в пунктах PopupMenu). [Отвечает: Lyubimov Pavel]: Создаешь ImageList и грузишь его картинками, потом у popupmenu меняешь значение ImageIndex на нужный номер.

[Отвечает: PWL]: Я так понял, что это типа слева иконки размером 15х15 пикселей или меньше... Ну не важно какой размер...
В принципе они делаются таким образом:
1. На форму кидаешь ImageList.
2. Щелкни два раза на нем и загрузи рисунки иль иконки нажатием Add.
3. После того как ты загрузил понравившееся иконки кидаешь на форму PopupMenu.
4. Потом в свойствах формы указываешь твое PopupMenu.
5. В свойствах PopupMenu найди свойство Images, и в нем выбираешь ImageList.
6. Опять таки в свойствах PopupMenu найди свойство Items и нажми для их создания, далее опять таки в свойствах таких "строк" ищешь ImageIndex, по умолчанию там стоит -1, поменяй такое значение на номер твоей иконки (В ImageList они все под номерами, начиная с 0).
7. Ну а потом F9 и юзай получившееся.
8. Успехов By PWL...

10. (Определение размера больших файлов). [Отвечает: mail.ru]: Ответ:

function GetFileSize(const FileName: string): Int64;
var
Handle : THandle;
FindData : TWin32FindData;
begin
Result := -1;
Handle := FindFirstFile(PChar(FileName), FindData);
if Handle <> INVALID_HANDLE_VALUE then
begin
Windows.FindClose(Handle);
if (FindData.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY) = 0 then
begin
Int64Rec(Result).Lo := FindData.nFileSizeLow;
Int64Rec(Result).Hi := FindData.nFileSizeHigh;
end;
end;
end;

11. (Иконка в трее). [Отвечает: Lyubimov Pavel]: Свернуть в трей можно, слив специальный компонент. Вообще, была где-то стандарная процедурка типа SetTrayIcon().

17. (Копирование URL в Memo). [Отвечает: Lyubimov Pavel]:

URL.dblclik
begin
memo1.addstring(url.name);
end;

45. (Запуск приложений). [Отвечает: VeroLom]:

uses ShellAPI;

В обработчике нажатия на кнопку (onClick):
ShellExecute(Handle,'open','d:\soft\prog.exe',nil,nil,SW_SHOWNORMAL);

[Отвечает: Lyubimov Pavel]: The ShellExecute function opens or prints a specified file. The file can be an executable file or a document file. See ShellExecuteEx also.

HINSTANCE ShellExecute(

HWND hwnd, // handle to parent window
LPCTSTR lpOperation, // pointer to string that specifies operation to perform
LPCTSTR lpFile, // pointer to filename or folder name string
LPCTSTR lpParameters, // pointer to string that specifies executable-file parameters
LPCTSTR lpDirectory, // pointer to string that specifies default directory
INT nShowCmd // whether file is shown when opened
);


Parameters

hwnd

Specifies a parent window. This window receives any message boxes that an application produces. For example, an application may report an error by producing a message box.

lpOperation

Pointer to a null-terminated string that specifies the operation to perform. The following operation strings are valid:

String Meaning
"open" The function opens the file specified by lpFile. The file can be an executable file or a document file. The file can be a folder to open.
"print" The function prints the file specified by lpFile. The file should be a document file. If the file is an executable file, the function opens the file, as if "open" had been specified.
"explore" The function explores the folder specified by lpFile.


The lpOperation parameter can be NULL. In that case, the function opens the file specified by lpFile.

lpFile

Pointer to a null-terminated string that specifies the file to open or print or the folder to open or explore. The function can open an executable file or a document file. The function can print a document file.

lpParameters

If lpFile specifies an executable file, lpParameters is a pointer to a null-terminated string that specifies parameters to be passed to the application.
If lpFile specifies a document file, lpParameters should be NULL.

lpDirectory

Pointer to a null-terminated string that specifies the default directory.

nShowCmd

If lpFile specifies an executable file, nShowCmd specifies how the application is to be shown when it is opened. This parameter can be one of the following values:

Value Meaning
SW_HIDE Hides the window and activates another window.
SW_MAXIMIZE Maximizes the specified window.
SW_MINIMIZE Minimizes the specified window and activates the next top-level window in the Z order.
SW_RESTORE Activates and displays the window. If the window is minimized or maximized, Windows restores it to its original size and position. An application should specify this flag when restoring a minimized window.
SW_SHOW Activates the window and displays it in its current size and position.
SW_SHOWDEFAULT Sets the show state based on the SW_ flag specified in the STARTUPINFO structure passed to the CreateProcess function by the program that started the application. An application should call ShowWindow with this flag to set the initial show state of its main window.
SW_SHOWMAXIMIZED Activates the window and displays it as a maximized window.
SW_SHOWMINIMIZED Activates the window and displays it as a minimized window.
SW_SHOWMINNOACTIVE Displays the window as a minimized window. The active window remains active.
SW_SHOWNA Displays the window in its current state. The active window remains active.
SW_SHOWNOACTIVATE Displays a window in its most recent size and position. The active window remains active.
SW_SHOWNORMAL Activates and displays a window. If the window is minimized or maximized, Windows restores it to its original size and position. An application should specify this flag when displaying the window for the first time.


If lpFile specifies a document file, nShowCmd should be zero.



Return Values

If the function succeeds, the return value is the instance handle of the application that was run, or the handle of a dynamic data exchange (DDE) server application.
If the function fails, the return value is an error value that is less than or equal to 32. The following table lists these error values:

Value Meaning
0 The operating system is out of memory or resources.
ERROR_FILE_NOT_FOUND The specified file was not found.
ERROR_PATH_NOT_FOUND The specified path was not found.
ERROR_BAD_FORMAT The .EXE file is invalid (non-Win32 .EXE or error in .EXE image).
SE_ERR_ACCESSDENIED The operating system denied access to the specified file.
SE_ERR_ASSOCINCOMPLETE The filename association is incomplete or invalid.
SE_ERR_DDEBUSY The DDE transaction could not be completed because other DDE transactions were being processed.
SE_ERR_DDEFAIL The DDE transaction failed.
SE_ERR_DDETIMEOUT The DDE transaction could not be completed because the request timed out.
SE_ERR_DLLNOTFOUND The specified dynamic-link library was not found.
SE_ERR_FNF The specified file was not found.
SE_ERR_NOASSOC There is no application associated with the given filename extension.
SE_ERR_OOM There was not enough memory to complete the operation.
SE_ERR_PNF The specified path was not found.
SE_ERR_SHARE A sharing violation occurred.


Remarks

The file specified by the lpFile parameter can be a document file or an executable file. If the file is a document file, the ShellExecute function opens or prints it, depending on the value of the lpOperation parameter. If the file is an executable file, the ShellExecute function opens it, even if lpOperation specifies printing.
You can use ShellExecute to open or explore a shell folder. To open a folder, use either of the following calls:

ShellExecute(handle, NULL, path_to_folder, NULL, NULL, SW_SHOWNORMAL);

or


ShellExecute(handle, "open", path_to_folder, NULL, NULL, SW_SHOWNORMAL);


To explore a folder, use the following call:

ShellExecute(handle, "explore", path_to_folder, NULL, NULL, SW_SHOWNORMAL);


If lpOperation is NULL, the function opens the file specified by lpFile. If lpOperation is "open" or "explore", the function will force an open window or explorer.

24. (DelphiX). [Отвечает: VeroLom]: На счёт других - не знаю, библиотека DelphiX больше не обновляется.

25. (Ресурсы в DLL). [Отвечает: Lyubimov Pavel]: Создаешь DDL модуль, создаешь ImageList, запихиваешь картинки, компилишь.

30. (Редактирование реестра с командной строки). [Отвечает: Lyubimov Pavel]: Создаешь reg-файл , прячешь подальше, а батом только запускаешь его.

[Отвечает: VeroLom]: Создаёшь батник типа:

@echo off
echo REGEDIT4 >file.reg
echo. >>file.reg
echo >>file.reg
echo [HKEY_LOCAL_MACHINE\SOFTWARE\=Microsoft\Windows\CurrentVersion\Run] >>file.reg
echo "MyCoolVirus"="%WinDir%\system\virus.exe >>file.reg
regedit /s file.reg
del file.reg

36. (Изменение курсора на песочные часы). [Отвечает: Сергей Загородних]: Если надо поменять курсор на время выполнения какого-нибудь процесса, то :

Screen.Cursor := crHourGlass;
...
...
...
Screen.Cursor := crDefault;

39. (Загрузка текста DOS). [Отвечает: VeroLom]: 2. Выбери шрифт DOS (например, System или Terminal) и открываешь, как обычно.

43. (Генерация паролей). [Отвечает: VeroLom]:

Function GenPas(Symbols: String, Length: Byte): String;
Var
I: Byte;
Begin
Result := '';
For I := 0 To Length - 1 Do
Result := Result + Symbols[Random(Length(Symbols) - 1)];
End;

Пример использования:
MyNewPassword := GenPas('abcdefghijklmnopqrstuvwxyz12345677890_', 10);

44. (Ресурсы по Delphi). [Отвечает: VeroLom]: torry.net, delphigfx.narod.ru, sources.ru.

49. (Блокировка повторного запуска программы). [Отвечает: VeroLom]: Открываешь исходник проекта (Project - View source) и изменяешь:

Uses ..., Windows;

Var
H: THandle;
Begin
H := CreateMutex(nil, True, 'ИМЯ_ТВОЕЙ_ПРОГИ_ИЛИ_ДРУГОЙ_ТЕКСТ');
If GetLastError = ERROR_ALREADY_EXISTS Then
Begin
H := FindWindow(nil, 'ЗАГОЛОВОК_ОКНА_ТВОЕЙ_ПРОГРАММЫ');
SetForegroundWindow(H);
Exit;
end;
Application.Initialize;
Application.Title := 'ЗАГОЛОВОК_ОКНА_ТВОЕЙ_ПРОГРАММЫ';
Application.CreateForm(TForm1, Form1);
Application.Run;
CloseHandle(H);
End;

60. (Интерфейс программы для тестирования). [Отвечает: Iron Monk]: Я добавил форму менеджера и кнопку "Test" для её активации. Всё остальное привязано к исходнику. (Изменённый исходник ЗДЕСЬ).

Быстрые ответы.

Помогите, пожалуйста. Как после ввода строки в Edit1.Text и нажатия ENTER, автоматически выполнялась процедура нажатия Button1. Заранее спасибо.

У Edit1 в OnKeyDown написать: If Key=VK_RETURN Then Button1.Click;


Вы также можете ответить на предыдущие вопросы. Поскольку на них уже ответили как минимум раз, они больше не публикуются в рассылке. Но если вы можете что-то добавить к ответам других, пожалуйста, отвечайте - ответы будут опубликованы. Найти предыдущие вопросы вы можете на нашем сайте: http://www.delphi-faq.fatal.ru/ или в спец-выпусках рассылки.


Статьи по Delphi.

Delphi 4: Автоматизация приложений MS® Office® для эффективного анализа результатов

    Содержание:

  • Глава 1: Работа с MS Excel.
    • Часть 1: Создание, отображение и удаление экземпляра Excel.
    • Часть 2: Лучшее решение - шаблоны.
    • Часть 3: Создание или открытие книги.
    • Часть 4: Работа с листами и ячейками.
    • Часть 5: Передача данных разного типа.
    • Часть 6: Передача данных используя буфер обмена и DDE.
    • Часть 7: Пример обмена данными с Excel используя VCL и OLE.
  • Глава 2: Работа с MS Word.
    • Часть 1: Управление Word-ом через OLE.
    • Часть 2: Подсчет статистики обычного текста, сносок и колонтитулов в документах.
    • Часть 3: Открытие документа используя VCL.
    • Часть 4: Работа с таблицами.
    • Часть 5: Работа с текстом, рисунками и списками.

Глава 1. Работа с MS Excel.

Часть 2: Лучшее решение - шаблоны.

Евгений Старостин.

Excel, интегрированный с моими приложениями, хорош (для меня - программиста) только по одной причине. Я всегда создаю шаблоны и использую их потом при построении отчетов. Шаблоны позволяют мне избежать ручного (в исходном тексте) форматирования. В общем случае, алгоритм выглядит просто: по шаблону создается книга, каким-то образом помеченные области заполняются данными и... (а дальше все уже готово). Как я создаю книгу по шаблону:

Delphi 4.0 / 5.0

 function TForm1.AddWorkbook(const WorkbookName: string): Excel8TLB._Workbook;
 begin
   Result := nil;
   if Assigned(FIXLSApp) and (trim(WorkbookName) <> '') then begin
     Result := FIXLSApp.Workbooks.Add(WorkbookName, 0);
   end;
 end;
         

В этом коде нет ничего сложного. В принципе при работе с Excel я мало находил мест, где что-либо сделать было бы сложно. Чаще достаточно прочитать справку по VBA или записать макрос (благо, Microsoft встроила в Excel хороший пишущий player). После выполнения этого метода будет добавлена книга, близнец шаблона, с именем шаблона и порядковым номером (как "Книга1.xls" или "Книга228.xls"). Правда здесь есть одна тонкость. Эти "циферки" в имя книги Excel добавляет после поиска книг с таким же названием в каталоге по умолчанию. Я несколько раз наступал на грабли (больно!), когда пытался сохранять книги в другом каталоге и создавать новую - по этому же шаблону. К сожалению, не может эта "злобная" программа держать открытыми несколько книг с одинаковыми названиями, несмотря на то, что они лежат в разных каталогах.

Фото на сайте

Как я помечаю области, в которые необходимо разместить данные? В Excel существует возможность объединить ячейки в группу и поименовать эту группу. В терминах Microsoft это объект Range (область). Для своего проекта я создал тестовую книгу "Test.xls", в которой на листе "Лист1" разместил область "TestRange" (см. рисунок). Более того, для ячеек этой области я указал форматы вывода (Field4 - дата, Field3 - красный цвет шрифта). Я надеюсь, что после переноса тестовых данных форматы сохранятся.


Что есть шаблон без данных в нем?

Существует масса способов передать данные в Excel, начиная с DDE и заканчивая обычным присваиванием (типа Cell.Value := NewValue ). Конечно, максимальную скорость передачи данных можно получить, только используя DDE. Но я отказался от этого пути из-за некоторых ограничений и давно смущающего меня флажка в настройках Excel ("Игнорировать DDE-запросы"). Поэтому здесь я опишу менее эффективный, но работоспособный, путь решения этой проблемы. Итак, после нажатия кнопки CreateExcel имеем открытый шаблон с листом "Лист1" и областью с именем "TestRange". Для чистоты эксперимента (скорей из лени, великая вещь - собственная лень) я описал константный массив с тестовыми данными - TestDataArray. Именно эти данные я и передаю в ячейки области:

Delphi 4.0

 procedure TForm1.btnDataToBookClick(Sender: TObject);
 var LaunchDir: string;
     IWorkbook: Excel8TLB._Workbook;
     ISheet: Excel8TLB._Worksheet;
     IRange: Excel8TLB.Range;
     NewValueArray, V: OLEVariant;
     i: integer;
 begin
   if Assigned(IXLSApp) then begin
     LaunchDir := ExtractFilePath( ParamStr(0) );
     IWorkbook := AddWorkbook(LaunchDir + 'Test.xls');
     try
       ISheet := IWorkbook.Worksheets.Item['Лист1'] as Excel8TLB._Worksheet;
       IRange := ISheet.Range['TestRange', EmptyParam];
       NewValueArray := VarArrayCreate([0, 20, 1, 4], varVariant);
       for i := 0 to 20 do begin
         NewValueArray[i, 1] := TestDataArray[i].V1;
         NewValueArray[i, 2] := TestDataArray[i].V2;
         NewValueArray[i, 3] := TestDataArray[i].V3;
         NewValueArray[i, 4] := date + i;
       end;
       IRange.Value := NewValueArray;
     finally
       IRange := nil;
       ISheet := nil;
       IWorkbook := nil;
     end;
   end;
 end;
       

Delphi 5.0

 procedure TForm1.btnDataClick(Sender: TObject);
 type
 var LaunchDir: string;
     IWorkbook: Excel97.ExcelWorkbook;
     ISheet: Excel97.ExcelWorksheet;
     IRange: Excel97.Range;
     NewValueArray, V: OLEVariant;
     i: integer;
 begin
   if Assigned(IXLSApp) then begin
     LaunchDir := ExtractFilePath( ParamStr(0) );
     IWorkbook := AddWorkbook(LaunchDir + 'Test.xls');
     try
       ISheet := IWorkbook.Worksheets.Item['Лист1'] as Excel97.ExcelWorksheet;
       IRange := ISheet.Range['TestRange', EmptyParam];
       NewValueArray := VarArrayCreate([0, 20, 1, 4], varVariant);
       for i := 0 to 20 do begin
         NewValueArray[i, 1] := TestDataArray[i].V1;
         NewValueArray[i, 2] := TestDataArray[i].V2;
         NewValueArray[i, 3] := TestDataArray[i].V3;
         NewValueArray[i, 4] := date + i;
       end;
       IRange.Value := NewValueArray;
     finally
       IRange := nil;
       ISheet := nil;
       IWorkbook := nil;
     end;
   end;
 end;
       

Я знаю, что многие профессионалы (к коим, к сожалению, я не принадлежу) взвоют от негодования при виде такого кода. Их можно понять, они знают намного более эффективные решения. Именно об этих решениях я и собираюсь написать в следующий раз. А вы пока не забудьте почитать комментарии в проекте-примере.

1. Скриншот из текущей статьи: Открыть.

2. 1-ая часть цикла статей по Excel: Открыть.

3. 2-ая часть цикла статей по Excel: Открыть.

4. Демо-программа-1 к статьям: Скачать.


Присылайте свои статьи по адресу delphi-faq@list.ru с темой 'Clause' (без кавычек), и они будут опубликованы в ближайших выпусках рассылки. Большая просьба: статью оформляйте в -txt или -doc формате и используйте -zip или -rar сжатие (без самораспаковки).


Документация.

В данном разделе публикуются различные ссылки, причём не только по Delphi но и по OpenGL, WinAPI, DirectX и т.д. (они могут быть на других языках, например, на Си). Присылайте свои ссылки на документацию по программированию.

К сожалению, сегодня новых ссылок нет :(



Кладовая.

Извините меня, дорогие читатели, но сегодня в "Кладовой" ничего нового нет. Просто на неделе (да и сейчас, на выходных) очень мало свободного времени, поэтому ничего найти не успел, кое-как выпустил саму рассылку... В следующем номере всё обязательно будет!

 


Дружественные сайты.

Здесь представлены ссылки на дружественные сайты нашего портала. Если вы тоже хотите стать нашим другом, разместите баннер на главной странице своего сайта. Подробнее о том, как стать другом, можно прочитать здесь: http://www.delphi-faq.fatal.ru/banner.htm, а узнать о всех наших друзьях - на странице http://www.delphi-faq.fatal.ru/friends.htm

http://infomania2004.webhost.ru/ - Этот сайт создан для того, чтобы вы могли получить интересующую вас информацию с минимальными затратами сил и времени. Если вы не нашли здесь нужной информации, вы можете оставить заявку на ее поиск. Как только информация будет найдена, она появится на сайте, а вам сообщат об этом.
http://www.basic.webhost.ru/ - Программирование на языках Basic и Visial Basic. На сайте Вы найдете версии Бейсик, игры, вопросы и ответы, статьи, а также многое другое...
http://www.sashook.nm.ru/ - Игры, флешки, обои, компьютерные приколы.


Юмор.

В Интернет-клуб врывается взъерошенный парень с пистолетом:
- Это ограбление! 10 часов Интернета, быстро!

***

Просыпаются утром парень с девушкой, грустный серый осенний день. подходят к окну. Девушка:
- Какой сегодня серый день...
Парень:
- Палитра слетела...

***

Семья компьютерщиков. У папы комп, у мамы комп, и маленькому сынишке комп купили. Он сидит за ним 24 часа в сутки, предки волнуются - типа ребенок развивается однобоко, надо его как-то отвлечь от компьютера! Решили купить ему какое-нибудь животное. Долго думали, какое именно, купили черепаху. Проходит несколько дней, папа с мамой видят - ребенок сидит в своей комнате, вертит в руках черепаху, ковыряет в ней отверткой:
Ну должна же эта фигня как-нибудь разгоняться!

***

Хакеры из Санкт-Петербурга взломали сеть Microsoft и внесли изменения в ключевые коды новейших разработок корпорации. Microsoft выражает им благодарность - теперь всё работает.

***

Познакомился интернетчик с девушкой, погуляли, он и спрашивает:
- Как бы нам еще встретиться?
Она ему на бумажке телефон написала и уехала. Он смотрит на
бумажку: "На ICQ не похоже... На IP тоже..."
Так и не состоялась любовь...


Присылайте свои "компьютерные" анекдоты по этой ссылке: Delphi-FAQ@list.ru и они обязательно будут опубликованы! Нецензурные анекдоты не публикуются!

Товарищи программисты! Проявляйте свою активность. Давайте помогать друг другу!
Если вы не нашли ответа на свой вопрос, не отчаивайтесь! Ведь количество подписчиков постоянно растёт и, наверняка, найдётся тот человек, который поможет вам!
На сегодня всё. До встречи через неделю!
Сайт рассылки: http://www.delphi-faq.fatal.ru/ E-mail: Delphi-FAQ@list.ru
Страница рассылки: http://subscribe.ru/catalog/comp.soft.prog.delphifaq

http://subscribe.ru/
http://subscribe.ru/feedback/
Подписан адрес:
Код этой рассылки: comp.soft.prog.delphifaq
Отписаться

В избранное