The Visual|window| function API function is the cornerstone of building a WINDWS application, and each of the Windows Application development tools, which provide the underlying functions, indirectly or directly invoke the Windows API functions, and in order to achieve functional expansion, It also provides an interface to invoke the WINDOWSAPI function, i.e. the ability to invoke a dynamic connection library. Visual C #, like other development tools, can also invoke the API functions of a dynamic-link library. NET Framework itself provides a service that allows the governed code to invoke the unmanaged functions implemented in the dynamic-link library, including the Windows API functions provided by the operating system. It is able to locate and invoke the output function, organizing its parameters (integer, String type, array, and structure, etc.) across the interoperation boundary as needed.
The following is an example of C # to briefly describe the basic process of invoking the API:
Declaration of dynamic Link library functions
Dynamic link library functions must be declared before use, relative to the vb,c# function declaration is more verbose, the former through the Api viewer paste, you can directly use, and the latter need to make some additional changes to the parameters of the work.
The Dynamic Link library function Declaration section generally consists of the following two parts, one is the function name or the index number, and the other is the file name of the dynamic link library.
For example, you want to call the MessageBox function in User32.DLL, we have to specify the name of the function MessageBoxA or MessageBoxW, and the name of the library User32.dll, we know Win32 The API typically has two versions of each function involving strings and characters, an ANSI version of Single-byte characters, and a Unicode version of Double-byte characters.
The following is an example of invoking an API function:
[DllImport ("KERNEL32.") DLL ", entrypoint=" Movefilew ", Setlasterror=true,
CharSet=CharSet.Unicode, Exactspelling=true,
Callingconvention=callingconvention.stdcall)]
public static extern bool MoveFile (string src, string dst);
Where the entry point entrypoint the entry location of the function in the dynamic link library, in a governed project, the original name and ordinal entry point of the objective function not only identifies a function that crosses the interop boundary. Also, you can map the entry point to a different name, which is to rename the function. Renaming can bring convenience to calling functions, by renaming, on the one hand, we don't have to break the brain for the size of a function, and it also guarantees consistency with existing naming conventions, allowing functions with different parameter types to coexist, and more importantly simplifying calls to ANSI and Unicode versions. CharSet is used to identify a function call in Unicode or ANSI version, Exactspelling=false will tell the compiler to let the compiler decide to use Unicode or an ANSI version. Please refer to the MSDN Online Help for additional parameters.
In C #, you can declare a dynamic-link library function in the entrypoint domain by name and ordinal, and if the function name used in the method definition is the same as the DLL entry point, you do not need to display the declaration function in the EntryPoint field. Otherwise, you must use the following attribute format to indicate a name and serial number.
[DllImport ("dllname", entrypoint= "functionname")]
[DllImport ("dllname", entrypoint= "#123")]
It's worth noting that you have to add "#" to the number sequence.
Here is an example of replacing a MessageBox name with a MsgBox:
[C #]
Using System.Runtime.InteropServices;
public class Win32 {
[DllImport ("user32.dll", entrypoint= "MessageBox")]
public static extern int MsgBox (int hWnd, string text, string caption, uint type);
}
Many governed dynamic link library functions expect you to pass a complex parameter type to a function, such as a user-defined struct type member or a class member defined by a governed code, at which point you must provide additional information to format this type to maintain the original layout and alignment of the argument.
C # provides a StructLayoutAttribute class by which you can define your own format type, and in the governed code, the format type is a struct or class member with a structlayoutattribute description. It enables the layout information that is expected from its internal members. There are three different options for layout:
Layout options
Describe
Layoutkind.automatic
To improve efficiency, allow the running state to reorder type members.
Note: Never use this option to invoke a dynamically linked library function that is not governed.
Layoutkind.explicit
Sort type members by FieldOffset property for each field
LayoutKind.Sequential
Sorts members of types that appear in the domain of the governed type definition where they are not governed.
Delivery structure Members
The following example shows how to define a point and rectangle type in the governed code and pass it as a parameter to the PtInRect function in the User32.dll library,
The non-governed prototypes of the function are declared as follows:
BOOL ptinrect (const RECT *LPRC, point pt);
Note that you must pass RECT structure parameters by reference, because the function requires a RECT structure pointer.
[C #]
Using System.Runtime.InteropServices;
[StructLayout (LayoutKind.Sequential)]
public struct Point {
public int x;
public int y;
}
[StructLayout (Layoutkind.explicit]
public struct Rect {
[FieldOffset (0)] public int left;
[FieldOffset (4)] public int top;
[FieldOffset (8)] public int right;
[FieldOffset] public int bottom;
}
Class Win32API {
[DllImport ("User32.dll")]
public static extern Bool PtInRect (ref Rect R, point P);
}
Like you can call the GetSystemInfo function to get system information:
? Using System.Runtime.InteropServices;
[StructLayout (LayoutKind.Sequential)]
public struct System_info {
public UINT Dwoemid;
public UINT dwPageSize;
public UINT lpminimumapplicationaddress;
public UINT lpmaximumapplicationaddress;
public UINT Dwactiveprocessormask;
public UINT Dwnumberofprocessors;
public UINT dwProcessorType;
public UINT dwallocationgranularity;
public UINT Dwprocessorlevel;
public UINT Dwprocessorrevision;
}
System_info PSI = new System_info ();
GetSystemInfo (ref PSI);
Passing of class members
Similarly, as long as the class has a fixed class member layout, you can also pass a class member to a dynamically linked library function that is not governed by the The following example mainly explains how to pass a sequential order-defined MySystemTime class to the User32.dll getsystemtime function, which functions with C + + calling specification as follows:
void GetSystemTime (systemtime* SYSTEMTIME);
Unlike passing value types, classes always pass arguments by reference.
[C #]
[StructLayout (LayoutKind.Sequential)]
public class MySystemTime {
public ushort Wyear;
public ushort Wmonth;
public ushort Wdayofweek;
public ushort Wday;
public ushort Whour;
public ushort Wminute;
public ushort Wsecond;
public ushort Wmilliseconds;
}
Class Win32API {
[DllImport ("User32.dll")]
public static extern void GetSystemTime (MySystemTime st);
}
Pass of callback function:
To invoke most dynamic-link library functions from a governed code, you simply create a governed function definition and then call it, which is straightforward.
If a dynamic link library function requires a function pointer as a parameter, you need to do the following steps:
First, you must refer to the documentation for this function to determine if the function requires a callback; second, you must create a callback function in the governed code; Finally, you can create a pointer to the function as a parameter to the DLL function.
Callback functions and their implementations:
Callback functions are often used in situations where tasks need to be repeated, such as for enumerating functions, such as enumfontfamilies (font enumeration) in the Win32 API, EnumPrinters (printer), EnumWindows (Window enumeration) functions. Let's take a window enumeration as an example, and talk about how to traverse all the windows that exist in the system by calling the Enumwindow function
The following steps are divided:
1. Reference the Declaration of a function before implementing the call
BOOL EnumWindows (Wndenumproc lpenumfunc, Lparmam Iparam)
Obviously this function requires a callback function address as an argument.
2. Create a governed callback function, which is declared as the representative type (delegate), which is what we call a callback, with two arguments hwnd and LPARAM, the first argument is a window handle, the second parameter is defined by the application, and two parameters are cosmetic.
When the callback function returns a value other than 0, the mark executes successfully, and zero implies failure, and this example always returns a true value for continuous enumeration.
3. Finally created to represent the object (delegate) and pass it as a parameter to the EnumWindows function, the platform automatically converts the representative into a callback format that the function can recognize.
[C #]
Using System;
Using System.Runtime.InteropServices;
Public delegate bool CallBack (int hwnd, int lParam);
public class Enumreportapp {
[DllImport ("user32")]
public static extern int EnumWindows (CallBack x, int y);
public static void Main ()
{
CallBack mycallback = new CallBack (enumreportapp.report);
EnumWindows (mycallback, 0);
}
public static bool (int hwnd, int lParam) {
Console.Write ("Window handle is");
Console.WriteLine (HWND);
return true;
}
}
Pointer type parameter passing:
In the case of Windows API function calls, most functions use pointer passing arguments, and for a struct variable pointer, we can sometimes use array-passing arguments in addition to passing parameters using the above class and struct methods.
The following function gets the user name by calling GetUserName
BOOL GetUserName (
LPTSTR lpbuffer,//user name Buffer
Lpdword nsize//Storage buffer size address pointer
);
[DllImport ("Advapi32.dll",
Entrypoint= "GetComputerName",
Exactspelling=false,
Setlasterror=true)]
static extern bool GetComputerName (
[MarshalAs (UnmanagedType.LPArray)] byte[] lpbuffer,
[MarshalAs (UnmanagedType.LPArray)] Int32[] nsize);
This function accepts two parameters, char * and int *, because you must assign a string buffer to accept the string pointer, you can use the string class instead of this parameter type, and of course you can declare a byte array to pass the ANSI string, You can also declare an array of long integers with only one element, using the array name as the second argument. The above function can be invoked as follows:
Byte[] Str=new byte[20];
Int32[] Len=new int32[1];
len[0]=20;
GetComputerName (Str,len);
MessageBox.Show (System.Text.Encoding.ASCII.GetString (str));
Finally, it should be recalled that each method must be preceded by a file header:
Using System.Runtime.InteropServices;
The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion;
products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the
content of the page makes you feel confusing, please write us an email, we will handle the problem
within 5 days after receiving your email.
If you find any instances of plagiarism from the community, please send an email to:
info-contact@alibabacloud.com
and provide relevant evidence. A staff member will contact you within 5 working days.