Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Сохранение/чтение DEVMODE [D7, WinXP]


Циркуль ©   (2008-04-22 18:34:00) 

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


unit Unit1;

interface

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

type
 TForm1 = class(TForm)
   btnSaveDevMode: TButton;
   edPrinterName: TEdit;
   btnGetDevMode: TButton;
   procedure btnSaveDevModeClick(Sender: TObject);
   procedure btnGetDevModeClick(Sender: TObject);
 private
   { Private declarations }
 public
   { Public declarations }
 end;

var
 Form1: TForm1;

implementation

{$R *.dfm}

uses
 winspool;

procedure TForm1.btnSaveDevModeClick(Sender: TObject);
var
 StubDevMode: TDeviceMode;
 DevMode: PDevMode;
 hPrinter: THandle;
 dmSize: Cardinal;
 Stream: TFileStream;
begin
 if OpenPrinter(PChar(edPrinterName.Text), hPrinter, nil) then
 begin
   try
     dmSize := DocumentProperties(Handle, hPrinter, PChar(edPrinterName.Text), StubDevMode, StubDevMode, 0);
     GetMem(DevMode, dmSize);
     try
       case DocumentProperties(Handle, hPrinter, PChar(edPrinterName.Text), DevMode^, StubDevMode,
                               DM_OUT_BUFFER or DM_IN_PROMPT) of
         IDOK:
           begin
             Stream := TFileStream.Create('C:\11111.ini', fmCreate);
             try
               Stream.Write(DevMode, dmSize);
             finally
               Stream.Free;
             end;
           end;
         IDCANCEL:
           Exit;
         else
           ShowMessage('Ошибка при получении свойств принтера');
       end;
     finally
       FreeMem(DevMode);
     end;
   finally
     ClosePrinter(hPrinter);
   end;
 end
 else
   ShowMessageFmt('Не удалось открыть принтер "%s"', [edPrinterName.Text]);
end;

procedure TForm1.btnGetDevModeClick(Sender: TObject);
var
 StubDevMode: TDeviceMode;
 DevMode: PDevMode;
 hPrinter: THandle;
 dmSize: Cardinal;
 dmFileSize: Integer;
 Stream: TFileStream;
begin
 if OpenPrinter(PChar(edPrinterName.Text), hPrinter, nil) then
   try
     dmSize := DocumentProperties(Handle, hPrinter, PChar(edPrinterName.Text), StubDevMode, StubDevMode, 0);
     GetMem(DevMode, dmSize);
     try
       Stream := TFileStream.Create('C:\11111.ini', fmOpenRead);
       try
         if dmSize = Stream.Size then
         begin
           Stream.Seek(0, soFromBeginning);
           Stream.ReadBuffer(DevMode, dmSize);
           case DocumentProperties(Handle, hPrinter, PChar(edPrinterName.Text), DevMode^, DevMode^,
                              DM_IN_BUFFER or DM_OUT_BUFFER or DM_IN_PROMPT) of
             IDOK: Caption := 'OK';
             IDCANCEL: Caption := 'Cancel'
             else
               Caption := 'Err'
           end;
         end
         else
           ShowMessage('Ошибка: отличаются размеры DEVMODE выбранного принтера и полученные из файла');
       finally
         Stream.Free;
       end;
     finally
       FreeMem(DevMode);
     end;
   finally
     ClosePrinter(hPrinter);
   end
 else
   ShowMessageFmt('Не удалось открыть принтер "%s"', [edPrinterName.Text]);
end;

end.


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


Циркуль   (2008-04-22 23:30:00) [1]

А, ну да... Ну все равно "везение" :)

Еще раз спасибо


Игорь Шевченко   (2008-04-22 22:19:00) [2]

Циркуль   (22.04.08 21:41) [3]

Нет, он не выделяется. В указатель читается его значение из файла, а возможно, память к тому времени еще не успела перезаписаться.


Циркуль   (2008-04-22 21:41:00) [3]

блин, неужели из-за того, что при GetMem(DevMode, dmSize) во втором случае просто выделяется тотже самый кусок памяти, который освободился после вызова первой процедуры?
жесть, сам бы ни за что не допер :)


Циркуль   (2008-04-22 21:37:00) [4]

ээээ... спасибо, конечно :)
а как это объясняет нормальную работу в случае когда жмем вторую кнопку, не закрывая приложение?
devmode тогда должен был бы заполняться мусором из файла, который туда попал при сохранении...


Игорь Шевченко   (2008-04-22 20:31:00) [5]

Я конечно извиняюсь, но TStream.ReadBuffer объявлен как
ReadBuffer(var Buffer; Count: Longint);

а Write как function Write(const Buffer; Count: Longint): Longint;

То есть, при Write неплохо бы говорить Write (DevMode^, ...)
а при ReadBuffer, соответственн, ReadBuffer (DevMode^, ...)
В твоем случае ты пишешь указатель и мусор в стеке за ним, а при чтении затираешь память


Наверх

Титульная страница Поиск, карта сайта Написать письмо