I have a custom text box and I'm developing a notepad app. I want to dynamically write the zoom factor of the text box to the label. so I need to use the textbox mousewheel event but it doesn't light up so it doesn't go inside the mousewheel. what should I do ?
first image for here
second image for here
this.txtBoxKryptonText.MouseWheel += new System.Windows.Forms.MouseEventHandler(this.txtBoxKryptonText_MouseWheel);
private void txtBoxKryptonText_MouseWheel(object sender, MouseEventArgs e)
{
int mousedeltaval = e.Delta / 120;
if (mousedeltaval == 1) //mousewheel up move
{
txtBoxKryptonText.ZoomFactor += 0.1F;
statusbarZoomState += 10;
toolStripStatusZoom.Text = "%" + statusbarZoomState;
}
else if (mousedeltaval == -1) //mousewheel down move
{
txtBoxKryptonText.ZoomFactor -= 0.1F;
statusbarZoomState -= 10;
toolStripStatusZoom.Text = "%" + statusbarZoomState;
}
}
Code looks ok to me.
Place your mouse pointer very close to the edge of the textbox and you'll see it works.
If you want to handle the events over the entire area you should probably do something like:
this.txtBoxKryptonText.ContainedControl.MouseWheel
+= new System.Windows.Forms.MouseEventHandler(this.txtBoxKryptonText_MouseWheel);
Related
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.
I am trying to make my dynamic generated picture boxes acts on a mouse hover like the "bing" do. Below is the picture attached of what bing search looks like on mouse hover :
Now this is my search results of a project I am working on, what i really want to do is that I want to make picture pop-up as the way which is shown above in bing search.
Please note that all of the picture boxes are generated dynamically on the run time.
if you are using picture boxes.
then you can enhance the current picture box like this
and use it.
//extending the picture box
public class PicControl : PictureBox
{
// variables to save the picture box old position
private int _OldWidth;
private int _OldHeight;
private int _OldTop;
private int _OldLeft;
public PicControl()
{
}
protected override void OnLoadCompleted(System.ComponentModel.AsyncCompletedEventArgs e)
{
_OldTop = this.Top;
_OldLeft = this.Left;
_OldWidth = this.Width;
_OldHeight = this.Height;
base.OnLoadCompleted(e);
}
protected override void OnMouseEnter(EventArgs e)
{
//once mouse enters
// take the backup of height width top left
//so we can restore once mouse leaves
_OldTop = this.Top;
_OldLeft = this.Left;
_OldWidth = this.Width;
_OldHeight = this.Height;
//decrease the control top left to show hover effect
this.Top = this.Top - 10;
this.Left = this.Left - 10;
// same increase the height width
this.Height = this.Height + 20;
this.Width = this.Width + 20;
// show to control on top of all
this.BringToFront();
//trigger the base event
base.OnMouseEnter(e);
}
protected override void OnMouseLeave(EventArgs e)
{
// mouse leaves now we have to restore
//picture box to its original position
this.Height = _OldHeight;
this.Width = _OldWidth;
this.Left = _OldLeft;
this.Top = _OldTop;
base.OnMouseLeave(e);
}
}
Now when you add this class in your project and build it,it will
show you PicControl in your toolbox you can replace pictureBox with PicContorl
in order get that effect.
hope it will helps you.
Here is some example how you could make very trivial popup for such images.
//Sample object representing one of your pictures
PictureBox pb1 = new PictureBox();
List<PictureBox> images = new List<PictureBox>();
images.Add(pb1);
int frameSize = 5;
PictureBox popup = new PictureBox();
popup.Visible = false;
popup.MouseLeave += (s, a) =>
{
popup.Visible = false;
};
foreach (var pb in images)
{
pb.MouseEnter += (s, a) =>
{
var sender = (PictureBox)s;
popup.Image = sender.Image;
popup.Left = sender.Left - frameSize;
popup.Top = sender.Top - frameSize;
popup.Width = sender.Width + (2 * frameSize);
popup.Height = sender.Height + (2 * frameSize);
popup.Visible = true;
popup.BringToFront();
};
}
Let's assume your picture boxes are in "images" collection. We have one more picture box which is hidden that will work as popup.
Next for each of them we bind to MouseEnter event. On MouseEnter we position popup picturebox above the hovered image and we set there same image but we make it slightly bigger and centered over underlying picture and we show the popup.
We are also bound to MouseLeave event of popup so when mouse leaves the popup it will dissapear.
Of course it's just a concept to inspire you for further development. Remember to mark as answer if helps you and you like it :)
Use this code in style sheet
.image:hover {
-webkit-transform:scale(1.2); transform:scale(1.2);
}
.image {
-webkit-transition: all 0.7s ease; transition: all 0.7s ease;
}
and pass this class to the image
<img alt="" src="../Sample%20Pictures/Chrysanthemum.jpg"
style="width: 301px; height: 196px" class="image " />
input:-
Output:-
I've been trying to solve my issue for quite a while and to be honest am getting nowhere. What i would like is when the user clicks the 'top' button on my panel it automatically goes to the top( and swaps with the one there.) and when they click the bottom button it automatically goes to the bottom. I'm setting the index panel manually but of course this doesnt work because its only viable for one panel (i have ten). Greatly appreciate some help in finding a method that can send the panel to the top of the stack regardless of its position.
Here is a image (basic) to help understand
Control ctrlToMove = (Control)this.bookControls[bookName];
int ctrlToMoveIndex = bookPanel.Controls.IndexOf(ctrlToMove);
int ctrlToSwapIndex = ctrlToMoveIndex - 5;
Control ctrlToSwap = bookPanel.Controls[ctrlToSwapIndex];
this.bookPanel.Controls.SetChildIndex(ctrlToMove, ctrlToSwapIndex);
this.bookPanel.Controls.SetChildIndex(ctrlToSwap, ctrlToMoveIndex);
Based on your drawing, I made a UserControl with a button on it:
void uc_ButtonClicked(object sender, EventArgs e) {
UserControl1 uc = sender as UserControl1;
if (uc != null) {
int childIndex = flowLayoutPanel1.Controls.GetChildIndex(uc);
if (childIndex > 0) {
UserControl1 ucTop = flowLayoutPanel1.Controls[0] as UserControl1;
flowLayoutPanel1.Controls.SetChildIndex(uc, 0);
flowLayoutPanel1.Controls.SetChildIndex(ucTop, childIndex);
}
}
}
According to your picture you have one control per row in panel. Thus I suggest you to use TableLayoutPanel instead of FlowLayoutPanel. Also I'd create user control for items in panel. E.g. it will have name PriorityUserControl and four buttons to increase, decrease, maximize, minimize it's 'priority' (I placed buttons horizontally just to save place on screen):
Next, create four events in this user control:
public event EventHandler PriorityMaximized;
public event EventHandler PriorityIncreased;
public event EventHandler PriorityDecreased;
public event EventHandler PriorityMinimized;
And rise appropriate event when button clicked:
private void topButton_Click(object sender, EventArgs e)
{
if (PriorityMaximized != null)
PriorityMaximized(this, EventArgs.Empty);
}
That's it. We have user control which tells whether it want to move up or down. Now add user controls to TableLayoutPanel (either manually or dynamically) and subscribe same event handlers of these four events to ALL user controls. Something like:
// create user control and attach event handlers
PriorityUserControl control = new PriorityUserControl();
control.PriorityMaximized += priorityUserControl_PriorityMaximized;
control.PriorityMinimized += priorityUserControl_PriorityMinimized;
control.PriorityIncreased += priorityUserControl_PriorityIncreased;
control.PriorityDecreased += priorityUserControl_PriorityDecreased;
// add another row to table
panel.RowStyles.Add(new RowStyle(SizeType.AutoSize));
panel.RowCount = panel.RowStyles.Count;
// add control table layout panel
panel.Controls.Add(control);
panel.SetRow(control, panel.RowCount - 1);
Good. All you should do now is implement these event handlers. It's simple. E.g. decreasing priority (i.e. moving down):
private void priorityUserControl_PriorityDecreased(object sender, EventArgs e)
{
// sender is a control where you clicked Down button
Control currentControl = (Control)sender;
// get position in panel
var position = panel.GetPositionFromControl(currentControl);
// just to be sure control is not one at the bottom
if (position.Row == panel.RowCount - 1)
return;
// we want to switch with control beneath current
Control controlToSwitch = panel.GetControlFromPosition(0, position.Row + 1);
// move both controls
panel.SetRow(currentControl, position.Row + 1);
panel.SetRow(controlToSwitch, position.Row);
}
Now implementation of maximizing priority (i.e. moving to top):
private void priorityUserControl_PriorityMaximized(object sender, EventArgs e)
{
Control currentControl = (Control)sender;
var position = panel.GetPositionFromControl(currentControl);
if (position.Row == 0 || panel.RowCount < 2)
return;
Control topControl = panel.GetControlFromPosition(0, 0);
panel.SetRow(currentControl, 0);
panel.SetRow(topControl, position.Row);
}
I believe you will create rest two handlers by yourself.
The key of what you want is setting up a clear and extendable algorithm capable to deal with the different positions of the Panels. Here you have a simple code showing certain approach to this problem:
public partial class Form1 : Form
{
int[] panelLocations;
Point[] pointLocations;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
panelLocations = new int[5];
pointLocations = new Point[5];
panelLocations[1] = 1;
panelLocations[2] = 2;
panelLocations[3] = 3;
pointLocations[1] = new Point(panel1.Left, panel1.Top);
pointLocations[2] = new Point(panel2.Left, panel2.Top);
pointLocations[3] = new Point(panel3.Left, panel3.Top);
}
private void relocate(int curPanel, bool goTop)
{
int curLoc = panelLocations[curPanel];
int newLoc = curLoc - 1;
if (!goTop)
{
newLoc = curLoc + 1;
}
if (newLoc < 1) newLoc = 3;
if (newLoc > 3) newLoc = 1;
if (newLoc != curLoc)
{
int otherIndex = Array.IndexOf(panelLocations, newLoc);
panelLocations[curPanel] = newLoc;
relocatePanel(curPanel);
panelLocations[otherIndex] = curLoc;
relocatePanel(otherIndex);
}
}
private void relocatePanel(int curIndex)
{
if (curIndex == 1)
{
panel1.Location = pointLocations[panelLocations[1]];
}
else if (curIndex == 2)
{
panel2.Location = pointLocations[panelLocations[2]];
}
else if (curIndex == 3)
{
panel3.Location = pointLocations[panelLocations[3]];
}
}
private void buttonTop1_Click(object sender, EventArgs e)
{
relocate(1, true);
}
private void buttonBottom1_Click(object sender, EventArgs e)
{
relocate(1, false);
}
}
Open a new project, add 3 panels (Panel1, Panel2 and Panel3... better put different background colors) and include two buttons (buttonUp and buttonDown). This code will make the Panel1 to go up and down (by changing its position with the other panels).
The idea is pretty simple: at the start you store the positions of all the Panels in an array. In another array, you store where each panel is located every time (1 is the original position of Panel1, etc.).
It is a quite simple code which you can improve and extend as much as required, but the idea is pretty reliable and you can use it in any case: a set of fixed positions through which the panels will be moving.
I'm using a ScrollableControl in my C# project and I'd like to know how to map the arrow keys to vertical/horizontal scrolling.
EDIT : my picture box gets the focus, and i managed to map the keys to scroll. The issue here is that when i hit an arrow key, it scrolls one time and then loses the focus to give it to a button next to the Scrollviewer. I'd like the scrollviewer NOT to lose that focus
This is my code, the second paragraph is the interesting one here.
private void drawMap(IGame game)
{
System.Windows.Forms.PictureBox pictureBox = new System.Windows.Forms.PictureBox();
pictureBox.Width = (int)Math.Sqrt((double)game.Map.grid.Count) * 50; pictureBox.Height = (int)Math.Sqrt((double)game.Map.grid.Count) * 50;
pictureBox.Paint += new System.Windows.Forms.PaintEventHandler(game.Map.afficher);
pictureBox.MouseEnter += pictureBoxFocus;
pictureBox.Click += pictureBoxFocus;
pictureBox.Click += mapClicked;
System.Windows.Forms.ScrollableControl sc = new System.Windows.Forms.ScrollableControl();
sc.Controls.Add(pictureBox);
sc.AutoScroll = true;
windowsFormsHost1.Child = sc;
}
Thank you in advance :)
PLUS : my scrolling algo is kinda dirty and don't works very well so i was wondering if there was an "easy way" to do it.
private void sc_PreviewKeyDown(object sender, System.Windows.Forms.PreviewKeyDownEventArgs e)
{
System.Windows.Forms.ScrollableControl sc = (System.Windows.Forms.ScrollableControl)sender;
switch (e.KeyValue)
{
case (int)System.Windows.Forms.Keys.Down:
sc.VerticalScroll.Value += 50;
break;
case (int)System.Windows.Forms.Keys.Up:
if(sc.VerticalScroll.Value - 50 < 0)
sc.VerticalScroll.Value = 0;
else sc.VerticalScroll.Value -= 50;
break;
case (int)System.Windows.Forms.Keys.Right:
sc.HorizontalScroll.Value += 50;
break;
case (int)System.Windows.Forms.Keys.Left:
if (sc.HorizontalScroll.Value - 50 < 0)
sc.HorizontalScroll.Value = 0;
else sc.HorizontalScroll.Value -= 50;
break;
}
windowsFormsHost1.Child.Focus();
}
I didn't find a way in C# for creating a button which will support opacity - instead of just appearing when show method is called, to have the ability to slowly fade it into view.
I created my own button and I would like to know what you think of the implementation.
Basically, I created a Windows Form, which supports opacity property and handled all the corner cases regarding "adding" a form to another form, specifically:
- location changed event
- the owner form lost focus
The form consist of a label, which represents the button's text and that's all.
The form constructor gets the text for the label, the desired size of the button and the speed (based on an Enum) for the button appear.
In the form load method the label is being located in the middle of the button
when the label or the form itself clicked a simple graphic is performed and an event is raised to whoever catches it.
My Code:
Created a Form - named buttonForm
Constructor
InitializeComponent();
this.Owner = owner;
_buttonText = buttonText;
_buttonSize = buttonSize;
_usedSpeedOpacity = SelectSpeedOpacity(showSpeed);
A method to illustrate click command - being called when the user clicks on the form and on the label itself:
this.Location = new Point(this.Location.X + 1, this.Location.Y);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
Thread.Sleep(50);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
this.Location = new Point(this.Location.X - 1, this.Location.Y);
if (Button_Clicked != null)
{
Button_Clicked();
}
form load - locating the label in the middle of the control etc
labelButtonText.Text = _buttonText;
this.Size = _buttonSize;
double remainning = this.Width - labelButtonText.Size.Width;
Point labelNewLocation = new Point(
(int)(remainning / 2),
(int)(this.Height / 2 - this.Font.Height / 2));
labelButtonText.Location = labelNewLocation;
FadeShow (and FadeHide the same)
int tempCounter = 0;
Opacity = 0;
Show();
while (tempCounter <= 1000)
{
if (Opacity == 1.0)
{
break;
}
if (tempCounter % 10 == 0)
{
Opacity += _usedSpeedOpacity;
}
Refresh();
tempCounter++;
}
this.Visible = true;
this.BringToFront();
Update location method so when the parent form moves i call this method
this.Location = new Point(
this.Location.X - (ParentFormLocation.X - newLocation.X),
this.Location.Y - (ParentFormLocation.Y - newLocation.Y));
ParentFormLocation = newLocation;
An event of my button_click
Thanks in advance,
Oz.
I did something similar with a windows form that changed its height. The way I did it was to implement a timer within the code so every half a second the opacity changed.
While the below is not a 100% correct answer without your code its difficult to show you.
void timer_Tick(object sender, EventArgs e)
{
if (btnName.Opacity < 100)
{
btnName.Opacity++;
timer2.Stop();
timer2.Interval = 5000;
timer2.Start();
} else {
timer2.Stop();
}
}