Hi Lukasz,
the most reliable solution I've found for your problem is to set a Hook for
mouse messages and determine if the mouse was clicked outside of your
control.
Example:
class whatever:
{
//
// All the hook stuff is to determine if mouse was pressed outside of
control.
// If so, hide control.
//
#region hook
public delegate int HookProc(int nCode, IntPtr wParam, IntPtr lParam);
//Declare hook handle as int.
static int hHook = 0;
//Declare mouse hook constant.
private const int WH_MOUSE = 7;
private const int WM_LBUTTONDOWN = 0x0201;
//Declare MouseHookProcedure as HookProc type.
HookProc MouseHookProcedure;
//Declare wrapper managed POINT class.
[StructLayout(LayoutKind.Sequential)]
private class POINT
{
public int x;
public int y;
}
//Declare wrapper managed MouseHookStruct class.
[StructLayout(LayoutKind.Sequential)]
private class MouseHookStruct
{
public POINT pt;
public int hwnd;
public int wHitTestCode;
public int dwExtraInfo;
}
//Import for SetWindowsHookEx function.
//Use this function to install thread-specific hook.
[DllImport("user32.dll",CharSet=CharSet.Auto,
CallingConvention=CallingConvention.StdCall)]
public static extern int SetWindowsHookEx(int idHook, HookProc lpfn,
IntPtr hInstance, int threadId);
//Import for UnhookWindowsHookEx.
//Call this function to uninstall the hook.
[DllImport("user32.dll",CharSet=CharSet.Auto,
CallingConvention=CallingConvention.StdCall)]
public static extern bool UnhookWindowsHookEx(int idHook);
//Import for CallNextHookEx.
//Use this function to pass the hook information to next hook procedure in
chain.
[DllImport("user32.dll",CharSet=CharSet.Auto,
CallingConvention=CallingConvention.StdCall)]
public static extern int CallNextHookEx(int idHook, int nCode,
IntPtr wParam, IntPtr lParam);
public int MouseHookProc(int nCode, IntPtr wParam, IntPtr lParam)
{
if(Visible && (wParam.ToInt32() == WM_LBUTTONDOWN) )
{
bool inside = true;
_IsMouseOutside = false;
//Marshall the data from callback.
MouseHookStruct MyMouseHookStruct = (MouseHookStruct)
Marshal.PtrToStructure(lParam, typeof(MouseHookStruct));
Point pt = PointToClient(new Point(MyMouseHookStruct.pt.x,
MyMouseHookStruct.pt.y));
Rectangle rect = new Rectangle(0,0, Width, Height);;
inside = rect.Contains(pt);
// do action depending on mouse position...
if(DDL.Visible)
inside |= DDL.Bounds.Contains(new Point(MyMouseHookStruct.pt.x,
MyMouseHookStruct.pt.y));
_IsMouseOutside = !inside;
if(_IsMouseOutside)Hide();
}
return CallNextHookEx(hHook, nCode, wParam, lParam);
}
#endregion
public whatever()
{
// do initialization here...
#region hook
// Create an instance of HookProc.
MouseHookProcedure = new HookProc(MouseHookProc);
hHook = SetWindowsHookEx(WH_MOUSE, MouseHookProcedure,
(IntPtr)0,AppDomain.GetCurrentThreadId());
//If SetWindowsHookEx fails.
if(hHook == 0 )
{
MessageBox.Show("SetWindowsHookEx Failed");
return;
}
#endregion hook
}
}
When disposing your control you should call UnhookWindowsHookEx.
Hope this helps.
Regards,
Munir Husseini (iCOMcept)