DoDragDrop from standard Label not working - c#

I can't figure out why attempting to drag text from a standard Label to Notepad (or any other control accepting text) doesn't work. I've looked at documentation and examples and I'm not seeing the problem. The cursor remains a circle with a line through it and if I register a FeedBack callback the event is always NONE. Creating a standard Windows Forms Application, dropping a Label control and registering MouseDown & MouseMove events I have this code where I call label1.DoDragDrop (label1, DragDropEffects.All | DragDropEffects.Link). Any help would be appreciated.
Here is my form code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace DragDropLabel
{
public partial class Form1 : Form
{
Point m_ClickLocation;
bool _bDragging = false;
public Form1()
{
InitializeComponent();
}
private void OnLabelMouseDown(object sender, MouseEventArgs e)
{
m_ClickLocation = e.Location;
_bDragging = true;
}
private void OnLabelMouseMove(object sender, MouseEventArgs e)
{
if (_bDragging)
{
Point pt = e.Location;
Size dragSize = SystemInformation.DragSize;
if (Math.Abs(pt.X - m_ClickLocation.X) > dragSize.Width / 2 ||
Math.Abs(pt.Y - m_ClickLocation.Y) > dragSize.Height / 2)
{
DragDropEffects rc = label1.DoDragDrop(label1, DragDropEffects.All | DragDropEffects.Link);
_bDragging = false;
}
}
}
}
}

First, change
DragDropEffects rc = label1.DoDragDrop(label1, DragDropEffects.All | DragDropEffects.Link);
to
label1.DoDragDrop(label1.Text, DragDropEffects.Copy);
Second, you must prepare your drop target. Lets assume, it is textbox. Here is exmple extension method which will allow to cofigure any textbox by calling MyTextBox.EnableTextDrop():
static class TextBoxExtensions
{
public static void EnableTextDrop(this TextBox textBox)
{
if(textBox == null) throw new ArgumentNullException("textBox");
// first, allow drop events to occur
textBox.AllowDrop = true;
// handle DragOver to provide visual feedback
textBox.DragOver += (sender, e) =>
{
if(((e.AllowedEffect & DragDropEffects.Copy) == DragDropEffects.Copy) &&
e.Data.GetDataPresent(typeof(string)))
{
e.Effect = DragDropEffects.Copy;
}
};
// handle DragDrop to set text
textBox.DragDrop += (sender, e) =>
{
if(((e.AllowedEffect & DragDropEffects.Copy) == DragDropEffects.Copy) &&
e.Data.GetDataPresent(typeof(string)))
{
((TextBox)sender).Text = (string)e.Data.GetData(typeof(string));
}
};
}
}

Standard edit controls (textboxes) do not support drag&drop and will not accept any dropped text.

Related

Make flowlayoutPanel in c# winforms touch scrollable to the right and left

I'm trying to make my flowlayoutPanel in winform .NET framework touch scrollable on a touchscreen to the right and left. I have found a Youtube tutorial that shows how to achieve touch scrollability but its only up and down.
This is what I tried but it only works for up and down touch scroll, how do I make it so it touch scrolls to right and left instead of up and down?
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace VendingMachineProject
{
public class TouchScroll
{
private Point mouseDownPoint;
private FlowLayoutPanel parentPanel;
public TouchScroll(FlowLayoutPanel panel)
{
parentPanel = panel;
AssignEvent(panel);
}
private void AssignEvent(Control control)
{
control.MouseDown += MouseDown;
control.MouseMove += MouseMove;
foreach(Control child in control.Controls)
{
AssignEvent(child);
}
}
private void MouseMove(object sender, MouseEventArgs e)
{
if(e.Button != MouseButtons.Left)
return;
Point pointDifference = new Point(Cursor.Position.X + mouseDownPoint.X, Cursor.Position.Y - mouseDownPoint.x);
if ((mouseDownPoint.X == Cursor.Position.X) && (mouseDownPoint.Y == Cursor.Position.Y))
return;
Point currAutoS = parentPanel.AutoScrollPosition;
parentPanel.AutoScrollPosition = new Point(Math.Abs(currAutoS.X) - pointDifference.X, Math.Abs(currAutoS.Y) - pointDifference.Y);
mouseDownPoint = Cursor.Position;
}
private void MouseDown(object sender, MouseEventArgs e)
{
if(e.Button == MouseButtons.Left)
this.mouseDownPoint = Cursor.Position;
}
}
}

How can I add context menu on listview item right click with the mouse?

I want to be able to click select item in the list view control and than to make right click with the mouse and show something.
This is the costum control I created :
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Search_Text_In_Files
{
public partial class ListViewCostumControl : UserControl
{
public static ListViewControl lvnf;
public ListViewCostumControl()
{
InitializeComponent();
lvnf = new ListViewControl();
lvnf.Location = new Point(50, 50);
lvnf.Size = new Size(50, 50);
lvnf.View = View.Details;
lvnf.Dock = DockStyle.Fill;
lvnf.SuspendLayout();
lvnf.LabelEdit = true;
lvnf.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.None;
lvnf.Columns.Add("", 984, HorizontalAlignment.Left);
//lvnf.Columns.Add("Subject", 200);
//lvnf.Columns.Add("Date", 300);
lvnf.Sorting = SortOrder.None;
//lvnf.ColumnClick += lvnf_ColumnClick;
//lvnf.Click += lvnf_Click;
//lvnf.SelectedIndexChanged += lvnf_SelectedIndexChanged;
this.Controls.Add(lvnf);
lvnf.ResumeLayout(false);
}
public class ListViewControl : System.Windows.Forms.ListView
{
public ListViewControl()
{
//Activate double buffering
this.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true);
//Enable the OnNotifyMessage event so we get a chance to filter out
// Windows messages before they get to the form's WndProc
this.SetStyle(ControlStyles.EnableNotifyMessage, true);
}
protected override void OnNotifyMessage(System.Windows.Forms.Message m)
{
//Filter out the WM_ERASEBKGND message
if (m.Msg != 0x14)
{
base.OnNotifyMessage(m);
}
}
}
private void ListViewNFTest_Load(object sender, EventArgs e)
{
}
}
}
Than in Form1 :
ListViewCostumControl.lvnf.MouseClick += Lvnf_MouseClick;
And in the event :
private void Lvnf_MouseClick(object sender, MouseEventArgs e)
{
if(e.Button == MouseButtons.Right)
{
var focusedItem = ListViewCostumControl.lvnf.FocusedItem;
if (focusedItem != null && focusedItem.Bounds.Contains(e.Location))
{
contextMenuStrip1.Show(Cursor.Position);
}
}
}
but it's not showing nothing when making a right click with the mouse on selected item in the list view.
First you need to declare context menu and at least one item.
private System.Windows.Forms.ContextMenuStrip contextMenuStrip1;
private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem1;
Next to you need to create objects and assign them to your listView.
this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components);
this.contextMenuStrip1.SuspendLayout();
this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem();
this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.toolStripMenuItem1});
this.contextMenuStrip1.Name = "contextMenuStrip1";
this.contextMenuStrip1.ResumeLayout(false);
lvnf.ContextMenuStrip = contextMenuStrip1;
Just look what designer does when you add the context menu.
You do not need to handle mouse events as it is done by context menu automatically. Instead use menu/item events.
If you need context menu to appear only on listView item/items selected, then you can handle opening event and suppress menu if no items selected.
private void contextMenuStrip1_Opening(object sender, CancelEventArgs e)
{
if (lvnf.SelectedItems.Count == 0)
e.Cancel = true;
}

Grouping different things together so that they will all be activated/deactivated all at once with minimum code

I don't know much about C# so I apologize in advance if my question has been answered elsewhere. I don't know what to search for.
I'm making a tic tac toe game in windows forms. I've set it up like this: each cell has 2 buttons(x and o) and two labels (X and O). Clicking one of the buttons will change the corresponding label's visible property to true while at the same time disabling (enable=false) the opposite button from being selected. There are 9 cells total. I also have a menu button (reset) that when clicked will enable all buttons and hide all labels so that the game may be re-played.
I'm looking for a way to reset all the items I want without having to individually type code for each item. Is there a way to group the items together so that they can all be fired at once with a minimum of code?
Source code is incomplete as I am still writing the program. I've posted the code for three cells.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Tick_Tack_Toe
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void xButton1_Click(object sender, EventArgs e)
{
xLabel1.Visible = true;
oButton1.Enabled = false;
}
private void oButton1_Click(object sender, EventArgs e)
{
oLabel1.Visible = true;
xButton1.Enabled = false;
}
private void xButton2_Click(object sender, EventArgs e)
{
xLabel2.Visible = true;
oButton2.Enabled = false;
}
private void oButton2_Click(object sender, EventArgs e)
{
oLabel2.Visible = true;
xButton2.Enabled = false;
}
private void resetToolStripMenuItem_Click(object sender,
EventArgs e)
{
xButton1.Enabled = true;
oButton1.Enabled = true;
xButton2.Enabled = true;
oButton2.Enabled = true;
xButton3.Enabled = true;
oButton3.Enabled = true;
xLabel1.Visible = false;
oLabel1.Visible = false;
xLabel2.Visible = false;
oLabel2.Visible = false;
xLabel3.Visible = false;
oLabel3.Visible = false;
}
}
}
One way you can do this is to loop through the controls collection. Since you seem to have a standard on the naming of the controls, you can first narrow the collection down to only those whose name begins with 'o' or 'x'. Then, you can look at the type of control, and if it's a label you can hide it, and if it's a button you can enable it:
private void ResetControls()
{
foreach (Control control in this.Controls)
{
// Only look at controls whose names begin with 'o' or 'x'
if (control.Name.StartsWith("o") ||control.Name.StartsWith("x"))
{
// Hide it if it's a label
if(control.GetType() == typeof(Label))
{
control.Visible = false;
}
// Enable it if it's a button
else if (control.GetType() == typeof(Button))
{
control.Enabled = true;
}
}
}
}
You mentioned that all your button and labels are inside their own panel control, which has it's own control collection. So you can modify the code above to first search for panel controls, then search the panel control's control collection for buttons and labels:
private void ResetControls()
{
foreach (Control control in this.Controls)
{
if (control is Panel)
{
var panel = control as Panel;
foreach (Control panelControl in panel.Controls)
{
// Only look at controls whose names begin with 'o' or 'x'
if (panelControl.Name.StartsWith("o") || panelControl.Name.StartsWith("x"))
{
// Hide it if it's a label
if (panelControl is Label)
{
panelControl.Visible = false;
}
// Enable it if it's a button
else if (panelControl is Button)
{
panelControl.Enabled = true;
}
}
}
}
}
}
Note that this is just one possible solution to get you going, but certainly not the best. Normally the controls would be created at runtime, added to a collection of some sort (usually an array called GameBoard or something like that), and placed on the form all by code. Their click events would all be hooked up to the same method, which would do the right thing based on either control name or some data in the Tag field.
They are grouped together in the Controls array of the form. Here is a simple example of how you can cycle through them:
private void doReset()
{
foreach (Control c in this.Controls)
{
if (c.GetType() == typeof(Button))
{
c.Enabled = true;
}
else if (c.GetType() == typeof(Label))
{
c.Visible = false;
}
}
}
You can do some more intelligent logic in there for the specific controls if you like. Something like adding a tag to each button if it gets picked up by the method or, naming each button in a certain way if it is to get picked up by the method.
Let's try following idea:
List<Button> buttons = new List<Button>();
List<Label> labels = new List<Label>();
buttons.Add(xButton1)
buttons.Add(oButton1)
buttons.Add(xButton2)
buttons.Add(oButton2)
...
labels.Add(xLabel1)
labels.Add(oLabel1)
labels.Add(xLabel2)
labels.Add(oLabel2)
...
foreach(var ctr in buttons)
{
ctr.Enabled = true;
}
foreach(var ctr in labels)
{
ctr.Enabled = true;
}
This is how I always do it. If you give each button a different text value inside the click event you can do different things depending on the text value.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Tick_Tack_Toe
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
MyButton.buttons = new List<MyButton>() {
new MyButton() { button = xButton1, label = xLabel1},
new MyButton() { button = xButton2, label = xLabel2},
new MyButton() { button = xButton3, label = xLabel3},
new MyButton() { button = oButton1, label = oLabel1},
new MyButton() { button = oButton2, label = oLabel2},
new MyButton() { button = oButton3, label = oLabel3}
};
foreach (MyButton button in MyButton.buttons)
{
button.button.Click += new EventHandler(Button_Click);
}
}
private void Button_Click(object sender, EventArgs e)
{
MyButton button = sender as MyButton;
button.label.Visible = true;
button.button.Enabled = false;
switch (button.button.Text)
{
case "X":
//enter your code here
break;
case "Y":
//enter your code here
break;
}
}
private void resetToolStripMenuItem_Click(object sender,
EventArgs e)
{
foreach (MyButton button in MyButton.buttons)
{
button.button.Enabled = true;
button.label.Visible = false;
}
}
}
public class MyButton
{
public static List<MyButton> buttons { get; set; }
public Button button { get; set; }
public Label label { get; set; }
}
}

C# - How to Change Dynamically the Mask of the MaskedTextBox?

Here's the problem:
I'm using a MaskedTextBox for phones masks. But, the Mask must accept two kinds of mask, like, the default mask is like this (00) 0000-0000, but sometimes the mask need to have one more slot, like this (00) 0000-00000.
This process must be dynamic. If the user type more than 10 chars, the MaskedTextBox will change his own mask.
Some time ago, I made it using VB.Net, but now, I need to do this using C#.
Here's just a example using VB.NET that I made some time ago.
Private Sub MaskedTextValidacao_Validating(sender As System.Object, e As System.ComponentModel.CancelEventArgs) Handles Me.Validating
Me.TextMaskFormat = MaskFormat.ExcludePromptAndLiterals
If Me.Text.Contains(" ") Or Me.Text.EndsWith(" ") Or Me.Text.StartsWith(" ") Then
Me.Text.Replace(" ", "")
End If
If Me.Text.Count.Equals(10) Or Me.MaskCompleted.Equals(True) Then
Me.BackColor = Color.LightGreen
Me.Text = Me.Text.TrimEnd
ElseIf Me.Text = "" Then
Me.BackColor = Color.White
Else
Me.BackColor = Color.LightCyan
End If
End Sub
Now, I'm trying to make something better and using C#.
Can someone help me? I mean, just give me a light, because I'm stuck!
You can make it like this :
public class CustomMaskedBox : MaskedTextBox
{
public CustomMaskedBox()
{
this.MaskInputRejected += CustomMaskedBox_MaskInputRejected;
this.Enter += CustomMaskedBox_Enter;
this.Leave += CustomMaskedBox_Leave;
}
void CustomMaskedBox_Leave(object sender, EventArgs e)
{
if (this.MaskFull)
{
this.BackColor = Color.LightGreen;
}
else
{
this.Mask = "(00) 0000-0000";
this.BackColor = Color.LightGreen;
}
if (!this.MaskCompleted)
{
this.BackColor = Color.LightCoral;
}
}
void CustomMaskedBox_Enter(object sender, EventArgs e)
{
this.BackColor = Color.LightBlue;
}
void CustomMaskedBox_MaskInputRejected(object sender, MaskInputRejectedEventArgs e)
{
if (this.MaskFull)
{
this.Mask = "(00) 0000-00000";
this.BackColor = Color.LightYellow;
}
}
}
You are looking for this I think( where maskedTextBox1 is control on form): So when the form starts it defaults to the Mask of
this.maskedTextBox1.Mask = "(00) 0000-0000";
When the user enters the values and the Mask is full then you can change the mask again:
private void maskedTextBox1_KeyDown(object sender, KeyEventArgs e)
{
if (this.maskedTextBox1.MaskFull)
{
this.maskedTextBox1.Mask = "(00) 0000-00000";
}
}
You can customise the key press/key down events to pick up the values dynamically.
thanks for the answers. I tried something and it's working.
It's use colors to identify if the field are Right or not. It also modify the mask.
Most part of it are in the Leave Event.
Think:
User type a number with 10 digits (00) 0000-0000
User leave the field
Then, the User enter again in the field and add a new digit (00)
0000-00000
User leave the field
Again, the user enter in the field and remove some digit (00)
0000-0000
The EVENT LEAVE can handle with this. I just like to know how can I do it in a "Professional Way",
I mean, this MaskedTextBox will be a part of a Class with others Custom Controls, so...there's a better way to do something like I did?
Here's the code that I made, and again, thanks guys!!
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace MaskedTextBox
{
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
}
private void maskedTextBox1_MaskInputRejected(object sender, MaskInputRejectedEventArgs e)
{
if (maskedTextBox1.MaskFull)
{
maskedTextBox1.Mask = "(00) 0000-00000";
maskedTextBox1.BackColor = Color.LightYellow;
}
}
private void maskedTextBox1_Enter(object sender, EventArgs e)
{
maskedTextBox1.BackColor = Color.LightBlue;
}
private void maskedTextBox1_Leave(object sender, EventArgs e)
{
if (maskedTextBox1.MaskFull)
{
maskedTextBox1.BackColor = Color.LightGreen;
}
else
{
maskedTextBox1.Mask = "(00) 0000-0000";
maskedTextBox1.BackColor = Color.LightGreen;
}
if (!maskedTextBox1.MaskCompleted)
{
maskedTextBox1.BackColor = Color.LightCoral;
}
}
}
}

Mousewheel scroll down event in C# winform programmatically done

I am trying do image slide show with picturebox Control and a trackbar. The trackbar gets minimum and maximum value corresponds to the number of images to show. I use a timer to get interval period for the slide along with trackbar valuechange.
Now, here is the main thing for each image in the picturebox I'm drawing a rectangle box over the image.
I am not able to draw on the first image when the form get load with first image. But I could do if I scroll the mouse wheel.
I need help to trigger the mouse wheel scroll event once after the first image get loaded.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace test
{
public partial class Form1 : Form
{
public event MouseEventHandler MouseWheel;
//MouseEventArgs k = new MouseEventArgs(MouseButtons.Middle,0,0,-1);
string[] pics = { "C:\\Downloads\\folder_picture_green.png", "C:\\Downloads\\Aetherpal.ico", "C:\\Downloads\\folder_picture_green.png" };
public Form1()
{
InitializeComponent();
this.trackBar1.Minimum = 0;
this.trackBar1.Maximum = (pics.Count() - 1);
//this.trackBar1.Maximum = 0;
imageupdate(0);
timer1.Start();
timer1.Interval = 3000;
this.MouseWheel += test;
this.MouseWheel(null, null);
}
private void test(object sender, System.Windows.Forms.MouseEventArgs e)
{
MessageBox.Show("Scrolled");
}
private void check(object sender, System.EventArgs e)
{
//if (Initializing == false) { return; }
if(this.trackBar1.Value < this.trackBar1.Maximum )
this.trackBar1.Value += 1;
else
timer1.Stop();
}
private void Valuechange(object sender, System.EventArgs e)
{
imageupdate(this.trackBar1.Value);
if(this.trackBar1.Value < this.trackBar1.Maximum)
timer1.Start();
}
private void imageupdate(int k)
{
this.pictureBox1.Refresh();
this.pictureBox1.Image = new Bitmap(pics[k]);
Pen blackPen = new Pen(Color.Blue, 5);
this.pictureBox1.Refresh();
using (Graphics g = this.pictureBox1.CreateGraphics())
{
g.DrawRectangle(blackPen, 10, 10, 100, 50);
}
}
}
}
You can add this code to your form to scroll your form (of course with MouseWheel):
private void Wheel(int ticks, bool down){
//WM_MOUSEWHEEL = 0x20a
Message msg = Message.Create(Handle, 0x20a, new IntPtr((down ? -1 : 1)<<16), new IntPtr(MousePosition.X + MousePosition.Y << 16));
for(int i = 0; i < ticks; i++)
WndProc(ref msg);
}
//Use it
Wheel(120,true);//Wheel down
Wheel(120,false);//Wheel up
NOTE: I can see you define a MouseWheel event in your own form. This will hide the base MouseWheel event, I don't think you have any reason to do this, your own MouseWheel can't work as the base one, you have to catch the win32 message and raise it yourself, we should use the base MouseWheel event instead. (Maybe you thought there isn't any MouseWheel event in your form class?)

Categories

Resources