For our application, we need to be able to print output at a specific location on a page. For example, we need to be able to print some text at exactly (1.00", 1.00") relative to the top left corner of the page. The problem lies in the fact that all coordinates in the various GDI calls are not relative to the upper left corner of the display, but are rather relative to a device dependent offset, which one obtains with code like:
int cx = ::GetDeviceCaps(hDC, PHYSICALOFFSETX);
int cy = ::GetDeviceCaps(hDC, PHYSICALOFFSETY);
These, of course, are in device units, so you convert them to logical units as desired. And then, you may adjust your coordinates in other API calls to get the output exactly where you need it.
This works like a charm when running under Windows directly. However, when using Terminal Services to print to a redirected printer on Windows Server 2008, the DeviceCaps functions no longer report correct information, at least for a large number of different printers. Device offsets are reported as 0, and when querying the printable region on a page, incorrect information is returned (the APIs overstate the amount of available real estate). Worse, it appears that either MS or the printer driver vendor is aware of the issue, because when the print job spools to your local machine (so that it can then spool to your local printer), all of the output is shifted by some compensating amount; an amount that appears to be a hack as it is nowhere close to the correct value reported by GetDeviceCaps when querying printer capabilities locally.
So, the result is that printed output gets shifted off the page ...
Has anyone else seen issues of this sort? Am I crazy to want precise control over printed output? Certainly, in order to paginate correctly, one needs an accurate value for the amount of available printable space, no? Any help or pointers would be appreciated.
The Microsoft Knowledgebase issue 959442 and the included hotfix should resolve the problem:
"The edges of a document are truncated when you try to print the document by using Terminal Services Easy Print from a client computer that is running Windows XP SP3, Windows Vista SP1, or Windows Server 2008"
Related
Is it possible at all to read the value (presumably a variable, since it changes every few seconds and is shown on screen) from a process in Windows? This is some custom, fairly old (10y) Windows GUI application that shows values (part counter) from manufacturing machine connected to it via some proprietary protocol (even using a dedicated PCI commmunications card).
I got the idea when reading about people modifying settings in a game (change high-score, change difficulty level, etc).
On Windows, there is an official API ReadProcessMemory for reading data from a process's memory:
ReadProcessMemory copies the data in the specified address range from the address space of the specified process into the specified buffer of the current process. Any process that has a handle with PROCESS_VM_READ access can call the function.
While I am hopeful that it works once the address/offset of the value in question is known, I am not so sure if this application will allocate memory differently when started the next time.
This is how I would approach it:
continuously, e.g. every second
take a screen shot of the application,
take a process dump (procdump from sysinternals) of the application
analyse the process dump and try to find the location/offset of the value in question
compare process dumps from different startups of the application to see if the value is at the same offset
Is this feasible, or is it completely obvious that memory allocation is very dynamic (between restarts and even during runtime) and using an offset-based approach will be doomed?
I have a file located at C:\printme.txt
I want to print it to my printer which is named POS80
Is there not a simple command for windows in the command prompt to say Print C:\printme.txt to POS80?
It should be noted that POS80 is also the default printer so a command that does not include the printer name but just sends to the default printer would be acceptable too.
Your mileage can vary using the legacy command Print
It MAY work if you have a line printer set to LPT1 and worth trying
Print C:\printme.txt "POS80" However I expect you are getting the error message "Unable to initialize device PRN" that is not unusual as PRN was traditionally LPT1.
Later you say its USB connected. which means its serial (old Com ports) whereas Line Printer (old LPT ports) were parallel hence the potential needs for fettling, but in windows you can use the port name for the printer and that resolves ports issue (files can become ports or vice versa) thus no real problem.
Now you could try messing with printer port redirections to get around that but it would likely mess up other application printing. Thus by far the simplest is make the printer the default one which is what you have.
To avoid the Save Output File As dialog when adding a print job to the default queue, ensure that your default printer isn't Microsoft XPS Document Writer, Microsoft Print to PDF, or other print-to-file options.
So what is Windows 10 doing when you right click print? Generally it fires up the associated FTA (File Type Application) which for .txt (or similar chosen) is NotePad.
Thus the simplest way to command line print plain text is
NotePad /pt C:\printme.txt "POS80"
NotePad settings can be changed in the registry before and after you print, via the command line, even skewing letters (fun to prank colleagues if you use 1 degree off kilter), however you cannot set line spacing or add graphics, for those you need to step up to WordPad which will accept docx, rtf, odt and most simple text file types.
Several other file types can also be printed in a similar way such as graphics images, using mspaint.
Later you say you are sending html as text and want graphic output not textual.
So the x problem is the files are not plain.txt they are plain.htm so need translation from html by graphic conversion (rendering) to pass through a printer language converter (printer driver) That's a totally different question but the answer is still much the same.
Traditionally you would simply use
rundll32.exe mshtml.dll,PrintHTML "C:\printme.txt"
But security exploits have made that simplicity more of a challenge thus
best to run it like this.
cd /D C:\Windows\System32 & rundll32.exe mshtml.dll,PrintHTML "C:\printme.txt"
And Microsoft Current Policy is "User confirmation is needed to print an HTML page through MSHTML.DLL." thus you need to hit print using sendkeys.
If your preference is FireFox rendering, from the command line you needed to install an extension, however with tightened security in windows 10, I dont know if that's still possible.
If you wish to print xml or html graphically in windows 10+ you can ask Edge --headless to print those for you to PDF, either as screen shot or rendered text, silently without enforced html confirmation ! And again you can print html automatically by using sendkeys to replace the user.
However printing PDF from the command line is where the real fun begins.
It is possible if the PDF is the correct type prepared for the printer (even a simple thermal or inkjet) then an old school copy /b file.pdf "printer" may work but dont send a big file to test, just a tiny Hello World!, or your carbon neutrality is instantly wiped out by reams of paper with one or two letters each.
My dirt cheap HP accepts files that can be viewed as PDF that start textually like this i.e. which have the PCLm 1 comment.
%PDF-1.7
%PCLm 1.0%
223 0 obj
<<
/Type /Page
/Parent 2 0 R
/Resources <<
/XObject <<
/Image0 3 0 R
/Image1 4 0 R
For most POS printers a PDF either needs to be processed in middleware or usually top end firmware such as onboard Direct PDF
Thus we come back to using html bitmap and text directives that will either need a print driver or be programmed to a port or file for later copy /b to device.
As you no doubt know Microsoft have not made it simple to print file.html default in fact the opposite resulting in many third part apps for win xp-win 11 such as https://www.bersoft.com/htmlprint/index.htm#overview amongst many other options.
Edit: I rephrased my question, please ignore all of the comments below (up to the 7th of May).
First off, I'll try to explain the problem:
My process is trying to show a Deskband programmatically using ITrayDeskBand::ShowDeskBand.
It works great at any time except for when the OS is loading all of its processes (after reset or logout).
After Windows boots and starts loading the various applications\services, the mouse cursor is set to wait for a couple of seconds (depends on how many applications are running \ how fast everything is).
If the mouse cursor is set to wait and the process is running during that time, the call will fail.
However, if my process waits a few seconds (after that time the cursor becomes regular) and then invokes the call, everything works great.
This behavior was reproduced both on Windows 7 and Windows Vista.
So basically what I'm asking is :
1) Just for basic knowledge, What the OS does when the cursor is set to busy?
2) The more important question : How can i detect programmatically when this process is over?
At first, I thought that explorer hadn't loaded properly so I've used WaitForInputIdle but it wasn't it.
Later I thought that the busy cursor indicates that the CPU is busy so I've created my process using IDLE_PRIORITY_CLASS but idle times were received while the cursor was busy.
Windows never stops loading applications and/or services!
As a matter of fact, applications come and go, some of these interactively some of these without any user interaction. Even Services are loaded at different points of time (depending on their settings and the external conditions - e.g the Smard Card Resource Manager Service might start only when the OS detects that a Smard Card device has connected). Applications can (but must not) stop automatically so do some Services.
One never knows when Windows has stop to load ALL applications and/or Services.
If ITrayDeskBand::ShowDeskBand fails, then wait for the TaskbarCreated message and then try again. (This is the same technique used by notification icons.)
The obvious approach would be to check whether ShowDeskband worked or not, and if not, retry it after a few seconds. I'm assuming you've already considered and rejected this option.
Since you seem to have narrowed down the criteria to which cursor is being displayed, how about waiting for the particular cursor you are wanting? You can find which cursor is being shown like this:
CURSORINFO cinfo;
ICONINFOEX info;
cinfo.cbSize = sizeof(cinfo);
if (!GetCursorInfo(&cinfo)) fail();
info.cbSize = sizeof(info);
if (!GetIconInfoEx(cinfo.hCursor, &info)) fail();
printf("szModName = %ws\n", info.szModName);
printf("wResID = %u\n", info.wResID);
Most of the simple cursors are in module USER32. The relevant resource IDs are listed in the article on GetIconInfo.
You apparently want to wait for the standard arrow cursor to appear. This is in module USER32, and the resource ID is 32512 (IDC_ARROW).
I suggest that you check the cursor type ten times a second. When you see the arrow cursor ten times in a row (i.e., for a full second) it is likely that Explorer has finished starting up.
I know that this is an old topic for vfp programmers. Still, I want to ask for advices that can improve the printing time for my particular case.
I recently asked to change a report written in vfp. It use commands such as fputs, etc. The user prints this report in a dot matrix printer and of course : no problem. But the user asked for column addition and some complex calculation in the report. We tried to avoid paper size changes. So my initial solution was to rework the report using report designer, and set the page orientation to landscape. The result is so slow when printed.When I open the print queue, it even shows error - printing status!
I've tried to instal the printer driver in my local PC ( the machine where I compiled the exe) and selected this printer, both with 'save printer environment' checked and unchecked. Still the same result.
Any suggestions? Other tricks for my case are welcomed. Thanks in advance.
Sometimes, and not sure if its your case, when creating a report in VFP, it saves the printer environment based on the computer used to develop it (ie: your machine). To check, and since all reports are nothing but .DBF tables renamed, try the following. Open the report as a table
USE YourReport.frx (you have to explicitly include the .frx extension)
BROWSE
The first line in the report is your environment information that includes paper size info, orientation and even printer information. Double click in the column "Expr". The only things you probably need in this column are
ORIENTATION=1 (or 0)
it may have other stuff and look something like
DRIVER=winspool
DEVICE=\some\printershare
OUTPUT=IP_192.168.1.22
ORIENTATION=1
PAPERSIZE=1
SCALE=100
ASCII=0
COPIES=1
DEFAULTSOURCE=15
PRINTQUALITY=600
COLOR=2
DUPLEX=2
YRESOLUTION=600
TTOPTION=3
COLLATE=0
You can remove the rest of it. Next, close this column and tab over about 10 more columns to "Tag" and "Tag2". They are also MEMO type fields. Open them up. Remove ALL data out of these two columns... BUT ONLY FOR THE FIRST ROW!!!! If you open them, you would see more embedded stuff about the printer, just remove it completely. Do NOT do a global replace to blank for all rows as that will kill the report content... ONLY the first row.
All this being said, I can't guarantee, but it may be the culprit... but then again, doing direct output on old dot-matrix printers might actually be faster than all the fancy rendering the printer drivers are doing.
Trying to print a report from the report designer through the windows driver to a dotmatrix printer will never be acceptably quick.
That's why they originally did the report using commands.
Your choices are either change the printer to a laser printer (probably not possible I'm guessing) or change the report back to the old style.
It's hardly difficult to print fast on a dot matrix printer with VFP reports, you should do it on a raw mode, but not on ?? or ??? way, I mean on API calls like this:
--- RawPrint VCX ---
http://www.universalthread.com/ViewPageNewDownload.aspx?ID=9556
You can use a wrapper, with kind-of "Formats" support it's a commercial software but it's worthy if you need to do a lot of reports with this kind of printer:
--- DosPrint 4 ---
http://www.victorespina.com.ve/hs/es/index.php/DOSPrint4_%28VFP%29
(disclaimer: the developer of DosPrint 4 it's a friend of mine, and I worked with him testing and supporting on the previous version DosPrint 3 on the spanish MS-VFP newsgroups and http://Portalfox.com)
Try using the Microsoft Generic Text only print driver
I can't copy the information in softice to disk/file. I am aware of IceExt but everytime I execute the command to dump the screen to disk(such as "!DumpScreen \??\c:\test.raw")it crashes my system entirely. When I try to copy with the mouse, the cursor only makes it possible to copy one line. I have already read through the softice manual. I just need a way to retrieve data from softice. Any help would be appreciated. I am using xp professional.
Turns out that no addons are required to accomplish this. Using the command "u cs:eip L 1000" from softice. You will then see a duplicate of the data within softice's screen displayed in the command window.
The u 'unassembles' code at the address cs:eip (the current EIP), the L specifies a length of 1000 bytes, you might need more than 1000 so adjust accordingly. Once you've done this you should exit SoftICE and select File / Save SoftICE History As from Symbol Loader, with any luck the resulting file will contain your code dump.You may have to to use F10 to step through inorder to get the data in softice's history log.
Using this method, I successfully dumped the entire code window and data window. The main drawback to this method is that the resulting text will contain alot of noise(unnecessary data). I haven't figured out how to get around this. This is a adaptation of woodmann's method.