views:

553

answers:

1

Using c# / windows forms. Trying to make a form's background transparent, without it losing its ability to receive clicks.

  1. this.Opacity makes the whole form transparent (not just the background

  2. BackColor = Color.Red;
    TransparencyKey = BackColor;

makes the background of the form transparent and click through-able. I want the form to be transparent , but it should be able to receive clicks

how?

+3  A: 

You need to handle WM_NCHITTEST. Note in the snippet below that m.lParam contains packed X and Y coordinates of the mouse position, relative to the top left corner of the screen, and you need to check if the location matches your transparent region.

In this example I'm returning HTCAPTION, which means this region will behave like a caption of the window, i.e. user will be able to drag the window by clicking and dragging this location. See here what other values can be returned and what they mean

protected override void WndProc(ref Message m) {
    switch (m.Msg) {
    case 0x84: // this is WM_NCHITTEST
        base.WndProc(ref m);
        if ((/*m.LParam.ToInt32() >> 16 and m.LParam.ToInt32() & 0xffff fit in your transparen region*/) 
          && m.Result.ToInt32() == 1) {
            m.Result = new IntPtr(2);   // HTCAPTION
        }
        break;
    default:
        base.WndProc(ref m);
        break;
    }
}
Rom
This was a cool thing to learn about, but it doesn't appear to work in this case. When I override WndProc in my form, and set the BackColor and the TransparencyKey to red, WndProc doesn't get called at all when I move the mouse over the transparent area, so I don't get a chance to set m.Result to HTCAPTION. Could you try this out? I'm very curious to see if this will work properly.
MusiGenesis
Check if you're calling base.WndProc(ref m) for all other cases in the switch(), since you should. I omitted that for simplicity, but I think I need to add it to the snippet
Rom
it either behaves like a caption (i.e. you drag the window by clicking there) or it's click-throughable (i.e. when you click, the window behind your window receives the click). Which one it that?
Rom
RE m.LParam math: the m.LParam contains both X and Y coordinates of the mouse pointer relative to the top left screen corner: the top 16 bits contain Y, the bottom 16 bits contain X. If you need to constrict this functionality to a limited region within the window as opposed to the whole window, than you need to calculate X and Y, then match them against your region, and this is what the commented portion is about. If you don't need the region calculation: remove it.
Rom
Which one it that? sorry for the confusion. I had placed a red background bitmap on the form. Now any label on the form is transparent and click-throughable but any of the red background not covered by a label is not transparent and is a caption. If the bitmap is removed its all click-throughable. if all the labels are removed (leaving only the background bitmap), then its all caption. I hope I am clear
@Rom: I didn't even have a switch statement in my sample - all I did was debug.print m.Msg and m.lParam. Moving the mouse around over the transparent region did not call WndProc at all (moving it around over the title bar area still did, however).
MusiGenesis