How F# adapts to the way we think – part1

July 29, 2010 by Maurizio Colucci · 6 Comments 

This is the first episode of a series meant to show how easily F# adapts to the way we think. I assume no knowledge of functional languages, but I do assume knowledge of an imperative language such as C#.

___

Suppose in your application you want to do the following:

if there is a dog whose name is jerry, print “hello”.

This is how we think, i.e. how the original thought forms in our mind. But, in order to implement this thought in ordinary imperative languages (such as C++ or C# before .NET 3), we’d have to translate it more or less like that:

for each d in dogs
   if d.name = jerry then
      print "hello"

which is not close to the original sentence. As the conditions to write become more complicated, this kind of code tends to become unreadable and unmantainable.


Let us now see how much more natural it is to express the same idea in F#, and how much closer to the original sentence the F# code is.

In order to translate this to F#, it is useful to slightly rephrase our original thought like that:

if there is, among all dogs, a dog D whose name is jerry, print “hello”.

This is closer to F#, but let us rephrase it again slightly:

if there exists, among all dogs, a dog D such that D.name = jerry, then print “hello”.

now the above is practically F#. In fact, the real F# code is:

if exists dogs (fun d -> d.name = "jerry") then print "hello"

as you can see, it reads almost the way you think:

if
exists
dogs
(fun d
->
d.name = "jerry") then print "hello"
if there exists in dogs a D such that d.name = “jerry”) then print “hello”


End note:

In the above, the exists function is defined as follows:

let exists x y = List.exists y x

In the next episode I’ll deal with more complicated (but still very common) sentences and show how naturally they translate to F#.

_______
Microsoft Bizspark logo Yellow blue soft is a proud Microsoft Bizspark partner. Tabbles (our flagship product) is developed entirely in F#, and WPF using Visual Studio 2010.

_______

FileSystemWatcher (.net wrapper): doesn’t work on FAT32 (removable or Samba)

July 26, 2010 by Andrea D'Intino · 1 Comment 

HELLO WORLD,

We’ve always perceived the FileSystemWatcher as “moody”, meaning that it would work on some disks and not on some other… but we couldn’t quite understand the reasons behind it. It would work on fixed HD but not always on removable drives

A few days ago we bought 2 of those fantastic mini NAS-adapters, which work indeed fine even if they:

1)  have an embedded Linux using Samba to manage the sharing.

2) support only FAT32 partitions.

Of course we started testing Tabbles furiously and we immediately started yelling “OMG, the FileSystemWatcher doesn’t work on Network drives!”. The reason of such a panic attack is that our auto-tagging rules and one click-tagging are based on the FileSystemWatcher and Tabbles looses much of its appeal without those.

After a bit of yelling and hair-tearing we googled “FileSystemWatcher Samba” until we stumble on this article suggesting to use the “Win9xWatcherStrategy class”… deeply moved in the heart, Maurizio tries immediately to implement this but soon enough he finds out that the method “Win9xWatcherStrategy” doesn’t exist in the FileSystemWatcherClass. This means that we’ll probably bin the .net FileSystemWatcher wrapper, and move to the lower-level Win32 function.

For any of you using Tabbles Portable: be aware that for the moment the auto-tagging rules work only if your USB drive is formatted as NTFS… sorry for that but we’ll try to fix this soon!

——

But we also have some good news here: totally out of the blue, Mr. Leandro “O Dragão” posted on our forum a solution to the annoying problem of  Tabbles not being able to track files moved with Explorer, have a look at this thread. This is among the most exciting thing that happened to us in the past months…we don’t really know a lot about it yet, but so far it looks really promising – Kudos to Leandro! :-D

Mr. Burns

Mr. Burns

(Not sure why, but I believe Mr. Burns would be proud of us!)

:mrgreen:

Shared-tabbles is in beta

July 9, 2010 by Andrea D'Intino · 1 Comment 

HELLO WORLD

Our most anticipated feature is now available for beta testing.  This is what it looks like right now:

The shared-tabbles feature is in beta

The shared-tabbles feature is in beta

Check the shared-tabbles thread on the forum (or subscribe via RSS).

We’re looking to hear from as many of you as possible out there! :-D

Andrea & Maurizio

First databases merged: on our way to p2p shared-tabbles!

June 17, 2010 by Andrea D'Intino · 3 Comments 

HELLO WORLD

What is going on:

Maurizio has been working on shared-tabbles: document management p2p technology (more info here and here).
Basically, instead of loading only one database, Tabbles would load several databases, one for each user, have them all in memory at the same time, and whenever a query was done (e.g.: showing the content of a tabble or a combination), Tabbles would query all the databases and merge the output of the queries.
The great question lying behind this approach was: will this merge badly slow down Tabbles? And based on our first test we believe that the answer is a BIG FAT “NO”!

Real-time database merge for p2p document management solution

First databases merged - no visible slowdown




…read (and discuss) the whole story on our forum!  :-D





How to have large file icons with SHGetFileInfo in C#

June 10, 2010 by Maurizio Colucci · 2 Comments 

HELLO WORLD,

for a long while people have been complaining about our icons being unsharp and “pixelated”… indeed they were, and the reason was we were using SHGetFileInfo (a Windows Shell API function) to obtain the file icon from the file path. This function can only cannot return the high definition icons we see in Windows Vista and Windows, such as the following:

How to get large icons in C#

Tabbles with large icons

So we started to investigate how to obtain the hi-res icons (called “jumbo” and “extralarge”) and found this article on how to get large icons using C++. The problem was to convert this code to C#. This is not easy, at least for me, because it requires, among other things, to write a wrapper for a COM interface, and I had no experience with this. Finally, with the help of this article, I made it. You can find the code below. (Remember that the interesting function is icon_of_path_large, whereas icon_of_path is the old function which can only return a low-res icon.)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Media.Imaging;
using System.Windows.Media;
using System.Diagnostics;

namespace WpfControlLibrary1
{
    public class c_icon_of_path
    {
        // Constants that we need in the function call

        private const int SHGFI_ICON = 0x100;

        private const int SHGFI_SMALLICON = 0x1;

        private const int SHGFI_LARGEICON = 0x0;

        private const int SHIL_JUMBO = 0x4;
        private const int SHIL_EXTRALARGE = 0x2;

        // This structure will contain information about the file

        public struct SHFILEINFO
        {

            // Handle to the icon representing the file

            public IntPtr hIcon;

            // Index of the icon within the image list

            public int iIcon;

            // Various attributes of the file

            public uint dwAttributes;

            // Path to the file

            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]

            public string szDisplayName;

            // File type

            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]

            public string szTypeName;

        };

        [System.Runtime.InteropServices.DllImport("Kernel32.dll")]
        public static extern Boolean CloseHandle(IntPtr handle);

        private struct IMAGELISTDRAWPARAMS
        {
            public int cbSize;
            public IntPtr himl;
            public int i;
            public IntPtr hdcDst;
            public int x;
            public int y;
            public int cx;
            public int cy;
            public int xBitmap;        // x offest from the upperleft of bitmap
            public int yBitmap;        // y offset from the upperleft of bitmap
            public int rgbBk;
            public int rgbFg;
            public int fStyle;
            public int dwRop;
            public int fState;
            public int Frame;
            public int crEffect;
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct IMAGEINFO
        {
            public IntPtr hbmImage;
            public IntPtr hbmMask;
            public int Unused1;
            public int Unused2;
            public RECT rcImage;
        }

        #region Private ImageList COM Interop (XP)
        [ComImportAttribute()]
        [GuidAttribute("46EB5926-582E-4017-9FDF-E8998DAA0950")]
        [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
        //helpstring("Image List"),
        interface IImageList
        {
            [PreserveSig]
            int Add(
                IntPtr hbmImage,
                IntPtr hbmMask,
                ref int pi);

            [PreserveSig]
            int ReplaceIcon(
                int i,
                IntPtr hicon,
                ref int pi);

            [PreserveSig]
            int SetOverlayImage(
                int iImage,
                int iOverlay);

            [PreserveSig]
            int Replace(
                int i,
                IntPtr hbmImage,
                IntPtr hbmMask);

            [PreserveSig]
            int AddMasked(
                IntPtr hbmImage,
                int crMask,
                ref int pi);

            [PreserveSig]
            int Draw(
                ref IMAGELISTDRAWPARAMS pimldp);

            [PreserveSig]
            int Remove(
            int i);

            [PreserveSig]
            int GetIcon(
                int i,
                int flags,
                ref IntPtr picon);

            [PreserveSig]
            int GetImageInfo(
                int i,
                ref IMAGEINFO pImageInfo);

            [PreserveSig]
            int Copy(
                int iDst,
                IImageList punkSrc,
                int iSrc,
                int uFlags);

            [PreserveSig]
            int Merge(
                int i1,
                IImageList punk2,
                int i2,
                int dx,
                int dy,
                ref Guid riid,
                ref IntPtr ppv);

            [PreserveSig]
            int Clone(
                ref Guid riid,
                ref IntPtr ppv);

            [PreserveSig]
            int GetImageRect(
                int i,
                ref RECT prc);

            [PreserveSig]
            int GetIconSize(
                ref int cx,
                ref int cy);

            [PreserveSig]
            int SetIconSize(
                int cx,
                int cy);

            [PreserveSig]
            int GetImageCount(
            ref int pi);

            [PreserveSig]
            int SetImageCount(
                int uNewCount);

            [PreserveSig]
            int SetBkColor(
                int clrBk,
                ref int pclr);

            [PreserveSig]
            int GetBkColor(
                ref int pclr);

            [PreserveSig]
            int BeginDrag(
                int iTrack,
                int dxHotspot,
                int dyHotspot);

            [PreserveSig]
            int EndDrag();

            [PreserveSig]
            int DragEnter(
                IntPtr hwndLock,
                int x,
                int y);

            [PreserveSig]
            int DragLeave(
                IntPtr hwndLock);

            [PreserveSig]
            int DragMove(
                int x,
                int y);

            [PreserveSig]
            int SetDragCursorImage(
                ref IImageList punk,
                int iDrag,
                int dxHotspot,
                int dyHotspot);

            [PreserveSig]
            int DragShowNolock(
                int fShow);

            [PreserveSig]
            int GetDragImage(
                ref POINT ppt,
                ref POINT pptHotspot,
                ref Guid riid,
                ref IntPtr ppv);

            [PreserveSig]
            int GetItemFlags(
                int i,
                ref int dwFlags);

            [PreserveSig]
            int GetOverlayImage(
                int iOverlay,
                ref int piIndex);
        };
        #endregion

        ///
        /// SHGetImageList is not exported correctly in XP.  See KB316931
        /// http://support.microsoft.com/default.aspx?scid=kb;EN-US;Q316931
        /// Apparently (and hopefully) ordinal 727 isn't going to change.
        ///
        [DllImport("shell32.dll", EntryPoint = "#727")]
        private extern static int SHGetImageList(
            int iImageList,
            ref Guid riid,
            out IImageList ppv
            );

        // The signature of SHGetFileInfo (located in Shell32.dll)
        [DllImport("Shell32.dll")]
        public static extern int SHGetFileInfo(string pszPath, int dwFileAttributes, ref SHFILEINFO psfi, int cbFileInfo, uint uFlags);

        [DllImport("Shell32.dll")]
        public static extern int SHGetFileInfo(IntPtr pszPath, uint dwFileAttributes, ref SHFILEINFO psfi, int cbFileInfo, uint uFlags);

        [DllImport("shell32.dll", SetLastError = true)]
        static extern int SHGetSpecialFolderLocation(IntPtr hwndOwner, Int32 nFolder,
                 ref IntPtr ppidl);

        [DllImport("user32")]
        public static extern int DestroyIcon(IntPtr hIcon);

        public struct pair
        {
            public System.Drawing.Icon icon {get;set;}
            public IntPtr iconHandleToDestroy{set;get;}

        }

        public static int DestroyIcon2(IntPtr hIcon)
        {
            return DestroyIcon(hIcon);
        }

        private static BitmapSource bitmap_source_of_icon  ( System.Drawing.Icon ic) {
                var ic2 = System.Windows.Interop.Imaging.CreateBitmapSourceFromHIcon(ic.Handle,
                                                        System.Windows.Int32Rect.Empty,
                                                        System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions( ) );
                ic2.Freeze();
                return ((BitmapSource) ic2 );
        }

        public static BitmapSource SystemIcon(bool small, ShellLib.ShellApi.CSIDL csidl)
        {

            IntPtr pidlTrash = IntPtr.Zero;
            int hr = SHGetSpecialFolderLocation(IntPtr.Zero, (int) csidl, ref pidlTrash);
            Debug.Assert(hr == 0);

            SHFILEINFO shinfo = new SHFILEINFO();

            uint SHGFI_USEFILEATTRIBUTES = 0x000000010;

            // Get a handle to the large icon
            uint flags;
            uint SHGFI_PIDL = 0x000000008;
            if (!small)
            {
                flags = SHGFI_PIDL | SHGFI_ICON | SHGFI_LARGEICON | SHGFI_USEFILEATTRIBUTES;
            }
            else{
                flags = SHGFI_PIDL | SHGFI_ICON | SHGFI_SMALLICON | SHGFI_USEFILEATTRIBUTES;
            }

            var res = SHGetFileInfo(pidlTrash, 0, ref shinfo, Marshal.SizeOf(shinfo), flags);
            Debug.Assert(res != 0);

            var myIcon = System.Drawing.Icon.FromHandle(shinfo.hIcon);
            Marshal.FreeCoTaskMem(pidlTrash);
            var bs = bitmap_source_of_icon(myIcon);
            myIcon.Dispose();
            bs.Freeze(); // importantissimo se no fa memory leak
            DestroyIcon(shinfo.hIcon);
            CloseHandle(shinfo.hIcon);
            return bs;

        }

        public static BitmapSource icon_of_path(string FileName, bool small, bool checkDisk, bool addOverlay)
        {
            SHFILEINFO shinfo = new SHFILEINFO();

            uint SHGFI_USEFILEATTRIBUTES = 0x000000010;
            uint SHGFI_LINKOVERLAY = 0x000008000;

            uint flags;
            if (small)
            {
                flags = SHGFI_ICON | SHGFI_SMALLICON ;
            }
            else{
                flags = SHGFI_ICON | SHGFI_LARGEICON ;
            }
            if (!checkDisk)
                flags |= SHGFI_USEFILEATTRIBUTES;
            if (addOverlay)
                flags |= SHGFI_LINKOVERLAY;

            var res = SHGetFileInfo(FileName, 0, ref shinfo, Marshal.SizeOf(shinfo), flags);
            if (res == 0)
            {
                throw(new System.IO.FileNotFoundException());
            }

            var myIcon = System.Drawing.Icon.FromHandle(shinfo.hIcon);

            var bs = bitmap_source_of_icon(myIcon);
            myIcon.Dispose();
            bs.Freeze(); // importantissimo se no fa memory leak
            DestroyIcon(shinfo.hIcon);
            CloseHandle(shinfo.hIcon);
            return bs;

        }

        public static BitmapSource icon_of_path_large(string FileName, bool jumbo, bool checkDisk)
        {

            SHFILEINFO shinfo = new SHFILEINFO();

            uint SHGFI_USEFILEATTRIBUTES = 0x000000010;
            uint SHGFI_SYSICONINDEX = 0x4000;

            int FILE_ATTRIBUTE_NORMAL = 0x80;

            uint flags;
            flags = SHGFI_SYSICONINDEX;

            if (!checkDisk)  // This does not seem to work. If I try it, a folder icon is always returned.
                flags |= SHGFI_USEFILEATTRIBUTES ;

            var res = SHGetFileInfo(FileName, FILE_ATTRIBUTE_NORMAL, ref shinfo, Marshal.SizeOf(shinfo), flags);
            if (res == 0)
            {
                throw (new System.IO.FileNotFoundException());
            }
            var iconIndex = shinfo.iIcon;

            // Get the System IImageList object from the Shell:
            Guid iidImageList = new Guid("46EB5926-582E-4017-9FDF-E8998DAA0950");

            IImageList iml;
            int size = jumbo ? SHIL_JUMBO : SHIL_EXTRALARGE;
            var hres = SHGetImageList(size, ref iidImageList, out  iml); // writes iml
            //if (hres == 0)
            //{
            //    throw (new System.Exception("Error SHGetImageList"));
            //}

            IntPtr hIcon = IntPtr.Zero;
            int ILD_TRANSPARENT = 1;
            hres = iml.GetIcon(iconIndex, ILD_TRANSPARENT, ref hIcon);
            //if (hres == 0)
            //{
            //    throw (new System.Exception("Error iml.GetIcon"));
            //}

            var myIcon = System.Drawing.Icon.FromHandle(hIcon);
            var bs = bitmap_source_of_icon(myIcon);
            myIcon.Dispose();
            bs.Freeze(); // very important to avoid memory leak
            DestroyIcon(hIcon);
            CloseHandle(hIcon);

            return bs;

        }
    }
}

You can download Tabbles on our download page!

.

.

.

Next Page »