Use Win32 class library in C # Programming

Source: Internet
Author: User

C # users often ask two questions: "Why should I write additional code to use features built in Windows? Why can't I complete this task for me without relevant content in the framework ?" When the Framework Team built their. NET part, they evaluated the work needed to enable. NET programmers to use Win32, and found that the Win32 API set was very large. They do not have enough resources to write managed interfaces for all Win32 APIs, test them, and write documents, so they have to prioritize the most important part. Many common operations have hosted interfaces, but many complete Win32 operations are not hosted.

Platform call (P/Invoke) is the most common method to complete this task. To use P/Invoke, You can compile a prototype that describes how to call a function, and then use this information to call the function at runtime. Another method is to use Managed Extensions to C ++ to wrap functions. This part will be introduced in future columns.

The best way to understand how to complete this task is through examples. In some examples, I only provide some code. The complete code can be downloaded.

Simple Example

In the first example, we will call the Beep () API to make a sound. First, I need to write appropriate definitions for Beep. Looking at the definition in MSDN, I found it has the following prototype:

BOOL Beep (
DWORD dwFreq, // Audio Frequency
DWORD dwDuration // audio duration
);

To use C # to compile this prototype, You need to convert the Win32 type to the corresponding C # type. Because DWORD is a 4-byte integer, we can use int or uint as the corresponding type of C. Since int Is a cls compatible type (can be used in all. NET languages), it is more common than uint, and in most cases, the difference between them is not important. The bool type corresponds to the BOOL type. Now we can use C # To compile the following prototype:

Public static extern bool Beep (int frequency, int duration );
 
This is a standard definition, but we use extern to indicate that the actual code of the function is elsewhere. This prototype tells the runtime how to call a function; now we need to tell it where to find the function.

We need to review the code in MSDN. In the reference information, we found that Beep () is defined in kernel32.lib. This means that the runtime code is included in kernel32.dll. We add the DllImport attribute in the prototype to notify the runtime of this information:

[DllImport ("kernel32.dll")]

This is all we have to do. The following is a complete example. The random sound generated by it is very common in sci-fi movies in 1960s.

Using System;
Using System. Runtime. InteropServices;

Namespace Beep
{
Class Class1
{
[DllImport ("kernel32.dll")]
Public static extern bool Beep (int frequency, int duration );

Static void Main (string [] args)
{
Random random = new Random ();

For (int I = 0; I <10000; I ++)
{
Beep (random. Next (10000), 100 );
}
}
}
}

The sound is enough to stimulate any listener! Because DllImport allows you to call any code in Win32, malicious code may be called. Therefore, you must be a fully trusted user before calling P/Invoke.

   Enumeration and constants

Beep () can be used to make arbitrary sound, but sometimes we want to make a specific type of sound, so we use MessageBeep () instead (). MSDN provides the following prototype:

BOOL MessageBeep (
UINT uType // sound type
);

This looks simple, but two interesting facts can be found in the annotations.

First, the uType parameter actually accepts a set of predefined constants.

Second, possible parameter values include-1, which means that although it is defined as a uint type, int is more suitable.

It is reasonable to use the enum type for the uType parameter. MSDN lists named constants, but does not provide any prompts for specific values. Because of this, we need to check the actual API.

If you have installed Visual Studio? And C ++, the Platform SDK is located in Program FilesMicrosoft Visual Studio. NETVc7PlatformSDKInclude.

To find these constants, I executed a findstr in this directory.

Findstr "MB_ICONHAND" *. h

It determines that constants are located in winuser. h, and then I use these constants to create my enum and prototype:

Public enum BeepType
{
SimpleBeep =-1,
IconAsterisk = 0x00000040,
IconExclamation = 0x00000030,
IconHand = 0x00000010,
IconQuestion = 0x00000020,
OK = 0x00000000,
}

[DllImport ("user32.dll")]
Public static extern bool MessageBeep (BeepType beepType );

Now I can use the following statement to call it: MessageBeep (BeepType. IconQuestion );
Processing Structure

Sometimes I need to determine the battery condition of my laptop. Win32 provides power management functions.

Search for MSDN and find the GetSystemPowerStatus () function.

BOOL GetSystemPowerStatus (
LPSYSTEM_POWER_STATUS lpSystemPowerStatus
);

This function contains a pointer to a structure that we have not processed. To process the structure, we need to use C # to define the structure. We start with the definition of unmanaged systems:

Typedef struct _ SYSTEM_POWER_STATUS {
BYTE ACLineStatus;
BYTE BatteryFlag;
BYTE BatteryLifePercent;
BYTE Reserved1;
DWORD BatteryLifeTime;
DWORD BatteryFullLifeTime;
} SYSTEM_POWER_STATUS, * LPSYSTEM_POWER_STATUS;

Then, use the C # type instead of the C type to get the C # version.

Struct SystemPowerStatus
{
Byte ACLineStatus;
Byte batteryFlag;
Byte batteryLifePercent;
Byte reserved1;
Int batteryLifeTime;
Int batteryFullLifeTime;
}

In this way, you can easily compile the C # prototype:

[DllImport ("kernel32.dll")]
Public static extern bool GetSystemPowerStatus (
Ref SystemPowerStatus systemPowerStatus );

In this prototype, we use "ref" to specify that the structure pointer will be passed instead of the structure value. This is a general method for processing the structure passed through pointers.

This function works well, but it is best to define the ACLineStatus and batteryFlag fields as enum:

Enum ACLineStatus: byte
{
Offline = 0,
Online = 1,
Unknown = 255,
}

Enum BatteryFlag: byte
{
High = 1,
Low = 2,
Critical = 4,
Charging = 8,
NoSystemBattery = 128,
Unknown = 255,
}

Note that because the fields in the structure are some bytes, we use byte as the basic type of The enum.



   String

Although there is only one. NET string type, this string type has several unique features in an unmanaged application. You can use character pointers and structures with nested character arrays. Each array needs to be properly encapsulated.

There are two different string representations in Win32:

ANSI
Unicode

Originally, Windows used single-byte characters, which saved storage space, but complicated multi-byte encoding was required when processing many languages. Windows NT? When it appears, it uses double-byte Unicode encoding. To solve this difference, Win32 API adopts a very clever approach. It defines the TCHAR type, which is a single-byte character on the Win9x Platform and a double-byte Unicode character on the WinNT platform. For each function that accepts A string or structure (including character data), Win32 API defines two versions of the structure and specifies Ansi encoding with the suffix, use W to specify the wide encoding (Unicode ). If you compile the C ++ program into A single byte, the variant is obtained. If the C ++ program is compiled into Unicode, the W variant is obtained. The Win9x Platform contains the Ansi version, while the WinNT platform contains the W version.

Since P/Invoke designers do not want you to worry about your platform, they provide built-in support to automatically use version A or version W. If the called function does not exist, the interoperability layer searches for and uses version A or version W for you.

The example can be used to illustrate the subtlety of String Support.

Simple string

The following is a simple example of a function that accepts string parameters:

Related Article

Contact Us

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.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.