yea so I have 2 panels with the same width and the same width of data in them. the top panel has autoscroll enabled. I would like to be able to scroll both panels, with the top panel scrollbar. which means that the bottom panel doesn't have a scroll bar. How would I do that?
alt text http://members.multimania.co.uk/jeff1524/pics/scrolling.jpg
EDIT: I tried panel2.AutoScrollPosition = panel1.AutoScrollPosition;
nothing
I also tried
e.Graphics.DrawRectangle(new Pen(Color.Pink,3), 10, 10, 30, 20);
e.Graphics.TranslateTransform(panel1.AutoScrollPosition.X, 0);
no movement on the rectangle.
What am i doing wrong?
Easy peasy. Implement the Scroll event for the 1st panel and have it Invalidate() the 2nd. Draw the text in the 2nd panel's Paint event, using the scroll position of the 1st:
private void panel1_Scroll(object sender, ScrollEventArgs e) {
panel2.Invalidate();
}
private void panel2_Paint(object sender, PaintEventArgs e) {
Point pos = new Point(panel1.AutoScrollPosition.X, 0);
TextRenderer.DrawText(e.Graphics, "nobugz waz here", panel2.Font, pos, Color.Black);
// Draw something
e.Graphics.TranslateTransform(pos.X, pos.Y);
e.Graphics.DrawLine(Pens.Black, 0, 0, 100, 100);
}
Even easier.
Just place the panels inside another panel that has the scroll bar (AutoScroll = true).
I've used this strategy.
Related
I have a C# WinForms project where I have to paint some things on my panel. I load in a grid from a file that translates to squares that are painted on the panel. Then I load in a file with dots that are then painted on top of the squares.
I then have a function that moves the dots around. But the repaint function is called every tick which causes the whole grid to flicker continously because it is painted so quick after each other.
How do I make it so that only the dots are repainted?
The repaint and paint functions are as follows:
private void Repaint(object sender, EventArgs e)
{
GridPanel.Invalidate();
}
private void GridPanel_Paint(object sender, PaintEventArgs e)
{
if ((GridPanel.Width != grid.Width || GridPanel.Height != grid.Height))
{
grid.Height = GridPanel.Height;
grid.Width = GridPanel.Width;
grid.setDimensions();
}
Graphics g = e.Graphics;
g.FillRectangle(new SolidBrush(Color.White), new Rectangle(0, 0, grid.Width, grid.Height));
foreach(Square square in grid.Squares)
{
if (square.Letter != '_')
{
SolidBrush color = new SolidBrush(square.Color);
g.FillRectangle(color, new Rectangle(square.X * grid.squareWidth, square.Y * grid.squareHeight, grid.squareWidth, grid.squareHeight));
}
}
foreach(Artist artist in grid.Artists)
{
SolidBrush color = new SolidBrush(artist.Color);
g.FillRectangle(color, new Rectangle(Convert.ToInt32(artist.X * grid.squareWidth), Convert.ToInt32(artist.Y * grid.squareHeight), grid.artistWidth, grid.artistHeight));
}
}
I also tried to use a second panel for the dots so I only have to repaint that one. But I cant get a transparent background working on the second panel, so the first panel is not visible this way.
Somebody knows a good solution for this problem?
I am trying to create a elipse in a textbox on double click. But it doesnt seem to happen.
panel.MouseClick += create_terms;
private void create_terms(object sender, EventArgs arg)
{
if (Phys_terms_check.Checked == true)
{
MouseEventArgs e = (MouseEventArgs)arg;
Graphics g = CreateGraphics();
SolidBrush p = new SolidBrush(Color.Red);
Pen erase = new Pen(Color.White);
Panel panel = (Panel)sender;
g.FillEllipse(p, e.X+panel.Left,e.Y+panel.Top,10,10);
}
}
The e.x and e.y seem to be giving relative coordinates from the sender. How to get point relative to the form.
add sender's top and left coordinates.
g.FillEllipse(p, e.X + textbox.Left, e.Y + textbox.Top, 10, 10);
but, this won't show, because textbox paint event fill fire and repaint textbox.
First of all: TextBoxes are old legacy and rather special Controls that do not support all things normal controls let you do.
Among the things that won't work are
Setting a BackgroundImage
Owner-drawing them
The latter includes any drawing in its Paint/OnPaint events.
You can code and hook-up the Paint event, but it won't get called.
You still can draw onto a TextBox using CreateGraphics, if you do it right, but as always with this function the result is non-persistent and will go away as soon as the system refreshes the TextBox itself, which is super-fast: as soon as you move your cursor over it the circle you draw may disappear..
The code to do it would have to look similar to this:
Graphics g = yourTextBox.CreateGraphics();
g.FillEllipse(Brushes.Red, yourTextBox.Width - 22, 2, 11, 11);
But as I said this will not persist, so it has little or no value.
If you want to draw onto something with a visible Text property you can use a Label:
private void yourLabel_Paint(object sender, PaintEventArgs e)
{
e.Graphics.FillEllipse(Brushes.Red, yourLabel.Width - 22, 2, 11, 11);
}
The result looks the same, but only the dot in the Label will persist, e.g. a Minimize-Maximize of the form.. In fact the dot in the TextBox didn't even survive calling my screenshot program, so I had use resort to pressing the Print-Key !
For drawing circles upon mouseclicks onto normal controls see this post!
I have a litle problem doing something I want.
What I want is quite simple.
I'm making a game tower defence for school.
When I clicked on a tower to place I want to see the tower when moving over my picturebox where everything happens in. This is no problem when I move it does what I want. But when I stop moving my Mouse I want the image stay on the position where it last was ( MouseHover).
But i don't get the mousehover event to do what I want. When I stop moving my mouse the image disapears and nothing is shown in my picturebox.
This is what i currently have for my MouseMove & MouseHover:
Note: I have already tried to use the MousePosition in the mousehover event but this doesn't work either. I hope someone can help me out on this ?
private void picGameArea_MouseMove(object sender, MouseEventArgs e)
{
Pen myPen = new Pen(Color.Black);
if (myGameLogic.tmpTower != null)
{
Xpos = e.X;
YPos = e.Y;
Graphics paper;
paper = picGameArea.CreateGraphics();
paper.DrawImage(myGameLogic.tmpTower.myImage, e.X - 25, e.Y -25, 50, 50);
paper.DrawEllipse(myPen, e.X - myGameLogic.tmpTower.Range, e.Y - myGameLogic.tmpTower.Range , myGameLogic.tmpTower.Range * 2, myGameLogic.tmpTower.Range * 2);
picGameArea.Invalidate();
}
}
private void picGameArea_MouseHover(object sender, EventArgs e)
{
Graphics paper;
paper = picGameArea.CreateGraphics();
if (myGameLogic.tmpTower != null)
{
paper.DrawImage(myGameLogic.tmpTower.myImage, Xpos - 25, YPos - 25, 50, 50);
}
picGameArea.Invalidate();
}
The image disappears because your next Paint event will redraw picGameArea and inside that event nothing will redraw your image of tmpTower.
You have 2 options:
move tmpTower drawing inside Paint event.
enable polling to redraw what is drawn on top by using timer.
There are mistakes in your code:
CreateGraphics required disposing, put it inside using or call paper.Dispose();
there is no need to handle MouseHover at all, this event is used for something like showing ToolTip, it only triggers once if mouse is inside control for some time.
calling Invalidate event will queue paint (it's like asking please, redraw my control some time later, when you have time), instead use Refresh before painting (and remove Invalidate).
Last one actually will fix your issue too...
I want the ToolTip to follow my mouse moving over one control. For example, let's take a panel. When mouse location is inside the Rectangle(100, 100, 50, 50) I want ToolTip to be visible and always on the right down of the mouse. When it's outside this rectangle, I want ToolTip to be invisible.
I tried to do this like that:
ToolTip toolTip = new ToolTip();
int x, y;
protected override void OnMouseMove(MouseEventArgs e)
{
if ((x == e.X) && (y == e.Y) && (new Rectangle(100, 100, 50, 50).Contains(e.Location))
toolTip.Show("some text", this, x + 10, y + 10);
else
{
x = e.X;
y = e.Y;
toolTip.Hide(this);
}
}
But there's a problem - when my toolTip shows up - it gets the focus and after that OnMouseMove(MouseEventArgs e) doesn't work any more. I tried to get the focus to the panel in the end of that function, but it doesn't work. I also tried some tricks with OnMouseHover, but it was the same effect.
Don't use a ToolTip for that - if the Panel is drawn on, draw your own ToolTip; otherwise, use a Panel and respond to MouseMove events from both, but ignore e.Location and instead use System.Windows.Forms.Cursor.Position and PointToClient.
On a blank winform code can be added to show lines that intersect (crosshairs) at the mouse pointer. The problem is that the lines don't show (or are partially hidden) by controls on the form (ie listview, splitcontainer, buttons).
How would I modify the code below to show on-top (bring to front...) of all the controls present on the form?
int lastX = 0;
int lastY = 0;
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
Region r = new Region();
r.Union(new Rectangle(0, lastY, this.Width, 1));
r.Union(new Rectangle(lastX, 0, 1, this.Height));
this.Invalidate(r);
this.Update();
Graphics g = Graphics.FromHwnd(this.Handle);
g.DrawLine(Pens.Chocolate, 0, e.Y, this.Width, e.Y);
g.DrawLine(Pens.Chocolate, e.X, 0, e.X, this.Height);
lastX = e.X;
lastY = e.Y;
}
private void Form1_MouseLeave(object sender, EventArgs e)
{
this.Invalidate();
}
You need a transparent window that's on top of all the other controls. The only way to get one is by overlapping the form with another form, made transparent with its TranparencyKey property. You'll find sample code for this in my answer in this thread.
Please just try first sending to back(Control.SendToBack()) the controls on the form (ie listview, splitcontainer, buttons). Put this at the FormLoad event. I have experimented the same nightmare with a Windows MDI application.
Hope that helps,
Enumerate through the desired controls and call the .BringToFront(); function on them.
listBox1.BringToFront();
According to the documentation, the region object should be in world co-ordinates, you're passing in client co-ordinates. Use Control.PointToScreen to map the rectangles' top left coordinate to world space.
I'd also be tempted to defer the drawing to the OnPaint method.