Is the PrintWindow function currently supported in MASM32?
http://msdn.microsoft.com/en-us/library/ms535695.aspx
Note: I had to install a newer version of the .NET Framework to get it running with C# code
http://www.codeproject.com/KB/cs/CapturingMinimizedWindow.aspx
I have included:
include \masm32\include\masm32rt.inc
well its a windows api, so all you need to do is update the include file if it isn't already there
or use loadlibrary->GetProcAddress to use it...
Quote
Printing Text in Win32
Printing text in Win32 can be a little complicated, but isn't quite as hard as some sources would have you believe. Although if your text has different colors, fonts, and sizes embedded, it can be a little more complicated, generally, It's a pretty simple matter.
First, of course, you'll have to obtain a Printer DC. This can be done using the Print Dialog - described in detail in Common Dialog Box Library - or using GetPrinterDC, bypassing the user entirely. On return, the Print Dialog has placed the printer's DC into the hDC member. This DC will be appropriate to the printer picked by the user. On the other hand, GetPrinterDC returns the DC for the system default printer. If you use this, but still want the user to supply the number of pages and so forth, then you'll have to obtain that information using a dialog, yourself. The Print Dialog returns that info in the PRINTDLG structure. If you want to present the user with all of the options as pertains to the current document, then you'll have to obtain those specs, and pop them into the PRINTDLG structure before calling it up for the user. To have the dialog obtain the various handles needed without having to go through all the steps yourself, then include the PD_RETURNDEFAULT flag in the PRINTDLG structure, and the dialog will not display, but still gather the information. Either way, you'll then have to parse out and use any specifications the user presented. Once those details have been attended to, it's time to set up for printing.
First off, it's best now to determine things such as characters per line, lines per page, and the line spacing to use for proper presentation with all printers. I find it very effective to use GetTextMetrics on the Printer DC, to get the average height of characters of the current font. This I place into a variable for incrementing the vertical position for TextOut. Using this method, I find that my line count - how many lines per page - can be the same for any printer. If the user selected Legal paper, then you can adjust the line count appropriately (get that info from PRINTDLG if used.) As well, you can use that figure for checking to see if any line of text will fall below, or partly below, the last DC line, by subtracting the height of the text from the last line of the DC, and saving that number as a comparison variable. Then, before shooting TextOut, you can see if the Y value of the location is past that minimum value. This prevents clipping the bottom of a line. Believe it or not, I find this method to be totally satisfactory in almost every printing job I program.
Alternatively, you can use GetDeviceCaps for the printer DC, as well as for the display, then divide the display value into the printer value, to obtain a ratio-per-pixel value, which you can then use to set the incremental values.You may very well want to do this for graphics, to scale the output if need be. Next, you can then calculate the lines per page by dividing the result of GetTextMetrics into the overall resolution of the printer, which you can get using GetDeviceCaps and calling up the VERTRES value (you can also use the HORZRES value for line lengths). If line lengths are not important, then you can skip that rigamarole, but if they are, you can use the information from GetTextMetrics and GetDeviceCaps, do the division, and arrive at a "characters per line" figure. Naturally, this will be important if you will be sending wider-than-normal characters, or perhaps mixed sizes in a line. Otherwise, you can use the height of that character to assume that so many characters will fit on a line, and leave it at that.
Once these variables are set, you can calculate the number of pages, if this is important, by dividing the total number of lines - if known - to be printed, by the number of lines per page, adding one page for any remainder of the division. Generally, if you're printing from an edit control or listbox, or similar control, you'll be able to easily get the total number of lines. As well, if the user has selected a certain page number to start and/or end printing at, then a variable for each of these can be set and checked as printing progresses. For page numbering, I just increment a counter every time StartPage is hit, converting and placing the page number on the page. To "skip" pages until a desired one is reached, I just jump to a little proc that loads the strings into a "dead" buffer until the right number has elapsed, then return to the printing proc and pick up sending to a fresh page.
As far as the AbortProc is concerned, if you're not going to actually deal with a "real" proc, then this little gem will serve:
AbortProc proc pdc:DWORD, error:DWORD
;---------------------------------------
return TRUE
;---------------------------------------
AbortProc endp
Yep, it's enough to satisfy Windows. However, if you're supplying an Abort window, then create a modeless dialog and point it's proc at this one. If the user presses the Abort button, set a variable - AbortDoc would be a good name, you think? - and check it each time before hitting StartPage. Actually, you could just as well use a modal dialog, but some consider that rude to tie up the machine until the whole thing's sent to the spooler. And, remember to destroy the dialog using DestroyWindow if it's modeless. In either case, use SetAbortProc to set up, and then, finally and at last, you can use StartDoc.
Once all of the calculations are done, then you can finally load a DOCINFO structure, and invoke StartDoc. The structure only need have it's size set and the lpszOutput member set to NULL (this member contains a null-terminated filename string if printing to a file). If you want to give the document a name (the one you'd see if you clicked up the Print Job box), put it's address into the pDocNamemember. Once done, invoke StartDoc and the race is on!
Here's where your first error checking can be done, if you want to do it, because StartDoc will return a value greater than zero if it's successful. This return value is also useful if you're wanting to set a priority for the print job, such as on a networked printer. You can, by the way, start the print job using only StartPage/EndPage, but the print job can end up interspersed with other jobs when printing.
Assuming success in StartDoc, you can then do any setup for the first page, and hit the inner loop, StartPage. Do any mapping mode changes and object selecting here, because you'll need to every time you hit StartPage. Again, success returns greater than zero. Once inside this tag, you stay there until that page is entirely sent to the printer DC. The functions within can include any of the GDI stuff, so long as you write to the page. Once done with that page - usually when incrementing a line counter and it hits your line number maximum - you catch EndPage. The DC is not actually sent to the Spooler until EndPage is sent, so you can tinker with the image in the DC all you like until sending that command. Again, an error check could be done here, although I fail to see any purpose for it other than to fall through to EndDoc.
Now, here's where you'll want to do your checking to see if you're printing another page, and if so, head back up to StartPage. If you have set a different mapping mode and selected objects into the printer DC, you have to do it again. In NT, it's not necessary, but it doesn't hurt to do it anyway, for compatibility.
If no more pages, just invoke EndDoc, delete the printer DC, and you're all done, folks.
Now for some nasty little details: generally speaking, any character you send to the printer will end up being printed - so this means no linefeeds, carriage returns, or any other such thing. Your proc, including any wordbreak proc, will have to parse them out as it goes. Depending on the type of doc you're printing, there can be quite a set of rules for printable characters. Retrieveing text from a list box or some such makes for no real problems, because you can get the text length of the item which does not include a terminator, and use that to shoot it to the printer DC.
As passed over above, you may also need to check a line for larger fonts, colors, and such before formatting it to send into the DC. If you saved off the horizontal resolution of the printer, then you can use GetTextExtentPoint32 to return the required size. Once you have picked up each section and subtracted it from the total available, you can then parse the line for a break, if need be, and then send that out. Changes to the colors and sizes can be made "as you go", so long as you calculated everything before sending it to the DC. To clarify a little, let's assume you got a horizontal resolution of 2700 for the printer, which is roughly 3-1/2 times that of the display. The text metrics for the selected font tell you the average character width, so you can divide that into the resolution and arrive at a characters per line range. If the line exceeds that, then you'll need to parse back to a line break below the value, and send just that out. This, of course, will also result in resetting your pointer to where you're picking up the text, so the next line won't skip the passed-over characters. Processing any formatting commands will depend on the individual file, of course, but in general, plain text is very simple. Once you're satisfied with the number of characters to be sent, then shoot them to the DC and get onto the next line.
Incrementing lines can be a little tricky, depending on what you're sending into the DC. As with any graphics environment, everything is done in terms of pixels or device units. For the display, of course, you deal with pixels; for a printer, it's dots. Basically - very basically - a printer has many more dots than the display, as discussed above. Every printer has a different resolution, it seems, making it necessary to provide some sort of proc to determine the line lengths, spacing, and so forth. For instance, I have two main printers - a Lexmark Z55, and an HP 712C. The Lexmark has a vertical resolution of over 3683 dots, while the HP has 3150. This makes for totally different ratios, as you can see. Of course, this also represents the printable area, which doesn't include margins, which you implement yourself. So, if you want to keep working in pixels, you simply have to obtain a conversion factor, set that up as the basic unit, then use that unit to adjust your pointer into the printer DC. For instance, once you obtain a multiplied value for the left margin and top margin, when going through the loop of StartPage, just set those values into your POINT structure, and that's where the first line goes. All adjustments to your pointer from then on will use the starting X factor for the beginning of a line, and make life far simpler for you.
There is a bit simpler way to format out and get disparate elements all formulated into a line of print and sent to the DC properly, which I have discovered to be the least-cumbersome method. First off, I designate a buffer large enough, at least, to hold all of the characters likely to fill a line in the printout. Next, I fill the buffer with spaces, then plaster the separate data items - such as columnar data with each item coming from a separate place - making sure no terminating zeroes are put in, except on the last item. Then I use invoke lstrlen, (buffer name) to determine the string length, then use TextOut to shoot it to the DC. If all of this data is shot using the same font (size and weight), then all of the stuff will fall right where you want it to.For dissimilar items, you'll have to keep track of actual pixel counts if you want to have that precision. DrawText prints right into a bitmap, so you may have to use the graphics method to print complex things, involving graphics elements as well as text.
As a little interesting (to me, of course, it was a headache) fact is that the pixel - to - display ratio is a funny thing. For instance, when I set a font to a height of 36 (lf.lfHeight) and sent it to my 200 DPI Lexmark printer, the text came out at just over 1/64 inch tall. Perfectly printed, I might add, but just a hair small for the recipient to read. To calculate relative sizes, I first use LOGFONT to set up a font and place zero in lf.lfHeight, to obtain a default size. This usually results in about a 12-point size. Then I retrieve the value of lfHeight, multiply it by how many itmes larger I want the current font, and plug that back in, use CreateFontIndirect again, then select the new font into the DC. Otherwise, you can use GetTextMetrics and retrieve the tmHeight member, which will give you the default size, as above. You can then use this to multiply (or divide) to achieve proportional sizes within your text. You can also directly manipulate the values in the TEXTMETRIC structure - but you had better be prepared for some mighty strange things when you don't get it just so.
You might not be shooting stuff from a listbox or somesuch, but instead need to arrange individual data items in a columnar format. Trying any other method of "pixelization" can be tricky and might not work right anyway, so for that, use TabbedTextOut. Since when shooting text to a DC, we don't get the convenience of using, say, a columnar listbox, we have to use another method to line everything up. The actual format of the command is
invoke TabbedTextOut, hdc, start X pos, start Y pos, ADDR (buffer), length of string, # of elements in the tab array, ADDR of the tabs array, origin of tab start
The positional members are self-explanatory. Since we should probably be using (I do) a POINT structure for the starting X and Y positions (I name it cpos, so in data it's cpos POINT<>), we should have those numbers available. So, the first one would be cpos.x and the second would be cpos.y. Next, of course, is the address of the string (we'll cover that shortly), the length of the string (i usually use lstrlen to get that), and then we get to the tabs array.
The single most simple method I've managed to devise to set the tabs positions is to first retrieve the TEXTMETRICS tmAveCharWidth member, then multiply it by however many characters I want each tab position set to. So, if I have four columns, I first decide at what character position I want each column to start at, then retrieve and multiply the tmAveCharWidth member by those amounts, and place each into a tabs array. I have first initialized and gotten the TEXTMETRIC structure after creating the currently selected font. Here's what the tabs array looks like in .data and a sample of placing the tab positions at 0, 24, 48, and 72:
TheTabs dd 0, 0, 0, 0
mov eax, tm.tmAveCharWidth
push eax
mov ecx, 24
mul ecx
mov TheTabs[4], eax
pop eax
push eax
mov ecx, 48
mul ecx
mov TheTabs[8], eax
pop eax
mov ecx, 72
mul ecx
mov TheTabs[12], eax
Of course, the tabs array could have as many members as might be used anywhere in our program, but in this case, we would still only use the first four, and tell TabbedTextOut that there's only four. This way, you can reuse the same tab array everywhere in the program.
So, we now have the four TheTabs members set (the first one remains at zero in this example). Next, make absolutely certain to shut off updating of the current position using invoke SetTextAlign,hdc, TA_NOUPDATECP, or else the results will be maybe funny, but certainly not what you intended! Next, you're going to have to format the string from the four data items all into one string, with Tab characters between items, to get this to work. I set up a buffer large enough for the whole finished string, then use lstrcat to place each data item in, place a 9 (tab character), then the next item, and so forth, until all items are placed in the buffer. Then, it's a simple matter - being sure that you've adjusted the X and Y positions for the start of the string properly - to get the string's length, then shoot it using TabbedTextOut like this:
invoke lstrlen, ADDR TheString
invoke TabbedTextOut, hdc, cpos.x, cpos.y, ADDR TheString, eax, 4, ADDR TheTabs, cpos.x
This places the string, with tabs expanded, from the starting point cpos.x, running to the right from there. Using this method, the final member - the origin to use for the tabs - is also the X starting point. Works every time. Naturally, if you have any doubt about the particular item(s) fitting into the space available, you may very well have to use GetTextExtentPoint32 to get the total width of the string, then compare it to the HORZRES member of GetDeviceCaps. This little struggle will, of course, depend on the type of stuff you're sending to the printer DC.
So, to try to put it all in a nutshell for you, here are the steps you can take to print text. The required steps are marked with an asterisk; the others can be used if you need them.
1. Obtain the printer DC*
2. Get the DC's horizontal and vertical resolutions
3. Set mapping mode to MM_TEXT, set color(s)
4. Establish a font and select it into the DC
5. Get the DC's TEXTMETRICs and set line spacing accordingly*
6. Use text metrics and horizontal resolution to set maximum characters per line
7. Use text metrics and vertical resolution to set maximum lines per page
8. Initialize a DOCINFO structure*
9. invoke SetAbortProc*
10. invoke StartDoc*
11. invoke StartPage*
12. Reset mapping mode, reselect objects, colors, etc.*
13. Set desired text to DC*
14. invoke EndPage*
15. If more pages, loop back up to (11)
16. invoke EndDoc*
17. Delete printer DC*
For some items, such as number 5, you might have to calculate those things "on the fly", because of the text involved. After resetting the font to the new size, use GetTextMetrics, then set that height into your line spacing. After finishing that line and resetting the new lower-on-the-page starting point, reset the line spacing to whatever font size is being used in that line, and after finishing that line, reset it again to any new font size. You just have to be sure that you reset to the next line down before using a smaller line spacing, because the next line could print right through the middle of the bigger font above (if that is the case). Otherwise, these steps outline the necessary ones in order to print text.
Example Code:
.data
TAB dd 3
FontTah db 'Tahoma',0
DatePict db "MM'-'dd'-'yyyy",0
TimePict db "hh':'mm':'ss tt",0
szPerR db ')',0
FontPrint LOGFONT <-10,0,0,0,600,FALSE,FALSE,FALSE,0,0,0,0,0,'Courier New'>
.data?
InchesOn dd ?
PageSize dd ?
PrtHeading dd ?
PrtColor dd ?
PH dd ?
.code
;===================================================
; Convert to pixels PROCEDURE
;===================================================
ConvToPix PROC PixelsPerIn:DWORD, VarSize
mov eax, PixelsPerIn
.if InchesOn
imul eax, 10
.else
imul eax, 1000
xor edx, edx
mov ecx, 254
div ecx
.endif
mov ecx, eax
mov eax, VarSize
imul eax, ecx
xor edx, edx
mov ecx, 10000
div ecx
ret
ConvToPix ENDP
;===================================================
; Print document PROCEDURE
;===================================================
Print PROC uses ebx esi
LOCAL tm:TEXTMETRIC
LOCAL lf:LOGFONT
LOCAL psd:PAGESETUPDLG
LOCAL pd:PRINTDLG
LOCAL doci:DOCINFO
LOCAL pt:POINT
LOCAL sz:SIZEL
LOCAL tr:TEXTRANGE
LOCAL rect:RECT
LOCAL hREdit:DWORD, hFontHead, hFontPrt, PtrX, PtrY, PaperX, PaperY, mL, mT, mR, mB, CurLine
LOCAL LinesLeft:DWORD, TabWth, hRgn, PageNum, OffSetX, OffSetY, AvgCharWth, MaxLine, hDC
LOCAL szBuff0[256]:BYTE, szBuff1[256]:BYTE, TimeBuff[32]:BYTE
LOCAL PrtBuff[1024*2]:BYTE, PrtWrap[1024*2]:BYTE
INVOKE GetFocus
mov hREdit, eax
;---------- [Zero out the structures] ----------
INVOKE RtlZeroMemory, addr psd, sizeof psd
INVOKE RtlZeroMemory, addr pd, sizeof pd
INVOKE RtlZeroMemory, addr doci, sizeof doci
INVOKE RtlZeroMemory, addr lf, sizeof lf
;---------- [Fill the page setup structure
mov psd.lStructSize, sizeof psd
push hWnd
pop psd.hwndOwner
push hInst
pop psd.hInstance
mov psd.rtMargin.left, 360
mov psd.rtMargin.top, 360
mov psd.rtMargin.right, 360
mov psd.rtMargin.bottom, 516
mov psd.ptPaperSize.x, 8500
mov psd.ptPaperSize.y, 11000
INVOKE GetDC, hREdit
mov hDC, eax
;---------- [Get page size
INVOKE lstrcpy, addr lf.lfFaceName, addr FontPrint.lfFaceName
INVOKE GetDeviceCaps, hDC, LOGPIXELSY
mov ecx, FontPrint.lfHeight
neg ecx
mul ecx
xor edx, edx
mov ecx, 72
div ecx
neg eax
mov lf.lfHeight, eax
mov eax, FontPrint.lfWeight
mov lf.lfWeight, eax
INVOKE CreateFontIndirect, addr lf
mov hFontPrt, eax
INVOKE SelectObject, hDC, hFontPrt
INVOKE GetDeviceCaps, hDC, LOGPIXELSY
imul eax, 10
push eax
INVOKE GetTextMetrics, hDC, addr tm
pop eax
xor edx, edx
mov ecx, tm.tmHeight
; add ecx, tm.tmInternalLeading
; add ecx, tm.tmExternalLeading
div ecx
.if edx
inc eax
.endif
mov PageSize, eax
INVOKE ReleaseDC, hREdit, hDC
INVOKE DeleteObject, hFontPrt
INVOKE GetUserDefaultLCID
mov edx, eax
INVOKE GetLocaleInfo, edx, LOCALE_IMEASURE, addr szBuff0, sizeof szBuff0
mov InchesOn, 1
.if byte ptr szBuff0 != '1'
mov InchesOn, 0
.endif
INVOKE SendMessage, hREdit, EM_EXGETSEL, 0, addr cr
mov pd.lStructSize, sizeof pd
MOVmd pd.hwndOwner, hWnd
MOVmd pd.hInstance, hInst
mov eax, cr.cpMin
mov ecx, hREdit
.if eax != cr.cpMax || F1SelectOn && ecx == hWndTemp
INVOKE SendMessage, hREdit, EM_GETLINECOUNT, 0, 0
mov ecx, PageSize
xor edx, edx
div ecx
.if edx
inc eax
.endif
mov pd.nMinPage, 1
mov pd.nMaxPage, ax
mov pd.nFromPage, 1
mov pd.nToPage, ax
mov eax, PD_RETURNDC or PD_SELECTION
.else
INVOKE SendMessage, hREdit, EM_GETLINECOUNT, 0, 0
mov ecx, PageSize
xor edx, edx
div ecx
.if edx
inc eax
.endif
mov pd.nMinPage, 1
mov pd.nMaxPage, ax
mov pd.nFromPage, 1
mov pd.nToPage, ax
mov eax, PD_RETURNDC or PD_NOSELECTION or PD_ALLPAGES
.endif
mov pd.Flags, eax
INVOKE PrintDlg, addr pd
.if eax
.if PH != 1
INVOKE GetDateFormat, NULL, NULL, NULL, offset DatePict, addr TimeBuff, 12
mov dword ptr TimeBuff[10], ' '
INVOKE GetTimeFormat, NULL, TIME_FORCE24HOURFORMAT, NULL, offset TimePict, addr TimeBuff[12], 12
mov dword ptr szBuff0, 00202020h
INVOKE lstrcat, addr TimeBuff, addr szBuff0
.endif
INVOKE GetDeviceCaps, pd.hDC, PHYSICALOFFSETX ; = device units left/right margin
mov OffSetX, eax
INVOKE GetDeviceCaps, pd.hDC, PHYSICALOFFSETY ; = device units top/bottom margin
mov OffSetY, eax
INVOKE GetDeviceCaps, pd.hDC, LOGPIXELSX
mov ebx, eax
INVOKE ConvToPix, ebx, psd.ptPaperSize.x
mov PaperX, eax
INVOKE ConvToPix, ebx, psd.rtMargin.left
mov mL, eax
INVOKE ConvToPix, ebx, psd.rtMargin.right
mov mR, eax
INVOKE GetDeviceCaps, pd.hDC, LOGPIXELSY
mov ebx, eax
INVOKE ConvToPix, ebx, psd.ptPaperSize.y
mov PaperY, eax
INVOKE ConvToPix, ebx, psd.rtMargin.top
mov mT, eax
INVOKE ConvToPix, ebx, psd.rtMargin.bottom
mov mB, eax
mov eax, OffSetX
mov ecx, OffSetY
sub mL, eax
sub mT, ecx
add mR, eax
add mB, ecx
INVOKE lstrcpy, addr lf.lfFaceName, addr FontPrint.lfFaceName
INVOKE GetDeviceCaps, pd.hDC, LOGPIXELSY
mov ecx, FontPrint.lfHeight
neg ecx
mul ecx
xor edx, edx
mov ecx, 72
div ecx
neg eax
mov lf.lfHeight, eax
mov eax, FontPrint.lfWeight
mov lf.lfWeight, eax
INVOKE CreateFontIndirect, addr lf
mov hFontPrt, eax
INVOKE lstrcpy, addr lf.lfFaceName, addr FontTah
mov lf.lfHeight, 52
mov lf.lfWeight, 600
INVOKE CreateFontIndirect, addr lf
mov hFontHead, eax
mov doci.cbSize, sizeof doci
mov doci.lpszDocName, offset AppName
mov eax, pd.Flags
and eax, PD_PRINTTOFILE
.if eax
mov eax, 'ELIF'
mov dword ptr szBuff0, eax
mov eax, ':'
mov dword ptr szBuff0+4, eax
lea eax, szBuff0
mov doci.lpszOutput, eax
.else
mov doci.lpszOutput, NULL
.endif
mov doci.lpszDatatype, NULL
mov doci.fwType, NULL
INVOKE StartDoc, pd.hDC, addr doci
mov ecx, hREdit
mov eax, pd.Flags
and eax, PD_SELECTION
xor eax, eax
.if eax
INVOKE SendMessage, hREdit, EM_EXLINEFROMCHAR, 0, cr.cpMin
mov CurLine, eax
mov ecx, PageSize
xor edx, edx
div ecx
mov PageNum, 0 ;eax
INVOKE SendMessage, hREdit, EM_EXLINEFROMCHAR, 0, cr.cpMax
sub eax, CurLine
.if sdword ptr eax < 0 || eax == 0
mov eax, 1
.endif
mov LinesLeft, eax
mov pd.nToPage, -1
.else
movzx eax, pd.nFromPage
dec eax
mov PageNum, eax
imul eax, PageSize
mov CurLine, eax
INVOKE SendMessage, hREdit, EM_GETLINECOUNT, 0, 0
or eax, eax
je AllDone
mov LinesLeft, eax
.endif
mov eax, mL
mov rect.left, eax
mov eax, PaperX
sub eax, mR
mov rect.right, eax
mov eax, mT
mov rect.top, eax
mov eax, PaperY
sub eax, mB
mov rect.bottom, eax
INVOKE CreateRectRgn, rect.left, rect.top, rect.right, rect.bottom
mov hRgn, eax
NextPage:
inc PageNum
mov eax, PageNum
.if ax > pd.nToPage
jmp AllDone
.endif
INVOKE StartPage, pd.hDC
mov eax, mT
mov PtrY, eax
INVOKE SelectObject, pd.hDC, hFontPrt
INVOKE SelectObject, pd.hDC, hRgn
;---------- [Get average character width and max line
mov eax, 'W i.'
mov dword ptr szBuff0, eax
INVOKE GetTextExtentPoint32, pd.hDC, addr szBuff0, 4, addr pt
mov eax, pt.x
shr eax, 2
mov AvgCharWth, eax
xor edx, edx
mov eax, rect.right
mov ecx, AvgCharWth
div ecx
dec eax
mov MaxLine, eax
;---------- [Get tab width
mov eax, 'WWWW'
mov dword ptr szBuff0, eax
INVOKE GetTextExtentPoint32, pd.hDC, addr szBuff0, 4, addr pt
mov eax, pt.x
shr eax, 2
imul eax, TAB
mov TabWth, eax
push pt.y
mov PrtHeading, 1
mov PrtColor, 1
;---------- [Page number
.if PrtHeading
INVOKE SelectObject, pd.hDC, hFontHead
mov eax, 'gaP('
mov dword ptr szBuff0, eax
mov word ptr szBuff0[4], ' e'
INVOKE BaseAscii, PageNum, addr szBuff0[6], 0, 10, 0, 1, 1
INVOKE lstrcat, addr szBuff0, addr szPerR
.if PH != 1
INVOKE lstrcpy, addr PrtBuff, addr TimeBuff
INVOKE lstrcat, addr PrtBuff, addr szBuff0
.else
INVOKE lstrcpy, addr PrtBuff, addr szBuff0
.endif
INVOKE lstrlen, addr FileName
mov ebx, eax
mov eax, mL
mov PtrX, eax
.if PrtColor
INVOKE SetTextColor, pd.hDC, 00ff0000h
.endif
INVOKE TextOut, pd.hDC, PtrX, PtrY, addr FileName, ebx
INVOKE lstrlen, addr PrtBuff
mov ebx, eax
INVOKE GetTextExtentPoint32, pd.hDC, addr PrtBuff, ebx, addr pt
mov eax, PaperX
sub eax, mR
sub eax, pt.x
mov PtrX, eax
push pt.x
.if PrtColor
INVOKE SetTextColor, pd.hDC, 00ffff00h
.endif
INVOKE TextOut, pd.hDC, PtrX, PtrY, addr TimeBuff, ebx
INVOKE lstrlen, addr szBuff0
mov ebx, eax
INVOKE GetTextExtentPoint32, pd.hDC, addr szBuff0, ebx, addr pt
pop ecx
mov eax, pt.x
add PtrX, ecx
sub PtrX, eax
.if PrtColor
INVOKE SetTextColor, pd.hDC, 00000000h
.endif
INVOKE TextOut, pd.hDC, PtrX, PtrY, addr szBuff0, ebx
mov eax, pt.y
add PtrY, eax
shr eax, 1
add PtrY, eax
INVOKE SelectObject, pd.hDC, hFontPrt
.endif
pop pt.y
NextLine:
mov eax, PtrY
add eax, pt.y
cmp eax, rect.bottom
jnb EndOfPage
mov eax, mL
mov PtrX, eax
INVOKE SendMessage, hREdit, EM_LINEINDEX, CurLine, 0
mov tr.chrg.cpMin, eax
INVOKE SendMessage, hREdit, EM_LINELENGTH, eax, 0
add eax, tr.chrg.cpMin
mov tr.chrg.cpMax, eax
inc CurLine
lea eax, PrtBuff
mov tr.lpstrText, eax
INVOKE SendMessage, hREdit, EM_GETTEXTRANGE, 0, addr tr
.if LinesLeft == 1 && byte ptr PrtBuff == 0dh
jmp EndOfLine
.endif
or eax, eax
je EndOfLine
.if PrtColor
INVOKE SetTextColor, pd.hDC, 00008000h ;PrnColors[16]
.endif
LoopLine:
xor esi, esi
INVOKE lstrlen, addr PrtBuff
mov ebx, eax
.if ebx >= MaxLine
mov ebx, MaxLine
INVOKE lstrcpy, addr PrtWrap, addr PrtBuff[ebx]
mov esi, 1
.endif
INVOKE TabbedTextOut, pd.hDC, PtrX, PtrY, addr PrtBuff, ebx, 1, addr TabWth, PtrX
.if PrtColor
INVOKE lstrcpyn, addr szBuff0, addr PrtBuff, 9
INVOKE SetTextColor, pd.hDC, 000000ffh
INVOKE TabbedTextOut, pd.hDC, PtrX, PtrY, addr szBuff0, 8, 1, addr TabWth, PtrX
INVOKE lstrcpyn, addr szBuff0, addr PrtBuff+9, 40
INVOKE SetTextColor, pd.hDC, 00000000h
mov ecx, 9
imul ecx, AvgCharWth
add ecx, PtrX
INVOKE TabbedTextOut, pd.hDC, ecx, PtrY, addr szBuff0, 39, 1, addr TabWth, PtrX
.endif
EndOfLine:
mov eax, pt.y
add PtrY, eax
.if esi
INVOKE lstrcpy, addr PrtBuff, addr PrtWrap
jmp LoopLine
.endif
dec LinesLeft
je EndOfPage
jmp NextLine
EndOfPage:
INVOKE EndPage, pd.hDC
.if LinesLeft
jmp NextPage
.endif
AllDone:
INVOKE EndDoc, pd.hDC
INVOKE DeleteDC, pd.hDC
INVOKE DeleteObject, hFontHead
INVOKE DeleteObject, hFontPrt
INVOKE DeleteObject, hRgn
.endif
ret
Print ENDP
Paul
Thanks,
I used:
.data
_PrintWindow db "PrintWindow",0
_user32 db "user32",0
.code
invoke GetModuleHandle,offset _user32
invoke GetProcAddress,eax,offset _PrintWindow
push 0
push memDC
push hwnd
call eax
In the current beta version 10 you have this prototype in user32.inc.
PrintWindow PROTO :DWORD,:DWORD,:DWORD