2011-09-28 68 views
1

可能重复:
“ResizeEnd” equivalent for usercontrols用户控制调整

我觉得自己很蠢,但我不能找到一个解决方案,我认为这是很容易出现问题。
我有一个用户控件(基本上)示出了在的图像绘制它的OnPaint阶段:

protected override void OnPaint(PaintEventArgs e) 
{ 
    if (img != null) 
     e.Graphics.DrawImage(img, ...); 
} 

当用户控制的大小时,它必须执行许多操作和一个(给定的特定条件)调整图像适合宽度或高度等...
图像显示可以是“沉重的”,所以当用户开始调整大小和移动鼠标,结果是一种缓慢运动这对最终用户不好。
所以我想知道是否有Windows消息报告我调整大小操作开始或完成:如果是这样,我可以停止重新调整大小时开始调整大小结束时重新绘制图像。
感谢大家

编辑:
我尝试这样做:

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; 
    } 
} 

,但这些消息不会被调用:(

+0

我可以假设你的控制带来调整因为它停靠在正在调整大小的面板或表单上? – hometoast

+0

@hometoast:是的,但我不控制容器形式...我的控件将被其他人使用... – Marco

回答

1

我在长时间调查后发表了一个答案。
首先我要感谢大家的贡献,因为你的建议让我走向正确的道路。感谢@Hans Passant,因为他在this post上的解决方案是非常重要的一部分。

该问题:

  • 假设我们有一个名为innCnt(内对照)用户控件包含在名为outCnt(外控制)另一用户控件,这反过来又应放置在一个形式我们不发展(所以不能编辑它的源)
  • 假设我们必须抓住EndResize事件innCnt

贡献:

  • 使用PreProcessMessage或压倒一切的WndProc(感谢@Cipi):
    我尝试了这些解决方案,但我没有收到WM_ENTERSIZEMOVEWM_EXITSIZEMOVE消息从Windows
  • 陷阱MouseDownOnResize事件(感谢@Cipi):
    这可能是好的,但该逻辑应该移动outCnt,因为innCnt如果用户正在调整控件或表单的大小,则无法接收MouseDown。
    反正我不喜欢太多的这种解决方案
  • Load事件innCnt,挂钩事件处理程序来控制的形式发生的事件(感谢@hometoast和@pikzen):
    我想这个解决方案(和通过@Hans here)提供的一个,但这不起作用,因为当innCnt被加载,即使如果不是在DesignMode,他的父母是outCnt的一部分,其母公司为空因为没有准备好一套! !

SOLUTION:
Basicly我不得不搬到@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放在另一个用户控件中,提供的解决方案将无法正常工作......

2

您可能会感兴趣由Form.ResizeBeginForm.ResizeEnd事件

如果您使用的是WPF,则此thread on MSDN可能会感兴趣。 WPF需要两轮牛车知道什么时候开始调整大小/结束

编辑

没注意到这是一个用户控件!此问题似乎解决您的问题: "ResizeEnd" equivalent for usercontrols

+0

这是一个用户控件,而不是一个窗体... – Marco

+0

马可,是的,但你的用户控件必须驻留在表单上。你可以让你的用户控件订阅表单事件。 – hometoast

+0

@hometoast:你能举个例子吗?我从来没有做过。而且,我的用户控件包含在另一个用户控件中:这是否会改变某些内容? – Marco

2

在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 
+0

感谢您的回答,但正如我之前提到的,我的容器不是表单,而我的用户控件将会提供给其他人,所以我无法强制他们做任何事情;我不知道谁是我的父母...... – Marco

+0

不是直接的容器,没有。但最终,用户控件(以及它的父母)必须驻留在表单上。 FindForm()方法正是为此而使用的。不知道您有多少层.Parent()深层 – hometoast

+0

请阅读我的解决方案,并告诉我您对此有何看法。我非常感谢你的帮助,非常感谢! – Marco

1

你真的想这样做(Windows消息)? :d

首先,你不能这样做,像覆盖PreProcessMessageWndProc因为我猜含形式将捕获的大小调整开始/结束消息(或任何其他消息),这样你的控制不会得到任何。要做到这一点的方法是在您的控件上实现IMessageFilter界面。然后你会得到你的控制这种方法,您可以通过接收到的消息m切换:

public bool PreFilterMessage(ref Message m)

然后在控制构造函数到:Application.AddMessageFilter(this);和你去那里,现在应用程序线程调用PreFilterMessage方法将收到的消息传递给它。

另一个想法:

如果让用户更改控件的大小与他们的鼠标,你可以捕获的MouseDown和OnResize设置bool MouseIsDown标志,那么您可以检查

if(MouseIsDown && Resizing == false) 
{ 
    Resizing = true; 
    //Start Resizing only once 
} 

而上的MouseUp :

if(Resizing == true && MouseIsDown == true) 
{ 
    Resizing = MouseIsDown = false; 
    //End the resizing once 
} 
+0

阅读我的解决方案并告诉我您对此有何看法。我非常感谢你的帮助,非常感谢! – Marco