I have implemented a picturebox in my in my form.I even implemented the scrollbars to make the image fit in it.so now the problem is when i try to scroll the button down,it scrolls down and immediately when i leave the mouse the button scrolls up ..here is the code implemnted please give some suggestions..
public void DisplayScrollBars()
{
// If the image is wider than the PictureBox, show the HScrollBar.
if (pictureBox1.Width > pictureBox1.Image.Width - this.vScrollBar1.Width)
{
hScrollBar1.Visible = false;
}
else
{
hScrollBar1.Visible = true;
}
// If the image is taller than the PictureBox, show the VScrollBar.
if (pictureBox1.Height >
pictureBox1.Image.Height - this.hScrollBar1.Height)
{
vScrollBar1.Visible = false;
}
else
{
vScrollBar1.Visible = true;
}
}
private void HandleScroll(Object sender, ScrollEventArgs se)
{
/* Create a graphics object and draw a portion
of the image in the PictureBox. */
Graphics g = pictureBox1.CreateGraphics();
g.DrawImage(pictureBox1.Image,
new Rectangle(0, 0, pictureBox1.Right - vScrollBar1.Width,
pictureBox1.Bottom - hScrollBar1.Height),
new Rectangle(hScrollBar1.Value, vScrollBar1.Value,
pictureBox1.Right - vScrollBar1.Width,
pictureBox1.Bottom - hScrollBar1.Height),
GraphicsUnit.Pixel);
pictureBox1.Update();
}
public void SetScrollBarValues()
{
// Set the Maximum, Minimum, LargeChange and SmallChange properties.
this.vScrollBar1.Minimum = 0;
this.hScrollBar1.Minimum = 0;
// If the offset does not make the Maximum less than zero, set its value.
if ((this.pictureBox1.Image.Size.Width - pictureBox1.ClientSize.Width) > 0)
{
this.hScrollBar1.Maximum =
this.pictureBox1.Image.Size.Width - pictureBox1.ClientSize.Width;
}
// If the VScrollBar is visible, adjust the Maximum of the
// HSCrollBar to account for the width of the VScrollBar.
if (this.vScrollBar1.Visible)
{
this.hScrollBar1.Maximum += this.vScrollBar1.Width;
}
this.hScrollBar1.LargeChange = this.hScrollBar1.Maximum / 10;
this.hScrollBar1.SmallChange = this.hScrollBar1.Maximum / 20;
// Adjust the Maximum value to make the raw Maximum value
// attainable by user interaction.
this.hScrollBar1.Maximum += this.hScrollBar1.LargeChange;
// If the offset does not make the Maximum less than zero, set its value.
if ((this.pictureBox1.Image.Size.Height - pictureBox1.ClientSize.Height) > 0)
{
this.vScrollBar1.Maximum =
this.pictureBox1.Image.Size.Height - pictureBox1.ClientSize.Height;
}
// If the HScrollBar is visible, adjust the Maximum of the
// VSCrollBar to account for the width of the HScrollBar.
if (this.hScrollBar1.Visible)
{
this.vScrollBar1.Maximum += this.hScrollBar1.Height;
}
this.vScrollBar1.LargeChange = this.vScrollBar1.Maximum / 10;
this.vScrollBar1.SmallChange = this.vScrollBar1.Maximum / 20;
// Adjust the Maximum value to make the raw Maximum value
// attainable by user interaction.
this.vScrollBar1.Maximum += this.vScrollBar1.LargeChange;
}
private void pictureBox1_Resize(object sender, EventArgs e)
{
// If the PictureBox has an image, see if it needs
// scrollbars and refresh the image.
if (pictureBox1.Image != null)
{
this.DisplayScrollBars();
this.SetScrollBarValues();
this.Refresh();
}
}
As I comment above, the correct way of doing this is to put your pictureBox in a panel and set the panel.AutoScroll=true. Also you need to set pictureBox.SizeMode=AutoSize so it is sized equal to the size of the image that it contains. Check: PictureBoxSizeMode Enumeration
Related
I wrote one project. I used DataGridViewAutoFilter library for filtering. But I have problem.
For filtering Drop-Down Filter List for a DataGridView Column Header Cell size(width) are very small. It come automatic size.
How to resize Drop-Down Filter List for a DataGridView Column Header Cell for filtering?
private void dataGridView1_BindingContextChanged(object sender, EventArgs e)
{
if (dataGridView1.DataSource == null) return;
foreach (DataGridViewColumn col in dataGridView1.Columns)
{
col.HeaderCell = new DataGridViewAutoFilterColumnHeaderCell(col.HeaderCell);
}
dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;
}
I found the solution : We must change SetDropDownList properties : DataGridViewColumnHeader.cs in DataGridViewAutoFilter.dll.İt is open source.
private void SetDropDownListBoxBounds()
{
Debug.Assert(filters.Count > 0, "filters.Count <= 0");
// Declare variables that will be used in the calculation,
// initializing dropDownListBoxHeight to account for the
// ListBox borders.
Int32 dropDownListBoxHeight = 6; // You must change!!!!!
Int32 currentWidth = 0;
Int32 dropDownListBoxWidth = 0;
Int32 dropDownListBoxLeft = 0;
// For each formatted value in the filters dictionary Keys collection,
// add its height to dropDownListBoxHeight and, if it is wider than
// all previous values, set dropDownListBoxWidth to its width.
using (Graphics graphics = dropDownListBox.CreateGraphics())
{
foreach (String filter in filters.Keys)
{
SizeF stringSizeF = graphics.MeasureString(
filter, dropDownListBox.Font);
dropDownListBoxHeight += (Int32)stringSizeF.Height;
currentWidth = (Int32)stringSizeF.Width;
if (dropDownListBoxWidth < currentWidth)
{
dropDownListBoxWidth = currentWidth;
}
}
}
// Increase the width to allow for horizontal margins and borders.
dropDownListBoxWidth += 40; //You must change !!!
// Constrain the dropDownListBox height to the
// DropDownListBoxMaxHeightInternal value, which is based on
// the DropDownListBoxMaxLines property value but constrained by
// the maximum height available in the DataGridView control.
if (dropDownListBoxHeight > DropDownListBoxMaxHeightInternal)
{
dropDownListBoxHeight = DropDownListBoxMaxHeightInternal;
// If the preferred height is greater than the available height,
// adjust the width to accommodate the vertical scroll bar.
dropDownListBoxWidth += SystemInformation.VerticalScrollBarWidth;
}
// Calculate the ideal location of the left edge of dropDownListBox
// based on the location of the drop-down button and taking the
// RightToLeft property value into consideration.
if (this.DataGridView.RightToLeft == RightToLeft.No)
{
dropDownListBoxLeft = DropDownButtonBounds.Right -
dropDownListBoxWidth + 1;
}
else
{
dropDownListBoxLeft = DropDownButtonBounds.Left - 1;
}
// Determine the left and right edges of the available horizontal
// width of the DataGridView control.
Int32 clientLeft = 1;
Int32 clientRight = this.DataGridView.ClientRectangle.Right;
if (this.DataGridView.DisplayedRowCount(false) <
this.DataGridView.RowCount)
{
if (this.DataGridView.RightToLeft == RightToLeft.Yes)
{
clientLeft += SystemInformation.VerticalScrollBarWidth;
}
else
{
clientRight -= SystemInformation.VerticalScrollBarWidth;
}
}
// Adjust the dropDownListBox location and/or width if it would
// otherwise overlap the left or right edge of the DataGridView.
if (dropDownListBoxLeft < clientLeft)
{
dropDownListBoxLeft = clientLeft;
}
Int32 dropDownListBoxRight =
dropDownListBoxLeft + dropDownListBoxWidth + 1;
if (dropDownListBoxRight > clientRight)
{
if (dropDownListBoxLeft == clientLeft)
{
dropDownListBoxWidth -=
dropDownListBoxRight - clientRight;
}
else
{
dropDownListBoxLeft -=
dropDownListBoxRight - clientRight;
if (dropDownListBoxLeft < clientLeft)
{
dropDownListBoxWidth -= clientLeft - dropDownListBoxLeft;
dropDownListBoxLeft = clientLeft;
}
}
}
// Set the ListBox.Bounds property using the calculated values.
dropDownListBox.Bounds = new Rectangle(dropDownListBoxLeft,
DropDownButtonBounds.Bottom, // top of drop-down list box
dropDownListBoxWidth, dropDownListBoxHeight);
}
/// <summary>
/// Gets the actual maximum height of the drop-down list, in pixels.
/// The maximum height is calculated from the DropDownListBoxMaxLines
/// property value, but is limited to the available height of the
/// DataGridView c`enter code here`ontrol.
I've made a custom control in C# and anytime that the user's cursor is hovering over the custom control I want the cursor to be displayed as the 'Hand'. Where do i place the code to do such a thing?
????.Cursor = Cursors.Hand;
in order to make it so the Hand Cursor is being displayed when hovering over this custom control?
namespace CustomRangeBar
{
public partial class RangeBar : UserControl
{
public RangeBar()
{
InitializeComponent();
label1.ForeColor = Color.Black;
this.ForeColor = SystemColors.Highlight; // set the default color the rangeBar
this.Click += new EventHandler(RangeBar_Click);
}
protected float percent = 0.0f; // Protected because we don't want this to be accessed from the outside
// Create a Value property for the rangeBar
public float Value
{
get
{
return percent;
}
set
{
// Maintain the value between 0 and 100
if (value < 0) value = 0;
else if (value > 100) value = 100;
percent = value;
label1.Text = value.ToString();
//redraw the rangeBar every time the value changes
this.Invalidate();
}
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
Brush b = new SolidBrush(this.ForeColor); //create brush that will draw the background of the range bar
// create a linear gradient that will be drawn over the background. FromArgb means you can use the Alpha value which is the transparency
LinearGradientBrush lb = new LinearGradientBrush(new Rectangle(0, 0, this.Width, this.Height), Color.FromArgb(255, Color.White), Color.FromArgb(50, Color.White), LinearGradientMode.Vertical);
// calculate how much has the rangeBar to be filled for 'x' %
int width = (int)((percent / 100) * this.Width);
e.Graphics.FillRectangle(b, 0, 0, width, this.Height);
e.Graphics.FillRectangle(lb, 0, 0, width, this.Height);
b.Dispose(); lb.Dispose();
}
private void RangeBar_SizeChanged(object sender, EventArgs e)
{
// maintain the label in the center of the rangeBar
label1.Location = new Point(this.Width / 2 - 21 / 2 - 4, this.Height / 2 - 15 / 2);
}
}
}
public void RangeBar_Click(object obj, EventArgs ea)
{
// This get executed if the pictureBox gets clicked
label1.text = "Increment 1";
}
UserControl derives from Control and therefore should already have a Cursor property inherited from that class. Do you not see a Cursor property in code/Properties?
I'm able to draw on the image using the below code. But my problem is, it is not a continuous line. It looks somehow broken. See below image for better understanding.
My XAML :
<Grid x:Name="Gridimage1" Grid.Column="0">
<Image Name="image1" HorizontalAlignment="Left" VerticalAlignment="Top" Stretch="Fill" >
</Image>
</Grid>
My c# code :
#region "Drawing on image"
static WriteableBitmap writeableBitmap;
static Image i;
public void DrawingOnImage() // this function will be called after image load
{
if (image1.Source != null)
{
i = new Image();
RenderOptions.SetBitmapScalingMode(image1, BitmapScalingMode.NearestNeighbor);
RenderOptions.SetEdgeMode(image1, EdgeMode.Aliased);
BitmapSource BitmapSrc = new FormatConvertedBitmap(image1.Source as BitmapSource, PixelFormats.Default, null, 0);
//writeableBitmap = new WriteableBitmap((int)image1.ActualWidth, (int)image1.ActualHeight, 96, 96, PixelFormats.Bgr32, null);
writeableBitmap = new WriteableBitmap(BitmapSrc);
image1.Source = writeableBitmap;
//image1.Stretch = Stretch.None;
image1.HorizontalAlignment = HorizontalAlignment.Left;
image1.VerticalAlignment = VerticalAlignment.Top;
i = image1;
image1.MouseMove += new MouseEventHandler(i_MouseMove);
image1.MouseLeftButtonDown +=
new MouseButtonEventHandler(i_MouseLeftButtonDown);
image1.MouseRightButtonDown +=
new MouseButtonEventHandler(i_MouseRightButtonDown);
}
}
static void i_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
DrawPixel(e);
}
static void i_MouseMove(object sender, MouseEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
DrawPixel(e);
}
}
static void DrawPixel(MouseEventArgs e)
{
double CR = i.Source.Height / i.ActualHeight;
double RR = i.Source.Width / i.ActualWidth;
int column = (int)(e.GetPosition(i).X * RR) ;
int row = (int)(e.GetPosition(i).Y * CR);
// Reserve the back buffer for updates.
writeableBitmap.Lock();
unsafe
{
// Get a pointer to the back buffer.
int pBackBuffer = (int)writeableBitmap.BackBuffer;
// Fin d the address of the pixel to draw.
pBackBuffer += row * writeableBitmap.BackBufferStride;
pBackBuffer += column * 4;
// Compute the pixel's color.
int color_data = 255 << 16; // R
color_data |= 128 << 8; // G
color_data |= 255 << 0; // B
// Assign the color data to the pixel.
*((int*)pBackBuffer) = color_data;
}
// Specify the area of the bitmap that changed.
writeableBitmap.AddDirtyRect(new Int32Rect(column, row, 1, 1));
// Release the back buffer and make it available for display.
writeableBitmap.Unlock();
}
#endregion
Image output :
You can see the line (pink color) I have drawn. It's not a continuous line. Where am I failing?
Update :
My findings after #loxxy's Inputs.Set oldx ,oldy to zero initialy.
if (oldx == 0 && oldy == 0)
{
writeableBitmap.DrawLineAa(column, row, column, row, SelectedColor);
}
else
{
if (Math.Abs(oldx - column) > 10 || Math.Abs(oldy - row) > 10)
{
writeableBitmap.DrawLineAa(column, row, column, row, SelectedColor);
}
else
{
writeableBitmap.DrawLineAa(column, row, oldx, oldy, SelectedColor);
}
}
oldx = column;
oldy = row;
Since you are drawing it pixel by pixel, the mouse has to update the coordinates at a much faster rate.
And I believe it relates to the DPI of the mouse... And you can do nothing about that.
So instead try drawing a line. So something like this in WPF:
WriteableBitmapExtensions.DrawLine
The mouse events you receive will not return consecutive points. If you move the mouse fast, the points returned will not be next to each other. If you want to draw a line under the mouse cursor, you need to draw a line from the previous point drawn to the current point on every MouseMove or MouseButtonDown callback.
My form has two objects: a background image that takes up the entire screen, and a dragable dialog control that only takes up a portion of the screen. I am using Mouse events for dragging and dropping the dialog control within the background image.
My problem is that while dragging, there is a copy of the control that is visible at it's previous location.
What is causing this shadow copy to appear, and how can I prevent it from happening?
My code looks something like this:
private void dialog_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
_dialogDragStart = e.Location;
dialog.MouseMove += new MouseEventHandler(dialog_MouseMove);
}
}
private void dialog_MouseUp(object sender, MouseEventArgs e)
{
dialog.MouseMove -= new MouseEventHandler(dialog_MouseMove);
_isDragging.Value = false;
}
private void dialog_MouseMove(object sender, MouseEventArgs e)
{
var difference = new Point(e.Location.X - _dialogDragStart.X, e.Location.Y - _dialogDragStart.Y);
if (!_isDragging.Value)
{
if (Math.Abs(difference.X) > SystemInformation.DragSize.Width || Math.Abs(difference.Y) > SystemInformation.DragSize.Height)
{
_isDragging.Value = true;
}
}
else if (_isDragging.Value && !difference.IsEmpty)
{
DialogOffset = GetValidDialogOffset(DialogOffset.X + difference.X, DialogOffset.Y + difference.Y);
this.Invalidate();
this.Update();
}
}
It should be noted that this entire UserControl contains a custom OnPaint event. The Paint event recalculates the Size and Location of the Dialog before painting it in a custom format. To get this working, I have simply adjusted the Location calculation to include the DialogOffset.
const int padding = 1;
const int shadowDepth = 3;
const int roudeCornerRadius = 5;
private void Paint(Graphics g, Rectangle clipRect)
{
try
{
dialog.Size = GetSize();
dialog.Location = new Point(
((backgroundImage.Width - dialog.Width) / 2) + DialogOffset.X,
((backgroundImage.Height - dialog.Height) / 2) + DialogOffset.Y);
if (Image != null && !backgroundImage.ClientRectangle.IsEmpty)
{
Rectangle imageBounds = new Rectangle(Point.Empty, Image.Size);
using (BufferedGraphics buffer = BufferedGraphicsManager.Current.Allocate(g, backgroundImage.ClientRectangle))
{
using (Bitmap img = ((Bitmap)backgroundImage).Clone(imageBounds, PixelFormat.Format16bppArgb1555) as Bitmap)
{
buffer.Graphics.Clear(Color.White);
buffer.Graphics.DrawImage(img,backgroundImage.ClientRectangle, imageBounds, GraphicsUnit.Pixel);
buffer.Render(g);
}
}
}
//Create Rectangles
Rectangle outerRect = dialog.ClientRectangle;
Rectangle innerRect = new Rectangle(padding, padding, outerRect.Width - (padding + shadowDepth), outerRect.Height - (padding + shadowDepth));
//create Paths
using (GraphicsPath innerPath = new GraphicsPath())
{
GraphicsHelper.GetRoundedRect(innerPath, innerRect, roudeCornerRadius, 1, 1);
//Assign outer rounded rectangle to the dialog's region property
Region region = new Region(innerPath);
if (dialog.Region != null)
dialog.Region.Dispose();
dialog.Region = region;
}
}
catch (Exception ex)
{
// Log error
}
}
I've seen suggestions to set the DoubleBufferred property to true, however its explicitly set to false in the existing code, and setting it to true causes no update at all while dragging.
I've tried taking a screenshot of the problem, however all screenshots only show one copy of the dialog control being dragged, even though I can clearly see a 2nd copy of the control on my screen while dragging.
What can be causing this, and how can I fix it?
I have a custom control that zooms on a custom drawn document canvas.
I tried using AutoScroll but it was not giving satisfactory results. When I would set AutoScrollPosition and AutoScrollMinSize back to back (in any order) it would force a paint and cause jitter each time the zoom changes. I assume this was because it was calling an Update and not Invalidate when I modified both properties.
I am now manually setting the HorizontalScroll and VerticalScroll properties with AutoScroll set to false like so each time the Zoom level or the client size changes:
int canvasWidth = (int)Math.Ceiling(Image.Width * Zoom) + PageMargins.Horizontal;
int canvasHeight = (int)Math.Ceiling(Image.Height * Zoom) + PageMargins.Vertical;
HorizontalScroll.Maximum = canvasWidth;
HorizontalScroll.LargeChange = ClientSize.Width;
VerticalScroll.Maximum = canvasHeight;
VerticalScroll.LargeChange = ClientSize.Height;
if (canvasWidth > ClientSize.Width)
{
HorizontalScroll.Visible = true;
}
else
{
HorizontalScroll.Visible = false;
HorizontalScroll.Value = 0;
}
if (canvasHeight > ClientSize.Height)
{
VerticalScroll.Visible = true;
}
else
{
VerticalScroll.Visible = false;
VerticalScroll.Value = 0;
}
int focusX = (int)Math.Floor((FocusPoint.X * Zoom) + PageMargins.Left);
int focusY = (int)Math.Floor((FocusPoint.Y * Zoom) + PageMargins.Top);
focusX = focusX - ClientSize.Width / 2;
focusY = focusY - ClientSize.Height / 2;
if (focusX < 0)
focusX = 0;
if (focusX > canvasWidth - ClientSize.Width)
focusX = canvasWidth - ClientSize.Width;
if (focusY < 0)
focusY = 0;
if (focusY > canvasHeight - ClientSize.Height)
focusY = canvasHeight - ClientSize.Height;
if (HorizontalScroll.Visible)
HorizontalScroll.Value = focusX;
if (VerticalScroll.Visible)
VerticalScroll.Value = focusY;
In this case, FocusPoint is a PointF structure that holds the coordinates in the bitmap which the user is focused on (for example, when they mouse wheel to zoom in they are focusing on the current mouse location at that time). This functionality works for the most part.
What does not work is the scroll bars. If the user tries to manually scroll by clicking on either scroll bar, they both keep returning to 0. I do not set them anywhere else in my code. I have tried writing the following in the OnScroll() method:
if (se.ScrollOrientation == ScrollOrientation.VerticalScroll)
{
VerticalScroll.Value = se.NewValue;
}
else
{
HorizontalScroll.Value = se.NewValue;
}
Invalidate();
But this causes some very erratic behavior including flicking and scrolling out of bounds.
How am I supposed to write the code for OnScroll? I've tried the base.OnScroll but it didn't do anything while AutoScroll is set to false.
I ended up implementing my own custom scrolling by creating 3 child controls: an HScrollBar, a VScrollBar, and a Panel.
I hide ClientSize and ClientRectangle like so:
public new Rectangle ClientRectangle
{
get
{
return new Rectangle(new Point(0, 0), ClientSize);
}
}
public new Size ClientSize
{
get
{
return new Size(
base.ClientSize.Width - VScrollBar.Width,
base.ClientSize.Height - HScrollBar.Height
);
}
}
The layout is done in OnClientSizeChanged:
protected override void OnClientSizeChanged(EventArgs e)
{
base.OnClientSizeChanged(e);
HScrollBar.Location = new Point(0, base.ClientSize.Height - HScrollBar.Height);
HScrollBar.Width = base.ClientSize.Width - VScrollBar.Width;
VScrollBar.Location = new Point(base.ClientSize.Width - VScrollBar.Width, 0);
VScrollBar.Height = base.ClientSize.Height - HScrollBar.Height;
cornerPanel.Size = new Size(VScrollBar.Width, HScrollBar.Height);
cornerPanel.Location = new Point(base.ClientSize.Width - cornerPanel.Width, base.ClientSize.Height - cornerPanel.Height);
}
Each ScrollBar has their Scroll event subscribed to the following:
private void ScrollBar_Scroll(object sender, ScrollEventArgs e)
{
OnScroll(e);
}
And finally we can allow MouseWheel events to scroll with the following:
protected override void OnMouseWheel(MouseEventArgs e)
{
int xOldValue = VScrollBar.Value;
if (e.Delta > 0)
{
VScrollBar.Value = (int)Math.Max(VScrollBar.Value - (VScrollBar.SmallChange * e.Delta), 0);
OnScroll(new ScrollEventArgs(ScrollEventType.ThumbPosition, xOldValue, VScrollBar.Value, ScrollOrientation.VerticalScroll));
}
else
{
VScrollBar.Value = (int)Math.Min(VScrollBar.Value - (VScrollBar.SmallChange * e.Delta), VScrollBar.Maximum - (VScrollBar.LargeChange - 1));
OnScroll(new ScrollEventArgs(ScrollEventType.ThumbPosition, xOldValue, VScrollBar.Value, ScrollOrientation.VerticalScroll));
}
}
For custom painting, you would use the following statement:
e.Graphics.TranslateTransform(-HScrollBar.Value, -VScrollBar.Value);
This worked perfectly without the glitches present when using AutoScroll.