What is right way to show large image in Winforms app with scroll-bars and keyboard scroll support?
Currenty i'm use Panel(AutoScroll=True) with nested PitureBox (SizeMod = AutoSize).
I have 2 question:
1) What control select for drawing image?
Panel and PitureBox cant be selected (focused) using Tab key. Using Button with AutoSize = true and FlatStyle = Flat is right solution?
2)How to scroll image in panel using keyboard. What keyboard events a need handle - Form, Panel or PictureBox. May be I should set for Panel AutoScroll=false and add to them HScroll and VScroll, that events I should handle?
What is right way for implement this elementary app?
(Just for info, main form have other Panel(Dock=Top) that contain some controls.)
As for the first question: There is no Control which is really well suited to draw on and still can get the Focus
. In the link below you can see how to make a selectable panel, though.
Now for the real problem: How to scroll an AutoScroll Panel
by keyboard..?
This is amazingly hard to do. Here is an example for a start:
private void Form1_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
{
if (panel1.Bounds.Contains( this.PointToClient( Cursor.Position ) ))
{
if (e.KeyValue == 33) panel1.AutoScrollPosition =
new Point(panel1.AutoScrollPosition.X, Math.Abs(panel1.AutoScrollPosition.Y) - 10);
if (e.KeyValue == 34) panel1.AutoScrollPosition =
new Point(panel1.AutoScrollPosition.X, Math.Abs(panel1.AutoScrollPosition.Y) + 10);
}
}
I test for the Panel
to contain the mouse. You may want to play around with the scroll amount.. Also replace the KeyValues
with proper Keys
;-) Set KeyPreview = true;
for the Form!
Note: This only works if there is no Control on the Form which can get the Focus.
Since most likely you have some such Controls
, like Buttons
, ListBoxes
etc.. here is another solution, which works in any case, I believe..:
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if (panel1.Bounds.Contains(this.PointToClient(Cursor.Position)))
switch (keyData)
{
case Keys.PageDown: { scroll(10); return true; }
case Keys.PageUp: { scroll(-10); return true; }
// maybe code for some more keys..?
}
return base.ProcessCmdKey(ref msg, keyData);
}
void scroll(int delta)
{
panel1.AutoScrollPosition = new Point(
panel1.AutoScrollPosition.X, Math.Abs(panel1.AutoScrollPosition.Y) + delta);
}
This doesn't need the Form to have KeyPreview = true;
.
Here is the MSDN explanation for AutoScrollPosition
.
Here is a post that suggests using a subclass for Panel
and/or PictureBox
, which is supposed to allow them to get Focus
. I couldn't get that to work though..(Nor does it seem to be any simpler in the end..)