1.5.9 is out + some news

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

HELLO WORLD,

this will be  a lazy update… the reason is that the last days were particularly hectic. Let me try and sum it up:

  • On Friday we were featured on GOTD.
  • Re-installed (read: fought with) phpbb, but now it works fine and has a lot of cool new things, including the much needed open-id mod (which now works like a charm!). I’m planning a blog post about phpbb: I’m not an expert but for sure there is a lot I know that is worth sharing :-)
  • Just released the 1.5.9 including Polish (and I just received the Hungarian translation too…will be in the next update).
  • Quite a few things fixed/improved in the shared-tabbles features
  • We sold the first Corporate licenses! Yes – it came as a surprise to us too!!! (The Corporate license will include the shared-tabbles features…which is not there yet!)
  • Something REALLY cool: Don Syme (the man behind F#) wrote a blog post about Tabbles!

Well, as I’m here, let me share some more visual stuff:

Ok, now look at our GOTD peak here:

gaotd-peak

look at our peak on the giveawayoftheday promotion!

Look at how sexy is our yahoo pipe (subscribe to RSS)

Tabbles yahoo-pipe, we use it to aggregate all our feeds
Tabbles yahoo-pipe, we use it to aggregate all our feeds

And finally, I just sketched this:

Tabbles new tag-line...or something

Tabbles new tag-line...or something. You like it? ;-)

GOOD NIGHT WORLD.

P.S.: on a sad note, I’m stuck with the error 0×80004005 whil trying to let people browse  shared folder on my Windows Server 2008 (sp2). Looks like there is no way out… anyone? :-O

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

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!

.

.

.

Tabbles + ScrapBook + Gyazo

June 1, 2010 by Andrea D'Intino · 2 Comments 

Here is an awesome trio of applications – and how they work nicely together – for all the Firefox users.

Gyazo

Let’s start from Gyazo:  a great screenshot capturing software that by simply right-clicking allows you to take a screenshot of a portion of your desktop and automatically uploads it on its own Gyazo server. As soon as you’ve done that a webpage will open in your browser showing the screenshot you’ve just taken – you can then send the link to anyone and they’ll be able to see your screenshot. :-)

Bereich auf dem Bildschirm wird ausgewählt Markierte Adresszeile zeigt den Link zum Screen

This alone is awesome and everyone would find it handy. Let’s have a look at the Firefox addons ScrapBook and ScrapBook Plus from Gomita.

Scrapbook – Scrapbook Plus

Menü von Scrapbook What do they do? To those of you who don’t know (and love) them already, ScrapBook allows you to save a complete website, by just one right-click. The website will be saved along with all its content (as links and pics) and can later be opened or edited. There is also a hierarchical menu for the archived websites. As each archived website is shown in your browser with it’s own path, you can now tag (categorize) all your saved websites with the Tabbles-Bookmarklets as you would do for online websites.

…ok, but where is the catch?

When I take a screenshot with Gyazo and archive it using ScrapBook, I can then tag-it with Tabbles, (as I tag everything else), and find it quick and easily – and browse it along with bookmarks and files. :-) Therefore: you can use Tabbles to tag the online links to the Gyazo-screenshots (as regular websites) as well as the screenshot files or the archived websites you saved on your hard-disk, tag all of them with Tabbles and find/browse them all in the same way! Awesome trio!  :-o I love it <3

Tabbles now supports Chinese and Japanese (nearly)

May 31, 2010 by Andrea D'Intino · 1 Comment 

HELLO WORLD

another small step for the humanity, but another huge step for us!!! :-D

tabbles-chinese-japanese

Tabbles in Chinese

Why did it take so long? (check the update below after this)

We previously tried to generate the .resx (the language file) using Zeta resource editor which works like a charm with languages using the Latin alphabet (as well as with Russian) but apparently didn’t produce a valid file when we tried to use it to localize Chinese and Japanese. Maurizio did first  tried with ResEx with Notepad++ and those failed… the problem lies in the file encoding: even if it’s they save an utf8 file, there seems to be something fishy about it – were we doing something wrong? Any hint would be appreciated. Then he successfully edited the Chinese .resx file in VisualStudio 2010,  and (surprise-surprise!) Emacs worked too:

Emacs Chinese localization tabbles

Emacs can produce a good localization file for Chinese

Now we’re investigating more localization tools that can handle Chinese/Japanese correctly… will update the post as soon as we find one.

Update: we realized that problem is only the editor (or its configuration)

Let’s look at them one by one: lets open the .resx file (the XML file containing the string ID and their localization) and let’s see how this .resx file looks in each editor:

Notepad++

Chinese localization Notepad++

Chinese localization file, Notepad++, some characters are not displayed correctly

Zeta resource editor

Chinese localization file, Zeta resource editor, some characters are not displayed correctly

Chinese localization file, Zeta resource editor, some characters are not displayed correctly

Emacs

Chinese localization file, Emacs, it looks perfect

Chinese localization file, Emacs, it looks perfect

Word 2010

“]Chinese localization file, Word 2010, it looks perfect

Chinese localization file, Word 2010, it looks perfect - p.s. Word 2010 rocks!

…but the funniest one is skype

Chinese text in Skype missing characters

Chinese text in Skype - in the editor it looks fine, in the body of the conversation there are missing characters... :-O

So, what’s going on here?

Plain and simple: each program appears to work just fine and they output a .resx file that is perfectly usable in Visual Studio 2010 -> Tabbles starts and the localized language is displayed correctly. Nonetheless, each editor has some issue with rendering some Chinese characters (just a few Kanji seem to be broken, but most of them are rendered just fine… :-O ).

Well, kinda happy ending, isn’t it? Now we know that we can go with our old beloved Zeta resource editor which is behaving well even if it didn’t seem so :-)

- >Now we need translators: :-)

We have a few for Chinese, but no one yet for Japanese… WE NEED YOU NOW! :-) Please check the translation page on our forum.

A. + M.

Next Page »