Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Общие вопросы > Собственными руками записать CD/DVD


Автор: Ner-zul 24.1.2007, 12:44

 Добрый день,

У меня есть клиентское приложение, которое работает с базами данных под управлением IB7.0. В процессе работы у меня формируется перечень ссылок на файлы, он обрабатывается определенным образом. После окончания обрабокти все файлы, с сылками которых, я работал группируются в одну папочку на локальном диске. Далее я запускал NeroBorning и записывал эту папку с файлами на CD-носитель. Я хочу чтобы запись на носитель осуществлялась в рамках моего приложения. Какими средствами мне лучше реализовать этот механизм? Я слышал есть вариант использовать COM-объекты, а есть вариант использовать API-функции, как самого виндовса так и пишушщих программ, в т.ч. и Nero. Но второй вариант ограничивает переносимость на другие машины, так как там должна быть установлена соответствующая программа, чтобы использовать соответсвующие функуции.
Если я прав, тогда выбор стоит остановить на COM-объектах, Так?
 Тогда какие конкретно COM-объекы мне надо использовать и каким образом?

 Буду благодарен если вы мне скините примерчик или дадите на него ссылку, а также на литературу конкретно отвечающую на мой вопрос.

Автор: _hunter 24.1.2007, 12:53
у неро есть набор API. оно есть и у окон -- IMAPI. а что использовать... -- что удобнее, то и используй.
статьи/примеры поищи на форуме -- вопрос не раз поднимался...

Автор: Snowy 24.1.2007, 13:03
Выбирай компонент на свой вкус smile
http://www.torry.net/pages.php?id=249

Автор: Ner-zul 24.1.2007, 14:21
ммм, слегка конкретизирую вопрос!

Мне необходиом почитать и посмотреть примеры использования COM в Delphi.
Желательно на тематику моей задачи.

Автор: Snowy 24.1.2007, 14:37
Ну так в чём проблема?
Вот компонент: http://www.torry.net/vcl/filedrv/cd/CDBurner.zip
Там всего один pas файл. Открывай смотри - это готовый действующий пример работы с интерфейсом службы записи компакт-дисков.
Дока ICDBurn в MSDN: http://msdn2.microsoft.com/en-us/library/ms646705.aspx

Автор: Ner-zul 24.1.2007, 16:52
спасибsmile

Автор: Ner-zul 24.1.2007, 18:19

   Еще вопос..)
  Вот, сижу , все читаю, все разбираю, все понимаю, но:

Я скачал паскалевский файл с описанием класса TCDBurner. 
Вроде бы даже установил его как компонент в свой Дельфи.

Далее я открыл хелп файл, лежавший с ним и там нашел что то типа примера, по использованию этого класса:

Код

unit Unit1;

interface

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

type
TForm1 = class(TForm)
Button1: TButton;


CDBurner1: TCDBurner;  <-- Жутко Ругается на эту строку!!!,

 говорит, что Field Form1.CDBurner1 does not have a corresponding component !!!



function CopyToCDBurnerArea(FromDir,ToDir : string ) : boolean;
procedure Button1Click(Sender: TObject);
end;

var
Form1: TForm1;
implementation

{$R *.DFM}
// Perform Folder copy
function TForm1.CopyToCDBurnerArea(FromDir,ToDir : string ) : boolean;
var
    lpFileOpStruct : TSHFileOpStruct;
begin
    lpFileOpStruct.wFunc := FO_COPY;
    lpFileOpStruct.pFrom := Pchar(FromDir+#0);
    lpFileOpStruct.pTo := Pchar(ToDir+#0);
    lpFileOpStruct.fFlags := FOF_NOCONFIRMATION or FOF_NOCONFIRMMKDIR or FOF_SILENT;
    Result := not Boolean(SHFileOperation(lpFileOpStruct));
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
// Copy a folder tree to the burn area
if not CopyToCDBurnerArea('C:\FolderToAdd', cdBurner1.BurnArea ) then ShowMessage('Cannot find C:\FolderToAdd');

// Start burning
CDBurner1.StartBurn;
end;

end.


Ошибка показана в коде примера стрелочкой=)

Я чето туплю уже час и не понимаю чего ей не хватает....
Я пробовал и просто подцеплять файл с описанием класса к проекту ...но всё не то.

Такую ошибку обычно выдаёт, если собственно ручно прописать в коде например определенние Buttona , а на форме его не поставить. Но что здесь то ставить... и куда?


Автор: Coder 25.1.2007, 02:37
пропиши отдельно, а не в классе формы.
Код

var
  CDBurner1: TCDBurner;

Автор: Ner-zul 25.1.2007, 10:48

Спасибо, эта проблема решена!

Автор: umen 25.1.2007, 12:44
Можно и в классе формы, просто надо на форму бросить компонент CDBurner

Автор: Ner-zul 25.1.2007, 13:24
  Товарищи, объсните пожалуйста что сей код значит:

Код

constructor TCDBurner.Create(AOwner: TComponent);
var bHasDrive: Bool;
  t: PWideChar;
  s: array[0..3] of widechar;

  pidl: pItemIDList;
  nameBuf: Array [0..MAX_PATH] of Char;
  alloc: IMalloc;

Begin
  if Not(AOwner is TForm) then Raise Exception.CreateFmt('Error: Component must be owned by TForm',[]);
  inherited Create(AOwner);
  fIsBurning:=FALSE;
  if csDesigning in ComponentState then Exit;

  fFiles:=TStringList.Create;
  bNagged:=FALSE;
  fFilesToBurnKB:=0;
  FInitialized:=FALSE;

  // Get the path to the burn area from the system
  fBurnArea := '';
    if SUCCEEDED(SHGetSpecialFolderLocation(0, CSIDL_CDBURN_AREA, pidl)) then
    begin
        If pidl <> Nil Then
      Begin
             If SHGetPathFromIDList(pidl, namebuf) Then
        Begin
                 fBurnArea := StrPas(namebuf);
          If fBurnArea[Length(fBurnArea)]<>'\' then fBurnArea:=fBurnArea+'\';
        End;
        If Succeeded(SHGetMalloc(alloc)) Then alloc.Free(pidl);
      End;
    End;
   try
    iiUnknown:=CreateCOMObject(CLSID_CDBurn);
    iiCDBurn:=iiUnknown as ICDBurn;
  except
    on E: Exception do
      Begin
        FLastError:='No XP Compatible CDR API present: '+E.Message;
        Exit;
      End;
  end;

  iiCDBurn.HasRecordableDrive(bHasDrive);
  if NOT bHasDrive then
    FLastError:='No CD Burner was found'
  else
    Begin
      t:=@s;
      if iiCDBurn.GetRecorderDriveLetter(t^,4) = S_OK then
      Begin
        FBurnDrive:=t;
        FInitialized:=TRUE;
      End
      else
        FLastError:='CD Recording not enabled on Burn drive.'
    End;
End;


 
 1) Вот такой еще вопрос: Раз это конструктор, нуноли мне его вызывать в теле программы  при использовании/создании объекта данного класса??? Автор в своем примере не использует его....Правда он в этом примере еще пару описок сделал.. то есть видно, что сам он его не тестировал.

 2) Меня здесь интересует свойство fBurnArea  класса TCDBurner. Как я понял это адрес того места где будет лежать буферные данные записываемые на CD. Динамически это свойство переопределить вроде как нельзя, так как оно только для чтения. У меня на строчке использующей это property вылетает ошибка ... типа Access Violation чтоли... вот. Объясните плиз как и откуда в него что заполняется.. и откуда появляются проблемы. Если что непонятно в моём вопросе, я уточню.)


P.S. Snowy, Вы уверены, что это рабочий пример??? http://www.torry.net/vcl/filedrv/cd/CDBurner.zip


Автор: Snowy 25.1.2007, 13:56
Цитата(Ner-zul @  25.1.2007,  13:24 Найти цитируемый пост)
Меня здесь интересует свойство fBurnArea  класса TCDBurner. Как я понял это адрес того места где будет лежать буферные данные записываемые на CD. Динамически это свойство переопределить вроде как нельзя, так как оно только для чтения.
Да. Так и есть. Переопределить его нельзя.
Эта настройка не может задаваться - она берётся из настроек системы.
При очень большом желании можно и переназначить в реестре.
Но для этого нужны админские права. И делать это крайне не рекомендовано.

Автор: Ner-zul 25.1.2007, 14:08
Хорошо, тогда у меня рождаются следующие вопросы:

1) Насколькоя я понимаю из объяснений автора, его пример вызовет мастер виндусовый по записи CD-дисков, а параметры задаю я и вызов этот тоже инициализирую я. Тогда я понимаю, что мне и не надо пытаться изменить дирректорию для буфферизованных данных, иначе мастер не сможет нормально все записать на диск, так? Если так, то что же мне делать??? Если его собственный пример выдает ошибки!!! ??? 
 
2)Может быть я както не правильно встроил его pas-овский файл в свой Delphi??? 

3)Он еще что-то говрит про то, что Мне обязательно надо работать с формой:
"constructor Create(AOwner: TComponent); -  Pass a TForm in as the owner.  If you need a non-visual version, register, and we'll talk."
И реально в описании конструктора, которое я привел есть строка:
Код


if Not(AOwner is TForm) then Raise Exception.CreateFmt('Error: Component must be owned by TForm',[]);
  inherited Create(AOwner);

 

А я как мне посоветовали, перенес объявление объекта TCDBurner за пределы формы:

Код

type
  TForm1 = class(TForm)
   
    function CopyToCDBurnerArea(FromDir,ToDir : string ) : boolean;

     private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  CDBurner1: TCDBurner;



Вот, может быть здесь Что не так???? Или это не то?

4)Вот такой еще вопрос: Раз это конструктор, нуноли мне его вызывать в теле программы  при использовании/создании объекта данного класса??? Автор в своем примере не использует его....Правда он в этом примере еще пару описок сделал.. то есть видно, что сам он его не тестировал.(это к предыдущему моему большому посту.)

Автор: Ner-zul 25.1.2007, 14:33
И еще вопрос :

5) Я скачал 3 файла:

Cdburner.pas - описание класса. Его я и встроил как компонент в Дельфи.
Cdburner.html - хэлп маленький с описанием части свойств класса и примером автора по его использованию, который впринципе отказывается работать!!!
Cdburner.dcr - вот что это за файл и че с ним делать я не понял... Может я чего упустил????????

Автор: Snowy 25.1.2007, 14:44
Цитата(Ner-zul @  25.1.2007,  14:08 Найти цитируемый пост)
Если так, то что же мне делать??? Если его собственный пример выдает ошибки!!! ??? 
Какие ошибки?

Цитата(Ner-zul @  25.1.2007,  14:08 Найти цитируемый пост)
Может быть я както не правильно встроил его pas-овский файл в свой Delphi??? 
Оптимально - положить его в папку Lib

Цитата(Ner-zul @  25.1.2007,  14:08 Найти цитируемый пост)
Он еще что-то говрит про то, что Мне обязательно надо работать с формой:
Да. Нужно установить его в систему и бросить на форму.

Цитата(Ner-zul @  25.1.2007,  14:08 Найти цитируемый пост)
А я как мне посоветовали, перенес объявление объекта TCDBurner за пределы формы:
Лучше просто бросить на форму.
Так будет больше заморочек.

Цитата(Ner-zul @  25.1.2007,  14:08 Найти цитируемый пост)
Вот такой еще вопрос: Раз это конструктор, нуноли мне его вызывать в теле программы  при использовании/создании объекта данного класса???
Если он брошен на форму, то конструктор будет вызван автоматически.
Если нет, то нужно вызывать вручную и в качестве параметра передавать форму.

Добавлено @ 14:45 
Цитата(Ner-zul @  25.1.2007,  14:33 Найти цитируемый пост)
Cdburner.dcr - вот что это за файл и че с ним делать я не понял... Может я чего упустил????????
Его тоже брось в Lib.
Это иконка для панели компонент.

Автор: Ner-zul 25.1.2007, 14:56
оооооо !!!!

Многое проясняется!

1) Ошибки все стандартные  Access Violation... по такому то адресу в экзешнике. Возникают чуть ли не на каждой строке...использования параметра класса.

2) С установкой компонента походу напряги: Я его и файл иконку переписал в lib, все как полагается, потом я открыл дельфи, выбрал Component , далее Install Component, далее я поставил C:\Program Files\Borland\Delphi6\Lib\CDBurner.pas 
в уже существующий компонент c:\program files\borland\delphi6\Lib\dclusr.dpk

а наверно надо было в новый, так??? Или как?? Если да то в какой именно...

Далее у меня все поставилось,  и я подумал, что все ок.

А иконка  у меня не появилась вообще на панели компонент, я там все пролистал, но ее не нашел. ЕЕ тоже как то доставлять надо??? И где именно она должна появиться?

То есть понятно , что мне нужно его установить и бросить на форму... вот с этим то я и не справился, не подскажите как мне это сделать по новой? или доделать?

Добавлено @ 15:04 




!!! Спасибо!!! Я нашел объект в на панеле в закладке Systems.
Ошибки пропали!

Автор: Ner-zul 25.1.2007, 15:21

Так, ситуация, такая, все отлично работает. Я доволен. Работает с ипользованием стандартного мастера виндовса.
  А допустим я хочу сделать так , чтобы этого окошка не было видно. Могу ли я его как нибудь сделать Visible:=False. А также отлавить его первый раз и нажать на нем кнопку Next, потом еще раз нажать Next, далее он проведет запись, и потом отловить это окошко в третий раз и нажать кнопку Finish. Тем самым я сделаю вид для пользователя , что никакого мастера собсна и не загружалось.. а запись прошла в фоне сама собой. Подскажите пожалуйста, как это можно реализовать. И есть ли в этом вообще смысл?
Особенно меня интересует механизм отлавливания окна и нажатия на нем кнопки.

Автор: Snowy 25.1.2007, 15:31
Там в доке написано.
Нужно самому ловить это окошко, отправлять комманды нажатия клавиш.
Но это уже другой вопрос.
Покопайся в FAQ. http://vingrad.ru/DELPHI-DLP-000797
Скачай  http://kickme.to/inqsoft, http://kickme.to/inqsoft
сли не поможет - создай новую тему в разделе WinAPI

Автор: Ner-zul 25.1.2007, 15:35
ок, спасибо еще раз!=)

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)