/* Copyright (c) Citrix Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms,
* with or without modification, are permitted provided
* that the following conditions are met:
*
* * Redistributions of source code must retain the above
* copyright notice, this list of conditions and the
* following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
using System.Windows.Forms;
using XenCenterLib;
namespace XenAdmin.Controls
{
///
/// Extension of which implements extra event handlers.
/// Currently:
///
/// -
/// OnScrollChange
/// Called when user initiates scrolling
///
///
///
internal class SmartScrollTextBox : TextBox
{
private bool _scrolledProgrammatically;
protected internal bool IsVerticalScrollBarAtBottom => GetPositionFromCharIndex(Text.Length - 1).Y < Height;
public void SetTextWithoutScrolling(string text)
{
var oldVerticalPosition = Win32.GetScrollBarPosition(Handle, Win32.ScrollBarConstants.SB_VERT);
Text = text;
Win32.SetScrollPos(Handle, (int)Win32.ScrollBarConstants.SB_VERT, oldVerticalPosition, true);
_scrolledProgrammatically = true;
Win32.PostMessageA(Handle, Win32.WM_VSCROLL, (int)Win32.ScrollBarCommands.SB_THUMBPOSITION + 0x10000 * oldVerticalPosition, 0);
}
#region Custom Events
///
/// Delegate for which is fired when the user initiates scrolling.
///
/// If the event is fired by or , consider hooking into the event, as the scrollbar position
/// changes after the keys have been pressed.
///
/// The new position of the scrollbar.
/// The orientation of the scrollbar.
public delegate void ScrollChange(int newPosition, Orientation scrollBarOrientation);
///
/// Event called when user initiates scrolling in the following ways:
///
/// - Moves the mouse wheel. This also supports horizontal scrolling (performed by holding shift)
/// - Drags the scrollbar
/// - Presses or keys
/// - Presses or keys
///
///
public event ScrollChange OnScrollChange;
#endregion
#region Control Overrides
protected override void WndProc(ref Message m)
{
if (OnScrollChange != null && !_scrolledProgrammatically)
{
int newPosition;
switch (m.Msg)
{
case Win32.WM_VSCROLL:
newPosition = Win32.GetScrollBarPosition(Handle, Win32.ScrollBarConstants.SB_VERT);
OnScrollChange.Invoke(newPosition, Orientation.Vertical);
break;
case Win32.WM_HSCROLL:
newPosition = Win32.GetScrollBarPosition(Handle, Win32.ScrollBarConstants.SB_HORZ);
OnScrollChange.Invoke(newPosition, Orientation.Vertical);
break;
case Win32.WM_MOUSEWHEEL:
// holding shift is horizontal scrolling
newPosition = Win32.GetScrollBarPosition(Handle, ModifierKeys == Keys.Shift ? Win32.ScrollBarConstants.SB_HORZ : Win32.ScrollBarConstants.SB_VERT);
OnScrollChange.Invoke(newPosition, ModifierKeys == Keys.Shift ? Orientation.Horizontal : Orientation.Vertical);
break;
}
}
if (_scrolledProgrammatically)
{
_scrolledProgrammatically = false;
}
base.WndProc(ref m);
}
protected override bool ProcessCmdKey(ref Message m, Keys keyData)
{
if (OnScrollChange != null && (m.Msg == Win32.WM_KEYDOWN || m.Msg == Win32.WM_SYSKEYDOWN))
{
switch (keyData)
{
case Keys.PageDown:
case Keys.PageUp:
case Keys.Down:
case Keys.Up:
OnScrollChange?.Invoke(Win32.GetScrollBarPosition(Handle, Win32.ScrollBarConstants.SB_VERT), Orientation.Vertical);
break;
}
}
return base.ProcessCmdKey(ref m, keyData);
}
#endregion
}
}