-
Собсно, стоит задача один раз задав настройки печати для принтера, их потом использовать. Для этого, видимо, надо как-то уметь хранить 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
public
end;
var
Form1: TForm1;
implementation
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 прочитается из файла, но в диалоге все равно будут значения по умолчанию. Причем в этом случае при закрытии диалога само по себе закрывается и приложение, без каких-либо ошибок.
-
Я конечно извиняюсь, но TStream.ReadBuffer объявлен как ReadBuffer(var Buffer; Count: Longint);
а Write как function Write(const Buffer; Count: Longint): Longint;
То есть, при Write неплохо бы говорить Write (DevMode^, ...) а при ReadBuffer, соответственн, ReadBuffer (DevMode^, ...) В твоем случае ты пишешь указатель и мусор в стеке за ним, а при чтении затираешь память
-
ээээ... спасибо, конечно :) а как это объясняет нормальную работу в случае когда жмем вторую кнопку, не закрывая приложение? devmode тогда должен был бы заполняться мусором из файла, который туда попал при сохранении...
-
блин, неужели из-за того, что при GetMem(DevMode, dmSize) во втором случае просто выделяется тотже самый кусок памяти, который освободился после вызова первой процедуры? жесть, сам бы ни за что не допер :)
-
Циркуль (22.04.08 21:41) [3]
Нет, он не выделяется. В указатель читается его значение из файла, а возможно, память к тому времени еще не успела перезаписаться.
-
А, ну да... Ну все равно "везение" :)
Еще раз спасибо
|