Solved

How to use PageSetUp API function from VB?

Posted on 1998-12-17
11
374 Views
Last Modified: 2008-03-10
I have found examples of how to use this API function from C code, but I do not know how to convert this to work in VB. For example I don't now how to reference a structure by its 'handle' which I must do to initialise the structure passed to the function.
0
Comment
Question by:burkmar
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 7
  • 3
11 Comments
 
LVL 1

Expert Comment

by:muffinthedog
ID: 1451126
burkmar,
think all your going to have to do is declare a variable of type
PAGESETUPDIALOG
Dim MyPageSetupDialog as PAGESETUPDIALOG

set all the elements of the structure for the lStructSize
set the lStructSize to Len(MyPageSetupDialog)
and call the PageSetupDlg function passing the structure
ret = PageSetupDlg(MyPageSetupDialog)

The structure will be passed by reference
0
 

Author Comment

by:burkmar
ID: 1451127

I have done this and all is well - the function invokes the page set up dialog, but the problem is that if I want to query, for example the page orientation specified by the user, this is NOTavailable directly from any of the components of the PAGESETUPDIALOG structure.  Instead its available from a structure called DEVMODE which is referenced by the PAGESETUPDIALOG structure - but only by a 'handle' to it.  Calling PageSetUpDlg with this component uninitialised, dynamically allocates storage for the DEVMODE structure and, I think, populates it with the info I need, but I do not know how to access it.  If declare a variable of type DEVMODE first, I don't know how I get its 'handle' to put into my PAGESETUPDIALOG structure.  It sounds complicated - try it and you will see what I mean.
0
 
LVL 1

Expert Comment

by:muffinthedog
ID: 1451128
burkmar,
    give me a bit and I'll see what I can do...
0
Online Training Solution

Drastically shorten your training time with WalkMe's advanced online training solution that Guides your trainees to action. Forget about retraining and skyrocket knowledge retention rates.

 
LVL 1

Expert Comment

by:muffinthedog
ID: 1451129
burkmar,

Dim dwRet As Long
Dim PSD As PAGESETUPDLG
Dim DM As DEVMODE
Dim pDevMode As Long

PSD.hwndOwner = Form1.hWnd
PSD.lStructSize = Len(PSD)

dwRet = PAGESETUPDLG(PSD)
If PSD.hDevMode Then
    pDevMode = GlobalLock(PSD.hDevMode)
    GlobalFree (PSD.hDevMode)
    CopyMemory DM, pDevMode, Len(DM)
    'Do whatever with DM here
End If
End Sub

Declare Function GlobalLock Lib "kernel32" (ByVal hMem As Long) As Long
Declare Function GlobalFree Lib "kernel32" (ByVal hMem As Long) As Long
Declare Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" (lpvDest As Any, ByVal lpvSource As Any, ByVal cbCopy As Long)

0
 
LVL 1

Expert Comment

by:muffinthedog
ID: 1451130
burkmar,
    Call GlobalFree after CopyMemory... sorry
0
 
LVL 1

Accepted Solution

by:
muffinthedog earned 150 total points
ID: 1451131
bufkmar,
    see previous comments...

If need set structure before calling just use GlobalAlloc... sorry not a better example, but time...
0
 

Author Comment

by:burkmar
ID: 1451132
Muffinthedog,

Thanks for your excellent help - I'm certainly learning a lot, but everytime some questions get answered, it just throws up more.  When I tried your example and queried the values in DM, they are all zero or empty.  In the information I've seen about using the PageSetUpDlg from 'C', the value of .hDevMode must be Null for the function to populate the structure with the defaults.  However I don't see how I can set a Long value to Null in VB - any ideas.  I tried doing a GlobalAlloc to allocate memory to it first - but no good.  I also tried populating the structure before calling the function (using GlobalAlloc, GlobalLock, CopyMemory and GlobalUnlock) but I just get some very weird results.

I appreciate that I have taken a lot of your time already, but yours is the best help I've had from any source in the WWWorld(!) so I'm going to be cheeky and ask for more!

Many thanks for the help you've already given me.
0
 
LVL 1

Expert Comment

by:muffinthedog
ID: 1451133
burkmar,
    try the following and let me know what happens...

Open a new project and add a command button to Form1

Put the following in the click event of the button

Dim PSD As PAGESETUPDLG
Dim DM As DEVMODE
Dim pDevMode As Long

PSD.hwndOwner = Form1.hWnd
PSD.lStructSize = Len(PSD)

dwRet = PAGESETUPDLG(PSD)
If PSD.hDevMode Then
    pDevMode = GlobalLock(PSD.hDevMode)
    CopyMemory DM, pDevMode, Len(DM)
    GlobalFree (PSD.hDevMode)
    'Do whatever with DM here
    MsgBox "DeviceName = " & DM.dmDeviceName
    MsgBox "Version Number = " & DM.dmSpecVersion
    MsgBox "Driver Version = " & DM.dmDriverVersion
    MsgBox "DEVMODE Size = " & DM.dmSize
    MsgBox "Private Data Size = " & DM.dmDriverExtra
    MsgBox "Paper Orientation = " & DM.dmOrientation
End If
End Sub

Add a module to the project and add the following...

Declare Function PAGESETUPDLG Lib "comdlg32.dll" Alias "PageSetupDlgA" (pPagesetupdlg As PAGESETUPDLG) As Long
Declare Function GlobalLock Lib "kernel32" (ByVal hMem As Long) As Long
Declare Function GlobalFree Lib "kernel32" (ByVal hMem As Long) As Long
Declare Function GlobalSize Lib "kernel32" (ByVal hMem As Long) As Long
Declare Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" (lpvDest As Any, ByVal lpvSource As Any, ByVal cbCopy As Long)

Public Const PSD_DEFAULTMINMARGINS = &H0 '  default (printer's)
Public Const PSD_DISABLEMARGINS = &H10
Public Const PSD_DISABLEORIENTATION = &H100
Public Const PSD_DISABLEPAGEPAINTING = &H80000
Public Const PSD_DISABLEPAPER = &H200
Public Const PSD_DISABLEPRINTER = &H20
Public Const PSD_ENABLEPAGEPAINTHOOK = &H40000
Public Const PSD_ENABLEPAGESETUPHOOK = &H2000 '  must be same as PD_*
Public Const PSD_ENABLEPAGESETUPTEMPLATE = &H8000 '  must be same as PD_*
Public Const PSD_ENABLEPAGESETUPTEMPLATEHANDLE = &H20000 '  must be same as PD_*
Public Const PSD_INHUNDREDTHSOFMILLIMETERS = &H8 '  3rd of 4 possible
Public Const PSD_INTHOUSANDTHSOFINCHES = &H4 '  2nd of 4 possible
Public Const PSD_INWININIINTLMEASURE = &H0 '  1st of 4 possible
Public Const PSD_MARGINS = &H2 '  use caller's
Public Const PSD_MINMARGINS = &H1 '  use caller's
Public Const PSD_NOWARNING = &H80 '  must be same as PD_*
Public Const PSD_RETURNDEFAULT = &H400 '  must be same as PD_*
Public Const PSD_SHOWHELP = &H800 '  must be same as PD_*

Public Const CCHDEVICENAME = 32
Public Const CCHFORMNAME = 32

Type DEVMODE
        dmDeviceName As String * CCHDEVICENAME
        dmSpecVersion As Integer
        dmDriverVersion As Integer
        dmSize As Integer
        dmDriverExtra As Integer
        dmFields As Long
        dmOrientation As Integer
        dmPaperSize As Integer
        dmPaperLength As Integer
        dmPaperWidth As Integer
        dmScale As Integer
        dmCopies As Integer
        dmDefaultSource As Integer
        dmPrintQuality As Integer
        dmColor As Integer
        dmDuplex As Integer
        dmYResolution As Integer
        dmTTOption As Integer
        dmCollate As Integer
        dmFormName As String * CCHFORMNAME
        dmUnusedPadding As Integer
        dmBitsPerPel As Integer
        dmPelsWidth As Long
        dmPelsHeight As Long
        dmDisplayFlags As Long
        dmDisplayFrequency As Long
End Type

Type POINTAPI
        x As Long
        y As Long
End Type

Type RECT
        Left As Long
        Top As Long
        Right As Long
        Bottom As Long
End Type

Type PAGESETUPDLG
        lStructSize As Long
        hwndOwner As Long
        hDevMode As Long
        hDevNames As Long
        flags As Long
        ptPaperSize As POINTAPI
        rtMinMargin As RECT
        rtMargin As RECT
        hInstance As Long
        lCustData As Long
        lpfnPageSetupHook As Long
        lpfnPagePaintHook As Long
        lpPageSetupTemplateName As String
        hPageSetupTemplate As Long
End Type

Run the program and click the command button...

When the printer setup dialog comes up, just click the OK button and see if anything is returned by the MsgBox statements...

If not, would you like a C wrapper DLL (kinda defeats the purpose though)?
0
 
LVL 1

Expert Comment

by:muffinthedog
ID: 1451134
""
hDevMode

Handle to a global memory object that contains a DEVMODE structure. On input, if a handle is given, the values in the corresponding DEVMODE structure are used to initialize the controls in the dialog box. On output, the dialog box sets hDevMode to a global memory handle for a DEVMODE structure that contains values specifying the user’s selections. If the user’s selections are not available, the dialog box sets hDevMode to NULL.


0
 

Author Comment

by:burkmar
ID: 1451135
Muffinthedog,

Your example worked superbly.  I thought that I'd tried this exact method after your last advice, but the code I am working with was so full of commented out efforts and garbage that I must of missed something.  Your help has been superb.  Many, many thanks.

Burkmar.
0
 
LVL 7

Expert Comment

by:JimMorgan
ID: 2130884
MuffinTheDog:

With the new search engine in EE, I was searching around for information on programmatically changing the pagesetup from VBA.  This is close, however we don't have the rich language capabilities of VB.

One of the problems we seem to find is when we try to prtDevMode in VBA and the database is made into a MDE, the code will not work.  I've been contemplating creating a VB routine outside of Access so that the current pagesetup for the printer could be saved, pagesetup changed either from user's desires or programatically, return to Access to view/print the report, then make another outside call to set the pagesetup back to its original state.

Do you think that these routines could be modified to do that?  It sure will help out a lot of us out over in the Access topic.

Thanks,

Jim
0

Featured Post

Instantly Create Instructional Tutorials

Contextual Guidance at the moment of need helps your employees adopt to new software or processes instantly. Boost knowledge retention and employee engagement step-by-step with one easy solution.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Have you ever wanted to restrict the users input in a textbox to numbers, and while doing that make sure that they can't 'cheat' by pasting in non-numeric text? Of course you can do that with code you write yourself but it's tedious and error-prone …
You can of course define an array to hold data that is of a particular type like an array of Strings to hold customer names or an array of Doubles to hold customer sales, but what do you do if you want to coordinate that data? This article describes…
Get people started with the process of using Access VBA to control Outlook using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Microsoft Outlook. Using automation, an Access applic…
Get people started with the process of using Access VBA to control Excel using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Excel. Using automation, an Access application can laun…

728 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question