- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Trying to learn a little about printing from a windows program:
When PrintDlg() is executed does it create the DEVMODE structure or is the common part ofDEVMODE already in memory?
Why is it necessary to use GlobalLock to retrieve a pointer to the DEVMODE structure, when addresses of other structures can be obtained by loc(structure)? I know that DEVMODE is a movable memory object, but most everything is in memory and is moved around by the OS.
Why is it necessary to use GlobalFree(hDevMode) and GlobalFree(hDevNames) after executing PrintDlg?
Thanks for any info!
Link Copied
4 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
1) PrintDlg creates the DEVMODE structure if PD%hDevMode is NULL on input; otherwise, you're expected to do memory handling yourself
2) The GlobalLock/GlobalFree mechanism is related to memory management. PrintDlg is one of rare APIs which allocates memorywhich you are supposed to use afterwards (again, in case PD%hDevMode.EQ.NULL). Note that most other APIs expect that you prepare the buffer and pass its LOC() and size, and you get a copy of the data. SincePrintDlg does not know from what language it is used, it must use the "least common denominator" memory manager -- native VirtualAlloc/GlobalLock/GlobalUnlock/GlobalFree mechanism. Actually, it's not theissue about "moveable memory" -- rather, once you receive the information about allocated memory (HANDLE PD%hDevMode) in order to release it, you must pass it back to the memory manager which allocated it (GlobalFree). HANDLE must be used rather than LOC because the system can't reliably unmap LOC onto the actual piece of allocated memory.
There's a similarmechanism with e.g. SHBrowseForFolder API -- it returns a LPITEMIDLIST, and you're supposed to release it using appropriate memory deallocator, in this case CoTaskMemFree (but the idea is the same).
Jugoslav
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
JugoslavDujic, thanks for the reply and information. Another question about printing:In a past post you outlined how to change DEVMODE so that the Print Dlg box would be initialized to Landscape paper orientation. The following is my approximation of your example:
type(T_DEVMODE) :: DM
Pointer(pDM, DM)
..
..
..
pd%Flags = PD_RETURNDEFAULT
iret = PrintDlg(pd)
pDM = GlobalLock(pd%hDEVMODE)
DM%Field1%DMORIENTATION = DMORIENT_LANDSCAPE
iret = GlobalUnlock(pd%hDEVMODE)
etc.....
In the Fortran_WinPrint example code (Authored by Steve Lionel and supplied with CVF 6) the procedure appears to be (again in myoutline):
type(T_DEVMODE) :: DEVMODE_struct
! note, no pointer to the DEVMODE_struct
..
pd%Flags = PD_RETURNDEFAULT
iret = PrintDlg(pd)
pDM = GlobalLock(pd%hDEVMODE)
DM%Field1%DMORIENTATION = DMORIENT_LANDSCAPE
iret = DocumentProperties(Null, hPrn, DefPrnName, &
DEVMODE_struct, DM_IN_BUFFER.OR. &
DM_OUT_BUFFER)
iret = GlobalUnlock(pd%hDEVMODE)
etc.....
Just curious.Is there any advantage of one procedure over the other ?
Message Edited by halcyong@fcc.net on 11-27-2004 07:14 AM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Code, called prior to generating print output:
FUNCTION printer_setup (hwin, hdc, orientation) RESULT (ok) IMPLICIT NONE INTEGER,INTENT(IN) :: hwin INTEGER,INTENT(OUT) :: hdc, orientation INTEGER :: lret LOGICAL :: ok TYPE(T_PRINTDLG) :: pd TYPE(T_DOCINFO) :: di ! this is a reworked version of a STRUCTURE TYPE T_DEVMODE_KT integer(BYTE) dmDeviceName(32) ! knowns BYTE integer(WORD) dmSpecVersion ! knowns WORD integer(WORD) dmDriverVersion ! knowns WORD integer(WORD) dmSize ! knowns WORD integer(WORD) dmDriverExtra ! knowns WORD integer(DWORD) dmFields ! knowns DWORD integer(SHORT) dmOrientation ! knowns short integer(SHORT) dmPaperSize ! knowns short integer(SHORT) dmPaperLength ! knowns short integer(SHORT) dmPaperWidth ! knowns short integer(SHORT) dmScale ! knowns short integer(SHORT) dmCopies ! knowns short integer(SHORT) dmDefaultSource ! knowns short integer(SHORT) dmPrintQuality ! knowns short integer(SHORT) dmColor ! knowns short integer(SHORT) dmDuplex ! knowns short integer(SHORT) dmYResolution ! knowns short integer(SHORT) dmTTOption ! knowns short integer(SHORT) dmCollate ! knowns short integer(BYTE) dmFormName(32) ! knowns BYTE integer(WORD) dmLogPixels ! knowns WORD integer(DWORD) dmBitsPerPel ! knowns DWORD integer(DWORD) dmPelsWidth ! knowns DWORD integer(DWORD) dmPelsHeight ! knowns DWORD integer(DWORD) dmDisplayFlags ! knowns DWORD integer(DWORD) dmDisplayFrequency ! knowns DWORD integer(DWORD) dmICMMethod ! knowns DWORD integer(DWORD) dmICMIntent ! knowns DWORD integer(DWORD) dmMediaType ! knowns DWORD integer(DWORD) dmDitherType ! knowns DWORD integer(DWORD) dmReserved1 ! knowns DWORD integer(DWORD) dmReserved2 ! knowns DWORD integer(DWORD) dmPanningWidth ! knowns DWORD integer(DWORD) dmPanningHeight ! knowns DWORD END TYPE T_DEVMODE_KT TYPE(T_DEVMODE_KT) :: devmode POINTER(dm, devmode) pd%lStructSize = SIZEOF(pd) pd%hwndOwner = hwin pd%hDevMode = NULL pd%hDevNames = NULL pd%hDC = NULL pd%Flags = IOR(PD_RETURNDC, PD_PRINTSETUP) pd%nFromPage = 0 pd%nToPage = 0 pd%nMinPage = 0 pd%nMaxPage = 0 pd%nCopies = 1 pd%hInstance = NULL pd%lCustData = 0 pd%lpfnPrintHook = NULL pd%lpfnSetupHook = NULL pd%lpPrintTemplateName = NULL pd%lpSetupTemplateName = NULL pd%hPrintTemplate = NULL pd%hSetupTemplate = NULL ok = PrintDlg (pd) IF (ok) THEN hdc = pd%hdc di%cbSize = SIZEOF (di) di%lpszDocName = LOC("KILTEL plot"C) di%lpszOutput = NULL ! a DevMode structure is returned with information about ! the selected page orientation: portrait=1, landscape=2; ! first, associate the c pointer with the global memory block ! allocated by PrintDlg; u sing GlobalLock works, whereas ! passing dm as the initialization of pd%hDevMode does not (?) dm = GlobalLock (pd%hDevMode) orientation = INT4(devmode%dmOrientation) ! free the DevMode global memory block lret = GlobalFree (pd%hDevMode) IF (orientation /= 2) orientation = 1 ! just to make sure ! need to free this block also lret = GlobalFree (pd%hDevNames) !di%lpszDatatype = !di%fwType = DI_APPBANDING IF (StartDoc(hdc, di) /= SP_ERROR) THEN ok = .TRUE. ELSE ok = .FALSE. lret = MessageBox (hwin,"Printer Problem"C,"Error!"C,MB_OK) END IF END IF END FUNCTION printer_setup
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Paul, thanks for the code example!
Still need some info on why DocumentProperties() was used in Fortran_WinPrint examplesupplied with CVF (see discussion above).Itmay bejust two different ways to achieve the same goal, but using DocumentProperties() may have some subtle advantages. Just curious. Once I get a better grib on the basics, it will be easier to follow the SDK and to address more complicated printing problems. Thanks.

Reply
Topic Options
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page