PDA

Click to See Complete Forum and Search --> : As Any


Michael L
Aug 5th, 2001, 05:34 PM
Declare Function SystemParametersInfo Lib "user32.dll" Alias "SystemParametersInfoA" (ByVal uAction As Long, ByVal uiParam As Long, pvParam As Any, ByVal fWinIni As Long) As Long

where uAction is
SPI_GETSCREENSAVETIMEOUT = 14
Retrieve the time-out period, in seconds, which must elapse before the screen saver begins running. uiParam must be 0. pvParam is a Long-type variable which receives the time-out value.

I am encountering this Any type and I need to get a handle on what it is. I am trying to work in Access 2000 and it just doesn't seem to be working. I have tried using type variant but it still won't compile.

All help thankfully received

Cheers
Michael
:confused:

Matthew Gates
Aug 5th, 2001, 05:44 PM
Try this:


Public Const SPI_GETSCREENSAVETIMEOUT = 14
Declare Function SystemParametersInfo Lib "user32" Alias "SystemParametersInfoA"
(ByVal uAction As Long, ByVal uParam As Long, lpvParam As Any, ByVal fuWinIni As
Long) As Long


Private Sub Command1_Click()
Dim intValue As Integer
Call SystemParametersInfo(SPI_GETSCREENSAVETIMEOUT, vbNull, intValue, 0)
MsgBox "Screen saver time-out value: " & intValue & " seconds."
End Sub

Michael L
Aug 5th, 2001, 05:58 PM
Thanks for the speedie reply I tried your suggestion I still get a type miss match error when I compile.

How can I find out more about this type any and is it supported in Access 2000?

Thanks
Michael

jim mcnamara
Aug 5th, 2001, 06:04 PM
What 'As Any" means is that VB doesn't support pointers.

Therefore, you cannot have a pointer to a place in memory as a datatype passed to a function. What is 'pointed to' can be a string, a long, etc., - ie., 'any' datatype.

What Matthew did was to define the datatype - ie, create type safety, so you don't get the blue screen of death when calling a function. Very sensible.

You can mess with the api declaration like this:

Declare Function SystemParametersInfoLong Lib "user32" Alias "SystemParametersInfoA" _ &
(ByVal uAction As Long, ByVal uParam As Long, ByRef lpvParam As Long, ByVal fuWinIni As
Long) As Long

Declare Function SystemParametersInfoString Lib "user32" Alias "SystemParametersInfoA" _ &
(ByVal uAction As Long, ByVal uParam As Long, ByRef lpvParam As String, ByVal fuWinIni As
Long) As Long

This creates type safety because the compiler knows what datatype to pass.

Jay Rogozinsky
Aug 9th, 2001, 05:02 PM
You wanted to understand 'Any'. This topic is best understood when you have a handle on stacks and assembly. Since I can't assume you do, I will do my best.

-----------------------
Something Simpler First
-----------------------

When you say "As Long" (or whatever) in a Declare it tells VB to do two things. First, it will check your code when you compile to ensure you are actually passing Long values or something it can turn into a Long value - for example, trying to pass a String will cause VB to generate a compile error. Second, it tells VB what to put on the 'stack' before it makes the call. If the declaration is wrong, all sorts of nasty and unpredicatable things can happen - if the called code expects two bytes (VB Integer) and you pass four (VB Long).

--------------
Something Else
--------------

When you see a declare that includes 'As String' you are seeing an illusion. You can't pass a string itself - only a pointer to a string. You will never likelly find an API Declare with this in it. If you do, it's because that call understands VB String Headers. I know people have said that the API only understands Pointers, actually most OS's are like this. This is because of the 'stack' - You don't want to copy the entire string onto the stack, so you pass a pointer to the string.

In VB, Strings exist like this. First, there is a small chunck of memory that contains things like the string length and so forth (a header). Then there is a chunk of memory that actually contains the string. When you create a Declare that has 'As String', VB will pass the pointer to the Strings header, not the pointer to the actual string contents. It is these contents you want to pass to the API. When you create a Declare that has 'BYVAL As String', VB will pass the pointer to the actual String data.

This is where the fun and learning curve starts...working towards understanding the use of "As Any'. If you create the Declare using 'As String', you can later, when you actually make the call, use BYVAL MyVariable. This will have the same effect as having BYVAL in your Declare.

---
Any
---

It comes down to this. You are ALWAYS passing either POINTERS or SMALL VALUES to API calls. So if that API expects a Pointer, how should you Declare it - after all, if you Declare As String, VB won't let you pass anything else. When you actually make the call to the API, you may want to pass a pointer to a string or you may want to pass the value contained in a Long. If you use 'As Any', you can pass anything you want, just make sure it's right.

...

Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (pasDest As Any, pasSource As Any, ByVal pasBytes As Long)

Therefore, when you actually call CopyMemory, you can pass a string (BYVAL MyString) or type (MyType) or the value IN a Long (BYVAL MyLong) or a pointer to where the Long is stored (MyLong) - one gives the value contain in the variable, one gives a pointer to where the variable is stored. Sometimes you want one, sometimes you want the other.

You could create x number of Declares with different names and different types. I find 'As Any' easier.

Hope this helps. It is a pretty intense topic.

Kaverin
Aug 10th, 2001, 09:40 PM
Or if you want to just put the ugliness of "As Any" behind you, change all of the "X As Any" appearances to "ByVal X As Long", and give it the address of the data. Since ultimate they're all pointers anyway, just give it exactly what it's expecting. For numeric data types and UDTs, use VarPtr(yourvar), and for string variables use StrPtr(yourvar). There's also an ObjPtr(), for objects but I've never seen that one used at all. I've heard people say VB doesn't support pointers, and it's bogus. It doesn't have pointers in the same sense as C does, but they're only addresses, and these 3 functions give you just that. It also eliminates the need for adding in ByVal before parameters that you pass to API functions, which are easy to forget if you're not accustomed to the "under the hood" operations.

And also, if an API parameter may be null, and in the declaration the type is "Any" and changed to "Byval .. As Long", using this allows you to properly pass null since it is basically defined as a pointer to nothing. #define NULL (void *)0 was a way to define it in C from a long time ago. Just give it a 0 when a null is to be passed in. vbNull is not null, it is 1. vbNull is a constant that is returned by VarType() on a variant to indicate it has no valid data. There are also instances where UDT parameters may allow the passing of null, such as CreateDC() used to create a display DC, where the DEVMODE struct isn't required. This eliminates the need for defining the large struct which isn't necessary for just a regular display DC.

Jay Rogozinsky
Aug 11th, 2001, 12:07 AM
Exactly right Kaverin.

I wanted to and forgot to mention vbNull ... way too many people are using it to represent what C calls NULL which is simply (a pointer) with the value 0 - this includes what the API expects as NULL Strings.

Yes, the alternative you mentioned using BYVAL As Long and using VarPtr and the like is good.

My discussion was intended to help people understand the under-the-hood reality also.

Kaverin
Aug 11th, 2001, 09:58 AM
That did remind me of something I forgot, which was for string parameters where you wanted to pass null, you can use vbNullString.