Solved

API call from Access 97

Posted on 1998-04-20
6
394 Views
Last Modified: 2008-02-01
Please Help!

I am trying to upgrade my Access 2.0 (16-bit) application to Access 97 (32-bit). My problem is with calls
to the Windows API from Access 97.  Basically what I am trying to do is: (1) open an "Explorer type window"
to display the file tree (This seems to work fine with the "GetOpenFileName" function), (2) send some default
paths with the "xFilter$" variable, (3) Select the file in the Explore type window and capture the File and path
to the xfilename$ variable, (4) send the Title$ variable "Select File" to the Explorer type window titlebar.  The problem seems to be with the "lstrcpy" function.  I have included some of my code to maybe help with the
solution.  This code seems to work fine when used in the Access 2.0 16 bit version. (with obvious changes
to the dll file names).  I would really appreciate anyone's help on this!


**MY Code *******************************************************************
Option Compare Database   'Use database order for string comparisons
Option Explicit

Type tagOPENFILENAME
     lStructSize As Long
     hWndOwner As Long
     hInstance As Long
     lpstrFilter As String
     lpstrCustomFilter As String
     nMaxCustFilter As Long
     nFilterIndex As Long
     lpstrFile As String
     nMaxFile As Long
     lpstrFileTitle As String
     nMaxFileTitle As Long
     lpstrInitialDir As String
     lpstrTitle As String
     flags As Long
     nFileOffset As Integer
     nFileExtension As Integer
     lpstrDefExt As String
     lCustData As Long
     lpfnHook As Long
     lpTemplateName As String
End Type

Public Declare Function GetOpenFileName Lib "comdlg32.dll" Alias "GetOpenFileNameA" (OPENFILENAME As tagOPENFILENAME) As Long

Public Declare Function GetSaveFileName Lib "comdlg32.dll" Alias "GetSaveFileNameA" (OPENFILENAME As tagOPENFILENAME) As Long

Public Declare Function lstrcpy& Lib "kernel32" Alias "lstrcpyA" (ByVal lpString1 As String, ByVal lpsSring2 As String)

Dim OPENFILENAME As tagOPENFILENAME


Function OpenCommDlg(F As Form) As String
 
  Dim xFilter$, xfilename$, FileTitle$, DefExt$
  Dim Title$, szCurDir$, APIResults%
 
  On Error GoTo Err_OpenCommDlg
   
    F.Visible = 0

    '*Define the filter string and allocate space in the "c" string
xFilter = "All (*.*)" & vbNullChar & "*.*" & vbNullChar
     xFilter = xFilter & "Text (*.txt)" & vbNullChar & "*.TXT" & vbNullChar
     xFilter$ = xFilter & "Access (*.mdb)" & vbNullChar & "*.MDB" & vbNullChar

    '* Allocate string space for the returned strings.
    xfilename$ = vbNullChar & Space$(255) & vbNullChar
    FileTitle$ = Space$(255) & vbNullChar

    '* Give the dialog a caption title.
    Title$ = "Select File" & vbNullChar

    '* If the user does not specify an extension, append TXT.
    DefExt$ = "TXT" & vbNullChar

    '* Set up the default directory
    szCurDir$ = CurDir$ & vbNullChar

    '* Set up the data structure before you call the GetOpenFileName

    OPENFILENAME.lStructSize = Len(OPENFILENAME)
    OPENFILENAME.hWndOwner = F.hwnd
    OPENFILENAME.lpstrFilter = lstrcpy(xFilter$, xFilter$)
    OPENFILENAME.nFilterIndex = 1
    OPENFILENAME.lpstrFile = lstrcpy(xfilename$, xfilename$)
    OPENFILENAME.nMaxFile = Len(xfilename$)
    OPENFILENAME.lpstrFileTitle = lstrcpy(FileTitle$, FileTitle$)
    OPENFILENAME.nMaxFileTitle = Len(FileTitle$)
    OPENFILENAME.lpstrTitle = lstrcpy(Title$, Title$)
    OPENFILENAME.lpstrDefExt = lstrcpy(DefExt$, DefExt$)
    OPENFILENAME.hInstance = 0
    OPENFILENAME.lpstrCustomFilter = 0
    OPENFILENAME.nMaxCustFilter = 0
    OPENFILENAME.lpstrInitialDir = lstrcpy(szCurDir$, szCurDir$)
    OPENFILENAME.nFileOffset = 0
    OPENFILENAME.nFileExtension = 0
    OPENFILENAME.lCustData = 0
    OPENFILENAME.lpfnHook = 0
    OPENFILENAME.lpTemplateName = 0

    '* This will pass the desired data structure to the Windows API,
    '* which will in turn use it to display the Open Dialog form.
Retry:

    APIResults% = GetOpenFileName(OPENFILENAME)
    If Len(RTrim$(xfilename$)) <= 1 Then GoTo Retry
    If APIResults% <> 0 Then
        OpenCommDlg = RTrim$(xfilename$)
    End If
    F.Visible = -1

Exit_OpenCommDlg:
    On Error GoTo 0
    Exit Function

Err_OpenCommDlg:
    MsgBox Err & " " & Error$, , "Open Common Dialog"
    Resume Exit_OpenCommDlg

End Function
0
Comment
Question by:fairfax
  • 4
  • 2
6 Comments
 
LVL 6

Expert Comment

by:clifABB
ID: 1425698
Two things I notice:

First, you are copying from xFilter$ to xFilter$
OPENFILENAME.lpstrFilter = lstrcpy(xFilter$, xFilter$)

Second (a less important but you should change it anyway), you have declared APIResults as in integer (%) it should be a long (%)

0
 
LVL 6

Expert Comment

by:clifABB
ID: 1425699
Sorry, that last sentense should read:
Second (a less important but you should change it anyway), you have declared APIResults as in integer (%) it should be a long (&)
0
 

Author Comment

by:fairfax
ID: 1425700
Thanks for your suggestions clifABB, but either I am too dense or I am overlooking something.  Anyway, I made the following code changes.
*************
Dim yFilter$, xTitle$

OPENFILENAME.lpstrFilter = lstrcpy(yFilter$, xFilter$)
OPENFILENAME.lpstrTitle = lstrcpy(xTitle$, Title$)

'Changed all APIResults variables from APIResults% to APIResults&

Based on the variables I'am trying to pass to the File Tree Window, I would expect the following results: Titlebar would read "Select File"   - instead, it reads 0.
                  in the ' Files of type' combo box, I expect to see - "All (*.*)"
                                                                                                 "*.*"  
                                                                                     "Text (*.txt)"
                                                                                             "*.TXT"  
again the value I actually see is 0.

Hope you have a couple of more suggestions I can try. Thanks!
         xFilter$ = xFilter & "Access (*.mdb)" & vbNullChar & "*.MDB" & vbNullChar
0
Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

 
LVL 6

Accepted Solution

by:
clifABB earned 100 total points
ID: 1425701
I'm sorry, I was completely wrong when I had you change lstrcpy from
lstrcpy(xFilter$, xFilter$)
to
lstrcpy(yFilter$, xFilter$)

I didn't completely realize what you were doing until I ran your code myself.  Basically what lstrcpy(xFilter$, xFilter$) doesn is return the pointer to the string.

With this knowledge, I can solve your problem.

In your structure (tagOPENFILENAME) change all occurances of string to long
example:
lpstrFileTitle As String -> lpstrFileTitle As Long

You are passing pointers to the strings, not the strings themselves.

This will work, I ran your code on my machine with these changes (including changing yFilter back to xFilter).

Now, I'm curious.  Why are you using the API to open the file dialog rather than the common dialog control?
0
 

Author Comment

by:fairfax
ID: 1425702
ClifABB, thanks for the extra input - I tried your suggestion with reference to xFilter and it worked great!  However I wasn't as successful when passing the other variables filename$, Title$, Filetitle$ and DefExt$).  Also from time to time the application has problems opening the File tree window.  -- I appreciate you sticking with me on this one.  I don't want to nickle-dime you on this but I would really appreciate your followup.  This is my first question to "Experts-Exchange" (what a great service!) so I'am not sure how to award these points at this time.  I want to make sure you get credit since you have been so helpful.  So I'am just going to give you the 100 points and look for any additional info you can give.  Thank again!
0
 
LVL 6

Expert Comment

by:clifABB
ID: 1425703
I don't mind.  As long as the questions refer to this initial question, then it's fair.  On the other hand, if the questions start drifting too far, then you should post a separate question.

First off, to your other variables (filename$ etc), they should all look similar:
OPENFILENAME.lpstrFile = lstrcpy(xfilename$, xfilename$)

And, in the structure tagOPENFILENAME, all declares that are strings should be declared as long.

Now, as to the question of my last comment, just curious why you aren't using the commondialog control that comes with Access?

Excuse me if I underestimate you but here's how to use it:

Place the commondialog control on your main form (preferably one that won't be closed when you use it).  Do this by selecting the menu option 'Insert/Activex Controls...'
Select Microsoft Common Dialog Control and click ok.

Now, using your code from above (with changes):

Function OpenCommDlg(F As Form) As String
   
  Dim xFilter$, xfilename$, FileTitle$, DefExt$
  Dim Title$, szCurDir$, APIResults%
   
  On Error GoTo Err_OpenCommDlg
     
    F.Visible = 0

    '*Define the filter string and allocate space in the "c" string
  xFilter = "All (*.*)|*.*|Text (*.txt)|*.TXT|Access (*.mdb)|*.MDB"

    '* Give the dialog a caption title.
    Title$ = "Select File"

    '* If the user does not specify an extension, append TXT.
    DefExt$ = "TXT"

    ActiveXCtl1.Filter = Filter$
    ActiveXCtl1.FilterIndex = 1
    ActiveXCtl1.Filename = filename$
    ActiveXCtl1.DialogTitle = Title$
    ActiveXCtl1.DefExt = DefExt$
    ActiveXCtl1.InitDir = CurDir$

Retry:
    ActiveXCtl1.ShowOpen
    If ActiveXCtl1.Filename = "" Then GoTo Retry
    OpenCommDlg = ActiveXCtl1.Filename
    F.Visible = -1

Exit_OpenCommDlg:
    On Error GoTo 0
    Exit Function

Err_OpenCommDlg:
    MsgBox Err & " " & Error$, , "Open Common Dialog"
    Resume Exit_OpenCommDlg

End Function

This is much easier than using the API calls.  What do ya think?
0

Featured Post

Announcing the Most Valuable Experts of 2016

MVEs are more concerned with the satisfaction of those they help than with the considerable points they can earn. They are the types of people you feel privileged to call colleagues. Join us in honoring this amazing group of Experts.

Question has a verified solution.

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

Suggested Solutions

Most everyone who has done any programming in VB6 knows that you can do something in code like Debug.Print MyVar and that when the program runs from the IDE, the value of MyVar will be displayed in the Immediate Window. Less well known is Debug.Asse…
Enums (shorthand for ‘enumerations’) are not often used by programmers but they can be quite valuable when they are.  What are they? An Enum is just a type of variable like a string or an Integer, but in this case one that you create that contains…
As developers, we are not limited to the functions provided by the VBA language. In addition, we can call the functions that are part of the Windows operating system. These functions are part of the Windows API (Application Programming Interface). U…
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…

808 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