One solution might be to:
Part 1 - non-rectangular overlap detection
1. Maintain a 1 bit deep bitmap (possibly a System.Drawing.Bitmap object, perhaps something custom) - where each bit represents a pixel in the panel, being set 1 if the area is covered by a control and 0 otherwise.
2. Have a similar (but smaller) 1 bit deep bitmap for the control being moved/added to the panel.
3. As the mouse moves calculate the bitwise AND for the bitmap of the movable control and the area of the panel bitmap 'under' it. As soon as you get a non-zero result, you know you have a collision.
Personally, I would implement this in a custom object, not a System.Drawing.Bitmap object, for performance benefits, although this will require some extra effort to transform a control's image to its detection-bitmap representation.
Note - although the bitmap uses a single bit per panel pixel, for efficiency I might use all 32 bits of an Int32, so one
collision = here & there
operation compares 32 pixels simultaneously. This will, of course, mean that the bitmap representing the movable control will need its bits shifted up to 32 bits (depending on the current mouse position). Or, just generate 32 distinct bitmaps for the movable control, and pick the one that indexes correctly with the current mouse X position.
Part 2 - bounding rectangle overlap detection
Since Part 1 involves the bitwise AND of x*y/1k Int32s for every mouse-move event (assuming that the 1 bit deep bitmap is stacked to use all the bits in an int), further optimization may be required.
(Note - a 64 pixel * 64 pixel control represented this way would have 2x64 Int32s as its bitmap, meaning for each mouse move event 128 Int32 AND operations, and sundry other actions, will be required).
This optimization would take the form of a bounding-rectangle intersection test on all the controls on the form. Even if you have a huge number of controls, this need not actually inspect each control's position and size:
I would implement an N-ary tree on the controls' X position (
Google N-ary tree[
^]) so that with a very small number of comparisons you can find the subset of controls whose X position + width overlaps (in part or in whole) the moveable control's surface area.
If you have a really large number of controls, I'd nest another nary tree, on the controls' Y position, inside each node of the X position tree.