Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / desktop / WinForms

Directional Pan and Scroll Toolbox Items

2.00/5 (2 votes)
17 Jan 2011CPOL5 min read 30.3K   476  
Thoroughly documented source you can compile to a Control Library (DLL)

Introduction

A panel makes a nice container because things 'stay put' on a panel; and hooking up a panel's Click() event to a timer activated by scroll/pan buttons on that panel makes quick work of both organizing the button placement and coordinating timer start/stop events with mouse down/up events on individual buttons, provided you have a handy class like the Btn9Panel containing constructors and methods which are ready to lay out all of the details as soon as the Visual Studio designer sees it, and before it gets to your toolbox.

Background

Most of the CodeProject articles I've seen deal with intricacies which take hours to ferret out, and although sometimes there are rather obvious and simplistic solutions for beginners, most of the articles deal with relatively complex or convoluted scenarios. Obviously, a lot of the readers don't have time to fool around with simple stuff once they get done with the really tricky stuff, so I figured I ought to offer some time-saver code... Maybe something to give a poor guy a chance to get fifteen minutes of extra sleep some night.

Using the Code

All it takes is to drag a Btn9Panel out of your toolbox onto a form to see what it does. The HorizPanel and VertPanel classes subclass the Btn9Panel, and you can drag all three onto a form and use the designer to change the dimensions or FlatAppearance elements offered when FlatStyle.Flat is in use.

There isn't anything really tricky enough about the code to make an issue of it here. The NineBtnCtrl.DLL source code is so thoroughly documented (even over-documented) that you should view it in the Visual Studio IDE so that you can toggle the outlining on and off for each region as you go through it. Completely collapsing it and then examining one section at a time will take a lot less time than trying to go through it here.

The only code you need to 'wire it up' after you drag one of these panels onto a form is this:

C#
btn9Panel1.Click +=new EventHandler(btn9Panel1_Click);
btn9Panel1.Enable();

following your form's InitializeComponent() statement. And the panel Click() event handler is also required:

C#
private void btn9Panel1_Click(object sender, EventArgs e) 
{ /* Call your scroll/pan code here */ }

The example in Btn9Form.cs only carries out two operations to illustrate 'scrolling' in the handler:

C#
ii = ii + btn9Panel1.Dx; jj = jj + btn9Panel1.Dy; 

Using the Dx and Dy increments of [+|-]1 furnished by the .DLL code each time the timer ticks will allow you to pan, scroll, change array indexes, or whatever you need to do; and as long as the mouse button is held down, the timer will keep on generating these increments and calling your code. So all you need to do is to decide how you like your scrolling done; and if you don't want to use the timer for some reason, you can call SetDxDy() to set Dx and Dy for you, so you can use the same code you've got to scroll programmatically as well as in response to the mouse button events. Call btn9Panel1.Disable() whenever you want to shut down the timer response to the button presses; and be sure to check, as noted in the .DLL source code, whether BtnDown is true before calling precisely controlled code in your application if you will be enabling or disabling the timer during critical periods.

The example Windows Form in Btn9Form.cs gives you an opportunity to run a form containing a button matrix and to change the MouseOver, MouseDown, Background, Border, and Checked colors while you can see the effect it has (the designer doesn't show the MouseOver or MouseDown colors on the design surface; only in the Properties window); and after you exit the Form, you can use the Properties dialog in the designer to set the default colors or panel dimensions, although you could also hard-code the new values into the .DLL source code and recompile it if you're that devoted to your predilections.

Screenshot of Btn9Form.cs when compiled and running

Btn9Form.cs also shows you the panel name, button name, button index, and direction (W, NW, N, etc.) while two integer values are incremented/decremented during a button press. The two subclasses having only two buttons will only scroll in the N-S or E-W directions, as you might surmise, provided your scroller code follows the usual map conventions.

Points of Interest

I initially wrote some scrolling code for two separate projects which I intended ultimately to merge but which do not interoperate. One of the segments is run analogously to a modal dialog, although the threading model doesn't see it that way and there are no calls to BackgroundWorker classes since I tied the two together. I had initially used a BackgroundWorker in one and a second Thread in the other, with a rather tricky set of semaphores used to enable, configure, start, control, stop, and disable the worker thread in the former segment; and a much simpler but still analogous set of semaphores used in the latter segment, even though the latter provided bidirectional scrolling and the former did not. The difference was that the latter scrolling events were started and stopped by eight buttons (in the same form as the Btn9Panel you see featured here) which scrolled only a single graphical image window, whereas the former scrolling events were started and stopped by twelve buttons (in the same form as the VertPanel you see featured here) and would, on demand, scroll in tandem a virtual window into an Array and the visible window in a PictureBox corresponding to that and containing a bitmap representation of the array contents.

Although in merging the two segments, I replaced both the BackgroundWorker and the second Thread with a single timer, I didn't merge and subclass the arrangement of the buttons as you see them in the HorizPanel and VertPanel, nor did I create a separate class for the bidirectional Btn9Panel. These classes were created especially for this CodeProject article, just because I thought the idea of distilling the functionality embodied by those implementations into a single, easy-to-use and easy to set-up toolbox item was worth a shot.

History

The Btn9Panel development work stemmed from my project, "The CQvis MultiGradient Palette Tool", which is a freeware program which you can download from a number of sites. That has a Thread doing the scrolling in it, but does not use the Start(), Suspend(), Sleep(), or Stop() methods to initiate or terminate scrolling, as you'll see if you use WinDbg or PEBrowse Professional to examine it. That second process thread runs continuously the whole time the program is running, and its behavior is governed entirely by semaphores.

License

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