.NET and API's - what a headache

NeuralJack

Well-known member
Joined
Jul 28, 2005
Messages
138
I need to know if im missing something big here. I program and program in VB.net just fine and very quickly until I have to use an API. At that moment it is EXACTLY like i was hit by a Mac Truck. One damn API declaration and usage will blow a whole in my progress for 1-3 solid days before i give up and ask on a forum how it should be used. Of course, when i ask on the forums there is about a 15 day period before the first response.. so there goes all productivity out the window. I am still very thrilled for any help by forum folks even if its months after the initial post. Forums rock. BUT, it doesnt change the fact that APIs and VB.NET together are not working well with ME.

I have never had a problem trying to figure out how to do something with my own research online for the correct code to use, EXCEPT when APIs are involved. By now I have many APIs figured out, after much grief, but now and then a new one comes up (now its MoveWindow API). The problem with APIs and VB.net seems to be that all of the APIs examples and declarations are in VB6 or earlier (at all the websites).. AND MOST (BUT NOT ALL) ARE NOT COMPATIBLE WITH .NET in that form. You have to tweak with those examples/declarations in a way that is rarely published anywhere that i can find. I search and search for the proper API usage in VB .NET with no success. Sometimes if you post on forums about this, the replys will just be links to more websites with yet more examples on how they were used in VB 6!

Most .NET programmers may not even notice this sort of thing becuase they dont use many various APIs or something. I use APIs constantly because i need to interface/react with programs outside of my own program.

Id be thrilled if some folks could answer a few questions for me:
1. Am I the only one?
2. Is there a source where i can find API declarations and examples for specifically VB.net? AllAPI site is terrible because its all, you guessed it, VB 6 or earlier garbage. Youd think by now .NET would have some API sites.
3. Are there tricks to converting API usage in VB6 to VB.Net?
4. My recent prob is with MoveWindow API if anyone can help.

This dont work:
Declaration:
Code:
Declare Function MoveWindow Lib "user32" Alias "MoveWindow" (ByVal hwnd As Long, ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal bRepaint As Long) As Long
Usage:
Code:
MoveWindow(hWnd, 100, 100, 400, 300, True)

- Yes, i have the correct window handle cuase ive tested it with SetForeGroundWindow.
 
Oh and yes, ive also use "1" instead of True

Usage:
Code:
MoveWindow(hWnd, 100, 100, 400, 300, 1)
 
Hah, i know this is classic but 30 mins after i posted here I finally stumbled upon a good declaration in an obscure corner of the net that works perfectly.
It goes like this:

Code:
    Declare Function MoveWindow Lib "user32" _
        (ByVal hWnd As IntPtr, _
         ByVal X As Integer, _
         ByVal Y As Integer, _
         ByVal nWidth As Integer, _
         ByVal nHeight As Integer, _
         ByVal bRepaint As Boolean) As Boolean

Yes, Ive heard before that Longs are bad in .Net API, but they seemed to work just fine with many many other APIs ive used. There are probably some tricks I could know about converting the VB6 version of this into the working version, and would love it if someone could point me in the right direction. But, even with those tricks around Id REALLLY think that someone should document API usage better for VB.NET in one place. As stated, there seems to be no place whatsoever that has a good database of accurate declarations and examples of .NET API.

Wouldnt you think MS would have such a database? Maybe I just dont have the website.
 
If you rely on others to create interop definitions for you then sooner or later youve going to hit problems. Creating the definitions isnt as exact as youd expect with people stubbing out parameters they arent using or changing the types of things to make particular code paths easy for them. Even Pinvoke.net has bad definitions on it. If you really use the native apis all the time you would be well served to learn how to pinvoke yourself. For example id interpret MoveWindow as the following in c#

Code:
/*
BOOL MoveWindow(
    HWND hWnd,
    int X,
    int Y,
    int nWidth,
    int nHeight,
    BOOL bRepaint
);
*/
[DllImport("user32.dll",CharSet=CharSet.Auto,SetLastError=true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool MoveWindow(
    [In] IntPtr hWnd,
    [In] Int32 X,
    [In] Int32 Y,
    [In] Int32 nWidth,
    [In] Int32 nHeight,
    [In,MarshalAs(UnmanagedType.Bool)] bool bRepaint
);

It may not look as inline as the VB syntax but last time i tried pinvoke in vb i ended up needing to hunt around weird parts of the docs trying to work out how to apply attributes properly.
 
You might want to take a look at this:
Api Viewer. It contains struct, constant, and function definitions in a variety of languages.

I personally dont have much trouble using the Windows API, and the conversion from VB6 to VB.Net (in terms of the API) wasnt particularly difficult for me. Generally the only modifications you need to make are changing Longs to either Integers or IntPtrs. (.Net represents handles and pointers with the IntPtr struct).

I got this from API Viewer. Again, I would change hwnd from Int32 to IntPtr so that you could use the Control.Handle property to get its hWnd (which is of type IntPtr). The return is an Int32, but it is easy enough to compare it to zero to see if the return is true or false.
[VB]
Declare Function MoveWindow Lib "user32.dll" ( _
ByVal hwnd As Int32, _
ByVal x As Int32, _
ByVal y As Int32, _
ByVal nWidth As Int32, _
ByVal nHeight As Int32, _
ByVal bRepaint As Int32) As Int32
[/VB]
 
if you use the HWND parameter as in Int32 it will only work on 32 bit platforms, youre effectively hardcoding the pointer length into the function declaration. If you use IntPtr it will still work on 64 bit system where 64 bit poitners are in use. In a similar vein you should compare it against IntPtr.Zero which is also guarenteed to be of the correct size on any given platform.

Pinvoke requires you to think about the parameters and give the invoke marshaller enough information to correctly interpret the results it gets, the more info you can give the more likely it is to be correct and the more likely it is to try an optimized route giving faster code. If you just straight translate parameters itll work but its probably not the most efficient or portable way to do so.
 
Thanks a ton for the information guys. With the API viewer 2004 software and pinvoke.net that should seriously cut some time off implementing these in the future.
Also, ill try to learn to pinvoke APIs myself in the near future. Although im not exactly sure where to start. Pinvoke-ing is basically just another word for declaring right? Besides looking online, im not sure where to even get enough information on APIs to go about declaring them myself. I do, however, understand how i can CONVERT VB6 declarations into .NET ones though.

Also, ill try to use IntPtr when using handles and such.

Thanks again fellas
 
At the core of things you have to be able to look at the original declaration in the original language, either i the headers or the msdn help, and work out how you represent that type and its marshalling semantics in managed code. For example DWORD turns out to be a UInt32 exactly which wont change. On the other hand * is a pointer which can change between platforms. Ive pinvoked quite a few things now and while there are surprises all over the places youll seldom go far wrong if you carefully read the docs and work out what goes in, what goes out and what is changed where.
 
Back
Top