Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations TouchToneTommy on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Windows 11 - any problems noted? 2

GriffMG

Programmer
Mar 4, 2002
6,314
FR
I just upgraded my lappie to W11, thinking that customers will be pushed to do so soon - as with W10, and not wanting any unforeseen issues to bite me!

I cannot see anything life threatening... any gotchas I should be looking for? like the fix for general fields required in W10?
 
To remove the printer environment from reports in older FoxPro versions you just empty the Expr1 field of the first reccord of the FRX. That's not exclsuive to VFP9 reports. And again, SET PRINTER TO NAME is the recommended way in most cases, you don't even need the system printer dialog.

What you surely need to make use of all the features and options, especially advanced options not only about orientation like which paper tray to use paper cut in receipt printers and anything else special you can't provide with a line in the printer options memo of an FRX, you'd set up with the printer drivers and dialogs of both Windows and the printer vendor. But once that's done and saved, it's all associated with the printer name and SET PRINTER TO NAME printername makes these settings and that's all you need.
 
To remove the printer environment from reports in older FoxPro versions you just empty the Expr1 field of the first reccord of the FRX. That's not exclsuive to VFP9 reports. And again, SET PRINTER TO NAME is the recommended way in most cases, you don't even need the system printer dialog.

What you surely need to make use of all the features and options, especially advanced options not only about orientation like which paper tray to use paper cut in receipt printers and anything else special you can't provide with a line in the printer options memo of an FRX, you'd set up with the printer drivers and dialogs of both Windows and the printer vendor. But once that's done and saved, it's all associated with the printer name and SET PRINTER TO NAME printername makes these settings and that's all you need.
Chriss, yes, you can make all the printer settings in Windows and create a separate printer for every setting. But sometimes that's not practical if a user needs different settings for every report like orientation, paper tray and custom margins. You don't want to create a new printer for every setting or you can end up having 50 different printers. A solution was to save the printer environment in the report. Because this is problematic, I applied a workaround to let the user choose these settings using SYS(1037, 1) and SYS(1037, 2) on a dummy report and then save the expr field of the dummy report in a separate "printer settings" table. I also let the user choose margins and save these as well in that table. The printer settings table has a record for every report and a few fields like the name of the report, expr field, top margin, left margin. Before printing, the saved expr field and margins are copied to the real report so these settings are applied upon printing. This way, instead of having a lot of printers in Windows you have all the settings saved in a VFP table and can change these settings easily anytime from the VPF app.
 
In my experience I only ever needed one or two printer setups. If you use this schema, you're not fixing yourself on name only.
 
Also, see this from VFPImaging blog, recovering a Bo Durban blog article "Bo Durban - Moxiedata Blog - Display the Print Dialog Using PrintDlgEx":

And the older one: http://web.archive.org/web/20100817...uid,7860a9ef-6260-4e6f-b472-5abe8e8d0e36.aspx
Scroll to "Issue: VFP SYS(1037) no longer has a PRINTER button in Vista" and see the code using the Windows API function DocumentProperties to even more directly go to printer setup.

Again, this points out the issue of SYS(1037) is an issue since Vista. I understand Windows 11 changes this once more in the app style dialog shown at foxite.

Would be interesting to know whether the one or other code example using PrintDlgEx and/or DocumentProperties also works in Windows 11 without setting the registry key for legacy printing dialog.

Besides that, a short code solution is to outsource the printer settings to Windows by showing the user the control panel printer overview with
Code:
Run /n control printers

You can also take the basis of the preconfigured printer under a specific name for generically chaning printer options, page layout, etc. pointing the user to setting that printer name settings, then printin under that name. That's another solution to not need 50 but only 1 (or 2) setup printers.
 
Last edited:
By the way, in both articles Bo Durban uses memory allocation to store a struct DEVMODE and and read it with SYS(2600). In a case a Windows API function needs a struct you don't need to go as low level, the struct can be stored in a String and the parameter type can be defined as @String instead of long/integer.

It's the second (and older) article that uses DocumentProperties that's more relevant. Because: If I understand correctly the change of SYS(1037) under Vista was that it only got to a pge setup without a printer button, that would go to DocumentProperties, not PrintDlgEx. Bo prefers PrintDlgEx in his second article because "Microsoft recommendeds for setting printer options in Vista". It allows both choosing the printer and setting preferences. I'd prefer DocumentProperties as setting the printer is already simple enough to not do by system dialog at all with APRINTERS and SET PRINTER TO NAME with one of the names of the APRINTERS array. Not only that, but DocumentProperties direclty goes into the printer preferences of one printer, not just an overview of all printers, that's instead easy to do with Run/n control printers, so I, personally, have no need for PrintDlgEx, except that it works within the VFP process and you can read out the settings made.

Do you really need to know the settings made? I say no, because the settings made are made, when you then don't change printer you have them set and your report just does need no printer settings embedded to run with whatever settings the user made in either DocumentProperties or PrintDlgEx. That's just pointing out the big advantage of using a printer name to print under that as the head setting that is determining all other settings. And those have not to be set in stone.

The aspect of using names for example to change a setting you don't get at directly by the page setup dialog, like the paper tray used, is not the only aspect to use a printer name for a fixed set of configurations. You typically only want some settings fixed and not touched by users. In my usages of the machanism, as said, I only ever needed 1 ror 2. In case of 1 it seems you can also handle that with embedding printer environment, but not if you have to manage a setting that VFP doesn't store into an FRX at all. That's another reason for the superiority of that solution. You don't seem to have encouterd such a case, if you can help yourself with SYS(1037,2) and SYS(1037,3) Well, good luck for not needing anything else. But then also you muddle with default printer settings when using SYS(1037,2) which you shouldn't do. To say it this way: If you don't like Windows deciding which printer is the default printer, then you surely also don't like if any application muddles with your default priter settings, don't you? You might to even be aware of that, but lookup the help on SYS(1037) and what the variants SYS(1037,1), SYS(1037,2) and SYS(1037,3) do.

The other situation I needed 2 setups of the same physical printer under two names in Windows to easily switch with SET PRINTER TO NAME name1 and SET PRINTER TO NAME name2 was with a setting that should easily work with the FRX Expr1 field, the TRAY choice. For whatever reasons the text line TRAY=X didn't set the paper tray, but using two printer names did that job. From that perspective you should expec the case that the reading out and setting of printer properties with the variants of SYS(1037) can also be unsuccessful. I strongly recommend working with printer names, even if it is just one and using DocumentProperties.

What I can't answer is whether DocumentProperties opens the same dialog in Windows 11 as it does in all other Windows versions: The printer specific page and other settings (note: SET PRINTER TO NAME is advised before DocumentProperties and for giving user the choice of printer use APRINTERS and your own dialog for that). That would solve the Win11 dialog change, I think. If it doesn't it may make PrintDlgEx an option, which you might prefer to have both printer choice and be able to go into specific printer settings from there.

In any case, the embedding of printer settings in reports becomes unnecessary.
 
Last edited:
Chriss, thank you for your links and ideas. Indeed I tried a similar approach like in the links you shared and called PrintDlgEx directly from VFP and worked with the DEVMODE structure. I used code and got help from Mike Gagnon, who very sadly passed away recently. At first it seemed like the ideal solution, but then errors appeared with some printers. As it wasn't robust I abandoned this approach and instead decided to offer the most important configurations in VFP directly, that are papersize, defaultsource (papyer tray), orientation, left margin, top margin. I never needed options like black-white/color, paper type etc. I believe all of these and other options belong to the printer settings in Windows. If you need to change these settings for some reports then you can create a second or third printer in Windows. But I guess in 99% of cases this won't be needed like the other options.

I use SET PRINTER TO NAME before printing and set it back to the default printer afterwards, so the default printer is never changed like you supposed

For every report I offer a menu to chose a printer and above mentioned settings. First I use APRINTERS() to let the user choose a printer by name. Then I use SET PRINTER TO NAME to set the chosen printer and create a dummy report in the backround to call SYS(1037). There the user can choose a paper tray, paper size and orientation. From the expr field of the dummy report I extract the information like paper tray, paper size etc. and store these in a table reportsettings.dbf. I also store the printer name and the name of the report in that table. Then I delete the dummy report and SET PRINTER TO NAME back to the default. In the menu, there are also two textfields where you can write a number for left margin and top margin in mm (needed for printing with Dot Matrix Printers).

When printing the report, I first make a copy of the original report file (frx), then use that frx as a table and copy the settings from reportsettings.dbf to the expr field of the report and also adjust margins like vpos. Then I SET PRINTER TO NAME to the printer associated with the report in reportsettings.dbf followed by REPORT FORM...
Then SET PRINTER TO NAME back to default. Of course I made functions to automate all of that so there's only one function call needed.

This has been working without a single error so far in many environments.

Would be interesting to know whether the one or other code example using PrintDlgEx and/or DocumentProperties also works in Windows 11 without setting the registry key for legacy printing dialog.
Unfortunately, PrintDlgEx doesn't work with these code examples on Windows 11, you still need to change the registry key to the legacy menu. And you have to make changes to the code for long printer names. It can still crash with some printer drivers, so I completely gave up on that.

For whatever reasons the text line TRAY=X didn't set the paper tray, but using two printer names did that job.

Reagrding the problem with the paper tray (defaultsource) you mentioned, you have to be careful to not simply use the numbers form the VFP help file as they can differ on some printers. Instead letting the user choose the paper tray by its name in the SYS(1037) menu and then reading the expr field gives you the correct number for the DEFAULTSOURCE, so you always target an existing paper tray. I never ran into a problem this way.

As I mentioned, I never needed to create the printer a second time in Windows Control Panel. In case it is needed, is there an easy was to copy the existing printer do it wihtout the need to install the driver again a second time. I would be nice to be able to copy the existing printer and then simply change the desired settings in the copy.

Regards,
Manni
 
Thanks for your feedback, Manni.

I haven't read it in it's entirety, so pardon me for ignoring details, I promise I read the rest later.

so the default printer is never changed like you supposed
SYS(1037,3) is documented as "Sets the default printer settings to a report's printer environment settings" and SYS(1037,2) is documented as "Sets a report's printer environment settings to the default printer settings". So no matter whether you SET PRINTER TO NAME somethingelse and use a dummy FRX file to store the printer settings, you essentially copy printer settings from your dummy FRX to the actual FRX through the default printer settings, thus you muddle with them.

I have to postpone reading details about how you handle the DEVM;ODE structure. I assume you construct the lines necessary for Expr1 from there. Well, I think of that as a cumbersome approach compared to lettting Windows store all printer settings to specifically the printer name I choose including options not working with Expr1, the tray is just one example, thanks for pointing out that can be solved, but I digress to learn all the specifics of this, if there are definitely settings not available to be set by Expr1. One example I remember wass the saturation setting of a thermal printer, that only was configurable within Windows and wouldn't ever come into an FRX expr1 field.
 
Chriss, I'm not muddling with the default printer at all.

I think there is an error in the VFP help file:

The VFP help says:
SYS(1037, 2): Sets a report's printer environment settings to the default printer settings.

But if you read the help file further it's not true, but the opposite:
SYS(1037,2) serves as a way to save current printer settings to a cursor temporarily so you can restore the printer environment later. As such, this function always stores complete details to the cursor you provide.

So SYS(1037, 2) takes the settings of the VFP default printer and stores them in the currently used report frx file. It doesn't change the settings of the default printer!

I believe the first table in the help file mixed up SYS(1037, 2) and SYS(1037, 3) and this causes a lot of confusion!

Only SYS(1037, 3) takes settings from a report file and applies them to the current VFP default printer. I never use this function.

In fact, I double checked again how I'm doing it and it works this way:

1. Save the current VFP default printer's name using SET("PRINTER", 3)
2. Let the user choose a printer GETPRINTERS()
3. Set the chosen printer temporarily as VFP default printer using SET PRINTER TO NAME
4. Create dummy cursor of a report and BLANK FIELDS expr, tag, tag2
5. Use SYS(1037, 2) to save the settings of the VFP default printer (the printer the user has chosen before) to the dummy report
6. Call SYS(1037, 1) to let the user choose settings like orientation, paper size, paper tray (defaultsource) and save these in the dummy report.
7. Parse the settings in the expr field of the dummy report and copy them to reportsettings.dbf together with the printer's name and the reports name.
8. Set VFP default printer to old default printer using SET PRINTER TO NAME

The VFP default printer remains the same and the settings are never changed!

When printing the report I open reportsettings.dbf, SET PRINTER TO NAME to the printer named stored in reportsettings.dbf and inject the expr field settings from reportsettings.dbf to the report file (to be exact a copy of it) followed by REPORT FORM. Then I set back to the VFP default printer using SET PRINTER TO NAME.

For the end user that's an easy and straight forward way to make individual settings for each and every report.

For edge cases like printer saturation etc., if you really need different settings for different reports, you can still add additional printers to Windows. But you end up having maybe a maximum of 3 or 4 printers in Windows instead if 20 or more when you need lots of different settings (orientation, paper size, paper tray) for every report. With the above approach you don't get lost in confusion and don't need an expert making these settings for you in Windows. If you think about it, creating seperate printers in windows is a big workaround and emerges only because of a lacking capabilities of VFP or Win32Api. You have one physical printer, so why have several printers in windows and install drivers again? When all or most of the settings you need can be targeted from VFP. It's not intuituve from the user's perspective to have the same printer several times in Windows and it creates more work in setting things up and maintaining it.

So I think the above approach is the best to give maximum comfort and options to the user, plus you are always free to add printers in Windows when you need more options :) You may disagree...

Regards,
Manni
 
Last edited:
Manni,

now I took the time to go through your now two posts and the htlp topic of SYS(1037) in all detail.

Regarding a fault in the documentation: That's surely possible. But I see you using the term VFP default printer. I won't get picky about this, it's true that you can set a current printer (call it default if you like) that differs from the default Windows printer. But you don't do that with GETPRINTER alone, you have to SET PRINTER TO NAME GETPRINTER() to change the current/default printer VFP uses, unless embedded report settings or, of course, another SET PRINTER changes that again. I take for grnted you pull together GETPRINTER() and SET PRINTER TO NAME, even if you don't do it as a one liner.

What I overlooked is that you use SYS(1037,1) to actually let users make settings, I thought and still think since Windows Vista that doesn't lead to the dialog you want to get to. I see tha actual stop you use to copy is directly from expr1 field of the dummy frx to the actual report, that will avoid changes in default printer settings, okay.

I also like that you solve not using system dialogs by making your own dialogs, but I wouldn't like to put that into expr1 lines, as easy as it is to have a COPIES=n text line and others.

I still have my bad experience with not being able to have all settings under users conrol and in the case I mentioned above this was essential so that line barcodes and QR barcodes could be scanned, very essential and not among the simple settings you're satisfied.

I wonder why you would need to fiddle with the DEVMODE struct. If you use either DocumentProperties (which I prefer, as it is specific to the current printer) or PrintDlgEx, which starts at the list of printers and needs the user to know right click to get to a specific printers settings, both dialogs will apply the settings made to how Windows maintains printer settings now and in all future Windows versions (unless MS makes another strange move again). What's important is, that I don't even need to care for how that's stored, these system dialogs simply do that. Of course not if the user exits with cancel, but that's not what I'm taking responsibility for.

I realize you say PrintDlgEx won't work, I would be more interested in DocumentProperties working. I'm not at all interested in translating the settings you can read from the DEVMODE struct to a corresponding expr1 frx value. So I still recommend emptying that. If DocumentProperties also only works with the registry key setting, well, then it's not a real big problem to programmatically make the reg key setting.

The only use case I still see for FRX embedded settings is, if they work for you and allow to run a report with all predefined printera and its settings, that's of course an advantage. It doesn't hold true for me in any case, though. If you have settings stored the way Window and the printer driver maintains them, you can use features of software configuarition management to provide them to a whole companies domain (DevOps department of a customer did that for us, in one case). So there also is no maintenance headache with that aspect.

Not embedding this in an FRX also isn't an issue to me in the sense of the encapsulation principle, as it's quite commonly recommended to drive reports with a report driving cursor you don't let the reports data environment create, but prepare it in code, which breaks the encapsulation in the FRX already anyway. In another thread I already said it's not naturally always the best way, if you have many report sections and groups and need to prepare a cursor structure with too many fields just to use that principle, there still is use for SET RELATION and lookup functions. Anyway, it's pointing out that encapsulation principle can be relaxed or extended by taking the report preparation code as part of a report, besides procedure files with functions called in expressions.

All in all, I understand that you worked quite hard on getting to your own solution and I think even just for that reason are not motivated to change to something else. I surely don't wish problems on you with settings you once will need and can't cater for with the VFP report settings system that is the expr1 memo. There's a bit more to VFPs reporting and hopefully you can always make it work, but perhaps you remember "my way", when it bites at some point.

To close this up, I always found it backward to introduce the "save printer environment" feature into the report builder. The feture that was actually added to VFP was the ability to UNtick this checkbox, not to enable this embedding. Embracing it as a general solution never occured to me, also a reason I wasn't that familiar with how SYS(1037,n) actually can be used. I found my final solution in not needing it anymore, at all.
 
Last edited:
Chriss, thank you for your lengthy response.

I see, for barcode readers you need a certain saturation level and settings for the printer that I never needed. In fact, when such settings are needed with my solution you can easily still do these in the Windows configuration of the printer or add a second printer. I think of it as a hybrid approach: the most common settings are available in the VFP app directly on a report basis and the special settings can be done in Windows in "your way", including adding more printers.

So far the basic settings in the expr field have always worked fine. In case this changes one day because of a Windows update, or if MS messes up the page layout dialog SYS(1037) like they have done with the Print Dialog, then I might have to get rid of the expr field completely. But for now I hope this day never comes.

If you have settings stored the way Window and the printer driver maintains them, you can use features of software configuarition management to provide them to a whole companies domain (DevOps department of a customer did that for us, in one case). So there also is no maintenance headache with that aspect.
This is a big argument for having everything stored in Windows, of course. As always, it depends on the customers environment which approach is more convenient. My customers have mostly workstations with their own printers and the workstations will be set up individually. For big companies your approach and the portability that comes with it seems more practical.

Regarding DocumentProperties, I don't understand how you can make use of these. I thought when using them you get access to the settings made in that menu from the calling program (VPF) and not that you use these WinAPI funcitons do change the settings in Windows. Also, it won't help you to add additional printers in Windows which still had to be done, no? Or is there an easy way to copy an existing printer with a simple command or action that I don't know of?

Thanks,
Manni
 
DocumentProperties is a Windows API functiun, just like PrintDlgEx as also provided in some of the links I posted earlier, also from Bo Durban.

Of course printer installation is required and one ingredient is knowing the printer name. I already said you don't have the necessity to install a printer multiple times, that's just an opportunit to switch between configurations, but once you have SET PRINTER TO NAME, for example as result of GETPRINTER(), as you do, DocumentProperties is givng you the dialog that SYS(1037) doen't get to directly and not anymore since Vista: The printer dialog. It seems to have the wrong name, as it seems about the page layout, but indeed it's giving you hands on simply all printer specific options.

For example after SET PRINTER TO NAME PdfCreator (a virtual PDF Printer) DocumentProperties gives you this dialog (see the title bar):
1731592277377.png
And for another printer that printers dialog will appear. And since this is Windows API it calls into Windows system and printer driver specific dialogs that store the settings there. It's a complete replacement for SYS(1037), let it depend on the reg key for legacy dialogs. Even if it would open the new Windows App style dialog, it's the official settings dialogs that simply set that printers settings. No need for them in the expr1 field.
 
Chris, I wasn't familiar with the DocumentProperties menu, probably because it was abolished since Vista. I see that it is providing you with all the options. But if you were formerly calling it via Sys(1037) or by calling the Win32 API function directly, the setting would only be applied to the current VFP printer, right? The setting is lost when you restart your VFP application. But my goal is to have the settings permanently saved for a specific report.

Let's assume I have only one printer installed like a HP Laserjet. When I print report1 I want want to address a specific paper tray, when I print report2 another paper tray, also report3 another paper tray. I don't want to make these settings everytime I'm printing, but only once for every report and then save these settings permanentely. So everytime I print report1 paper tray 1 is used automatically, when I print report2, paper tray 2 is used etc.

I don't see another way of achieving that than by making use of the expr field or by creating several printers in Windows - DocumentProperties can't help me with that, right?

Thanks,
Manni
 
Last edited:
the setting would only be applied to the current VFP printer.
No, you call the exact same dialogs you get as if you go this route in Windows control panel printers&scanner section:

1731627072199.png
Showing up the exact same dialog:
1731627224930.png
Do you assume this isn't stored in Windows / in the printer you configure that way? It's Windows API, not FoxPro API, it's not just making changes for a report, for an FRX, for VFP or the VFP process, it changes the printer settings and persists them.

What this isn't changing is an FRX, but you persist the preferences made for the printer and no value in an FRX expr1 will then use these preferences.
 
Thank you Chris, I'm understanding it now.

But still, the changes wouldn't be saved in combination with a repor but be applied to all reports which use that printer.

I need to have the settings stored in association with the name of the report.

Regards,
Manni
 
That's a reason for storing that into a report. But when you said you'd need 50 printer installations/names or your users should be able to make setting changes for ever print job, that's solving it too. What you're after is more precisely a way to once settle the configuration for each report and have it automatically apply when a report is run.

Well, I think you could store the DEVMODE struct and reapply it, reset it to what you initially read and be done with that instead of VFPs expr1, which would work better in case of settings that refuse to work as simple text lines in FRX expr1 memo fields.

You avoided the problem of needing to interpret the DEVMODE struct content and turn them into lines for FRX expr1 by using SYS(1037) in all it's variants with dummy reports or cursors. Instead you could concentrate on the DEVMODE struct as the representation óf all settings and store it into a blob field as meta data of an FRX.

In all my use cases of printing any report that's normal enough to not need specialties would go to a printer with whatever exact settings it had and challengening reports all only where about very specific printers like label printers that also only ever get used with label reports, not any other.
 
Note... DEVMODE struct has a member dmDriverExtraData - This field can contain implementation-specific printer driver data. Its size in bytes is specified by the dmDriverExtra field. This binary data not possible share between printer drivers.
 
This binary data not possible share between printer drivers.
I wouldn't do that, but instead of having the expr1 printer specific use the DEVMODE printer specific to reproduce the settings.

Meta data table reportsettings:
id integer, report varchar(50). printername varchar(50), devmode blob

Select printername, devmode from reportsettings where report = x
Set printer to name (printername)
* set the devmode by SetPrinter API function https://learn.microsoft.com/en-us/windows/win32/printdocs/setprinter
* => DEVMODE only goes back to the printer it came from, no problem with unsharable struct data.
Report Form...
 
Chris, the idea of saving the DEVMODE structure instead of the information for expr1 would allow for more settings to be saved. Like you said very well it would be better than relying on the expr field and would save work parsing the information of the DEVMODE structure or SYS(1037).

But there are some questions unsolved for me: I've experienced problems calling DocumentPropeties directly via Win32 API as it crashed on some workstations. I haven't been able to identify the reason, it might be due to the DEVMODE structure that was passed to DocumentPropeties or because of parsing that information after the menu closes. Also, relying on the legacy menu is no guarantee that it will work in the future. Plus, when you activate the legacy menu with the registry key, you have to change it back afterwards because the legacy menu has flaws on Windows 11. For example, when you print with the legacy menu (applications like Wordpad are also using it) the number of copies will be ignored.

Another thing I'm wondering: Once you have obtained the DEVMODE, you have to store it to the report before printing (tag or tag2 field?). But what happens to the expr field, can I leave it blank. Will the information the expr field be ignored because the information in tag, tag2 takes precedence.

Note... DEVMODE struct has a member dmDriverExtraData - This field can contain implementation-specific printer driver data. Its size in bytes is specified by the dmDriverExtra field. This binary data not possible share between printer drivers.

Thank you for pointing that out, Martina. It might have to do with the problems I encountered.

Thanks,
Manni
 
id integer, report varchar(50). printername varchar(50), devmode blob
Chris, there's something to look out for, the printername can be longer than 50 characters and you have to use other Win32 API function to get the whole name (DEVNAMES structure), making it a bit more complicated.
 

Part and Inventory Search

Sponsor

Back
Top