By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
457,759 Members | 1,236 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 457,759 IT Pros & Developers. It's quick & easy.

Can API declarations be placed on the declarations section of a form module?

P: n/a
MLH
Would the following work if placed in a form module rather than a
global module?

Declare Sub InternetCloseHandle Lib "wininet.dll" (ByVal hInet As
Long)

Nov 12 '05 #1
Share this Question
Share on Google+
9 Replies


P: n/a
MLH <CR**@NorthState.net> wrote in news:ot8qrvo9e5163170rj9avlrtu58qu1u7s5@
4ax.com:
Would the following work if placed in a form module rather than a
global module?

Declare Sub InternetCloseHandle Lib "wininet.dll" (ByVal hInet As
Long)


I would try:

Private Declare Function InternetCloseHandle Lib "wininet.dll" _
(ByVal hInet As Long) As Integer

It's interesting that you've chosen to declare this as a Sub. At compile
time this raises no error. I didn't try it at run time. But the Function
returns a boolean or integer the value of which indicates success or
failure in closing the handle. This information might be worthwhile enough
to warrant any increased resource use (if there is any, or if it's
noticeable) that a function might require and a sub not require. If one
gets a zero (false) one can call GetLastError to see just what the problem
is.

Such functions can be called as subs. Regardless of the return value, or my
own words about its value I find that in my own FTP class, I use:

Private Sub Class_Terminate()
InternetCloseHandle mHOpenFile
InternetCloseHandle mHFoundFile
InternetCloseHandle mHConnect
InternetCloseHandle mHInternet
End Sub

Of course, I assume in a form module one would do this in the Form Close
event.

.... Last Error Stuff

Private Declare Function GetLastError Lib "kernel32" () As Long

Public Property Get FindFirstFile() As Long
FindFirstFile = FtpFindFirstFile(mHConnect, mStrFindFileName, mWFD, 0,
0)
If GetLastError() And ERROR_FTP_TRANSFER_IN_PROGRESS =
ERROR_FTP_TRANSFER_IN_PROGRESS Then
InternetCloseHandle mHConnect
FindFirstFile = FtpFindFirstFile(mHConnect, mStrFindFileName, mWFD,
0, 0)
End If
InternetCloseHandle mHFoundFile
mHFoundFile = FindFirstFile
End Property
--
Lyle
(for e-mail refer to http://ffdba.com/contacts.htm)
Nov 12 '05 #2

P: n/a
TC
Lyle Fairfield <Mi************@Invalid.Com> wrote in message news:<Xn*******************@130.133.1.4>...
(snip)
If one gets a zero (false) one can call
GetLastError to see just what the problem is.

Not so in VBA. The value of GetLastError will have been altered by
other calls that VBA makes "behind the scenes" when returning from the
DLL call.

You must always use Err.LastDLLError to check the result of DLL calls
from VBA. VBA saves the correct GetLastError value in that property of
the error object, for that purpose.

TC
Nov 12 '05 #3

P: n/a
aa**********@yahoo.com (TC) wrote in news:be37bfe0.0311202128.62ac0124
@posting.google.com:
Lyle Fairfield <Mi************@Invalid.Com> wrote in message news: <Xn*******************@130.133.1.4>... (snip)
If one gets a zero (false) one can call
GetLastError to see just what the problem is.

Not so in VBA. The value of GetLastError will have been altered by
other calls that VBA makes "behind the scenes" when returning from the
DLL call.

You must always use Err.LastDLLError to check the result of DLL calls
from VBA. VBA saves the correct GetLastError value in that property of
the error object, for that purpose.

TC


I think your statement may be too strong. In the case of the Wininet
Functions GetLastError seems to return the same value as Err.LastDllError.
(Has Err always had the LastDllError Property? I do not know. The code I
posted is several years old. I recall thinking I needed to use LastDllError
and then discarding that notion, but I can't remember why.). But I have
tested my assertion specifically only with

Private Declare Function FtpFindFirstFile Lib "wininet.dll" Alias
"FtpFindFirstFileA" _
(ByVal hFtpSession As Long, ByVal strSearchFile As String, _
lpFindFileData As WIN32_FIND_DATA, ByVal dwFlags As Long, _
ByVal dwContent As Long) As Long

and

Private Declare Function InternetFindNextFile Lib "wininet.dll" Alias
"InternetFindNextFileA" _
(ByVal hFoundFile As Long, lpFindFileData As WIN32_FIND_DATA) As
Boolean

While I can understand that it's quite possible that under some
circumstances the equivalence of GetLastError and LastDllError might not
exist, I can report that GetLastError has served without any reported
problem for at least three years in an application that when run (weekly?)
uses functions in which it is referenced several thousand times per hour.
At the same time one tries not to have errors, (at least I do), and so
GetLastError may have been referenced infrequently.

As an aside, for error messages with Wininet I use:

Private Declare Function InternetGetLastResponseInfo Lib "wininet.dll" _
Alias "InternetGetLastResponseInfoA" _
(lngError As Long, _
ByVal strBuffer As String, _
lngBufferLength As Long) As Boolean

Public Sub ConnectToServer()
InternetCloseHandle mHConnect
mHConnect = InternetConnect(mHInternet, _
mStrServerName, _
INTERNET_DEFAULT_FTP_PORT, _
mStrUserName, _
mStrPassWord, _
INTERNET_SERVICE_FTP, 0, 0)
If mHConnect = 0 Then ShowLastResponseInfo
End Sub

Public Sub ShowLastResponseInfo()
Dim lngError As Long
Dim strError As String
Dim strBuffer As String
Dim lngBufferLength As Long
strBuffer = String(2047, " ") & vbNullChar
lngBufferLength = 2048
If InternetGetLastResponseInfo(lngError, strBuffer, lngBufferLength) =
0 Then
MsgBox "Last response information could not be read!",
vbInformation, "FTP"
Else
If lngError <> 0 Then strError = " Error " & lngError
If lngBufferLength <> 0 Then _
MsgBox Left(strBuffer, lngBufferLength), vbInformation, "FTP" &
strError
End If
End Sub

--
Lyle
(for e-mail refer to http://ffdba.com/contacts.htm)
Nov 12 '05 #4

P: n/a
TC

"Lyle Fairfield" <Mi************@Invalid.Com> wrote in message
news:Xn*******************@130.133.1.4...
aa**********@yahoo.com (TC) wrote in news:be37bfe0.0311202128.62ac0124
@posting.google.com:
Lyle Fairfield <Mi************@Invalid.Com> wrote in message news: <Xn*******************@130.133.1.4>...
(snip)
If one gets a zero (false) one can call
GetLastError to see just what the problem is.

Not so in VBA. The value of GetLastError will have been altered by
other calls that VBA makes "behind the scenes" when returning from the
DLL call.

You must always use Err.LastDLLError to check the result of DLL calls
from VBA. VBA saves the correct GetLastError value in that property of
the error object, for that purpose.

TC


I think your statement may be too strong. In the case of the Wininet
Functions GetLastError seems to return the same value as Err.LastDllError.
(Has Err always had the LastDllError Property? I do not know. The code I
posted is several years old. I recall thinking I needed to use

LastDllError and then discarding that notion, but I can't remember why.). But I have
tested my assertion specifically only with


(snip code)
You may have just been lucky!

A few minutes googling gave the following.
http://msdn.microsoft.com/library/de...us/debug/base/
getlasterror.asp
"Visual Basic: Applications should call err.LastDllError instead of
GetLastError."

http://www.partware.com/ebooks/api/r...lasterror.html
"Although GetLastError works perfectly in Visual Basic, it will sometimes
not appear to work. This is because Visual Basic implicitly uses the API
frequently to perform tasks which are seemingly intrinsic to the language.
These hidden API function calls will usually overwrite the error code which
your code may be trying to read. To compensate for this, the LastDllError
property of the Err object, predefined in Visual Basic, caches the error
code from the last API function explicitly called by your program. You
should use the expression Err.LastDllError instead of the GetLastError
function to debug failed API function calls."

http://www.google.com.au/search?q=ca...com/books/1861
002432/chapter_2432_03.asp+getlasterror++lastdllerr+OR+la stdllerror&hl=en&ie
=UTF-8
"Internally, VB is making Win32 calls all the time in your application.
Sometimes, when you make a Win32 call, this may trigger an event within your
application that causes VB to make other Win32 calls (we'll address window
messages later on in the book). Well, what happens if your initial call
causes an error, but the internal Win32 call made by VB clears out the value
of the error? You get the situation that we just saw. GetLastError returns a
zero, but Err.LastDllError returns the correct error code.
In previous versions of VB, the LastDllError property didn't exist, and
strange situations like the one we just saw popped up again and again.
Therefore, the VB designers decided to add the LastDllError to the Err
object. This property should be used when a Win32 call is made that causes
an error, because VB will track your Win32 call and make sure that this
property reflects any possible error conditions."

http://www.mvps.org/vb/index2.html?t...matmessage.htm
"It can be frustrating looking up values returned by Err.LastDllError, to be
sure. What's that? You use GetLastError? As much as I hate to tell you,
that's really not very smart. You see, the way Microsoft designed VB,
there's a whole lotta API calls going on behind your back There's no
guarantee that calling GetLastError will result in that set by the API call
you made."

Cheers,
TC

Nov 12 '05 #5

P: n/a
"TC" <a@b.c.d> wrote in news:1069473807.510665@teuthos:

"Lyle Fairfield" <Mi************@Invalid.Com> wrote in message
news:Xn*******************@130.133.1.4...
aa**********@yahoo.com (TC) wrote in news:be37bfe0.0311202128.62ac0124
@posting.google.com:
> Lyle Fairfield <Mi************@Invalid.Com> wrote in message news:

<Xn*******************@130.133.1.4>...
> (snip)
>
>> If one gets a zero (false) one can call
>> GetLastError to see just what the problem is.
>
>
> Not so in VBA. The value of GetLastError will have been altered by
> other calls that VBA makes "behind the scenes" when returning from
> the DLL call.
>
> You must always use Err.LastDLLError to check the result of DLL calls
> from VBA. VBA saves the correct GetLastError value in that property
> of the error object, for that purpose.
>
> TC


I think your statement may be too strong. In the case of the Wininet
Functions GetLastError seems to return the same value as
Err.LastDllError. (Has Err always had the LastDllError Property? I do
not know. The code I posted is several years old. I recall thinking I
needed to use

LastDllError
and then discarding that notion, but I can't remember why.). But I have
tested my assertion specifically only with


(snip code)
You may have just been lucky!

A few minutes googling gave the following.
http://msdn.microsoft.com/library/de...en-us/debug/ba
se/ getlasterror.asp
"Visual Basic: Applications should call err.LastDllError instead of
GetLastError."

http://www.partware.com/ebooks/api/r...lasterror.html
"Although GetLastError works perfectly in Visual Basic, it will
sometimes not appear to work. This is because Visual Basic implicitly
uses the API frequently to perform tasks which are seemingly intrinsic
to the language. These hidden API function calls will usually overwrite
the error code which your code may be trying to read. To compensate for
this, the LastDllError property of the Err object, predefined in Visual
Basic, caches the error code from the last API function explicitly
called by your program. You should use the expression Err.LastDllError
instead of the GetLastError function to debug failed API function
calls."

http://www.google.com.au/search?q=ca...ip.com/books/1
861
002432/chapter_2432_03.asp+getlasterror++lastdllerr+OR+la stdllerror&hl=en
&ie
=UTF-8
"Internally, VB is making Win32 calls all the time in your application.
Sometimes, when you make a Win32 call, this may trigger an event within
your application that causes VB to make other Win32 calls (we'll address
window messages later on in the book). Well, what happens if your
initial call causes an error, but the internal Win32 call made by VB
clears out the value of the error? You get the situation that we just
saw. GetLastError returns a zero, but Err.LastDllError returns the
correct error code. In previous versions of VB, the LastDllError
property didn't exist, and strange situations like the one we just saw
popped up again and again. Therefore, the VB designers decided to add
the LastDllError to the Err object. This property should be used when a
Win32 call is made that causes an error, because VB will track your
Win32 call and make sure that this property reflects any possible error
conditions."

http://www.mvps.org/vb/index2.html?t...matmessage.htm
"It can be frustrating looking up values returned by Err.LastDllError,
to be sure. What's that? You use GetLastError? As much as I hate to tell
you, that's really not very smart. You see, the way Microsoft designed
VB, there's a whole lotta API calls going on behind your back There's no
guarantee that calling GetLastError will result in that set by the API
call you made."

Cheers,
TC


Probably I wrote this before LastDllError existed and were I to start
again, Probably I would use LastDllError.

On the other hand I am not a supporter of Googling to substantiate any
claim. Often the stuff found is wrong, less often for MVPs sites. I've
almost completely given up on instructions about using API functions in
VBA. I tend to munge the C++ code found in its include files.

As I explained, my application has stood the test of time. I don't think
I'll change it right now.

Back to my original point. When one tests the return value of a Declared
Function, one can often gain information that may prompt one to check
GetLastError or LastDllError. When one declares a DLL Function as Sub, one
may lose that capability.

--
Lyle
(for e-mail refer to http://ffdba.com/contacts.htm)
Nov 12 '05 #6

P: n/a
TC

"Lyle Fairfield" <Mi************@Invalid.Com> wrote in message
news:Xn*******************@130.133.1.4...

(snip)
On the other hand I am not a supporter of Googling to substantiate any

claim.

I agree. But it is clearly stated in MSDN: "Visual Basic: Applications
should call err.LastDllError instead of GetLastError."

TC
(off for the day)

Nov 12 '05 #7

P: n/a
MLH
Off Google, I retrieved this code and wanted to try it out.
I just didn't know where to put its various elements, so I
pasted it into a form module and began spreading it around
from there. I never could get it to work. It was posted by
Ben Ball on 2002-08-14 16:25:41 PST. My thinking was
to put the declarations on declarations page of a form
module and the function elsewhere in the form module.

Seems to work at compile time, but I get "Error in loading
DLL" at runtime - on the following specific line in the FN:
hInet = InternetOpenA("www.hp.com", 0, vbNullString, vbNullString, 0)
Note that I could not use the "Private" reserved word in my
form module & had to take it out...

'===> Begin Ben's Posted Code <===
Private Declare Sub InternetCloseHandle Lib "wininet.dll" ( _
ByVal hInet As Long)
Private Declare Function InternetOpenA Lib "wininet.dll" ( _
ByVal sAgent As String, ByVal lAccessType As Long, _
ByVal sProxyName As String, ByVal sProxyBypass As String, _
ByVal lFlags As Long) As Long
Private Declare Function InternetOpenUrlA Lib "wininet.dll" ( _
ByVal hOpen As Long, ByVal sUrl As String, _
ByVal sHeaders As String, ByVal lLength As Long, _
ByVal lFlags As Long, ByVal lContext As Long) As Long
Private Declare Sub InternetReadFile Lib "wininet.dll" ( _
ByVal hFile As Long, ByVal sBuffer As String, _
ByVal lNumBytesToRead As Long, lNumberOfBytesRead As Long)
Public Function OpenURL( _
ByVal URL As String) As String
Const INET_RELOAD = &H80000000
Dim hInet As Long
Dim hURL As Long
Dim Buffer As String * 2048
Dim Bytes As Long

hInet = InternetOpenA( _
"www.hp.com", 0, _
vbNullString, vbNullString, 0)
hURL = InternetOpenUrlA( _
hInet, URL, vbNullString, 0, 0, 0)

Do
InternetReadFile hURL, Buffer, Len(Buffer), Bytes
If Bytes = 0 Then Exit Do
OpenURL = OpenURL & Left$(Buffer, Bytes)
Loop

InternetCloseHandle hURL
InternetCloseHandle hInet
End Function
'===> End Ben's Posted Code <===

Nov 12 '05 #8

P: n/a
TC
See if this helps:

http://msdn.microsoft.com/archive/de...us/dnarvbtips/
html/msdn_msdn55.asp

It is quite acceptable to place the "Declare" declarations at the top of the
form module, then use those declared functions elsewere in that module.

If you wanted to use those functions from >several< modules, you would move
the Declare's to a standard module & declare them Public - not Private.

You can not make them Public in a form module - only in a standard module or
class module.

However, you can always make them Private, to limit their scope to that one
module. So I don't understand what you mean by saying that you could not use
Private in your form module, & had to take it out.

HTH,
TC
"MLH" <CR**@NorthState.net> wrote in message
news:d5********************************@4ax.com...
Off Google, I retrieved this code and wanted to try it out.
I just didn't know where to put its various elements, so I
pasted it into a form module and began spreading it around
from there. I never could get it to work. It was posted by
Ben Ball on 2002-08-14 16:25:41 PST. My thinking was
to put the declarations on declarations page of a form
module and the function elsewhere in the form module.

Seems to work at compile time, but I get "Error in loading
DLL" at runtime - on the following specific line in the FN:
hInet = InternetOpenA("www.hp.com", 0, vbNullString, vbNullString, 0)
Note that I could not use the "Private" reserved word in my
form module & had to take it out...

'===> Begin Ben's Posted Code <===
Private Declare Sub InternetCloseHandle Lib "wininet.dll" ( _
ByVal hInet As Long)
Private Declare Function InternetOpenA Lib "wininet.dll" ( _
ByVal sAgent As String, ByVal lAccessType As Long, _
ByVal sProxyName As String, ByVal sProxyBypass As String, _
ByVal lFlags As Long) As Long
Private Declare Function InternetOpenUrlA Lib "wininet.dll" ( _
ByVal hOpen As Long, ByVal sUrl As String, _
ByVal sHeaders As String, ByVal lLength As Long, _
ByVal lFlags As Long, ByVal lContext As Long) As Long
Private Declare Sub InternetReadFile Lib "wininet.dll" ( _
ByVal hFile As Long, ByVal sBuffer As String, _
ByVal lNumBytesToRead As Long, lNumberOfBytesRead As Long)
Public Function OpenURL( _
ByVal URL As String) As String
Const INET_RELOAD = &H80000000
Dim hInet As Long
Dim hURL As Long
Dim Buffer As String * 2048
Dim Bytes As Long

hInet = InternetOpenA( _
"www.hp.com", 0, _
vbNullString, vbNullString, 0)
hURL = InternetOpenUrlA( _
hInet, URL, vbNullString, 0, 0, 0)

Do
InternetReadFile hURL, Buffer, Len(Buffer), Bytes
If Bytes = 0 Then Exit Do
OpenURL = OpenURL & Left$(Buffer, Bytes)
Loop

InternetCloseHandle hURL
InternetCloseHandle hInet
End Function
'===> End Ben's Posted Code <===

Nov 12 '05 #9

P: n/a
TC,

"will" should be "may well"

Terry
"TC" <aa**********@yahoo.com> wrote in message
news:be**************************@posting.google.c om...
Lyle Fairfield <Mi************@Invalid.Com> wrote in message news:<Xn*******************@130.133.1.4>... (snip)
If one gets a zero (false) one can call
GetLastError to see just what the problem is.

Not so in VBA. The value of GetLastError will have been altered by
other calls that VBA makes "behind the scenes" when returning from the
DLL call.

You must always use Err.LastDLLError to check the result of DLL calls
from VBA. VBA saves the correct GetLastError value in that property of
the error object, for that purpose.

TC

Nov 12 '05 #10

This discussion thread is closed

Replies have been disabled for this discussion.