Programming Microsoft Windows Ce Net 3Rd [Electronic resources] نسخه متنی

اینجــــا یک کتابخانه دیجیتالی است

با بیش از 100000 منبع الکترونیکی رایگان به زبان فارسی ، عربی و انگلیسی

Programming Microsoft Windows Ce Net 3Rd [Electronic resources] - نسخه متنی

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
لیست موضوعات
توضیحات
افزودن یادداشت جدید






Compact Framework Unique Classes


The Compact Framework supports a series of classes that are not on the standard desktop version of the .NET Framework class library. These classes are provided to support a few of the unique situations that mobile applications encounter. They include classes for dealing with the soft keyboard, or soft input panel (SIP); infrared communication; and interprocess communication.

MessageWindow


The MessageWindow class provides a method for unmanaged code to send standard window messages to Compact Framework applications. On the desktop, the Control class provides a WndProc method that can be overridden to see all the window messages sent to the control. Because most window classes in the framework are derived from the Control class, this lets a desktop application monitor window messages for almost every window in the application. In the Compact Framework, however, the Control class doesn't provide a WndProc method, so there's no way to see the window messages sent to the controls in the application. The MessageWindow class, unique to the Compact Framework, is an exception. This class creates a hidden window and provides not only a WndProc method to monitor messages sent to the window but also an Hwnd property that provides the handle to the window.

Instead of creating an instance of the MessageWindow class, applications derive a class from MessageWindow and then override the WndProc method so that the message sent to the window can be seen. The WndProc method is defined as

protected virtual new void MessageWindow.WndProc (Message m);

The only parameter is an instance of a Message structure that describes the message received by the window. The Message structure has the following properties:

public IntPtr Message.HWnd;
public int Message.Msg;
public IntPtr Message.WParam;
public IntPtr Message.LParam;
public IntPtr Message.Result;

The properties represent the standard parameters of a call to a window procedure: the handle to the window, the message value, the wParam value, and the lParam value. The additional property, Result, is the value returned by the message. The Message structure also has one interesting method, Create, shown here:

public static Create (IntPtr hwnd, Int32 msg, IntPtr wparam, IntPtr lparam);

This method provides a single-line initialization function for the other properties in the structure.

The following code fragment shows how the MessageWindow class can be used.

using Microsoft.WindowsCE.Forms;
public class MyMsgWnd : MessageWindow
{
protected override void WndProc (ref Message m)
{
// WM_USER is defined as 0x400
if (m.Msg == 0x400)
{
string s = string.Format (
"WM_USER received wParam:{0:X} lParam:{1:X} ",
m.WParam.ToInt32(), m.LParam.ToInt32());
MessageBox.Show (s);
}
base.WndProc (ref m);
}
}

This code fragment shows the declaration of the MyMsgWnd class derived from MessageWindow. MyMsgWnd overrides the WndProc method and displays a message box when a window receives a WM_USER message created by MyMsgWnd. Because this is a managed application, there is no declaration for all the standard window messages. A glance at any Windows CE SDK will show that WM_USER is defined as 0x400 in Winuser.h.

The MessageWindow class has two static methods that can be used to send or post window messages to other windows. They are the appropriately named SendMessage and PostMessage, shown here:

public static void MessageWindow.PostMessage (Message m);
public static void MessageWindow.SendMessage (Message m);

The two methods each take a Message structure as their single argument.

MessageWindow also exposes the handle of the window created by the class in the read-only property Hwnd, defined as

public IntPtr MessageWindow.Hwnd;

The Hwnd property is unique in the Compact Framework because it's the only place where a real window handle is exposed to managed code. Other controls in the Compact Framework don't expose their window handles and therefore can't be sent to other applications. The MessageWindow class will be used in the IrSquirtCF example later in this chapter.

InputPanel


The InputPanel class provides Compact Framework applications information regarding the state of the SIP (the soft keyboard) on the Pocket PC or other embedded devices with a soft keyboard. In addition, the InputPanel class can be used to control the state of the SIP, enabling the application to show or hide the SIP as needed. The methods and properties of the InputPanel class are shown here:

public void InputPanel.InputPanel ( );
public Rectangle InputPanel.Bounds;
public Rectangle InputPanel.VisibleDesktop;
public bool InputPanel.Enabled;
public event EventHandler InputPanel.EnabledChanged;

Interestingly, the methods of the InputPanel class are not marked static, so to monitor or control the SIP, the class must first be instantiated. The InputPanel constructor takes no arguments. The InputPanel read-only properties Bounds and VisibleDesktop, both defined as rectangles, provide information about the size and position of the SIP as well as the size of the desktop area not obscured by the SIP.

The VisibleDesktop property provides the rectangle that is the area of the desktop not covered by the SIP. This rectangle changes depending on whether the SIP is displayed or hidden. When the SIP is displayed, the rectangle ranges from just below the navigation bar to just above the top of the SIP window. When the SIP is hidden, the rectangle includes all of the area of the screen below the navigation bar, including the area of the menu bar if one was created by the application.

The Bounds rectangle describes the size and location of the SIP when it's displayed. This rectangle doesn't change if the SIP is hidden. Instead, it always shows the location and size of the SIP as if it were being displayed. Applications wanting to adjust their windows to avoid being covered by the SIP should use the VisibleDesktop property instead of the Bounds property.

The Enabled property is set to true if the SIP is displayed and false if the SIP is hidden. The property is settable, providing the application the ability to show or hide the SIP simply by changing this property.

The InputPanel class contains an event that can be hooked to notify the application when the state of the SIP changes from hidden to shown or shown to hidden. The delegate associated with this event contains only the default object and the EventArgs parameters, so when the event fires, the event handler must query the new state of the SIP using the Enabled parameter.

Working with the SIPUnless the FormBorderStyle property of the Form class is set to null, the Pocket PC implementation of the runtime overrides the Size and Location properties, preventing an application from resizing a form in response to the SIP being shown or hidden. A workaround for this issue is to create a Panel control or a property sheet on the form and then place all the other controls for the form on that control. An example of using the EnableChanged event can be seen in the IrSquirtCF example later in this chapter. In the example, the EnableChanged event is overridden to adjust the size of the output list box control.

IrDA Classes


The Compact Framework supports managed classes for Infrared Data Association (IrDA) communication. The classes are extensions of the Socket class provided both in the desktop version of the Framework Class Library and in the Compact Framework. The extensions center around two classes: IrDAClient, which provides the interface to the IrDA socket stream, discovery information, and status information about the current connection; and IrDAListener, which provides server support for listening for other devices that want to initiate an infrared (IR) connection with the device. A number of other classes provide support for these two major classes.

IrDAClientThe IrDAClient class provides the following methods and properties:

public void IrDAClient ();
public void IrDAClient (IrDAEndPoint);
public void IrDAClient (string);
public void Connect(IrDAEndPoint);
public void Connect(string);
public void Close();
public IrDADeviceInfo[] DiscoverDevices(int);
public static IrDADeviceInfo[] DiscoverDevices(int, Socket);
static string GetRemoteMachineName (Socket s);
public Stream GetStream();
public string RemoteMachineName;

This variety of methods and properties provides most of the functionality needed for IR communication. To initiate communication with another device, an application first uses the DiscoverDevices method to determine whether any devices are in range. This process is shown in the following code fragment:

IrDAClient irClient;
irClient = new IrDAClient();
IrDADeviceInfo[] di = irClient.DiscoverDevices(4);
if (di.Length > 0)
{
foreach (IrDADeviceInfo device in di)
Console.WriteLine ("Device:"+device.DeviceName+" discovered.");
}
else
Console.WriteLine ("No devices discovered.");

The single parameter DiscoverDevices is the maximum number of devices to return.

Once a device has been detected, the application can connect to a specific service on the device by calling the Connect method on an IrDAClient class. Connect can take one of two different parameters, either an IrDAEndPoint class describing the device and service to connect to or simply a string requesting a connection to a specific named service provided by the other device.

After a connection is made successfully, the GetStream method is called to get an instance of a stream class to communicate with the other device. The stream class is the same class that forms the basis for the filestream classes used elsewhere in the Framework. The stream class contains the requisite read and write methods for sending and receiving bytes from the other device.

When communication is completed with the other device, the stream class and the IrDAClient class should be closed. In addition, after the Close methods have been called, the Dispose methods on both classes should be called before the class goes out of scope. This ensures that any system resources used by those classes will be freed immediately instead of waiting until a garbage collection occurs.

IrDAListenerThe IrDAListener class is used to create an IrDA server socket that can listen for incoming connection requests. The interesting methods and properties of IrDAListener are shown here:

public IrDAListener(IrDAEndPoint);
public IrDAListener(string);
public IrDAEndPoint LocalEndpoint {get;}
public IrDAClient AcceptIrDAClient();
public Socket AcceptSocket();
public bool Pending();
public void Start();
public void Stop();

The IrDAListener constructor can specify either an IrDAEndPoint class or simply the name of the infrared service that the server should advertise. Once an instance of the class is created, the start method is called to listen for any incoming requests for connections. Connections can be detected by calling the Pending method. The Pending method will return true when another device has requested an infrared connection. Once a connection request is detected, the server calls the AcceptSocket method, which returns an instance of an IrDAClient class that is then used for communication.

The following code fragment shows the process of creating an IrDAListener class and waiting for a connection:

IrDAListener irListen;
IrDAClient irClientSrv;
Stream s;
irListen = new IrDAListener("MySquirt");
irListen.Start();
while (isRunning)
{
if (irListen.Pending())
break;
if (isRunning)
Thread.Sleep (500);
}
irClientSrv = irListen.AcceptIrDAClient();
s = irClientSrv.GetStream();

Notice that the Pending method call is made within a polling loop. Unfortunately, Pending doesn't block, so a server thread must continually call Pending to determine when a client device wants to connect. Because polling must be done relatively infrequently in a Windows CE device to avoid running down the battery, the preceding code sleeps the thread for half a second before checking again for a connection. This polling process is best done on a thread other than the primary thread of the application.

The IrSquirtCF example later in this chapter demonstrates the use of the IrDA classes. That example demonstrates device discovery, operating as an IR server, and operating as an IR client.

/ 169