![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Сохранение/чтение 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^, ...)
В твоем случае ты пишешь указатель и мусор в стеке за ним, а при чтении затираешь память