2016-03-20 16 views
1

私はWinFormで自分のカスタムボタンを操作しています。私はすでに仕事を終えています。しかし、私の最後の問題は、ボタンがInvalidateのプロパティが変更されたときに表示されないということです。 setブロックとOnResizeブロックのInvalidateメソッドを呼び出しますが、ボタンでは機能しません。しかし、これは実行時に修正されるか、再構築されます。どうすれば修正できますか?ここでデザイン時にカスタムボタンのInvalidate()メソッドが機能しないのはなぜですか?

は、例えば絵です:

enter image description here

マイコード:

public class AltoButton : Control 
      { 
       int radius; 
       RoundedRectangle roundedRect; 
       Color inactive1, inactive2, pressed1, pressed2; 
       LinearGradientBrush InactiveGB, MouseOverGB, BorderGB, currentGB; 
       public AltoButton() 
       { 
        inactive1 = Color.FromArgb(44, 188, 210); 
        inactive2 = Color.FromArgb(33, 167, 188); 

        pressed1 = Color.FromArgb(64, 168, 183); 
        pressed2 = Color.FromArgb(36, 164, 183); 

        radius = 10; 
        roundedRect = new RoundedRectangle(Width, Height, radius); 

        SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer | 
          ControlStyles.SupportsTransparentBackColor | ControlStyles.UserPaint, true); 
       } 

       protected override void OnPaint(PaintEventArgs e) 
       { 
        e.Graphics.SmoothingMode = SmoothingMode.HighQuality; 
        roundedRect = new RoundedRectangle(Width, Height, radius); 
        InactiveGB = new LinearGradientBrush(new Rectangle(0, 0, Width, Height), inactive1, inactive2, 90f); 
        MouseOverGB = new LinearGradientBrush(new Rectangle(0, 0, Width, Height), pressed1, pressed2, 90f); 
        BorderGB = new LinearGradientBrush(new Rectangle(0, 0, Width, Height), Color.FromArgb(162, 120, 101), Color.FromArgb(162, 120, 101), 90f); 
        if (currentGB == null) 
         currentGB = InactiveGB; 
        e.Graphics.FillPath(currentGB, roundedRect.Path); 
        e.Graphics.DrawPath(new Pen(BorderGB), roundedRect.Path); 
       } 
       protected override void OnResize(EventArgs e) 
       { 
        Invalidate(); 
        base.OnResize(e); 
       } 
       protected override void OnMouseEnter(EventArgs e) 
       { 
        currentGB = MouseOverGB; 
        Invalidate(); 
        base.OnMouseEnter(e); 
       } 
       protected override void OnMouseLeave(EventArgs e) 
       { 
        base.OnMouseLeave(e); 
        currentGB = InactiveGB; 
        Invalidate(); 
       } 
       public int Radius 
       { 
        get 
        { 
         return radius; 
        } 
        set 
        { 
         radius = value; 
         Invalidate(); 
        } 
       } 
    } 
    public class RoundedRectangle 
     { 
      Point location; 
      int radius; 
      GraphicsPath grPath; 
      public RoundedRectangle(int width, int height, int radius) 
      { 
       location = new Point(0, 0); 
       this.radius = radius; 

       Rectangle upperLeftRect = new Rectangle(0, 0, 2 * radius, 2 * radius); 
       Rectangle upperRightRect = new Rectangle(width - 2 * radius - 1, 0, 2 * radius, 2 * radius); 
       Rectangle lowerLeftRect = new Rectangle(0, height - 2 * radius - 1, 2 * radius, 2 * radius); 
       Rectangle lowerRightRect = new Rectangle(width - 2 * radius - 1, height - 2 * radius - 1, 2 * radius, 2 * radius); 

       grPath = new GraphicsPath(); 
       grPath.AddArc(upperLeftRect, 180, 90); 
       grPath.AddArc(upperRightRect, 270, 90); 
       grPath.AddArc(lowerRightRect, 0, 90); 
       grPath.AddArc(lowerLeftRect, 90, 90); 
       grPath.CloseAllFigures(); 

      } 
      public RoundedRectangle() 
      { 
      } 
      public GraphicsPath Path 
      { 
       get 
       { 
        return grPath; 
       } 
      } 
      public Rectangle Rect 
      { 
       get 
       { 
        return new Rectangle(location.X, location.Y, 2 * radius, 2 * radius); 
       } 
      } 
     } 
public int Radius 
     { 
      get 
      { 
       return radius; 
      } 
      set 
      { 
       radius = value; 
       Invalidate(); 
      } 
     } 
     public Color Inactive1 
     { 
      get 
      { 
       return inactive1; 
      } 
      set 
      { 
       inactive1 = value; 
       Invalidate(); 
      } 
     } 
     public Color Inactive2 
     { 
      get 
      { 
       return inactive2; 
      } 
      set 
      { 
       inactive2 = value; 
       Invalidate(); 
      } 
     } 
     public Color Pressed1 
     { 
      get 
      { 
       return pressed1; 
      } 
      set 
      { 
       pressed1 = value; 
       Invalidate(); 
      } 
     } 
     public Color Pressed2 
     { 
      get 
      { 
       return pressed2; 
      } 
      set 
      { 
       pressed2 = value; 
       Invalidate(); 
      } 
     } 
+1

あなた 'currentGB'フィールドが盗聴されています。それは古いブラシであり、正しいサイズの新しいブラシではありません。ブラシを保管しないでください。作成するのが非常に安いですが、周りを守るのに非常に高価です。 * usingステートメントを正しく使用するようになりました。 –

答えて

1

OnResizeオーバーライドを削除し、あなたがtrueに設定されたスタイルでControlStyles.ResizeRedrawが含まれます。

あるいは、Control.ResizeRedrawプロパティをtrueに設定します。

更新日:実際問題はより簡単です。特定のWidthHeightを使用して作成されたcurrentGBフィールドにキャッシュされたブラシがあります。

サイズが変更されたときあなたはそれがある方法あなたのコードを維持することができ、そしてちょうどnullcurrentGBを設定する(あなたが本当にすべてのこれらのブラシを配置しなければならないが、それはまた別の話だ):

protected override void OnResize(EventArgs e) 
{ 
    currentGB = null; 
    Invalidate(); 
    base.OnResize(e); 
} 
+0

ありがとう@イワン、それは素晴らしい仕事をした。実際には、色などのブラウズ可能なプロパティ(get-set)用のブラシを保存しています。使用後にブラシが破棄された場合、現在のデザイナのプロパティ値はどのように取得できますか?私が前に追加しなかった残りのコードは、上記の更新された質問にあります。多分もっと効率的な方法があります。それを見てください。 –

+0

あなたが言うことをしました。何も格納されていません。マウスの状態とif-else条件を使用しました。もう一度@ Ivanに感謝します。あなたは素晴らしいです。 –

1

として、上記のイワンは、私はusingステートメントを使用した後に処分するために使用したと述べた。私は補完的な解決策としてこの答えを追加しました。

protected override void OnPaint(PaintEventArgs e) 
     { 
      e.Graphics.SmoothingMode = SmoothingMode.HighQuality; 
      roundedRect = new RoundedRectangle(Width, Height, radius); 

      if (state == MouseState.Leave) 
       using (LinearGradientBrush inactiveGB = new LinearGradientBrush(new Rectangle(0, 0, Width, Height), inactive1, inactive2, 90f)) 
        e.Graphics.FillPath(inactiveGB, roundedRect.Path); 
      else if (state == MouseState.Over) 
       using (LinearGradientBrush activeGB = new LinearGradientBrush(new Rectangle(0, 0, Width, Height), active1, active2, 90f)) 
        e.Graphics.FillPath(activeGB, roundedRect.Path); 

      using (LinearGradientBrush BorderGB = new LinearGradientBrush(new Rectangle(0, 0, Width, Height), Color.FromArgb(162, 120, 101), Color.FromArgb(162, 120, 101), 90f)) 
       e.Graphics.DrawPath(new Pen(BorderGB), roundedRect.Path); 
     } 
     protected override void OnResize(EventArgs e) 
     { 
      Invalidate(); 
      base.OnResize(e); 
     } 
     protected override void OnMouseEnter(EventArgs e) 
     { 
      state = MouseState.Over; 
      Invalidate(); 
      base.OnMouseEnter(e); 
     } 
関連する問題