views:

96

answers:

1

Context: I'm working on a WPF application where the user often has to transcribe bits of data manually from other programs. Not having dual monitors, this involves a lot of Alt-tabbing.

I figured that it would be quite nice to have the same functionality as in Visual Studio for tooltips - where you can hit Ctrl to render them slightly transparent.

The "problem" I have is that you can only (usefully) play with transparency if your window AllowsTransparency, which in turn is only possible if WindowStyle = None. I don't really want to get into all the complications of having to recreate title bar etc on my application.

Is there any decent alternative?

+2  A: 

With a little bit of Win32 Interop you can get an HWND of your window and use CreateRgn and define a clipping region for your window, this would render any portion of the window "see-through" as you need. It will also modify hit-testing, thus, the window is not only "see through" but is also "click through".

Here are some bits from one of my pet projects, this eliminates the client area of the window. Some of the code here may be specific to WPF, but ultiamtely the Win32 APIs shown here have been present since the early 90s.

    [DllImport("gdi32.dll")]
    internal static extern IntPtr CreateRectRgnIndirect([In] ref Mubox.Win32.Windows.RECT lprc);

    [DllImport("gdi32.dll")]
    internal static extern IntPtr CreateRectRgn(int nLeftRect, int nTopRect, int nRightRect, int nBottomRect);

    [DllImport("user32.dll")]
    internal static extern int SetWindowRgn(IntPtr hWnd, IntPtr hRgn, bool bRedraw);

    [DllImport("gdi32.dll")]
    internal static extern int CombineRgn(IntPtr hrgnDest, IntPtr hrgnSrc1, IntPtr hrgnSrc2, CombineRgnStyles fnCombineMode);

    public enum CombineRgnStyles : int
    {
        RGN_AND = 1,
        RGN_OR = 2,
        RGN_XOR = 3,
        RGN_DIFF = 4,
        RGN_COPY = 5,
        RGN_MIN = RGN_AND,
        RGN_MAX = RGN_COPY
    }

    #endregion

                    IntPtr windowRegion = Control.Windows.CreateRectRgn(0, 0, parkingWindowRect.Width, parkingWindowRect.Height);
                    Mubox.Win32.Windows.RECT clipRect = new Mubox.Win32.Windows.RECT();

                        Mubox.Win32.Windows.GetClientRect(this.Handle, out clipRect);
                        clipRect.Left = (parkingWindowRect.Width - clipRect.Width) / 2;
                        clipRect.Right += clipRect.Left;
                        clipRect.Top = (parkingWindowRect.Height - clipRect.Height) - clipRect.Left;
                        clipRect.Bottom = parkingWindowRect.Height - clipRect.Left;


                    IntPtr clipRegion = Control.Windows.CreateRectRgnIndirect(ref clipRect);
                    Control.Windows.CombineRgn(windowRegion, windowRegion, clipRegion, Windows.CombineRgnStyles.RGN_XOR);
                    Control.Windows.DeleteObject(clipRegion);
                    Control.Windows.SetWindowRgn(this.Handle, windowRegion, true);
Shaun Wilson
Thanks, I'll give it a try tomorrow..
Benjol
I think you mean specific to WinForms, and what's a Mubox? The only reference Google finds to "Mubox.Win32.Windows" is this page :(
Benjol
Ok, managed to work out that I had to roll my own RECT structure. As far as I can see I only have the option of completely transparent here, no opaque?
Benjol
Mubox is @ http://mubox.codeplex.com, the code provided above is not part of the public/open-source version. Using a region allows you to define a clipping area that is non-rectangular if you like. Clipping is not the same as transparency, that is, you can't define an opacity level. You can define a region as small as 1 pixel or as large as the window. I use it to block out the client area of a window which I use as a control-frame for an external/3rd-party application (e.g. faking the NC area of another app which does not provide any NC control.)
Shaun Wilson