2016-07-26 3 views
0

どうにかして、Googleや私の言葉の問題が私に解決策をもたらさない場所に自分自身を戻すことができます。カーソルを点滅させるためにカスタムコントロールにタイマーを追加する

このように、System.Windows.Forms.Controlから派生したTextBoxをゼロから作成しています。私はこれまでにText変数を描画することができましたし、編集機能も追加しました(普通のTextBoxのように)。

恐ろしい時間のかかる練習のアイデアは、私が開発したソフトウェアで使用するために最大限のテーマ機能を持つ独自のライブラリを作成することです。

したがって、私の問題:TextBoxに点滅カーソルを描画します。

私は、CursorPositionがどこにあるかに応じて左から右に移動する静的線を描くことができます。コントロール(したがってif(blinker))からSystem.Timers.Timerまでのタイマーを追加しましたが、System.Windows.Forms.Timerも試しましたが、コントロールがフォームに追加されても描画イベントを発生させないときに私のプロパティを設定することを許可しないため、 。 TickイベントにInvalidate(_Cursor)というイベントを配置して、カーソル位置だけが再描画されるようにしました。引き続き引数なしで試しても使用できないようにしました。

protected override void OnPaint(PaintEventArgs e) 
{ 
    ... 
    if (Focused) 
    { 
     if (blinker) 
      e.Graphics.FillRectangle(new SolidBrush(_CursorColor), _Cursor); 
     foreach (Rectangle border in Borders) 
     { 
      if(_DrawBorders[Borders.IndexOf(border)]) 
       e.Graphics.FillRectangle(new SolidBrush(BorderColor), border); 
     } 
    } 
    ... 
} 

私は私が持っていた恐ろしいちらつきや入力の問題を手伝ってくれました

DoubleBuffered = true; 
SetStyle(ControlStyles.UserPaint | ControlStyles.Selectable | ControlStyles.ResizeRedraw | 
ControlStyles.OptimizedDoubleBuffer | ControlStyles.StandardClick | ControlStyles.AllPaintingInWmPaint, true); 

にも設定されています。

EDIT **(REMOVED AS IT IS FIXED USING COMMENT BY Hans Passant's SUGGESTION)**

わかりましたので、今、タイマーが作動していることを、問題に私は上記に。カーソルを描く。

private void _CursorBlinkTime_Tick(object sender, EventArgs e) 
    { 
     blinker = !blinker; 
     Console.WriteLine("Blink!"); 
     Invalidate(); 
    } 

    protected override void OnPaint(PaintEventArgs e) 
    { 
     Height = TextRenderer.MeasureText("A", Font).Height + (2 * BorderWidth) + (2 * TextPadding); 
     CursorPosition = (BorderWidth + TextPadding) + (_SelectedStart * (TextRenderer.MeasureText("_", Font).Width)); 
     _InputBounds = new Rectangle(BorderWidth + TextPadding, BorderWidth + TextPadding, Width - (2 * BorderWidth) - (2 * TextPadding), Height - (2 * BorderWidth)); 
     base.OnPaint(e); 
     e.Graphics.Clear(BackColor); 

     e.Graphics.DrawString(Text, Font, new SolidBrush(TextColor), _InputBounds.Location); 
     foreach (Rectangle border in Borders) 
     { 
      if (_DrawBorders[Borders.IndexOf(border)]) 
       e.Graphics.FillRectangle(new SolidBrush(InactiveBorderColor), border); 
     } 

     if (Focused) 
     { 
      // This is where the Cursor is drawn, right before the borders. 
      // I've tried to move it to after the border is drawn but same result, nothing is drawn. 
      // I've ran through the entire OnPaint using Step-by-Step and while it does 
      // fire the draw event, nothing is drawn. 
      // BackColor = FromArgb(40,40,40), _CursorColor = Color.Red 
      // _Cursor is a Rectangle that reads at this moment: 
      // Rectangle(5,0,2,21) Which given all other variables should show result? 
      if (blinker) 
       e.Graphics.FillRectangle(new SolidBrush(_CursorColor), _Cursor); 
      foreach (Rectangle border in Borders) 
      { 
       if(_DrawBorders[Borders.IndexOf(border)]) 
        e.Graphics.FillRectangle(new SolidBrush(BorderColor), border); 
      } 
     } 
     else if (!Focused) 
     { 
      if(string.IsNullOrWhiteSpace(Text)) 
       e.Graphics.DrawString(WaterMarkText, Font, new SolidBrush(WaterMarkColor), _InputBounds.Location); 
     } 
    } 
+1

だからあなたの問題はVSデザイナーでありますか? 'if(!DesignMode)yourtimer.Start();' – TaW

+0

タイマー自体は、コントロールが最初にフォーカスを取得したときにのみ開始され、フォーカスが失われると停止します。クラスにTimerを追加するだけで、私はVS Desingerを使用することができません。自分のデザイナーのスクリーンショットをオリジナルの投稿に追加して追加します。 – Hurly

+0

タイマーは静的なものにする必要があります。制御。 OnEnter/OnLeave()のオーバーロードで、それを作成して(nullの場合)、Tickイベントの登録を解除/登録するのがベストです。また、設計時に決して使用されないようにし、何かを "混乱させる"ことはできません。 –

答えて

0

わかりましたので、私はあきらめるとしようとして停止することを決定した後、私は私が持っていたカーソルのすべての痕跡を除去し、再びそれを描くを見て始めました。それを修正しました。その後、私はタイマーを訪問するために戻り、System.Windows.Forms.Formから派生したクラスを使用しないときには、System.Windows.Forms.Timerは、あなたが持っていたと思うもののすべてのオンスを混乱させると考えました。そこで、私はSystem.Timers.Timer(以前はモバイル開発で大きな成功を収めていました)に移りました。

私が持っていたすべての問題が解決しました。あなたの助けをもう一度お願いします!私はこの場所が大好きです。ここで

は、コードの変更です:

private double _CursorInterval; 
    /// <summary> 
    /// Values below 500ms not recommended, due to safety hazards on epilepsy. 
    /// </summary> 
    public double CursorInterval 
    { 
     get { return _CursorInterval; } 
     set { _CursorInterval = value; } 
    } 

    private bool blink = false; 

    protected override void OnPaint(PaintEventArgs e) 
    { 
     base.OnPaint(e); 
     Height = TextRenderer.MeasureText("A", Font).Height + (2 * BorderWidth) + (2 * TextPadding); 
     _InputBounds = new Rectangle(BorderWidth + TextPadding, BorderWidth + TextPadding, Width - (2 * BorderWidth) - (2 * TextPadding), Height - (2 * BorderWidth) - (2 * TextPadding)); 

     if (blink) 
      e.Graphics.FillRectangle(new SolidBrush(BorderColor), new Rectangle(_InputBounds.Location, new Size(1, _InputBounds.Height))); 
    } 

    System.Timers.Timer blinkTimer; 
    protected override void OnGotFocus(EventArgs e) 
    { 
     if (!DesignMode) 
     { 
      blinkTimer = new System.Timers.Timer(CursorInterval); 
      blinkTimer.Elapsed += TimerElapsed; 
      blinkTimer.Start(); 
      Console.WriteLine("OnGotFocus - I was here."); 
     } 
     blink = true; 
     Invalidate(); 
     base.OnGotFocus(e); 
    } 

    private void TimerElapsed(object sender, System.Timers.ElapsedEventArgs e) 
    { 
     blink = !blink; 
     Console.WriteLine("TimerElapsed - I was here."); 
     Invalidate(); 
    } 

    protected override void OnLostFocus(EventArgs e) 
    { 
     if(!DesignMode) 
     { 
      blink = false; 
      blinkTimer.Stop(); 
      blinkTimer.Elapsed -= TimerElapsed; 
      Console.WriteLine("OnLostFocus - I was here."); 
     } 
     Invalidate(); 
     base.OnLostFocus(e); 
    } 

    protected override void OnClick(EventArgs e) 
    { 
     base.OnClick(e); 
     Focus(); 
    } 
関連する問題