Solved

How to select a printer without PrintDialog ?

Posted on 1998-11-24
17
1,376 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 8
  • 5
  • 3
  • +1
17 Comments
 
LVL 2

Expert Comment

by:lortega
ID: 1347754
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
ID: 1347755
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
ID: 1347756
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
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 1

Expert Comment

by:Oli2
ID: 1347757
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
ID: 1347758
of course I mean changing the Registry key temporarily by using TRegistry in your code.
Oli
0
 
LVL 1

Expert Comment

by:Oli2
ID: 1347759
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
ID: 1347760
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
ID: 1347761
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
 

Author Comment

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

Expert Comment

by:philipleighs
ID: 1347763
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
ID: 1347764
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
ID: 1347765
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
ID: 1347766
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
ID: 1347767
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
ID: 1347768
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
ID: 1347769
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
ID: 1347770
I use WriteProfileString and it works correctly.
Thanks.
0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Delphi XE10 Round Image 2 184
Strange behavior when a form is closed 6 68
how can i search if string exist in array ? 3 69
How to build JSON File in Delphi 6 3 68
This article explains how to create forms/units independent of other forms/units object names in a delphi project. Have you ever created a form for user input in a Delphi project and then had the need to have that same form in a other Delphi proj…
In this tutorial I will show you how to use the Windows Speech API in Delphi. I will only cover basic functions such as text to speech and controlling the speed of the speech. SAPI Installation First you need to install the SAPI type library, th…
The Email Laundry PDF encryption service allows companies to send confidential encrypted  emails to anybody. The PDF document can also contain attachments that are embedded in the encrypted PDF. The password is randomly generated by The Email Laundr…

735 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