Wednesday, March 16, 2005

OK, I am back to the surface still alive and breathing after been drowned in the sea of project deadlines.

A few important links from this morning news scan:

1. The Indigo CTP documents are available at:

http://winfx.msdn.microsoft.com/library/default.asp?url=/library/en-us/indigo_con/html/503fae4b-014c-44df-a9c7-c76ec4ed4229.asp

And as Sam Gentile righfully mentiones - “Go read, get used to it, it's your future.“

2. Cool project at Codeproject.com:

Implement an explorer using .net compact flamework in Pocket PC

 

 

 

3/16/2005 3:12:51 PM (GMT Standard Time, UTC+00:00)  #    Comments [43]  | 
 Friday, February 04, 2005

In his recent post Mike Zintel divuldges some information on the past, present and future of evolution of the NetCF and asking some feedback on the priorities for v.Next. As I already pointed out in my previouse post, CF lacks essential support for developing SOA such as WS-* protocol suite or Indigo. So seeing that CF team is thinking on leveraging it is very encoraging sign. The only problem I see here is the timing. Mike mentions this in the context of V3, but we need it now. The project that I am working on is a real time trading system that utilizes desktop as well as CE devices clients. In the case of desktop the usage of WSE is no brainer and fits in the architecture that I designed pretty well. But in case of CE devices I have to go through some loops by utilizing a Web Service in the middle for outgoing messages and a custom UDP communication for incoming. Plus by the time the CF V3 will be coming out the Indigo should be available so it would make sence to implement Indigo for CF V3 as well. How about if CF team would release a WS-* for CF as and add-on not tied up to V3, but may be to some Service Pack for v2 of CF and provided a full support for Indigo in the V3. I think this should be a feasable option since MS already has the WSE in the v2.0 which is pretty stable and shouldn't pose a lot problems when porting the code to CF v2.

2/4/2005 3:32:23 PM (GMT Standard Time, UTC+00:00)  #     | 
 Friday, January 14, 2005

Check out the Neil's Call to Action... post. Make a donation if you appreciate not only the always growing SDF, but also the invaluable help, support, tips, tricks and code the we provide in our blogs. Remember that accordingly to the latest studies one of the main things that make you happy is being kind or helping to others, whether friends or strangers...

1/14/2005 2:17:15 PM (GMT Standard Time, UTC+00:00)  #    Comments [34]  | 
 Wednesday, January 12, 2005

You should be aware that it's not feasible to call EnumWindows API in the CF, since the usage of the delegates as a native callbacks is not supported in the v1 (it will be supported in CF v2 though). But there's a way to emulate functionality of this API by using GetWindow and GetWindowText:

public static Window[] EnumerateTopWindows()

{

      ArrayList winList = new ArrayList();

      IntPtr hwnd = IntPtr.Zero;

      Window window = null;

      StringBuilder sb = null;

                 

      // Get the first window

      hwnd = GetActiveWindow();

      hwnd = GetWindow(hwnd, GW_HWNDFIRST);

     

      while(hwnd != IntPtr.Zero)

      {    

            IntPtr parentWin = GetParent(hwnd);

            // Make sure that the window doesn't have a parent

            if ((parentWin == IntPtr.Zero))

            {

                  int length       = GetWindowTextLength(hwnd);

                  // Check if it has caption text

                  if (length > 0)

                  {

                        window = new Window();

                        window.Handle = hwnd;

                        sb = new StringBuilder(length + 1);

                        GetWindowText(hwnd, sb, sb.Capacity);

                        window.Caption = sb.ToString();

                        winList.Add(window);

                  }

            }

                 

            hwnd = GetWindow(hwnd, GW_HWNDNEXT);

      }

      return (Window[])winList.ToArray(typeof(Window));

}

 Download the sample code from here.

EnumerateWindowsProj.zip (5.82 KB)
1/12/2005 5:03:23 PM (GMT Standard Time, UTC+00:00)  #     | 
 Monday, January 03, 2005
 Wednesday, December 29, 2004

As you know CF v1 (it will be available in CF v2 though) doesn't provide implementaion of the FromHbitmap method that allows creation of the managed Bitmap object from native window handle (HBITMAP). The solution that I provide is based on the idea of creation of a managed Bitmap from an in memory array/stream of a bitmap file like for example is done in the XrossOne Mobile GDI+. We can get the information on the Bitmap using GetObject API including a pointer to the bitmap bits which we can copy to the managed array:

public static Bitmap FromHbitmap(IntPtr handle)

{

     BITMAP bm = new BITMAP();

     // Get info

     GetObject(handle, Marshal.SizeOf(bm), ref bm);

     // Create our Bitmap buffer

     BitmapBuffer bmpBuffer = new BitmapBuffer(bm.bmWidth, bm.bmHeight, (short)bm.bmBitsPixel);

     // Native pointer to bmp bits

     IntPtr pBits = new IntPtr(bm.bmBits);

     // Create temp array for bitmap bits to workaround a bug in the Marshal.Copy -

     // it never uses the startIndex

     byte[] tempBits = new byte[bm.bmWidthBytes * bm.bmHeight];

     //Get the bits to the temporary managed byte array.

     Marshal.Copy(pBits, tempBits, 0, bm.bmWidthBytes * bm.bmHeight);

     // Copy from the temporary managed byte to our buffer

     System.Buffer.BlockCopy(tempBits, 0, bmpBuffer.buffer, offset, tempBits.Length);

     // Create managed Bitmap

     return bmpBuffer.CreateBitmap();

}

You can download the whole implementation for the BitmapBuffer class and the sample here.

FromHbitmapProject.zip (6.63 KB)
12/29/2004 10:42:10 PM (GMT Standard Time, UTC+00:00)  #     | 
 Friday, December 10, 2004

 

There’s a known solution to enable HTTP 1.1 Compression for Web Services that’s been described on dotnetjunkies site. The solution that they propose is to override GetWebRequest and GetWebResponse methods in your WS generated proxy file. If you’d try to implement this solution for CF you’d get an “no suitable method found to override" exception. The problem is that Microsoft “forgot” to expose these methods as overridable in the WebClientProtocol class in the v1 of CF, but… they have silently updated the WebClientProtocol class to expose the GetWebRequest and GetWebResponse as virtual (overridable) methods in one of the Service Packs.

So, in order to be able to compile the sample from dotnetjunlies, you'd need to update the System.Web.dll in the \CompactFrameworkSDK\v1.0.5000\Windows CE directory. Here's the tricky part. The steps are:

 

1. Download the CF SP2 developer redistributable:

 

http://www.microsoft.com/downloads/details.aspx?familyid=10600643-09b3-46d8-ba28-bc494bc20d26&displaylang=en

 

2. Unpack one of the CAB's from the distribution (I've used WinRAR to unpack the netcf.core.ppc3.x86.CAB file).

 

3. Rename the SYC6B2~1.014 file to System.Web.dll

 

4. Copy it to the fore mentioned directory.

 

Here you go, now you should be able to modify the web service proxy files to use using Standard HTTP 1.1 Compression.

 

Oh… and also make sure you’re running the SP2 bits on the device as well.

 

I’ve put together a CF sample that includes SharpZipLib and the code from the article. The sample uses the StockService sample Web Service from WSE 2.0 distribution.

 

You can download the sample here.

WSCompression.zip (226.13 KB)
12/10/2004 4:11:00 PM (GMT Standard Time, UTC+00:00)  #     | 
 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)  #     |