title: Textbox - Maintain scroll bar position during text updates
body: <p>I have to show information to the user that updates every 100 milliseconds, this means the contents of the textbox I show it in are constantly being changed and if they are scrolling through them when they are being changed the update will cause them to loose their scroll bar position</p>
  
  <p>How do I prevent this? I've reduced the effect a lot by adding all text at once.</p>
  
  <p>Current code:</p>
  
  <pre><code>string textboxStr = "";
  foreach (string debugItem in debugItems)
  {
      textboxStr += debugItem + Environment.NewLine;
  }
  
  debugForm.Controls[0].Text = textboxStr;
  </code></pre>
  
  <p>Update 1:</p>
  
  <p>Used the solution provided below and it's not working, the scroll bar still resets to its default position meaning you loose your position and your pointer resets too.</p>
  
  <p>Implementation:</p>
  
  <p>In class:</p>
  
  <pre><code>[System.Runtime.InteropServices.DllImport("user32.dll")]
  public static extern bool LockWindowUpdate(IntPtr hWndLock);
  </code></pre>
  
  <p>In function:</p>
  
  <pre><code>var originalPosition = ((TextBox)debugForm.Controls[0]).SelectionStart;
  
  LockWindowUpdate(((TextBox)debugForm.Controls[0]).Handle);
  
  debugForm.Controls[0].Text = textboxStr;
  
  ((TextBox)debugForm.Controls[0]).SelectionStart = originalPosition;
  ((TextBox)debugForm.Controls[0]).ScrollToCaret();
  
  LockWindowUpdate(IntPtr.Zero);
  </code></pre>
  
  <p>Update 2:
  Used the 2nd solution provided below and it's not working. The scroll bar still jumps to the top even mid way while scrolling. Then sometimes when you're not even on it the scroll bar will start jumping up and down (Every 100 ms, when it updates the text).</p>
  
  <p>Implementation:
  In class:</p>
  
  <pre><code>[DllImport("user32.dll")]
  static extern int SetScrollPos(IntPtr hWnd, int nBar, int nPos, bool bRedraw);
  [DllImport("user32.dll", CharSet = CharSet.Auto)]
  private static extern int GetScrollPos(IntPtr hWnd, int nBar);
  [DllImport("user32.dll")]
  private static extern bool PostMessageA(IntPtr hWnd, int nBar, int wParam, int lParam);
  private const int SB_VERT = 0x1;
  private const int SB_THUMBPOSITION = 4;
  private const int WM_VSCROLL = 0x115;
  </code></pre>
  
  <p>In function:</p>
  
  <pre><code>var currentPosition = GetScrollPos(debugForm.Controls[0].Handle, SB_VERT);
  
  debugForm.Controls[0].Text = textboxStr;
  
  SetScrollPos(debugForm.Controls[0].Handle, SB_VERT, currentPosition, false);
  PostMessageA(debugForm.Controls[0].Handle, WM_VSCROLL, SB_THUMBPOSITION + 65535 * currentPosition, 0);
  </code></pre>
  
  <p>Example text:</p>
  
  <pre><code>Active Scene: Level0
  --------------------------------------------------
  Settings
      Fps: 60
      GameSize: {Width=600, Height=600}
      FreezeOnFocusLost: False
      ShowCursor: False
      StaysOnTop: False
      EscClose: True
      Title: 
      Debug: True
      DebugInterval: 100
  --------------------------------------------------
  Entities
      Entity Name: Player
          moveSpeed: 10
          jumpSpeed: 8
          ID: 0
          Type: 0
          Gravity: 1
          Vspeed: 1
          Hspeed: 0
          X: 20
          Y: 361
          Z: 0
          Sprites: System.Collections.Generic.List`1[GameEngine.Sprite]
          SpriteIndex: 0
          SpriteSpeed: 0
          FramesSinceChange: 0
          CollisionHandlers: System.Collections.Generic.List`1[GameEngine.CollisionHandler]
  --------------------------------------------------
  Key Events
      Key: Left
      State: DOWN
      Key: Left
      State: UP
      Key: Right
      State: DOWN
      Key: Right
      State: UP
      Key: Up
      State: DOWN
      Key: Up
      State: UP
  </code></pre>