Okay, so I have a Grid with 4 child Images, each positioned in all four corners of the Grid like so.
The purpose of the bottom two Child Images, is to stretch the grid. So when the user drags these corners, the Grid will stretch.
My problem is that the Children will stretch too, which I don't want.
Is there any way to ensure that the size of the children does not stretch with the Grid?
Thanks.
P.S. I could detach the Child Images from the Grid, but it is much simpler and more elegant this way as the x/y positions remain at the edges of the Grid perfectly, I just want to ensure they do not Scale with it, if possible.
Create Grid and add Children
//ImageGrid
ImageControl.Height = 500;
ImageControl.Width = 500;
ImageControl.ManipulationMode = ManipulationModes.All;
canvas.Children.Add(ImageControl);
ImageControl.Children.Add(tickBtn);
ImageControl.Children.Add(delBtn);
ImageControl.Children.Add(skewBtn);
ImageControl.Children.Add(strBtn);
ImageManipulation.Image_Drag = new CompositeTransform();
ImageManipulation.Image_Drag.CenterX = imW / 2;
ImageManipulation.Image_Drag.CenterY = imH / 2;
ImageControl.RenderTransform = ImageManipulation.Image_Drag;
strBtn.ManipulationDelta += ImageManipulation.resBtn_Manip;
skewBtn.ManipulationDelta += MaskManipulation.skewBtn_Manip;
dragControl.ManipulationDelta += ImageManipulation.movBtn_Manip;
Manipulation Class
public static CompositeTransform Image_Drag;
public static void resBtn_Manip(object sender, ManipulationDeltaRoutedEventArgs e)
{
Mask_Drag.ScaleX += e.Delta.Translation.X;
Mask_Drag.ScaleY += e.Delta.Translation.X;
}
public static void movBtn_Manip(object sender, ManipulationDeltaRoutedEventArgs e)
{
Mask_Drag.TranslateX += e.Delta.Translation.X;
Mask_Drag.TranslateY += e.Delta.Translation.Y;
}
public static void skewBtn_Manip(object sender, ManipulationDeltaRoutedEventArgs e)
{
Mask_Drag.ScaleX -= e.Delta.Translation.X;
Mask_Drag.ScaleY += e.Delta.Translation.Y;
if (Mask_Drag.ScaleX < 0.5)
{
Mask_Drag.ScaleX = 0.5;
}
if (Mask_Drag.ScaleY < 0.5)
{
Mask_Drag.ScaleY = 0.5;
}
}
Related
I have a small Form to paint a grid. But when I resize it, which I mean drag the edge of the form, there is something wrong with my grid. below is the image:
As you can see, the form is keep repainting it when I hold the mouse button. I think I can fix the problem by change the way the resize event call the repaint event. Is there anyway that the repaint event only be called after I release the mouse button?
Here is the snap code of how I draw the grid:
private void PictureBox_paint(object sender, PaintEventArgs e)
{
viewsizeX = pictureBox.Width;
viewsizeY = pictureBox.Height;
cellSizeX = 50;
cellSizeY = 50;
numOfCellsX = (viewsizeX - (viewsizeX % cellSizeX)) / cellSizeX;
numOfCellsY = (viewsizeY - (viewsizeY % cellSizeY)) / cellSizeY;
// draw horizontal lines of gird
for (int y = 0; y <= numOfCellsY; ++y)
{
g.DrawLine(bgp, 0, y * cellSizeY, viewsizeX, y * cellSizeY);
}
// draw vertical lines of griļ¼ +6 because here we are drawing 6 more lines on the right of the grid for further moving.
for (int x = 1; x <= numOfCellsX * 2; ++x)
{
int position = (x * cellSizeX) + changeValue;
if (position >= 0 && position <= viewsizeX)
{
g.DrawLine(bgp, position, 0, position, viewsizeY);
}
}
My event list :
Respond to the ResizeBegin and ResizeEnd events. As in:
private disablePaint = false;
private void MyForm_ResizeBegin(object sender, EventArgs e) {
disablePaint = true;
}
private void MyForm_ResizeEnd(object sender, EventArgs e) {
disablePaint = false;
}
private void PictureBox_paint(object sender, PaintEventArgs e) {
if (disablePaint) return;
// your paint code here
}
Do not paint while resizing is in progress. Note the use of the disablePaint flag.
Im creating a small map for a cemetery and I want to zoom in and zoom out to the map. So my idea is to resize all the content of the panel which is buttons.
My code is here:
foreach (Control btn in this.panel3.Controls)
{
if ((btn) is Button)
{
btn.Width += 10;
btn.Height += 10;
}
}
is there any other way to do it? I am not satisfied because it doesn't look like zoom in or a way to may it more like zoom in. Thanks in advance.
Your code only zooms in the buttons separately. What you may need is to stretch the whole area of buttons. Something like this (I haven't tested):
foreach (Button btn in panel3.Controls.Where(c => c is Button).Cast<Button>())
{
const double zoom = 1.1;
//increase position
btn.Left = Convert.ToInt32(btn.Left * zoom);
btn.Top = Convert.ToInt32(btn.Top * zoom);
//increase size
btn.Width = Convert.ToInt32(btn.Width * zoom);
btn.Height = Convert.ToInt32(btn.Height * zoom);
}
You can use the Scale method of the Panel to zoom in and out the contents of the panel.
private void buttonZoomIn_Click(object sender, EventArgs e)
{
cemetaryPanel.Scale(new SizeF(1.1f, 1.1f));
}
private void buttonZoomOut_Click(object sender, EventArgs e)
{
cemetaryPanel.Scale(new SizeF(0.9f, 0.9f));
}
I have a drag and drop interface in my Universal Windows App, where the user can add a textbox to the image, and drag and scale it around, as if it was a textbox in MSPaint, but it can be edited after it is placed, by double-tapping it.
I have implemented this as such:
textBox.LostFocus sets textBox.IsReadOnly = true;
textBox.DoubleTapped sets IsReadOnly back to false, so that it can drag around.
textBox.ManipulationDelta moves the textBox around.
Now I have the problem that the textBox has this rubberbanding effect going on, and that this blocks the manipulation event.
Is there a way to disable this? Or can I for example say when the mouse clicks (or finger or whatever), that it should start the manipulation event?
Code for a new TextBox:
private TextBox CreateManipulativeTextBox(string text)
{
var textBox = new TextBox
{
Text = text,
Background = new SolidColorBrush(Color.FromArgb(0, 0, 0, 0)),
BorderBrush = new SolidColorBrush(Color.FromArgb(128, 0, 0, 0)),
Width = 150,
Height = 50,
ManipulationMode = ManipulationModes.TranslateX | ManipulationModes.TranslateY | ManipulationModes.Scale,
RenderTransform = new CompositeTransform()
};
// Doubletap gives edit possibility, tap outside loses editability
textBox.LostFocus += TextBoxOnLostFocus;
textBox.DoubleTapped += TextBoxOnDoubleTapped;
// Add manipulation events
textBox.ManipulationStarted += OnManipulationStarted;
textBox.ManipulationDelta += OnManipulationDelta;
textBox.ManipulationCompleted += OnManipulationCompleted;
return textBox;
}
Code for focus and defocus:
private void TextBoxOnDoubleTapped(object sender, DoubleTappedRoutedEventArgs doubleTappedRoutedEventArgs)
{
(sender as TextBox).IsReadOnly = false;
}
private void TextBoxOnLostFocus(object sender, RoutedEventArgs routedEventArgs)
{
(sender as TextBox).IsReadOnly = true;
}
Code for manipulation:
private void OnManipulationStarted(object sender, ManipulationStartedRoutedEventArgs e)
{
if (sender is TextBox)
(sender as TextBox).IsReadOnly = true;
((FrameworkElement)sender).Opacity = 0.6;
}
private void OnManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
{
var frameworkElement = (FrameworkElement)sender;
var transform = (CompositeTransform)frameworkElement.RenderTransform;
// LEFT-RIGHT bounds
if (e.Delta.Translation.X < 0) // Going left
{
if (DrawingArea.ActualWidth / 2 + (transform.TranslateX + e.Delta.Translation.X) - frameworkElement.ActualWidth / 2 > 0)
{
// Staying inside, apply translation
transform.TranslateX += e.Delta.Translation.X;
}
else
{
// Trying to go outside, because scale sucks to work with, move image back inside
transform.TranslateX = frameworkElement.ActualWidth / 2 - DrawingArea.ActualWidth / 2;
}
}
else // Going right
{
if (DrawingArea.ActualWidth / 2 - (transform.TranslateX + e.Delta.Translation.X) +
frameworkElement.ActualWidth * (0.5 - transform.ScaleX) > 0)
{
// Staying inside, apply translation
transform.TranslateX += e.Delta.Translation.X;
}
else
{
// Trying to go outside, because scale sucks to work with, move image back inside
transform.TranslateX = frameworkElement.ActualWidth * (0.5 - transform.ScaleX) + DrawingArea.ActualWidth / 2;
}
}
// UP-DOWN bounds
if (e.Delta.Translation.Y < 0) // Going up
{
if (DrawingArea.ActualHeight / 2 + (transform.TranslateY + e.Delta.Translation.Y) - frameworkElement.ActualHeight / 2 >
0)
{
// Staying inside, apply translation
transform.TranslateY += e.Delta.Translation.Y;
}
else
{
// Trying to go outside, because scale sucks to work with, move image back inside
transform.TranslateY = frameworkElement.ActualHeight / 2 - DrawingArea.ActualHeight / 2;
}
}
else // Going down
{
if (DrawingArea.ActualHeight / 2 - (transform.TranslateY + e.Delta.Translation.Y) +
frameworkElement.ActualHeight * (0.5 - transform.ScaleY) > 0)
{
// Staying inside, apply translation
transform.TranslateY += e.Delta.Translation.Y;
}
else
{
// Trying to go outside, because scale sucks to work with, move image back inside
// transform.TranslateY = image.ActualHeight*(0.5 - transform.ScaleY) + DrawingArea.ActualHeight/2;
// Dragging down, remove image
DrawingArea.Children.Remove(frameworkElement);
}
}
// Only allow scaling when both dimensions are smaller than the drawingarea
if (frameworkElement.ActualHeight * (transform.ScaleY * e.Delta.Scale) < DrawingArea.ActualHeight &&
frameworkElement.ActualWidth * (transform.ScaleX * e.Delta.Scale) < DrawingArea.ActualWidth)
{
transform.ScaleX *= e.Delta.Scale;
transform.ScaleY *= e.Delta.Scale;
}
}
private void OnManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e)
{
((FrameworkElement)sender).Opacity = 1;
}
EDIT: This only happens with touch, when the mouse drags the item around it works.
How do I get the pinch-to-zoom x and y scaling values independent of each other for a Windows Store App? I'm currently using ManipulationDeltaRoutedEventArgs's ManipulationDelta structure, but as you can see it only offers a single scale.
// Global Transform used to change the position of the Rectangle.
private TranslateTransform dragTranslation;
private ScaleTransform scaleTransform;
// Constructor
public MainPage()
{
InitializeComponent();
// Add handler for the ManipulationDelta event
TestRectangle.ManipulationDelta += Drag_ManipulationDelta;
dragTranslation = new TranslateTransform();
scaleTransform = new ScaleTransform();
TestRectangle.RenderTransform = this.dragTranslation;
}
void Drag_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
{
// Move the rectangle.
dragTranslation.X += e.Delta.Translation.X;
dragTranslation.Y += e.Delta.Translation.Y;
// Scaling, but I want X and Y independent!
scaleTransform.ScaleX = e.Delta.Scale;
scaleTransform.ScaleY = e.Delta.Scale;
}
XAML:
<Rectangle Name="TestRectangle"
Width="200" Height="200" Fill="Blue"
ManipulationMode="All"/>
Code mostly taken from here.
I ended up using Handling Two, Three, Four Fingers Swipe Gestures in WinRT App to grab the coordinates of the two fingers, calculated the initial difference between them, and then scaled accordingly as the distance changed.
int numActiveContacts;
Dictionary<uint, int> contacts;
List<PointF> locationsOfSortedTouches;
void myCanvas_PointerPressed(object sender, PointerRoutedEventArgs e) {
PointerPoint pt = e.GetCurrentPoint(myCanvas);
locationsOfSortedTouches.Add(new PointF((float) pt.Position.X, (float) pt.Position.Y));
touchHandler.TouchesBegan(locationsOfSortedTouches);
contacts[pt.PointerId] = numActiveContacts;
++numActiveContacts;
e.Handled = true;
}
void myCanvas_PointerMoved(object sender, PointerRoutedEventArgs e) {
var pt = e.GetCurrentPoint(myCanvas);
var ptrId = pt.PointerId;
if (contacts.ContainsKey(ptrId)) {
var ptrOrdinal = contacts[ptrId];
Windows.Foundation.Point currentContact = pt.Position;
locationsOfSortedTouches[ptrOrdinal] = new PointF((float) pt.Position.X, (float) pt.Position.Y);
//distance calculation and zoom redraw here
}
e.Handled = true;
}
I am working on a touch screen POS in WinForms.
I have a flowlayoutpanel and add buttons dynamically but I dont want to show a scrollbar.
I use 2 buttons to scroll instead, so please help me how to scroll without showing a scrollbar
Try placing the FlowLayoutPanel inside another panel with these properties:
flowLayoutPanel1.AutoScroll = false;
flowLayoutPanel1.AutoSize = true;
flowLayoutPanel1.AutoSizeMode = AutoSizeMode.GrowAndShrink;
From here, you have to control yourself the location of the FlowLayoutPanel1 inside your panel (which should also have AutoScroll = false;) based on your two buttons.
Take two buttons btnLeft and btnRight and try this code :
private void btnLeft_Click(object sender, EventArgs e)
{
if (flowPanelItemCategory.Location.X <= xpos)
{
xmin = flowPanelItemCategory.HorizontalScroll.Minimum;
if (flowPanelItemCategory.Location.X >= xmin)
{
xpos -= 100;
flowPanelItemCategory.Location = new Point(xpos, 0);
}
}
}
private void btnRight_Click(object sender, EventArgs e)
{
if (flowPanelItemCategory.Location.X <= xpos)
{
xmax = flowPanelItemCategory.HorizontalScroll.Maximum;
if (flowPanelItemCategory.Location.X < xmax)
{
xpos += 100;
flowPanelItemCategory.Location = new Point(xpos, 0);
}
}
}