Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2009.05.03;
Скачать: CL | DM;

Вниз

Сохранение/чтение DEVMODE   Найти похожие ветки 

 
Циркуль   (2008-04-22 18:34) [0]

Собсно, стоит задача один раз задав настройки печати для принтера, их потом использовать. Для этого, видимо, надо как-то уметь хранить 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 20:31) [1]

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

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

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


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

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


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

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


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

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

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


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

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

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



Страницы: 1 вся ветка

Текущий архив: 2009.05.03;
Скачать: CL | DM;

Наверх




Память: 0.49 MB
Время: 0.018 c
15-1235882735
KilkennyCat
2009-03-01 07:45
2009.05.03
Чтой-то было тут, пока я спал ? О_0


2-1237207156
madmech
2009-03-16 15:39
2009.05.03
Как рисовать на канве BitBtn?


4-1209066995
Тыщ
2008-04-24 23:56
2009.05.03
ProcessID и иконка родительской консольной программы


6-1202811616
Doomer
2008-02-12 13:20
2009.05.03
NetBios


2-1237538453
igorntk
2009-03-20 11:40
2009.05.03
Уникальные поля в DBase