如何更改默认打印机

发布于 2024-12-09 21:01:00 字数 1735 浏览 4 评论 0原文

我试图在列出打印机索引的组合框的更改事件中更改默认打印机。我使用“打印机”来获取打印机索引,但实际打印是使用专有打印代码完成的,该代码允许直接打印 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 将发送的位置

打印作业实际上是正在打印的 PDF

 ShellExecute(Application.Handle, 'print', PChar(sPath), nil, nil, SW_HIDE); 

目标是将默认打印机更改为选定的打印机,以便将 pdf 打印到所需的打印机,然后在退出应用程序时将打印机返回到原始默认值

I am attempting to change the default printer in the on change event of a combo box that list the printer index. I use "Printers" to get the printer index but the actual printing is done with proprietary print code that allows for direct to pdf printing and easier page layout. I am trying to use the below code to change the default printer and then my print code will print to that printer. However the program becomes unresponsive without any errors or program not responding messages when this line of code executes:

SendMessage( HWND_BROADCAST, WM_WININICHANGE, 0,LongInt(cs1));

Here is the full function.

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;

Anyone have any tips or a better way to do this?

As a side note this is not my function. It's a piece of code I picked up while searching for a solution to my problem.

Few more pieces of info:

The user selects the printer in the drop down. This is where the PDF will be sent

The print job is actually a PDF being printed using

 ShellExecute(Application.Handle, 'print', PChar(sPath), nil, nil, SW_HIDE); 

The goal is to change the default printer to the selected printer in order to print the pdf to the desired printer and then return the printer to the original default on exit of the application

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

忆伤 2024-12-16 21:01:00

尝试使用 Win32_Printer WMI 类列出打印机和设置默认打印机< /a> 设置默认打印机的方法。

{$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.

Try using the Win32_Printer WMI class to list the printers and the SetDefaultPrinter method to set the default printer.

{$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.
万劫不复 2024-12-16 21:01:00

只需简单浏览一下 此链接,您就会发现您错过了最关键的函数 SetDefaultPrinterA/SetDefaultPrinterW在“winspool.drv”中,

广播消息的设计也是为了对其他正在运行的程序有礼貌,让它们知道某些内容已经更改了默认打印机,即使在上面的文章中,它似乎也没有注意到结果,以便您可以更改对 PostMessage 的调用

Just a brief look at this link and it appears you're mising the most critical function SetDefaultPrinterA/SetDefaultPrinterW in 'winspool.drv'

Also the broadcast message is designed to be polite to other running programs to let them know something has changed the default printer, even in the above article it doesn't seem to pay any attention to the result so you could change the call to PostMessage

橙味迷妹 2024-12-16 21:01:00

我还尝试使用“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;

I also tried to use the "SendMessage( HWND_BROADCAST, WM_WININICHANGE, 0,LongInt(cs1))" code block and my program was hang. So, I tried to simply write the SetDefaultPrinter as local function and then no hang occours. Here is the code that works fine for me.

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;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文