可能重复:
“ResizeEnd;相当于用户控制
我觉得自己很愚蠢,但我找不到一个我认为简单的问题的解决方案
我有一个用户控件,它(基本上(显示了在onPaint阶段绘制的图像:
protected override void OnPaint(PaintEventArgs e)
{
if (img != null)
e.Graphics.DrawImage(img, ...);
}
当调整用户控件的大小时,它必须执行许多操作,其中一个是(给定特定条件(调整图像大小以适应宽度或高度等。
显示的图像可能很"重",所以当用户开始调整大小并移动鼠标时,结果是一种缓慢的移动,这对最终用户来说不好
所以我想知道是否有窗口消息报告我调整大小操作正在开始或完成:如果是这样,我可以在调整大小开始时停止重新绘制,在调整大小结束时重新绘制图像
感谢大家
编辑:
我试过这个:
protected override void WndProc(ref Message m)
{
const int WM_ENTERSIZEMOVE = 0x0231;
const int WM_EXITSIZEMOVE = 0x0232;
switch (m.Msg)
{
case WM_ENTERSIZEMOVE: resizing = true; break;
case WM_EXITSIZEMOVE: resizing = false; break;
}
}
但这些消息永远不会被调用:(
您可能对Form.ResizeBegin和Form.Resi泽End事件感兴趣。
如果您正在使用WPF,MSDN上的这个线程可能会引起您的兴趣。WPF要求黑客知道调整大小何时开始/结束
编辑
没有注意到这是一个UserControl!这个问题似乎解决了你的问题:"ResizeEnd";相当于用户控件
你真的想这么做(windows消息(吗?:D
首先,你不能像覆盖PreProcessMessage
或WndProc
那样做,因为我猜包含表单会捕获调整大小的开始/结束消息(或任何其他消息(,所以你的控件不会得到任何消息。这样做的方法是在控件上实现IMessageFilter
接口。然后你会得到这种方法在你的控制下,你可以切换通过收到的消息m:
public bool PreFilterMessage(ref Message m)
然后在控件构造函数中添加:Application.AddMessageFilter(this);
,现在应用程序线程正在调用PreFilterMessage
方法,并将收到的消息传递给它。
另一个想法:
如果你让用户用鼠标改变控件的大小,你可以诱捕MouseDown并设置bool MouseIsDown
标志。然后在OnResize
中,你可以检查
if(MouseIsDown && Resizing == false)
{
Resizing = true;
//Start Resizing only once
}
在MouseUp上:
if(Resizing == true && MouseIsDown == true)
{
Resizing = MouseIsDown = false;
//End the resizing once
}
在UserControl的Load事件中,将事件处理程序挂接到控件的窗体事件。
抱歉,我有一个VB项目打开了,我会在有时间的时候把它转换成答案。
Private Sub UserControl1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
AddHandler Me.FindForm.ResizeBegin, AddressOf MyFormsResizeBegin
AddHandler Me.FindForm.ResizeEnd, AddressOf MyFormsResizeEnd
End Sub
Private Sub MyFormsResizeBegin(sender As Object, e As EventArgs)
'tell your control to wait.
End Sub
Private Sub MyFormsResizeEnd(sender As Object, e As EventArgs)
'say everything is ok to continue
End Sub
经过长时间的调查,我发布了一个答案
首先,我要感谢大家的贡献,因为你们的建议使我走上了正确的道路。也感谢@Hans Passant,因为他在这篇帖子中的解决方案是一篇重要的文章。
问题:
- 假设我们有一个名为innCnt(内部控件(的用户控件,包含在另一个名称为outCnt外部控件(的用户名控件中,而该用户名控件又应该以我们不开发的形式放置(因此我们无法编辑其源代码(
- 假设我们必须在innCnt中捕获
EndResize
事件
贡献:
- 使用
PreProcessMessage
或覆盖WndProc
(感谢@Cipi(:
我尝试了这些解决方案,但没有收到来自Windows的WM_ENTERSIZEMOVE和WM_EXITSIZEMOVE- 陷阱
MouseDown
和OnResize
事件(感谢@Cipi(:
这可能是可以的,但该逻辑应该移到outCnt上,因为如果用户正在调整控件或窗体的大小,innCnt将无法接收MouseDown。
无论如何,我不太喜欢这个解决方案- 在innCnt的
Load
事件中,将事件处理程序挂接到控件的窗体事件(感谢@hometoast和@pikzen(:
我尝试了这个解决方案(以及@Hans在这里提供的解决方案(,但它不起作用,因为当innCnt加载时,即使不在DesignMode
中,他的父级也是outCnt的一部分,其父级为null,因为没有准备好 - 陷阱
解决方案:
基本上,我不得不将@Hans逻辑移到outCnt中,但不能移到Load
事件中,因为即使在这里,父级仍然为空!
public class OuterControl
{
protected override void OnParentChanged(EventArgs e)
{
if (!this.DesignMode)
{
Form form = this.FindForm();
if (form != null)
{
form.ResizeBegin += (s, ea) =>innerCnt.Resizing = true;
form.ResizeEnd += (s, ea) => innerCnt.Resizing = false;
}
}
base.OnParentChanged(e);
}
}
public class InnerControl
{
private bool resizing = false;
public bool Resizing {
get { return resizing; };
set {
resizing = value;
if (!resizing) {
// Resizing is just finished:
// let's do what we need
}
}
}
protected override void OnResize(EventArgs e)
{
if (Resizing)
{
base.OnResize(e);
return;
}
else
{
// Perform resizing actions
}
}
}
已知问题:
我敢肯定,如果outCnt被放在另一个用户控件中,所提供的解决方案将不起作用。。。