I initialize the PageSetupDlg.flags with PSD_INHUNDREDTHSOFMILLIMETERS or PSD_MARGINS and have been using A4 = 210 mm x 294 mm as my default papersize.
I then have been converting the formated range of a richedit control to twips by multiplying the mm dimensions by the factor 56.7, before sending to the printer. This works OK for me.
My problem is this, when I use PSD_INTHOUSANDTHSOFINCHES or PSD_MARGINS and select Letter (8.5 inch x 12 inch) as my papersize, I have a problem with the twips procedure because its setup for mm conversion and not inch conversion.
My question is this, can some demonstrate a English twips procedure or a procedure that can be applied to any selected papersize, whether English format or metric format is required or used by the user on the fly, or at least provide me a good convsersion formula.
Thanks, Steve
"There are 1440 twips to an inch, 567 twips to a centimeter"
http://support.microsoft.com/kb/76388
Here is an excerpt from my print routine. The twips macro might be helpful (although I must admit I have not fully understood your problem - it's a very simple conversion...).
twips MACRO arg
push arg
call twipsP
EXITM <eax>
ENDM
; 567 twips per cm: A4 = 21 X 29,7 cm
; twips = 21*567 X 29.7X567 = 11907 * 16839,9
PrintRTF proc
LOCAL fSuccess:SDWORD
LOCAL hPrDC:DWORD
LOCAL OldSel:CHARRANGE
LOCAL psd:PAGESETUPDLG
LOCAL docInfo:DOCINFO
LOCAL fr:FORMATRANGE
call ClearLocVars ; clear all structure elements
push edi
push esi
mov psd.lStructSize, sizeof PAGESETUPDLG
.data
prtMargins dd 700, 100, 900, 700
.code
mov esi, offset prtMargins
lea edi, psd.rtMargin
m2m ecx, 4
push ecx
push esi
push edi
mov psd.Flags, PSD_INHUNDREDTHSOFMILLIMETERS or PSD_DEFAULTMINMARGINS ;PSD_MARGINS
; mov psd.DEVMODE.dmScale, 50
rep movsd
m2m psd.hwndOwner, hWin
invoke PageSetupDlg, addr psd ; get a printer device context
pop esi ; the unchanged order is
pop edi ; intentional: we swap the pointers
pop ecx
.if eax==0
invoke CommDlgExtendedError
test eax, eax
jne PriError
.else
rep movsd
invoke GlobalLock, psd.hDevMode
push eax
; mov [eax.DEVMODE.dmScale], 80 ; optional scaling of output
mov esi, rv(GlobalLock, psd.hDevNames)
movzx eax, word ptr [esi.DEVNAMES.wOutputOffset]
add eax, esi
push eax
movzx eax, word ptr [esi.DEVNAMES.wDeviceOffset]
add eax, esi
push eax
movzx eax, word ptr [esi.DEVNAMES.wDriverOffset]
add eax, esi
push eax
call CreateDC ; hPrDC=CreateDC(lpszDriver, lpszDevice, lpszOutput, pDeviceMode)
mov hPrDC, eax
invoke GlobalUnlock, psd.hDevNames
invoke GlobalUnlock, psd.hDevMode
ShowDevCaps = 0
if ShowDevCaps eq 0
invoke GlobalFree, psd.hDevNames
invoke GlobalFree, psd.hDevMode
else
pushad
pushad
mov esi, rv(GlobalLock, psd.hDevMode) ; we need to access the memory
movzx eax, word ptr [esi.DEVMODE.dmOrientation] ; it's a "short" variable, but Masm needs "word"
.if eax==DMORIENT_PORTRAIT
MsgBox 0, "Portrait", "Hi", MB_OK
.elseif eax==DMORIENT_LANDSCAPE
MsgBox 0, "Landscape", "Hi", MB_OK
.else
MsgBox 0, "WTF", 0, MB_OK
.endif
invoke GlobalUnlock, psd.hDevMode ; unlock the mem
invoke GlobalFree, psd.hDevMode ; and free it
popad
mov ebx, rv(GetDeviceCaps, hPrDC, PHYSICALWIDTH) ; yields 4960, a factor 2.x too small
mov esi, rv(GetDeviceCaps, hPrDC, PHYSICALHEIGHT) ; yields 7015 - expected 16840 for A4
mov edi, rv(GetDeviceCaps, hPrDC, PHYSICALOFFSETY) ; yields 100
deb 1, "GdCaps", ebx, esi, edi
popad
jmp @F
endif
mov docInfo.cbSize, sizeof DOCINFO
mov docInfo.lpszDocName, chr$("TinyRtf")
invoke StartDoc, hPrDC, addr docInfo ; start a print job
.if eax==SP_ERROR
invoke DeleteDC, hPrDC
jmp PriError
.endif
; invoke SendMessage, hEdit, EM_SETTARGETDEVICE, hPrDC, cxPhys ; not needed
m2m fr.hdc, hPrDC
m2m fr.hdcTarget, hPrDC
mov fr.rc.left, twips(psd.rtMargin.left) ; psd:PAGESETUPDLG
neg eax
mov fr.rc.right, eax
add fr.rc.right, twips(psd.ptPaperSize.x)
sub fr.rc.right, twips(psd.rtMargin.right)
mov fr.rc.top, twips(psd.rtMargin.top)
neg eax
mov fr.rc.bottom, eax
add fr.rc.bottom, twips(psd.ptPaperSize.y)
sub fr.rc.bottom, twips(psd.rtMargin.bottom)
; Get the current selection into a CHARRANGE
invoke SendMessage, hEdit, EM_EXGETSEL, 0, addr fr.chrg
mov eax, fr.chrg.cpMax
mov edx, fr.chrg.cpMin
mov OldSel.cpMax, eax
mov OldSel.cpMin, edx
sub eax, edx
.if sdword ptr eax<=127 ; User has not selected a lot of text, therefore print all pages
invoke SendMessage, hEdit, EM_SETSEL, 0, -1
invoke SendMessage, hEdit, EM_EXGETSEL, 0, addr fr.chrg
.endif
; Use GDI to print successive pages
.Repeat
invoke StartPage, hPrDC
mov fSuccess, eax
.Break .if sdword ptr eax<=0
push fr.rc.bottom
invoke SendMessage, hEdit, EM_FORMATRANGE, 1, addr fr
pop fr.rc.bottom
; The rc.bottom member may be changed after the message is sent. If it is changed, it must indicate the
; largest rectangle that can fit within the bounds of the original rectangle and still contain the specified
; text without printing partial lines. It may be necessary to reset this value after each page is printed.
; These dimensions are given in TWIPS. ([url=http://support.microsoft.com/kb/129860]MS Support[/url])
; deb 1, "Loop", eax, fr.chrg.cpMin, fr.chrg.cpMax
.Break .if eax<=fr.chrg.cpMin
.Break .if eax>=fr.chrg.cpMax
mov fr.chrg.cpMin, eax
invoke EndPage, hPrDC
mov fSuccess, eax
.Until sdword ptr eax<=0
invoke SendMessage, hEdit, EM_FORMATRANGE, 0, 0 ; free the cache, important
.if fSuccess>0
invoke EndDoc, hPrDC
.else
invoke AbortDoc, hPrDC
.endif
invoke DeleteDC, hPrDC
invoke SendMessage, hEdit, EM_EXSETSEL, 0, addr OldSel ; restore old selection
.endif
; mov eax, fSuccess
@@:
pop esi
pop edi
ret
PriError:
MsgBox 0, "Printing problem", 0, MB_OK
jmp @B
PrintRTF endp
twipsP proc
.data
tw2cm REAL4 0.567
.code
ffree st(7)
ffree st(7)
fld tw2cm
fild dword ptr [esp+4]
fmul
fistp dword ptr [esp+4]
pop edx
pop eax
jmp edx
twipsP endp
Thanks JJ I will look thru your example.
Thanks Michael, I knew there was as standard, just could not find it.
Steve