2011-09-28 72 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