Advanced C# splash screen

I once posted about how to make a splash screen with C#; yet it’s still a rectangle. While it’s true that you can replace my picture with something that have curvy edges, you’ll have aliased edges i.e. crooked and crude pixels around the edges.

Example of an aliased picture, the edges are not smooth and you can't see through the semitransparent parts

There’s a solution: alpha-blend the picture and you can see through the form; pixels with alpha value of neither 0 or 255 will be mixed appropriately with the background.

Alpha-blended picture. The edges are smoother and you can see through the form

To achieve this, you have to write your custom painting function with windows API, specifically this one

[DllImport("user32.dll", ExactSpelling = true, SetLastError = true)]
public static extern bool UpdateLayeredWindow(IntPtr hwnd, IntPtr hdcDst, ref Point pptDst, ref Size psize, IntPtr hdcSrc, ref Point pprSrc, Int32 crKey, ref BLENDFUNCTION pblend, Int32 dwFlags);

Which can be a daunting task. Luckily we have someone from Visual C# kicks did the hard work and released the source for public use! But that’s not the end of my story just yet. I wanted the splash screen to fades in and out. The timing part was easy, just a timer and several more lines of code and it’s done.

        enum Phases {
            FadeIn,
            Hold,
            FadeOut
        };
        Phases CurrentPhase = Phases.FadeIn;
        int FadeInStep = 0;
        const int FadeInLast = 20;
        int HoldStep = 0;
        const int HoldLast = 80;
        int FadeOutStep = 20;
        const int FadeOutLast = 0;
        const int OpacityMultiplier = 5;

        private void timerFade_Tick(object sender, EventArgs e)
        {
            if (CurrentPhase == Phases.FadeIn)
            {
                if (FadeInStep < FadeInLast)
                {
                    FadeInStep++;
                    this.Opacity = (OpacityMultiplier * FadeInStep) / 100.0;
                }
                else
                    CurrentPhase = Phases.Hold;
            }
            else if (CurrentPhase == Phases.Hold)
            {
                if (HoldStep < HoldLast)
                {
                    HoldStep++;
                    this.UpdateFormDisplay(this.BackgroundImage);
                }
                else
                    CurrentPhase = Phases.FadeOut;
            }
            else if (CurrentPhase == Phases.FadeOut)
            {
                {
                    FadeOutStep--;
                    this.Opacity = (OpacityMultiplier * FadeOutStep) / 100.0;
                }
                else
                    this.Close();
            }

I have even altered the custom paint code to utilize the form’s transparency factor

                //Set up blending options
                API.BLENDFUNCTION blend = new API.BLENDFUNCTION();
                blend.BlendOp = API.AC_SRC_OVER;
                blend.BlendFlags = 0;
                blend.SourceConstantAlpha = (byte)(255 * this.Opacity);
                blend.AlphaFormat = API.AC_SRC_ALPHA;

                API.UpdateLayeredWindow(this.Handle, screenDc, ref topPos, ref size, memDc, ref pointSource, this.BackColor.ToArgb(), ref blend, API.ULW_ALPHA);

But that didn’t work to my expectation! The form is fading in and out gradually but the alpha blending effect is lost.

Fugly!

After fiddling around, I figured out that the custom paint code somehow didn’t override all the necessary painting functions and the setter of this.Opacity call those functions every time it’s changed. Searching around the list of functions can be overridden I found nothing interesting

That function doesn't help...

So I created a new variable and leave the form’s default Opacity alone. After all, if I have adjusted transparency myself in the custom paint function, who needs .NET’s alpha-blend-incapable render? The code above becomes:

        double MyOpacity = 0;

            if (CurrentPhase == Phases.FadeIn)
            {
                if (FadeInStep < FadeInLast)
                {
                    FadeInStep++;
                    MyOpacity = (OpacityMultiplier * FadeInStep) / 100.0;
                    this.UpdateFormDisplay(this.BackgroundImage);
                }
                else
                    CurrentPhase = Phases.Hold;
            }
            else if (CurrentPhase == Phases.Hold)
            {
                if (HoldStep < HoldLast)                 {                     HoldStep++;                     this.UpdateFormDisplay(this.BackgroundImage);                 }                 else                     CurrentPhase = Phases.FadeOut;             }             else if (CurrentPhase == Phases.FadeOut)             {                 if (FadeOutStep > FadeOutLast)
                {
                    FadeOutStep--;
                    MyOpacity = (OpacityMultiplier * FadeOutStep) / 100.0;
                    this.UpdateFormDisplay(this.BackgroundImage);
                }
                else
                    this.Close();
            }
        }
                //Set up blending options
                API.BLENDFUNCTION blend = new API.BLENDFUNCTION();
                blend.BlendOp = API.AC_SRC_OVER;
                blend.BlendFlags = 0;
                blend.SourceConstantAlpha = (byte)(255 * MyOpacity);
                blend.AlphaFormat = API.AC_SRC_ALPHA;

                API.UpdateLayeredWindow(this.Handle, screenDc, ref topPos, ref size, memDc, ref pointSource, this.BackColor.ToArgb(), ref blend, API.ULW_ALPHA);

And Voilร !

Alpha blended splash against my blog in the background, you can see through the semi-transparent form

You can get the project, source code and complied binary here.

Life with Ubuntu

First, Happy new year to you and your family ๐Ÿ™‚

I have been using Linux on a daily basis for several months now and so far life is quite comfortable. For the first time I can simply forget what people have been telling meย  since day one –ย  “you always need antivirus protection”. Heh, how the hell viruses is gonna infect my computer when even I myself can’t modify the system files! Yes, it’s true that if enough people use it there will be some folks spend time to carve into each input box in the whole operating system to find exploits but considering the rate of Firefox adoption over IE, I’d say it may took decades before Linux can take over. This world is resistant to changes, even if it’s good.

Though the default Ubuntu distribution works out of the box and satisfy the needs of most user, it’s oriented to the naive, who doesn’t have the need for more complex configurations, say – multilingual inputs. That’s when Google comes in handy but it may take a while and some searching skills to find what you need. There’s many question and answer in the Ubuntu forums but they are not always anwered satisfactorily.

Below is a collection of what I have to Google for the past months.

Japanese input

I posted about Japanese on Windows back from last year but I don’t really need Japanese for Linux until now – when my HDD is somewhere in the middle of snowstorms in America and I’m working on a little USB flash drive. It kinda feels like a netbook except it’s faster ๐Ÿ˜›

Windows doesn’t differentiate between input language and keyboard layout –ย  it combines both into the IME environment. The result is hideous registry settings to configure what should be readily available. It’s a different thing on Kubuntu: the keyboard layout you can configure in System Settings > Regional & Language > Keyboard Layout is for your physical keyboard only, which means if tells the operating system if there’s something special about your keyboard, like is it laid out in Dvorak, does it have extra function keys, does it have the Japanese switch button etc. To input languages you have to use the input method (IME) which is what translates what you type on the keyboard to something else according to configuration. For example, the Vietnamese input method translates Tie61ng Viet65 into “Tiแบฟng Viแป‡t” and the Japanese input method translate katakana into “ใ‚ซใ‚ฟใ‚ซใƒŠ”. All this happens within an input framework. To put it simple, an input framework is a tool that let you switch between languages (This is not technically correct but you’ll know better when you have become familiar with it). Being an operating system of choices, there’s three framework for you to choose on Linux: UIM, SCIM and iBus with iBus being the future.

To install iBus, first add the following line to /etc/apt/sources.list

deb http://ppa.launchpad.net/ibus-dev/ibus-1.2-karmic/ubuntu karmic main #IBus 1.2 for Karmic

Then run

sudo apt-get install ibus ibus-gtk

Once iBus has been installed, you can install input languages, say Vietnamese and Japanese:

sudo apt-get install ibus-unikey ibus-anthy

You can activate iBus with

im-switch -s ibus

It requires a restart and then you are good to go! ๐Ÿ™‚ Note that instead of using the command line apt-get, you can type “ibus” into the software installer to find the packages and install them.

You can see the language you want to type is not bound to any specific keyboard layout here – at the start of this post you can have Qwerty, Dvorak or Colemak – that doesn’t matter, you can use it to input the language you have installed!

References: ibus @ ubuntu vn, ibus project

Multilingual input with Opera 10

Opera is a great browser, many of the functionality that defines the modern browser is from opera – say tabbed browsing, integrated search function, modular design and many others. Should Opera be free from the start it could have overthrown IE as the most popular browser. Well, what’s history is history already ๐Ÿ™‚

I use Opera on linux for the sake of simplicity – it provides all the functions I need without the need to install any fancy plugin (I’m talking about you, Firefox). It’s a surprise that I can’t use iBus to type Vietnamese in Opera when I first installed it :(.

I found out why: the default version you can download from Opera’s homepage is compiled with the Qt3 library while iBus works with Qt4 only. Luckily Opera is also compiled with Qt4 but you’ll need to cruise around some FTP servers to get it.ย  Click here to get version 10.10 for ubuntu/x86, which is the latest at the time of writing.

When 128MB isn’t enough or how to expand your Ubuntu installation on a USB stick

Kubuntu 9.10 comes with a new feature: make a USB stick bootable and persists your changes between sessions. At first you may think the default storage space of 128 MB could be enough but after some themes, customizations and application s (namely Firefox); 128MB is used up in no time.

Your Linux home is stored within an image file in the root of the drive – casper-rw. You can allow Linux to use a bigger share of your stick by expanding the file then imposes ext3 formatting on it with the following steps:

# dd if=/dev/zero bs=1M count=1024 >> casper-rw
# e2fsck -f casper-rw
# resize2fs -f casper-rw
# e2fsck -f casper-rw

1024 means 1024MB, change this to whatever size you want. Note that this capacity is added to your existing quota, so if you have 128MB already then after this command you have 1153MB for storage.

File managing – Norton Commander style

While Kubuntu have dolphin as a pretty good file manager, iallowsng you to split windows and drag the navigation dock around, it’s still get nowhere close the original NC feel (say tabbing, F3, F4 and F5). Of course Midnight Commander have been around since Linux was still stuck in the server rooms but what? A text mode program on the all cute KDE Oxygen? Does not sound right to me.

Good thing that there’s Krusader. It’s a bit old but seems to work fine. The menu bar, button bar and command line stays true to the tradition – I feel like home ๐Ÿ™‚