Using the Win32 class library in C #

Source: Internet
Author: User
Tags bool emit win32 visual studio

C # users often ask two questions: "Why should I write additional code to use features that are built into Windows?" Why is there no corresponding content in the framework for me to do this task? "When the framework team built their. NET section, they evaluated the work that needed to be done to make the. NET programmer able to use Win32, and found the Win32 API set very large." They do not have enough resources to write managed interfaces for all Win32 APIs, test them, and write documents, so they can only prioritize the most important ones. Many common operations have managed interfaces, but there are many complete Win32 parts that do not have managed interfaces.

Platform Invoke (P/invoke) is the most common way to accomplish this task. To use P/invoke, you can write a prototype that describes how to call a function, and then the runtime uses this information to invoke it. Another approach is to wrap the function using Managed Extensions to C + +, which will be covered in a later column.

The best way to understand how to do this is through the example. In some cases, I only give some of the code, and the complete code is available for download.

Simple example

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

BOOL Beep (
DWORD Dwfreq,//Voice frequency
DWORD dwduration//Sound duration
);

To write this prototype in C #, you need to convert the Win32 type to the corresponding C # type. Since a DWORD is a 4-byte integer, we can use int or uint as the C # corresponding type. Because int is a CLS-compliant type (which can be used with all. NET languages), it is more commonly used than uint, and in most cases the difference between them is not important. The type bool corresponds to bool. Now we can write the following prototype in C #:

public static extern bool Beep (int frequency, int duration);
 
This is a fairly standard definition, except that we use extern to indicate that the actual code for the function is elsewhere. This prototype will tell the runtime how to call the 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 find that Beep () is defined in Kernel32.lib. This means that the Run-time code is included in the Kernel32.dll. We add the DllImport attribute to the prototype to tell the runtime:

[DllImport ("kernel32.dll")]

This is all the work we have to do. The following is a complete example of a random sound that is common in sci-fi movies in the the 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);
}
}
}
}

It's loud enough to excite any listener! Because DllImport allows you to invoke any code in Win32, it is possible to invoke malicious code. So you must be a fully trusted user, and the runtime can make P/invoke calls.

Enumerations and Constants

Beep () can be used to emit arbitrary sounds, but sometimes we want to emit certain types of sounds, so we use MessageBeep () instead. MSDN gives the following prototypes:

BOOL MessageBeep (
UINT Utype//voice type
);

This looks simple, but there are two interesting facts that can be found in the comments.

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

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

For Utype parameters, it is reasonable to use the enum type. MSDN lists the named constants, but does not give any hint as to the specific values. Because of this, we need to look at the actual API.

If you have Visual Studio installed? and C + +, the Platform SDK is located under \program Files\Microsoft Visual Studio. Net\vc7\platformsdk\include.

To find these constants, I performed a findstr in the directory.

Findstr "Mb_iconhand" *.h

It determines that the constants are 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 invoke it with the following statement: MessageBeep (beeptype.iconquestion);
Processing structure

Sometimes I need to determine the battery condition of my notebook. WIN32 provides a power management function for this purpose.

Search MSDN to find the GetSystemPowerStatus () function.

BOOL GetSystemPowerStatus (
Lpsystem_power_status Lpsystempowerstatus
);

This function contains pointers to a structure that we have not yet processed. To handle the structure, we need to define the structure in C #. We start from an unmanaged definition:

typedef struct _SYSTEM_POWER_STATUS {
BYTE ACLineStatus;
BYTE Batteryflag;
BYTE batterylifepercent;
BYTE Reserved1;
DWORD Batterylifetime;
DWORD BatteryFullLifetime;
} system_power_status, *lpsystem_power_status;

You can then get a C # version by substituting C # for the type of C..

struct SystemPowerStatus
{
BYTE ACLineStatus;
BYTE Batteryflag;
BYTE BatteryLifePercent;
BYTE reserved1;
int batterylifetime;
int batteryfulllifetime;
}

In this way, you can easily write a C # prototype:

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

In this prototype, we use "ref" to indicate that the struct pointer will be passed instead of the struct value. This is a general method of dealing with structures passed by pointers.

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

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 structure's fields are some bytes, we use byte as the basic type of the enum.

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.