Tuesday, December 07, 2004

A question has recently popped up on CF newsgroups on how to connect to a network resource programmatically. There's no managed API's exist to handle that, but as always native API's and P/Invoke comes to our rescue. On a desktop as well as in Windows CE this functionality's been handled by a network API's such as WNetAddConnection3, WNetCancelConnection2 etc... The documentation on them is pretty straightforward.

[DllImport("coredll")]

private static extern int WNetAddConnection3(

                  IntPtr hwndOwner,

                  NETRESOURCE lpNetResource,

                  string lpPassword,

                  string lpUserName,

                  int dwFlags);

 

[DllImport("coredll")]

private static extern int WNetCancelConnection2(

                  string lpName,

                  int dwFlags,

                  int fForce);

The WNetAddConnection3 accepts as a parameter the pointer to the NETRESOURCE structure so I declared it as the following:

private class NETRESOURCE

{

      public int dwScope;

      public int dwType;

      public int dwDisplayType;

      public int dwUsage;

      public IntPtr lpLocalName;

      public IntPtr lpRemoteName;

      public IntPtr lpComment;

      public IntPtr lpProvider;

}

In order to assign the values to lpLocalName and lpRemoteName members we'll use the MarshalEx.StringToHGlobalUni call from SDF. So, the call to WNetAddConnection3 looks like that:

NETRESOURCE NetRes = new NETRESOURCE();              

      NetRes.dwScope = RESOURCE_GLOBALNET | RESOURCE_REMEMBERED;

      NetRes.dwType = RESOURCETYPE_DISK;

      NetRes.dwDisplayType = RESOURCEDISPLAYTYPE_SHARE;

      NetRes.dwUsage = RESOURCEUSAGE_CONNECTABLE;

      NetRes.lpRemoteName = MarshalEx.StringToHGlobalUni(netRes);

      NetRes.lpLocalName = MarshalEx.StringToHGlobalUni(shareName);

      NetRes.lpComment = IntPtr.Zero;

      NetRes.lpProvider = IntPtr.Zero;

                       

      int ret = WNetAddConnection3(hwnd, NetRes, password, userName, 1);

 

      if (ret != 0)

      {

            throw new System.ComponentModel.Win32Exception(ret, ((NetworkErrors)ret).ToString());

      }                      

 After you've made successfull mapping you should be able to access your network resource by using System.IO's functionality like File.Copy, File.Create, File.Delete etc... Keep in mind that since Windows CE does not support drive letters, your share name will be mapped to the reserved root \Network. So if you named your share as “REMOTE“, you'll access it as “\Network\REMOTE\somefile.txt”.

You can download the source code for the Network class and a sample here.

MapDriveProject.zip (7.34 KB)
12/7/2004 3:25:23 PM (GMT Standard Time, UTC+00:00)  #     | 
 Monday, December 06, 2004

A few days ago I had a dream - my wife was holding a big hardcover book. When I opened it I realized that it's a book of blogs of all OpenNETCF.org's gig. Hmm... Since my wife doesn't read blogs this is not a bad idea - I thought to myself. When I woke up, I pondered on the dream a little bit thinking what a crasy dream I had and then was carried away by the usual daily activities. And then today I come upon this post by Scoble in which he referres to the book of blogs and now the dream I had doesn't seem to be so much crasy at all... So, what do you think about that? Do you think it would be worth collecting all the tips, tricks and wizdom we've blogged over the years here, and publishing it as a book?

12/6/2004 6:49:40 PM (GMT Standard Time, UTC+00:00)  #     | 

I've updated the SIPControl to draw images in place of buttons. It required just minimal changes to the code. I added Image and ImageDown properties to the KeyButton class, and added an new override to the DrawButton method to support image drawing:

private void DrawButton(string text, Graphics gx, Rectangle rc, Color foreColor, Image image)

{

      Brush foreBrush = new SolidBrush(foreColor);

     

      // draw image

      gx.DrawImage(image, rc.Left, rc.Top);

      //Center the text

      SizeF size = gx.MeasureString(text, this.Font);

           

      int X = rc.Left + (int)(rc.Width - size.Width)/2;

      int Y = rc.Top + (int)(rc.Height - size.Height)/2;

                 

      gx.DrawString(text, this.Font, foreBrush, X, Y);

                 

      foreBrush.Dispose();

}

I've also modified the OnPaint method to recognize if the KeyButton has an image assigned. So now, if you'd want to have image to draw a button, the client code would look like that:

ButtonRow row1 = new ButtonRow(new string[]{"q","w","e","r","t","y","u","i","o","p","[","]"}, 5, 20);

row1.Space = 0;

//Assign images

foreach(KeyButton button in row1.Buttons)

{

      button.Image = bitmap;

      button.ImageDown = bitmapDown;

}

And here's the screen shot of the sample:

Download the new version of the SIPControl and a sample here.

SIPTest1.zip (10.05 KB)

12/6/2004 5:51:37 PM (GMT Standard Time, UTC+00:00)  #     | 
 Friday, December 03, 2004

As you probably know that if you would want to implement a full “kiosk” mode on Pocket PC – which means that you need to hide the “Start” and SIP buttons to prevent users getting into underlying system. It’s easy to employ – just remove a MainMenu from a Form, set ControlBox to false and set the WindowState = FormWindowState.Maximized in the form’s Load event. But what if I still need clients to use SIP to enter some text? We could use the SipShowIM API, but this call will make the SIP button to appear again breaking the “kiosk” mode. So, to solve this puzzle I’ve created the SIPControl  - an owner-drawn control that allows creation of any type of SIP’s. Here’s the code snip that shows how to create a full SIP keyboard on your form:

sipFull = new SIPControl();

                 

// Location and size

sipFull.Location = new Point(1, 60);

sipFull.Size =    new Size(240, 90);

     

//Create ButtonRows

ButtonRow row1 = new ButtonRow(new string[]{"Q","W","E","R","T","Y","U","I","O","P"}, 1, 0);

row1.Space = 4;

// Add ButtonRow to the Rows collection

sipFull.Rows.Add(row1);

ButtonRow row2 = new ButtonRow( new string[]{"A","S","D","F","G","H","J","K","L"}, 10, 22);

row2.Space = 4;

sipFull.Rows.Add(row2);

ButtonRow row3 = new ButtonRow( new string[]{"Z","X","C","V","B","N","M"}, 30, 44);

row3.Space = 4;

sipFull.Rows.Add(row3);

ButtonRow row4 = new ButtonRow(  new string[]{"1","2","3","4","5","6","7","8","9","0"}, 1, 66);

row4.Space = 4;

sipFull.Rows.Add(row4);

                 

// Hook up the Click event

sipFull.ButtonClick+=new ButtonClickEventHandler(sipFull_ButtonClick);

this.Controls.Add(sipFull);        

 And here’s how the sample looks:

 

You can download the SIPControl and a sample from here.

SIPTest.zip (7.8 KB)
12/3/2004 4:44:53 PM (GMT Standard Time, UTC+00:00)  #     | 
 Tuesday, November 23, 2004

In his recent post Alex Feinman shows how to create XmlDataSource. This is a really great and usefull piece of code that shows how to implement databinding by the means of xml file.

If your your XML data is not that complex and close to the DataSet's xml serialized schema you can use the Paul Wilson's Open-Source ADO.NET XML Provider, that implements appropriate .NET Framework Data Provider interfaces and allows accessing and filtering the XML data by way of sql statements. I've ported the code for Compact Framework. Here's the screen shot of a sample client:

You can download the source code from here.

XmlDbProvider.zip (147.42 KB)

 

11/23/2004 7:48:30 PM (GMT Standard Time, UTC+00:00)  #     | 
 Wednesday, November 17, 2004

Chris Forsberg of pocketpcdn reminds us about this really cool resource created by Microsoft: We Rock 247. The Smart Client Sample download includes all required SDK's, tools and a source code for web client, winform client, web services and mobile client. The mobile part includes a few applications for Pocket PC and Smartphone (Packman and RoadRunner) and shows how to implement MVC pattern, MD5 password hashing, exception tracing, database wrapper (a la stored procedures), forms stack and many more really useful stuff.

11/17/2004 7:25:36 PM (GMT Standard Time, UTC+00:00)  #     | 
 Thursday, November 11, 2004

Recently I've come upon this diamond in the MSDN library Improving .NET Application Performance and Scalability. It's in fact an actual book where each chapter is a choke full of invaluable tips on how to create performant and scalable applications in .NET. A must read for every .NET developer experienced or not.

11/11/2004 1:27:29 PM (GMT Standard Time, UTC+00:00)  #     | 
 Monday, October 18, 2004

Everybody has been talking about Service-Oriented Architecture (SOA) lately. And it’s not about Web Services, but essentially about service been abstracted from the implementation, published specs of its interface and a formal contract between service provider and its customer.  So, mostly it is about standards in the communication between different platforms and systems – this is where SOAP, WSE (Indigo in the future) come to play. It’s all nice and dandy when you develop SOA systems for desktops/servers, but we’d immediately step into uncharted territory if you try to apply SOA principals when developing for mobile devices. Yes, we can call to Web Services from .NET CF client, we can even communicate with servers which implement WSE (big thanks to Casey for his wonderful work here), but you’d fall short if your project should require a 2 way real-time communication with a desktops or other devices in the almost always connected (WIFI) environment. So this rant is to bring attention of Microsoft folks on this very important subject. Mobile devices are not only used in the end-user retail environment, but also in the enterprise. We need WSE or Indigo for mobile devices.

10/18/2004 3:03:05 AM (GMT Daylight Time, UTC+01:00)  #     | 
 Thursday, September 30, 2004

You have probably heard about .NET to Go Mobility Road Show. It is a “FREE deeply technical and eminently useful mobile applications solutions workshop”. I am all setup at New York location for the partner / “Ask the Experts” table. Swing by to say hello or any other questions you might have.

9/30/2004 2:21:04 PM (GMT Daylight Time, UTC+01:00)  #    Comments [34]  |