Pages: [1]
|
 |
|
Author
|
Topic: PrintWindow API support (Read 5497 times)
|
loki_dre
Guest
|
|
|
|
Logged
|
|
|
|
evlncrn8
|
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...
|
|
|
Logged
|
|
|
|
PBrennick
Never be satisfied
Member
    
Gender: 
Posts: 2096
Never under-estimate the power of an idea
|
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
|
|
|
Logged
|
|
|
|
loki_dre
Guest
|
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
|
|
|
Logged
|
|
|
|
hutch--
Administrator
Member
    
Posts: 12013
Mnemonic Driven API Grinder
|
In the current beta version 10 you have this prototype in user32.inc. PrintWindow PROTO :DWORD,:DWORD,:DWORD
|
|
|
Logged
|
|
|
|
|
Pages: [1]
|
|
|
 |