Thursday, June 23, 2005

Continuing the theme of extending the functionality of the intrinsic controls in the .NetCF, I am going to show you the way to show the horizontal scrollbar in the ListBox.

In order to achieve this we once again turn to the Windows Mobile SDK docs. The docs state that we could use the LB_SETHORIZONTALEXTENT message to set the width of the scrollbar in the ListBox. But this will work only if the ListBox is defined with the WS_HSCROLL style which we should be able to modify by employing GetWindowLong and SetWindowLong API calls. I've taken the ListBoxExtender class from the previouse post and added the following code in it:

private void ModifyStyle(uint addStyle, uint removeStyle)

{    

      // Get current window style

      uint windowStyle = GetWindowLong(handle, GWL_STYLE);

 

      if (addStyle != 0)

      {

            // Modify style

            SetWindowLong(handle, GWL_STYLE, windowStyle | addStyle);

      }

      else

      {

            // Remove style

            SetWindowLong(handle, GWL_STYLE, windowStyle & ~removeStyle);

      }

      // Let the window know of the changes

      SetWindowPos(handle, IntPtr.Zero, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOZORDER | SWP_NOSIZE | SWP_FRAMECHANGED);

}

 

public void SetScrollWidth(int width)

{

      // Set the scroll width

      SendMessage(handle, LB_SETHORIZONTALEXTENT, width, 0);

}

 

public bool HorizontalScrollbar

{

      get

      {

            return horizontalScrollbar;

      }

      set

      {

            if (horizontalScrollbar == value)

                  return;

            horizontalScrollbar = value;

                       

            if (horizontalScrollbar)

            {

                  ModifyStyle((uint)WS_HSCROLL, 0);

            }

            else

            {

                  ModifyStyle(0, (uint)WS_HSCROLL);

            }

      }

}

We shouldn't forget the appropriate P/Invoke declarations:

const int LB_GETHORIZONTALEXTENT  = 0x0193;

const int LB_SETHORIZONTALEXTENT  = 0x0194;

 

const long WS_HSCROLL    =      0x00100000L;

 

const int SWP_FRAMECHANGED    = 0x0020;

const int SWP_NOMOVE          =     0x0002;

const int SWP_NOSIZE          =     0x0001;

const int SWP_NOZORDER        =     0x0004;

 

const int GWL_STYLE         =  (-16);

 

 

[DllImport("coredll.dll")]

static extern int SendMessage(IntPtr hwnd, int msg, int wParam, int lParam);

[DllImport("coredll.dll")]

static extern uint GetWindowLong(IntPtr hwnd, int index);

[DllImport("coredll.dll")]

static extern void SetWindowLong(IntPtr hwnd, int index, uint value);

[DllImport("coredll.dll")]

static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X,

      int Y, int cx, int cy, uint uFlags);

You can download the full version of the ListBoxExtender here:

ListBoxExtender.zip (1.35 KB)

After the code's updated, you can use the ListBoxExtender class the following way:

listBoxEx = new ListBoxExtender(listBox1);

...

listBoxEx.HorizontalScrollbar = true;

listBoxEx.SetScrollWidth(200);

Now, the most attentive should be able to notice that I am passing some hardcoded value to the SetScrollWidth method, which of course is not going to work for all possible cases. In order to have an appropriate behaviour of the scrollbar you will have to indentify the longest string item in your ListBox and pass it to the SetScrollWidth .

6/23/2005 10:10:20 PM (GMT Daylight Time, UTC+01:00)  #     |