上边两幅图片中显示的异常有谁遇到过。别把后边一幅中的异常当做简单的空引用异常。空引用异常时最值得怀疑的,.net下边有很多与空引用一点关系都没有的东西都会抛出空引用。我在测试自己编写的一个ContextContainer时遇到的,代码贴到后边。ListCtrl一个UserControl,里边放了一个ListBoxEva(这是自己扩展出的,里边能放图片、Checkbox、radiobutton)。如果把ListBoxEva的Dock属性设置为Fill,就会出现问题。放ListBox一样会出现问题,只要设置dock属性为Fill。当New一个ListCtrl后,有一个默认大小,但是如果将它传给ContextContainer的构造函数,在构造函数里,它的大小就会变成2X2,没有任何编码去修改它,它就这么莫名其妙的变了。不管在外边把这个ListCtrl的Size设置为多少,都会变。
当尝试从弹出的提示中展开、查看各个属性值时,就会发生上边的异常。正常运行不会产生任何异常,不过运行过后弹出的大小只是一个黑点。即使不将ListBox属性设置为Fill,仍然有这个问题。只是弹出的不是一个黑点而已。不管怎样,执行完ContextContainer的构造函数中的下面一句后this.Size并没改成_dropDownContent.Size。
this.Size = _dropDownContent.Size;
当尝试从弹出的提示中展开、查看各个属性值时,就会发生上边的异常。正常运行不会产生任何异常,不过运行过后弹出的大小只是一个黑点。即使不将ListBox属性设置为Fill,仍然有这个问题。只是弹出的不是一个黑点而已。不管怎样,执行完ContextContainer的构造函数中的下面一句后this.Size并没改成_dropDownContent.Size。
this.Size = _dropDownContent.Size;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Drawing.Design;
using System.ComponentModel;
using System.Windows.Forms.VisualStyles;
using System.Drawing.Drawing2D;namespace TR0217.ControlEx
{
public enum ContextMode
{
/// <summary>
/// dropDownContent closed after singl click on it's child control
/// </summary>
SingleSelect,
/// <summary>
/// dropDownContent closed after lost focus
/// </summary>
MultiSelect,
/// <summary>
/// dropDownContent closed as soon as mouse moved out of the dropdown parent
/// </summary>
ToolTip
}
[ToolboxItem(false)]
public class ContextContainer : ToolStripDropDown
{
private Control _dropDownContent;
private ToolStripControlHost _dropDownAssistant;
private ContextMode _contextMode;
private Rectangle _activeRect;
private bool _focusOnOpen;
private bool _resizable = false; public bool Resizable
{
get { return _resizable; }
set { _resizable = value; }
}
public Control DropDownContent
{
get { return _dropDownContent; }
} public bool FocusOnOpen
{
get { return _focusOnOpen; }
set { _focusOnOpen = value; }
} public ContextMode ContextMode
{
get
{
return _contextMode;
}
set
{
_contextMode = value;
}
} public ContextContainer(Control dropDownContent)
{
if (dropDownContent == null)
{
throw new ArgumentNullException("dropdowncontent shoul not be null!");
} _dropDownContent = dropDownContent;
this._activeRect = Rectangle.Empty;
_dropDownAssistant = new ToolStripControlHost(dropDownContent);
_contextMode = ContextMode.MultiSelect;
this.Padding = this.Margin = _dropDownAssistant.Padding = _dropDownAssistant.Margin = Padding.Empty;
this.Items.Add(_dropDownAssistant);
this.AutoClose = true;
//this.ResizeRedraw = true;
this.MinimumSize = dropDownContent.Size;
dropDownContent.MinimumSize = dropDownContent.Size;
//this.MaximumSize = dropDownContent.Size;
//dropDownContent.MaximumSize = dropDownContent.Size;
this.Size = _dropDownContent.Size;
_dropDownContent.Disposed += delegate(object sender, EventArgs e)
{
_dropDownContent = null;
Dispose(true);
};
_dropDownContent.Paint += new PaintEventHandler(_dropDownContent_Paint);
foreach (Control ctrl in _dropDownContent.Controls)
{
ctrl.MouseClick += new MouseEventHandler(ctrl_MouseClick);
}
} void _dropDownContent_Paint(object sender, PaintEventArgs e)
{
if(_resizable)
PaintSizeGrip(e);
//if (_resizable)
//{
// //drow a grip at correct plase
// if (_resizeRight)
// {
// if (_resizeBottom)
// Console.WriteLine("");//right-bottom
// else
// Console.WriteLine("");//right-top
// }
// else
// {
// if (_resizeBottom)
// Console.WriteLine("");//left-bottom
// else
// Console.WriteLine("");//left-top
// }
//}
} void ctrl_MouseClick(object sender, MouseEventArgs e)
{
if (_contextMode == ContextMode.SingleSelect)
{
if(e.Button == MouseButtons.Left)
this.Hide();
}
}
private void ShowContent()
{
if (_activeRect != Rectangle.Empty)
{
Point location = new Point(_activeRect.Left, _activeRect.Bottom);
Rectangle screenRect = (Screen.FromRectangle(_activeRect)).WorkingArea;
_resizeRight = true;
_resizeBottom = true;
if (location.X + Size.Width > (screenRect.Left + screenRect.Width))
{
location.X = (screenRect.Left + screenRect.Width) - Size.Width;
_resizeRight = false;
} if (location.Y + Size.Height > (screenRect.Top + screenRect.Height))
{
location.Y -= Size.Height + _activeRect.Height;
_resizeBottom = false;
}
Show(location, ToolStripDropDownDirection.BelowRight);
}
} /// <summary>
/// show the dropdown content as the control's context
/// </summary>
/// <param name="control"></param>
public void Show(Control control)
{
if(control == null)
throw new ArgumentNullException("control shoul not be null!");
_activeRect = control.RectangleToScreen(control.ClientRectangle);
ShowContent();
} /// <summary>
/// show the drop content as if a control occupy the rect area
/// usually serve as screen tip
/// </summary>
/// <param name="rect">active rect, in screen coordiante</param>
public void Show(Rectangle rect)
{
_activeRect = rect;
ShowContent();
} protected override void OnOpening(System.ComponentModel.CancelEventArgs e)
{
if (_dropDownContent.IsDisposed || _dropDownContent.Disposing)
{
e.Cancel = true;
return;
}
base.OnOpening(e);
} protected override void OnOpened(EventArgs e)
{
base.OnOpened(e);
if (_focusOnOpen)
{
_dropDownContent.Focus();
}
if (_contextMode == ContextMode.ToolTip)
{
if (hHook == 0)
{
MouseHookProcedure = new HookProc(MouseHookProc);
hHook = SetWindowsHookEx(WH_MOUSE, MouseHookProcedure,
GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName), 0);
}
}
} protected override void OnClosed(ToolStripDropDownClosedEventArgs e)
{
if (hHook != 0)
{
UnhookWindowsHookEx(hHook);
hHook = 0;
}
base.OnClosed(e);
} protected override void OnSizeChanged(EventArgs e)
{
if (_resizable)
{
_dropDownContent.MinimumSize = this.Size;
//_dropDownContent.MaximumSize = this.Size;
_dropDownContent.Size = this.Size;
}
base.OnSizeChanged(e);
}
protected override void WndProc(ref Message m)
{
if (Resizing(ref m))
{
return;
}
base.WndProc(ref m);
}
public bool ProcessResizing(ref Message m)
{
if (m.Msg == 0x0084)
{
m.Result = (IntPtr)(-1);
return true;
}
return false;
}
private bool _resizeRight = false;
private bool _resizeBottom = false;
private Rectangle rectGrip;
private Rectangle rectHorizontal;
private Rectangle rectVertical;
private Rectangle rectThis; private bool Resizing(ref Message m)
{
if (m.Msg == 0x0084)
{
if (_resizable)
{
Point pt;
GetCursorPos(out pt);
rectThis = _dropDownContent.RectangleToScreen(_dropDownContent.ClientRectangle);
if (_resizeRight)
{
rectVertical = new Rectangle(rectThis.Right - 3, rectThis.Top + 3, 6, this.Height - 6);
if (_resizeBottom)//right-bottom
{
rectGrip = new Rectangle(rectThis.Right - 3, rectThis.Bottom - 3, 6, 6);
rectHorizontal = new Rectangle(rectThis.Left + 3, rectThis.Bottom - 3, this.Width - 6, 6); if (rectGrip.Contains(pt))
m.Result = (IntPtr)(17);//right bottom
else if (rectHorizontal.Contains(pt))
m.Result = (IntPtr)(15);//bottom
else if (rectVertical.Contains(pt))
m.Result = (IntPtr)(11);//right
}
else//right-top
{
rectGrip = new Rectangle(rectThis.Right - 3, rectThis.Top - 3, 6, 6);
rectHorizontal = new Rectangle(rectThis.Left + 3, rectThis.Top - 3, this.Width - 6, 6); if (rectGrip.Contains(pt))
m.Result = (IntPtr)(14);//right top
else if (rectHorizontal.Contains(pt))
m.Result = (IntPtr)(12);//top
else if (rectVertical.Contains(pt))
m.Result = (IntPtr)(11);//right
}
}
else
{
rectVertical = new Rectangle(rectThis.Left - 3, rectThis.Top + 3, 6, this.Height - 6);
if (_resizeBottom)//left-bottom
{
rectGrip = new Rectangle(rectThis.Left - 3, rectThis.Bottom - 3, 6, 6);
rectHorizontal = new Rectangle(rectThis.Left + 3, rectThis.Bottom - 3, this.Width - 6, 6);
if (rectGrip.Contains(pt))
m.Result = (IntPtr)(16);//left bottom
else if (rectHorizontal.Contains(pt))
m.Result = (IntPtr)(15);//bottom
else if (rectVertical.Contains(pt))
m.Result = (IntPtr)(10);//left
}
else//left-top
{
rectGrip = new Rectangle(rectThis.Left - 3, rectThis.Top - 3, 6, 6);
rectHorizontal = new Rectangle(rectThis.Left + 3, rectThis.Top - 3, this.Width - 6, 6);
if (rectGrip.Contains(pt))
m.Result = (IntPtr)(13);//left top
else if (rectHorizontal.Contains(pt))
m.Result = (IntPtr)(12);//top
else if (rectVertical.Contains(pt))
m.Result = (IntPtr)(10);//left
}
}
return true;
}//end of "if (_resizable)"
}
return false;
} private delegate int HookProc(int nCode, int wParam, IntPtr lParam);
private int hHook = 0;
private const int WH_MOUSE = 14;
private HookProc MouseHookProcedure; [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
private static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId); [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
private static extern bool UnhookWindowsHookEx(int idHook); [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
private static extern int CallNextHookEx(int idHook, int nCode, int wParam, IntPtr lParam); [DllImport("kernel32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
private static extern int GetCurrentThreadId(); [DllImport("kernel32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
private static extern IntPtr GetModuleHandle(string name); [DllImport("User32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
private static extern void GetCursorPos(out Point pt);
private int MouseHookProc(int nCode, int wParam, IntPtr lParam)
{
Point pt;
GetCursorPos(out pt);
if (_contextMode == ContextMode.ToolTip)
{
if (!_activeRect.Contains(pt))
{
this.Hide();
}
}
return CallNextHookEx(hHook, nCode, wParam, lParam);
} private VisualStyleRenderer sizeGripRenderer;
public void PaintSizeGrip(PaintEventArgs e)
{
if (e == null || e.Graphics == null || !_resizable)
{
return;
}
GraphicsState gs = null;
Size clientSize = _dropDownContent.ClientSize;
using (Bitmap gripImage = new Bitmap(0x10, 0x10))
{
using (Graphics g = Graphics.FromImage(gripImage))
{
if (Application.RenderWithVisualStyles)
{
if (this.sizeGripRenderer == null)
{
this.sizeGripRenderer = new VisualStyleRenderer(VisualStyleElement.Status.Gripper.Normal);
}
this.sizeGripRenderer.DrawBackground(g, new Rectangle(0, 0, 0x10, 0x10));
}
else
{
ControlPaint.DrawSizeGrip(g, _dropDownContent.BackColor, 0, 0, 0x10, 0x10);
}
}
gs = e.Graphics.Save();
e.Graphics.ResetTransform();
if (!_resizeBottom)
{
if (!_resizeRight)
{
e.Graphics.RotateTransform(180);
e.Graphics.TranslateTransform(-clientSize.Width, -clientSize.Height);
}
else
{
e.Graphics.ScaleTransform(1, -1);
e.Graphics.TranslateTransform(0, -clientSize.Height);
}
}
else if (!_resizeRight)
{
e.Graphics.ScaleTransform(-1, 1);
e.Graphics.TranslateTransform(-clientSize.Width, 0);
}
e.Graphics.DrawImage(gripImage, clientSize.Width - 0x10, clientSize.Height - 0x10 + 1, 0x10, 0x10);
e.Graphics.Restore(gs);
}
}
}//end of class
}//end of namespace
http://topic.csdn.net/u/20100924/15/69b43bf7-2ab8-4ca2-ad4b-a064bd282e9d.html?seed=736174406&r=68619784#r_68619784
http://tr0217.blog.163.com/album/#m=2&aid=124645305&pid=6420130310