我正在尝试更改列出打印机索引的组合框的on change事件中的默认打印机。我使用“打印机”来获取打印机索引,但实际打印是使用专有打印代码完成的,该代码允许直接进行PDF打印和更简单的页面布局。我正在尝试使用以下代码更改默认打印机,然后我的打印代码将打印到该打印机。但是,当执行此代码行时,程序没有响应,没有任何错误或程序没有响应消息:
SendMessage( HWND_BROADCAST, WM_WININICHANGE, 0,LongInt(cs1));
这是完整的功能。
function TMainFrm.SetDefaultPrinter(const PrinterName: string): boolean;
// Printername is bv: '\\MYPRINTER\HP5-k'
var
s2 : string;
dum1 : Pchar;
xx, qq : integer;
const
cs1 : pchar = 'Windows';
cs2 : pchar = 'Device';
cs3 : pchar = 'Devices';
cs4 : pchar = #0;
begin
xx := 254;
GetMem( dum1, xx);
Result := False;
try
qq := GetProfileString( cs3, pchar( PrinterName ), #0, dum1, xx);
if (qq > 0) and (trim( strpas( dum1 )) <> '') then
begin
s2 := PrinterName + ',' + strpas( dum1 );
while GetProfileString( cs1, cs2, cs4, dum1, xx) > 0 do
WriteProfileString( cs1, cs2, #0);
WriteProfileString( cs1, cs2, pchar( s2 ));
case Win32Platform of
VER_PLATFORM_WIN32_NT :
SendMessage( HWND_BROADCAST, WM_WININICHANGE, 0,LongInt(cs1));
VER_PLATFORM_WIN32_WINDOWS :
SendMessage( HWND_BROADCAST, WM_SETTINGCHANGE, 0,LongInt(cs1));
end; { case }
Result := True;
end;
finally
FreeMem( dum1 );
end;
end;
任何人都有任何提示或更好的方法吗?
作为旁注,这不是我的功能。这是我在搜索问题的解决方案时选择的一段代码。
更多信息:
打印作业实际上是使用
打印的PDF ShellExecute(Application.Handle, 'print', PChar(sPath), nil, nil, SW_HIDE);
目标是将默认打印机更改为所选打印机,以便将pdf打印到所需的打印机,然后在退出应用程序时将打印机恢复为原始默认值
答案 0 :(得分:3)
尝试使用Win32_Printer
WMI类列出打印机,并使用SetDefaultPrinter
方法设置默认打印机。
{$APPTYPE CONSOLE}
uses
SysUtils,
ActiveX,
ComObj,
Variants;
procedure ListPrinters;
const
wbemFlagForwardOnly = $00000020;
var
FSWbemLocator : OLEVariant;
FWMIService : OLEVariant;
FWbemObjectSet: OLEVariant;
FWbemObject : OLEVariant;
oEnum : IEnumvariant;
iValue : LongWord;
begin;
FSWbemLocator := CreateOleObject('WbemScripting.SWbemLocator');
FWMIService := FSWbemLocator.ConnectServer('localhost', 'root\CIMV2', '', '');
FWbemObjectSet:= FWMIService.ExecQuery('SELECT DeviceID, Name FROM Win32_Printer','WQL',wbemFlagForwardOnly);
oEnum := IUnknown(FWbemObjectSet._NewEnum) as IEnumVariant;
while oEnum.Next(1, FWbemObject, iValue) = 0 do
begin
Writeln(Format('DeviceID %s Name %s',[FWbemObject.DeviceID,FWbemObject.Name]));
FWbemObject:=Unassigned;
end;
end;
function SetDefaultPrinter(const DeviceID:string):boolean;
var
FSWbemLocator : OLEVariant;
FWMIService : OLEVariant;
FWbemObject : OLEVariant;
begin;
FSWbemLocator := CreateOleObject('WbemScripting.SWbemLocator');
FWMIService := FSWbemLocator.ConnectServer('localhost', 'root\CIMV2', '', '');
FWbemObject := FWMIService.Get(Format('Win32_Printer.DeviceID="%s"',[DeviceID]));
if not VarIsClear(FWbemObject) then
Result:=FWbemObject.SetDefaultPrinter()=0
else
Result:=false;
end;
begin
try
CoInitialize(nil);
try
ListPrinters;
SetDefaultPrinter('HP LaserJet'); //here you must pass the DeviceID of one the printers listed above
finally
CoUninitialize;
end;
except
on E:EOleException do
Writeln(Format('EOleException %s %x', [E.Message,E.ErrorCode]));
on E:Exception do
Writeln(E.Classname, ':', E.Message);
end;
Writeln('Press Enter to exit');
Readln;
end.
答案 1 :(得分:2)
只是简单地看一下this link,看来你正在'winspool.drv'中找到最关键的函数SetDefaultPrinterA / SetDefaultPrinterW
此外,广播消息被设计为对其他正在运行的程序有礼貌,让他们知道某些内容已经更改了默认打印机,即使在上面的文章中它似乎也没有注意结果,因此您可以更改呼叫到PostMessage
答案 2 :(得分:0)
我还尝试使用&#34; SendMessage(HWND_BROADCAST,WM_WININICHANGE,0,LongInt(cs1))&#34;代码块和我的程序挂起。所以,我试着简单地将SetDefaultPrinter写为本地函数,然后没有挂起。这是适合我的代码。
function SetDefaultPrinter(const PrinterName: string): boolean;
// Printername is bv: '\\MYPRINTER\HP5-k'
var
s2 : string;
dum1 : PChar;
xx, qq : integer;
const
cs1 : pChar = 'Windows';
cs2 : pChar = 'Device';
cs3 : pChar = 'Devices';
cs4 : pChar = #0;
begin
xx := 254;
GetMem( dum1, xx);
Result := False;
try
qq := GetProfileString( cs3, pChar( PrinterName ), #0, dum1, xx);
if (qq > 0) and (trim( strpas( dum1 )) <> '') then
begin
s2 := PrinterName + ',' + strpas( dum1 );
while GetProfileString( cs1, cs2, cs4, dum1, xx) > 0 do
WriteProfileString( cs1, cs2, #0);
WriteProfileString( cs1, cs2, pChar( s2 ));
case Win32Platform of
VER_PLATFORM_WIN32_NT :
SendMessage( HWND_BROADCAST, WM_WININICHANGE, 0, LongInt(cs1));
VER_PLATFORM_WIN32_WINDOWS :
SendMessage( HWND_BROADCAST, WM_SETTINGCHANGE, 0,LongInt(cs1));
end; { case }
Result := True;
end;
finally
FreeMem( dum1 );
end;
end;