Click here to Skip to main content
15,892,059 members
Please Sign up or sign in to vote.
2.50/5 (2 votes)
hello, i have:

C#
private void scrollup_Click(object sender, EventArgs e)
        {
            t.Enabled = false;
            while (t.Enabled == false)
            {
                scroll(telep.Handle, (speedslider.Value * 2));
            }
        }



where t is my timer. scroll(telep.Handle, (speedslider.Value * 2)); is short for a very very long and boring function, that pretty much scrolls the scrollbar by the value of a track bar multiplied by two (2).
Using while (t.Enabled == true) is not very good because if I try to interact with the form while it is scrolling, the form becomes unresponsive for a sec, then is scrolled all the way to the bottom.

I was thinking of using a timer for scrolling 2 pixels every, lets say for e.g., 30 milliseconds, but I do not know much about timers.

If someone could throw me into the correct direction, or even completely tell me how to do this, that would be great.

thanks to all who answer.
Posted
Updated 21-Feb-11 16:07pm
v2

Even if you use a timer, if it's fired every 30ms and you have UI code in the handler, then your UI will still be mostly unresponsive. You need to look at doing this in a different way, perhaps via a background thread.

[Update]
~~~~~~~~~

Actually you could use a worker thread and Sleep. Something like this will do what you want. You will see a smooth scrolling, and your UI should remain responsive:

C#
private void ScrollButton_Click(object sender, EventArgs e)
{
    var worker = new BackgroundWorker();
    worker.DoWork += ScrollWorker_DoWork;
    worker.RunWorkerAsync();
}

void ScrollWorker_DoWork(object sender, DoWorkEventArgs e)
{
    for (int value = 0; value < someValue; value++)
    {
        scroll(value);
        Thread.Sleep(30); // experiment with this, try 60, 90, etc.
    }
}
 
Share this answer
 
v2
Comments
vlad781 21-Feb-11 22:06pm    
um, do you have an idea of how i do that?
Nish Nishant 21-Feb-11 22:15pm    
Check out my updated answer.
vlad781 21-Feb-11 22:20pm    
i already have the scroll effect down. here is the entire process for the scroll:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool GetScrollInfo(IntPtr hwnd, int fnBar, ref SCROLLINFO lpsi);

[DllImport("user32.dll")]
static extern int SetScrollInfo(IntPtr hwnd, int fnBar, [In] ref SCROLLINFO lpsi, bool fRedraw);

[DllImport("User32.dll", CharSet = CharSet.Auto, EntryPoint = "SendMessage")]
static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

struct SCROLLINFO
{
public uint cbSize;
public uint fMask;
public int nMin;
public int nMax;
public uint nPage;
public int nPos;
public int nTrackPos;
}

enum ScrollBarDirection
{
SB_HORZ = 0,
SB_VERT = 1,
SB_CTL = 2,
SB_BOTH = 3
}

enum ScrollInfoMask
{
SIF_RANGE = 0x1,
SIF_PAGE = 0x2,
SIF_POS = 0x4,
SIF_DISABLENOSCROLL = 0x8,
SIF_TRACKPOS = 0x10,
SIF_ALL = SIF_RANGE + SIF_PAGE + SIF_POS + SIF_TRACKPOS
}

const int WM_VSCROLL = 277;
const int SB_LINEUP = 0;
const int SB_LINEDOWN = 1;
const int SB_THUMBPOSITION = 4;
const int SB_THUMBTRACK = 5;
const int SB_TOP = 6;
const int SB_BOTTOM = 7;
const int SB_ENDSCROLL = 8;

public Form1()
{
InitializeComponent();

t.Interval = 30;
t.Tick += new EventHandler(t_Tick);
t.Enabled = true;

}

void t_Tick(object sender, EventArgs e)
{

{
//if (button1_Click)
//scroll(textBox1.Handle,1);
}
}

private void textBox1_TextChanged(object sender, EventArgs e)
{

}

private Timer t = new Timer();

// Scrolls a given textbox. handle: an handle to our textbox. pixels: number of pixels to scroll.
void scroll(IntPtr handle, int pixels)
{

{
IntPtr ptrLparam = new IntPtr(0);
IntPtr ptrWparam;
// Get current scroller posion

SCROLLINFO si = new SCROLLINFO();
si.cbSize = (uint)Marshal.SizeOf(si);
si.fMask = (uint)ScrollInfoMask.SIF_ALL;
GetScrollInfo(handle, (int)ScrollBarDirection.SB_VERT, ref si);

textBox1.DeselectAll();

// Increase posion by pixles
if (t.Enabled)
{
if (si.nPos < (si.nMax - si.nPage))
si.nPos += pixels;
else
{
ptrWparam = new IntPtr(SB_ENDSCROLL);
t.Enabled = false;
SendMessage(handle, WM_VSCROLL, ptrWparam, ptrLparam);
}
}

if (t.Enabled == false)
{
if (si.nPos > (si.nMin))
si.nPos -= pixels;
else
{
ptrWparam = new IntPtr(SB_ENDSCROLL);
t.Enabled = true;
SendMessage(handle, WM_VSCROLL, ptrWparam, ptrLparam);
}
}
// Reposition scroller
SetScrollInfo(handle, (int)ScrollBarDirection.SB_VERT, ref si, true);
Nish Nishant 21-Feb-11 22:23pm    
Ok, I know that. So call your scroll function from the worker thread (as in my example).
vlad781 21-Feb-11 22:22pm    
here is the continued:


// Reposition scroller
SetScrollInfo(handle, (int)ScrollBarDirection.SB_VERT, ref si, true);

// Send a WM_VSCROLL scroll message using SB_THUMBTRACK as wParam
// SB_THUMBTRACK: low-order word of wParam, si.nPos high-order word of wParam
ptrWparam = new IntPtr(SB_THUMBTRACK + 0x10000 * si.nPos);
SendMessage(handle, WM_VSCROLL, ptrWparam, ptrLparam);
}
}

private void button2_Click(object sender, EventArgs e)
{
t.Enabled = false;
while (t.Enabled == false)
{
scroll(textBox1.Handle, 1);
}
}


private void button1_Click(object sender, EventArgs e)
{
t.Enabled = true;
while (t.Enabled == true)
{
scroll(textBox1.Handle, 1);
}
}
}
}


done
The page on MSDN[^] shows how to use the Tick event of the timer, which is the normal way to do this sort of thing. You control the periodicity by using the Interval property, for your 30 milliseconds, set it to 30 but be sure that your scroll method completes within this time period.
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900