Solved

How to select a printer without PrintDialog ?

Posted on 1998-11-24
17
1,314 Views
Last Modified: 2010-08-05
Hello everybody !

Is there someone who knows how to select a printer without using PrintDialog ?
I explain :
I'm using a Delphi 3.0 program to create and print WinWord files.
The user can choice a printer in a combobox which contains the list of available printers of Windows.
I'm using the printer (printers) object to propose this list and to know the printindex and the name of the selected printer.
In my code I send WordBasic orders to WinWord to create the word document.
But before I want to specifie the printer selected by the user to windows.
I know the existence of the OpenPrinter and SetPrinter functions of Windows but I don't know how to use it.
Can you give me some examples ?

Thanks.

0
Comment
Question by:nk51
  • 8
  • 5
  • 3
  • +1
17 Comments
 
LVL 2

Expert Comment

by:lortega
Comment Utility
Just add a buttons adn a listbox and try this...


procedure TForm1.FormShow(Sender: TObject);
begin
     ListBox1.Items := Printer.printers;
end;


procedure TForm1.Button1Click(Sender: TObject);
begin
  Printer.PrinterIndex := ListBox1.ItemIndex;
  Printer.BeginDoc;
  Printer.Canvas.TextOut(10,10,'Luis');
  Printer.EndDoc;
end;

0
 

Author Comment

by:nk51
Comment Utility
It's no so simple.
I'm french and perhaps I don't use a good english.
My question was :
How to change the default printer of windows without PrintDialog component?
With your example I only can print canvas.
I want to print a .DOC file on the printer of my choice without using the printdialog component (so, with code).
I want to know how to change the default printer of windows in my code.
Thanks.

0
 

Author Comment

by:nk51
Comment Utility
I think I have to use OpenPrinter, SetPrinter of Windows but I have some pbs to use this functions.
I need some examples.
Thanks.
0
 
LVL 1

Expert Comment

by:Oli2
Comment Utility
why not change HKEY_LOCAL_MACHINE\Config\0001\System\CurrentControlSet\Control\Print\Printers
i.e. change the Key "default" = "HP Laserjet 1" into some Printer you want to use.
For that, read the printerNames out by using TPrinter.Printers, that is a TStringList with all available Printers. I didn't try it, but it should work.
The only hard thing about it is, that TPrinter.Printers does show the Printer Name and the Connection. Into the registry-key you should only write the Printer Name. So you would somehow have to extract the printer Name out of TPrinter.Printers.
Good luck !

0
 
LVL 1

Expert Comment

by:Oli2
Comment Utility
of course I mean changing the Registry key temporarily by using TRegistry in your code.
Oli
0
 
LVL 1

Expert Comment

by:Oli2
Comment Utility
me again...
I did a litlle research and here's some news:
TPrinter.SetPrinter seems to only take action in your program.
If I understood you right, you want to change the default printer for winword.exe.
In this case to me it seems, working with TRegistry is the onliest way.
Oli
0
 
LVL 3

Expert Comment

by:philipleighs
Comment Utility
Here is what Microsoft have to say about this:


HOWTO: Get and Set the Default Printer in Windows

Last reviewed: March 4, 1998
Article ID: Q135387 The information in this article applies to:

•Microsoft Windows Software Development Kit (SDK) for Windows version 3.1 •Microsoft Win32 Application Programming Interface (API) included with: - Microsoft Windows NT versions 3.5, 3.51 - Microsoft Windows 95







SUMMARY

In all versions of Windows, the appropriate way to get the default printer is to use GetProfileString, and the appropriate way to set the default printer is to use WriteProfileString. This works whether the default printer information is stored in the WIN.INI file or in the registry.





MORE INFORMATION





Notes to Keep in Mind



•The Device value you get or set actually contains three elements separated by commas as follows:



      <printer name>,<driver name>,<port>





For example:





      My Printer,HPPCL5MS,lpt1:



•When setting the default printer, you must specify valid names for these elements. That is, you must specify a valid printer, driver, and port. If not, programs such as Print Manager may set the printer back to the previous valid printer, and other programs may become very confused. You can use the EnumPrinters API to retrieve the printer name, driver name, and port name of all available printers. •Windows 95 and Windows NT map most .INI file references to the registry. Because of this mapping, GetProfileString and WriteProfileString still function as they do under 16-bit Windows (Microsoft Windows and Windows for Workgroups). •After setting the default printer, notify all other applications of the change by broadcasting the WM_WININICHANGE message.





Sample Code



   // This code uses a sample profile string of "My Printer,HPPCL5MS,lpt1:"
   // To get the default printer for Windows 3.1, Windows 3.11,
   // Windows 95, and Windows NT use:
   GetProfileString("windows", "device", ",,,", buffer, sizeof(buffer));

   -----

   // To set the default printer for Windows 3.1 and Windows 3.11 use:
   WriteProfileString("windows", "device", "My Printer,HPPCL5MS,lpt1:");
   SendMessage(HWND_BROADCAST, WM_WININICHANGE, 0, 0L);

   -----

   // To set the default printer for Windows 95 use:
   WriteProfileString("windows", "device", "My Printer,HPPCL5MS,lpt1:");
   SendMessageTimeout(HWND_BROADCAST, WM_WININICHANGE, 0L,
   (LPARAM)(LPCTSTR)"windows", SMTO_NORMAL, 1000, NULL);

   -----

   // To set the default printer for Windows NT use:
   /* Note printer driver is usually WINSPOOL under Windows NT */
   WriteProfileString("windows", "device", "My Printer,WINSPOOL,lpt1:");
  SendMessageTimeout(HWND_BROADCAST, WM_WININICHANGE, 0L, 0L,
  SMTO_NORMAL, 1000, NULL);




There are two circumstances where the code won't work:



1.If the customer leaves out the SendMessage, no other application will recognize the change in the .INI settings.

2.If a different 32-bit application does not handle the WIN.INI change message, then it will appear to that application as if the default printer has not been changed. The user will need to exit and re-enter Windows 95 to have the other application recognize the printer change.



This is the preferred method of changing the printer if the code is to be platform independent; this method will work on Windows 3.1, Windows 95 and Windows NT.



For additional information, please see the following article(s) in the Microsoft Knowledge Base:



   ARTICLE-ID: Q140560
   TITLE     : How to Set the Default Printer Programmatically in Windows
               95






------------------------------------------------------------------------


Additional query words: 3.11
Keywords : GdiPrn kbcode kbprint
Version : WINNT:3.1,3.5,3.51,4.0; WIN95
Platform : Win95 winnt
Issue type : kbhowto




Last reviewed: March 4, 1998
© 1998 Microsoft Corporation. All rights reserved. Terms of Use.
0
 

Author Comment

by:nk51
Comment Utility
All your answers are very interessant but I think I don't have the answer I expected.
I want to select a printer as in the printer dialog box of windows in the list of printers but without the printdialog.
So in my code. I try with the printer object but it seems to work only in the delphi environnement and not the winword environnement.

 
0
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 

Author Comment

by:nk51
Comment Utility
Sorry, you (oli2 & philipleighs) had right. The only and best way is to change the registry.
Thanks
0
 
LVL 3

Expert Comment

by:philipleighs
Comment Utility
The best way is to do what the MS document says. The system.ini file is mirrored into the registry. It doesn't work the other way around.
Also, changing the ini file will update both local machine and current user, and send a WM_INI_CHANGED message.

By using the documented method, you get some assurance that it will work on the listed platforms. This is probably not the case if hack the registry.

0
 

Author Comment

by:nk51
Comment Utility
I can't totally accept Philipleighs' proposed answer because only one part of the answer is correct.
I explain :
(see http://www.experts-exchange.com/Q.10102173)
In my code I make modifications in the registry.
After those modifications I have to notify all others applications of those changes by broadcasting the WM_WININICHANGE message.
Under win95 I have to use the SendMessageTimeOut function.
The SDK give this example :
SendMessageTimeOut(HWND_BROADCAST,WM_WININICHANGE,0,0L,(LPARAM)(LPCTSTR)"windows",SMTO_NORMAL,1000,NULL);
But it doesn't work !
Does anybody know how to use this function ?
If you have some examples, it will be great !
Thanks in advance.
0
 
LVL 3

Accepted Solution

by:
philipleighs earned 100 total points
Comment Utility
Hi nk51.

I wrote two little apps.

One does this in a button click event:

SendMessageTimeout(HWND_BROADCAST, WM_WININICHANGE, Longint(0),
LParam(PChar('windows')), SMTO_NORMAL, 1000, dw);


The other application does this:

unit sample;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;

type
  TForm1 = class(TForm)
  private
    { Private declarations }
  public
    procedure WMIniChange(var msg: TMessage); message WM_WININICHANGE;
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.WMIniChange(var msg: TMessage);
  begin
    ShowMessage('ini changed');
  end;

end.



So I run both programs, click the button which sends the message, then the other program says 'ini changed'.
Just copy the SendMessageTimeout code into your app.

Cheers,
Phil.

0
 
LVL 3

Expert Comment

by:philipleighs
Comment Utility
Whoops, I forgot to mention that dw is declared as a DWORD.

procedure TForm1.Button1Click(Sender: TObject);
var dw: DWORD;
begin
SendMessageTimeout(HWND_BROADCAST, WM_WININICHANGE, Longint(0),
LParam(PChar('windows')), SMTO_NORMAL, 1000, dw);
end;

0
 

Author Comment

by:nk51
Comment Utility
Your last answer is good but the SendMessageTimeout function erase the modification I made in the registry and restore the previous value.
Have you an idea about what's happening ?

0
 

Author Comment

by:nk51
Comment Utility
Your last answer is good the SendMessageTimeout function erase the modification I made in the registry and restore the previous value.
Have you an idea about what's happening ?

0
 
LVL 3

Expert Comment

by:philipleighs
Comment Utility
Are you changing the registry directly, or are you using WriteProfileString?

If you do it the way it says in the MS doc, it will update the registry for you.
If you write to the registry, then send INI_CHANGE, then Windows will synchronise the registry with WIN.INI. ie, the contents of WIN.INI will be copied into the registry overwriting your changes.

Use WriteProfileString.

0
 

Author Comment

by:nk51
Comment Utility
I use WriteProfileString and it works correctly.
Thanks.
0

Featured Post

Highfive + Dolby Voice = No More Audio Complaints!

Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

Join & Write a Comment

Introduction The parallel port is a very commonly known port, it was widely used to connect a printer to the PC, if you look at the back of your computer, for those who don't have newer computers, there will be a port with 25 pins and a small print…
Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
In this seventh video of the Xpdf series, we discuss and demonstrate the PDFfonts utility, which lists all the fonts used in a PDF file. It does this via a command line interface, making it suitable for use in programs, scripts, batch files — any pl…
Here's a very brief overview of the methods PRTG Network Monitor (https://www.paessler.com/prtg) offers for monitoring bandwidth, to help you decide which methods you´d like to investigate in more detail.  The methods are covered in more detail in o…

763 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

9 Experts available now in Live!

Get 1:1 Help Now