【问题标题】:How to change the default printer如何更改默认打印机
【发布时间】:2011-10-14 14:44:48
【问题描述】:

我试图在列出打印机索引的组合框的 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 打印到所需的打印机,然后在退出应用程序时将打印机恢复为原始默认值

【问题讨论】:

  • 你试过Printers.PrinterIndex := IndexOfYourPrinter
  • 我没有。我假设 Printers.PrinterIndex 只有在我使用打印机而不是我们使用的自定义打印类进行打印时才有效。我将对其进行测试,看看是否能给我想要的结果
  • 值得一试,但我的自定义打印类使用默认打印机进行打印,并且 Printers.PrinterIndex 不会更改默认值
  • 您不应使用默认打印机。您应该使用选定的打印机。更改默认打印机是用户应该做的事情。你不能在他们背后做这件事。
  • 你不需要平台案例,因为WM_WININICHANGE = WM_SETTINGCHANGE

标签: delphi delphi-2010


【解决方案1】:

尝试使用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.

【讨论】:

    【解决方案2】:

    简单看一下this link,您似乎错过了“winspool.drv”中最关键的函数 SetDefaultPrinterA/SetDefaultPrinterW

    此外,广播消息旨在对其他正在运行的程序有礼貌,让他们知道某些东西已经改变了默认打印机,即使在上面的文章中,它似乎也没有注意结果,所以你可以改变调用发邮件

    【讨论】:

    • PostMessage 解决了这个问题。程序现在按预期运行感谢@JamesB
    【解决方案3】:

    我还尝试使用“SendMessage(HWND_BROADCAST, WM_WININICHANGE, 0,LongInt(cs1))”代码块,我的程序被挂起。因此,我尝试将 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;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-03-16
      • 1970-01-01
      • 1970-01-01
      • 2011-10-17
      • 2011-08-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多