Colloring panels with mousemove - c#

I have create a field of small panels on a form and I want the user to be able to color these panels. To color them you have to simpely click the panel, this works. Now I want to be able to let the use click a panel and drag over other panels to color more panels at once.
I have added the mousedown and mouseup event to all panels to set a boolean. The I use the mousemove event to color the panels. Yet only the first panel gets collored.
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;
using System.Diagnostics;
namespace Application
{
public partial class Form1 : Form
{
private const int dim = 25;
private int cols;
private int rows;
private bool mouse_down = false;
private sbyte fill = -1;
private Panel pnlTmp;
public Form1()
{
InitializeComponent();
this.buildGrid();
}
/// <summary>
/// Rebuild the grid to fit the screen.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void toolStripMenuItem2_Click(object sender, EventArgs e)
{
this.buildGrid();
}
/// <summary>
/// Build the grid to fit the screen.
/// </summary>
private void buildGrid()
{
panel1.Controls.Clear();
cols = int.Parse(Math.Floor((double)panel1.Width / dim).ToString());
rows = int.Parse(Math.Floor((double)panel1.Height / dim).ToString());
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
Panel pnl = new Panel();
pnl.BorderStyle = BorderStyle.FixedSingle;
pnl.Width = dim;
pnl.Height = dim;
pnl.Location = new Point(j * 25 + 1, i * 25 + 1);
pnl.Name = string.Format("pnl-{0}-{1}", j, i);
pnl.MouseDown += new MouseEventHandler(pnl_MouseDown);
pnl.MouseUp += new MouseEventHandler(pnl_MouseUp);
pnl.MouseMove += new MouseEventHandler(pnl_MouseHover);
panel1.Controls.Add(pnl);
}
}
}
void pnl_MouseHover(object sender, EventArgs e)
{
if (mouse_down)
{
Panel p = (Panel)sender;
if (p != pnlTmp)
{
if (fill == -1)
fill = (p.BackColor == SystemColors.Control) ? (sbyte)1 : (sbyte)0;
if (fill == 1)
p.BackColor = Color.Blue;
else
p.BackColor = SystemColors.Control;
Debug.WriteLine(p.Name);
}
pnlTmp = p;
}
}
void pnl_MouseDown(object sender, MouseEventArgs e)
{
Debug.WriteLine("true");
mouse_down = true;
}
void pnl_MouseUp(object sender, MouseEventArgs e)
{
Debug.WriteLine("false");
mouse_down = false;
fill = -1;
}
private void panel1_MouseLeave(object sender, EventArgs e)
{
//mouse_down = false;
//fill = -1;
}
}
}
I have tried debugging the application and the result was that only the first panel keeps firing the event, even if I am moving over other panels.
Could someone tell me why this is?

Your problem is caused by a feature called "mouse capture". It is controlled by the Control.Capture property. The default behavior is that it is turned on automatically in the OnMouseDown() method, before it fires the MouseDown event.
Mouse capture forces all mouse events to be directed to the window that you clicked, even if you move the mouse outside of the window. Which is why you only ever get the MouseMove and MouseUp events for the panel that you clicked on. It is important in a number of scenarios, particularly to reliably generate the Click and MouseUp events.
The workaround is to simply turn the capture back off in your MouseDown event handler:
void pnl_MouseDown(object sender, MouseEventArgs e) {
((Control)sender).Capture = false;
}
Do note that you now have a new problem, your "mouse_down" variable is no longer reliable. If you move the mouse outside of any panel, or outside of the form, and release the mouse then the MouseUp event is sent to the wrong window and your mouse_down variable remains set to true even though the mouse is no longer down. You lost the guarantee provided by the capture feature. You solve that problem by checking the button state in your MouseMove event handler, like this:
private void pnl_MouseMove(object sender, MouseEventArgs e) {
if (e.Button == MouseButtons.Left) {
// etc...
}
}
Beware that I fixed your incorrect pnl_MouseHover event handler and renamed it to pnl_MouseMove. I can see how you ended up making this mistake, but it possibly did prevent you from discovering this solution yourself. Careful with that axe Eugene ;)

Related

Zooming in ComboBox not working as expected

I have an application that scans an image to display on the application. After the image is scanned, I have the option to zoom the image. There's a combo box on the application that display the zoom percentage as well.
I can zoom fine using my mouse wheel and the combo box % changes accordingly which is fine. The problem happens if I manually select the combo box and select a zoom percentage, say 50%, then there's no changes at all.
Code:
private void ImageBox_ZoomLevelsChanged(object sender, EventArgs e)
{
this.FillZoomLevels();
}
private void ZoomComboBox_Click(object sender, EventArgs e)
{
}
private void FillZoomLevels()
{
ZoomComboBox.Items.Clear();
foreach (int zoom in ImageBox.ZoomLevels)
ZoomComboBox.Items.Add(string.Format("{0}%", zoom));
}
Am I doing anything wrong? Appreciate any help.
When there is more than one control on the Panel, and the ScrollBars are shown, the MouseWheel event of the Panel would be raised, but if there's only a PictureBox on the Panel whose Image large enough to make the panel's ScrollBars visible, then the MouseWheel event of the Panel won't be raised, instead, the Form's MouseWheel event fires.
In the following sample, I just add a PictureBox onto the Panel without any other controls added, set a large Image to the PictureBox which make the Panel's ScrollBars invisible, since there's only one control on the panel, the MouseWheel event of the Panel won't be raised, but the Form's MouseWheel event be raised, we handle this event instead, handle the Form's KeyDown and KeyUp events as well.
Furthermore, set the SizeMode of the PictureBox to StretchImage instead of AutoSize, thus when we change the size of the PictureBox, the Image in the PictureBox will resize to fit the PictureBox.
The PictureBox.Scale() method won't help you in this screnario, change the size of the PictureBox instead.
public partial class Form4 : Form
{
public Form4()
{
InitializeComponent();
}
bool ctrlKeyDown;
bool shiftKeyDown;
private void Form4_Load(object sender, EventArgs e)
{
this.ctrlKeyDown = false;
this.shiftKeyDown = false;
//If there's only PictureBox control on the panel, the MouseWheel event of the form raised
//instead of the MouseWheel event of the Panel.
this.MouseWheel += new MouseEventHandler(Form4_MouseWheel);
this.KeyDown += new KeyEventHandler(Form4_KeyDown);
this.KeyUp += new KeyEventHandler(Form4_KeyUp);
//this is important for zooming the image
this.pictureBox2.SizeMode = PictureBoxSizeMode.StretchImage;
}
void Form4_KeyUp(object sender, KeyEventArgs e)
{
this.ctrlKeyDown = e.Control;
this.shiftKeyDown = e.Shift;
}
void Form4_KeyDown(object sender, KeyEventArgs e)
{
this.ctrlKeyDown = e.Control;
this.shiftKeyDown = e.Shift;
}
void Form4_MouseWheel(object sender, MouseEventArgs e)
{
bool IsGoUp = e.Delta > 0 ? true : false;
if (this.ctrlKeyDown)
{
if (IsGoUp && this.panel1.HorizontalScroll.Value > 5)
{
this.panel1.HorizontalScroll.Value -= 5;
}
if (!IsGoUp && this.panel1.HorizontalScroll.Value < this.panel1.HorizontalScroll.Maximum - 5)
{
this.panel1.HorizontalScroll.Value += 5;
}
}
else if (this.shiftKeyDown)
{
int hStep = (int)(this.pictureBox2.Image.Width * 0.02);
int vStep = (int)(this.pictureBox2.Image.Height * 0.02);
if (IsGoUp)
{
this.pictureBox2.Width += hStep;
this.pictureBox2.Height += vStep;
}
else
{
this.pictureBox2.Width -= hStep;
this.pictureBox2.Height -= vStep;
}
}
else
{
if (IsGoUp && this.panel1.VerticalScroll.Value > 5)
{
this.panel1.VerticalScroll.Value -= 5;
}
if (!IsGoUp && this.panel1.VerticalScroll.Value < this.panel1.VerticalScroll.Maximum - 5)
{
this.panel1.VerticalScroll.Value += 5;
}
}
}
}

C# WPF mouse click event

I'm using C# with WPF. I have a grid of buttons and I need to do the following: If the user presses one button, moves the cursor and releases it on another button, the content of the first button is moved to the other one, something like dragging.
I tried using The previewmousedown and the previewmouseup button events to know which button the mouse is pressed on and which button it is released on but the previewmouseup event is fired also on the button the mouse is pressed on (not on the one the mouse is released on).
Any ideas about how to implement this in other ways, please? Thanks a lot in advance.
The easiest way to do drag & drop is with the built-in DragDrop API. Here's a proof of concept for you, where buttons can be clicked normally *and* dragged to swap their content.
If you want to change the behavior so the content is copied or moved (instead of swapped), just change the lines under the comment in OnButtonDrop.
ButtonDragging.xaml:
<Window x:Class="WpfTest2.ButtonDragging"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<DockPanel LastChildFill="True">
<Label x:Name="_statusLabel" DockPanel.Dock="Bottom" Content=" " />
<Grid x:Name="_grid" />
</DockPanel>
</Window>
ButtonDragging.xaml.cs:
public partial class ButtonDragging
{
private Button _mouseDownButton;
private Point _mouseDownLocation;
public ButtonDragging()
{
InitializeComponent();
BuildButtonGrid();
}
private void BuildButtonGrid()
{
const int rows = 5;
const int columns = 5;
var starLength = new GridLength(1d, GridUnitType.Star);
for (var i = 0; i < rows; i++)
_grid.RowDefinitions.Add(new RowDefinition { Height = starLength });
for (var i = 0; i < columns; i++)
_grid.ColumnDefinitions.Add(new ColumnDefinition { Width = starLength });
for (var i = 0; i < rows; i++)
{
for (var j = 0; j < columns; j++)
{
var button = new Button { Content = $#"({i}, {j})", AllowDrop = true };
Grid.SetColumn(button, i);
Grid.SetRow(button, j);
button.PreviewMouseMove += OnButtonMouseMove;
button.PreviewMouseLeftButtonDown += OnButtonLeftButtonDown;
button.PreviewMouseLeftButtonUp += OnButtonLeftButtonUp;
button.Drop += OnButtonDrop;
button.Click += OnButtonClick;
button.LostMouseCapture += OnButtonLostMouseCapture;
_grid.Children.Add(button);
}
}
}
private void OnButtonClick(object sender, RoutedEventArgs e)
{
_statusLabel.Content = $#"You clicked {(sender as Button)?.Content}!";
}
private void ClearPendingDrag()
{
_mouseDownButton = null;
_mouseDownLocation = default(Point);
}
private void OnButtonDrop(object sender, DragEventArgs e)
{
ClearPendingDrag();
var source = e.Data.GetData(typeof(object)) as Button;
if (source == null)
return;
var target = (Button)sender;
if (target == source)
return;
var sourceContent = source.Content;
var targetContent = target.Content;
// As a proof of concept, this swaps the content of the source and target.
// Change as necessary to get the behavior you want.
target.Content = sourceContent;
source.Content = targetContent;
_statusLabel.Content = $#"You swapped {sourceContent} with {targetContent}!";
}
private void OnButtonLeftButtonDown(object sender, MouseButtonEventArgs e)
{
var button = (Button)sender;
_mouseDownButton = button;
_mouseDownLocation = e.GetPosition(button);
if (!Mouse.Capture(button, CaptureMode.SubTree))
ClearPendingDrag();
}
private void OnButtonLeftButtonUp(object sender, MouseButtonEventArgs e)
{
ClearPendingDrag();
}
private void OnButtonMouseMove(object sender, MouseEventArgs e)
{
if (_mouseDownButton == null)
return;
var position = e.GetPosition(_mouseDownButton);
var distance = position - _mouseDownLocation;
if (Math.Abs(distance.X) > SystemParameters.MinimumHorizontalDragDistance ||
Math.Abs(distance.Y) > SystemParameters.MinimumVerticalDragDistance)
{
var button = (Button)sender;
var data = new DataObject(typeof(object), button);
data.SetData("Source", sender);
DragDrop.DoDragDrop(button, data, DragDropEffects.Move);
ClearPendingDrag();
}
}
private void OnButtonLostMouseCapture(object sender, MouseEventArgs e)
{
ClearPendingDrag();
}
}
Note that there are probably some third-party (and open source) drag and drop solutions out there that are more MVVM-friendly. It's worth checking out, but this should get you a minimum viable deliverable.
Take a look at this blog post. This is the best drag and drop article I read online.
From the link below here are the series of events for a drag and drop operation:
Dragging is initiated by calling the DoDragDrop method for the source control.
The DoDragDrop method takes two parameters:
data, specifying the data to pass
allowedEffects, specifying which operations (copying and/or moving) are allowed
A new DataObject object is automatically created.
This in turn raises the GiveFeedback event. In most cases you do not need to worry about the GiveFeedback event, but if you wanted to display a custom mouse pointer during the drag, this is where you would add your code.
Any control with its AllowDrop property set to True is a potential drop target. The AllowDrop property can be set in the Properties window at design time, or programmatically in the Form_Load event.
As the mouse passes over each control, the DragEnter event for that control is raised. The GetDataPresent method is used to make sure that the format of the data is appropriate to the target control, and the Effect property is used to display the appropriate mouse pointer.
If the user releases the mouse button over a valid drop target, the DragDrop event is raised. Code in the DragDrop event handler extracts the data from the DataObject object and displays it in the target control.
To detect a mouse Drag operation on the source, source control needs to subscribe to MouseLeftButtonDown and MouseMove.
void Window1_Loaded(object sender, RoutedEventArgs e)
{
this.DragSource.PreviewMouseLeftButtonDown += new MouseButtonEventHandler(DragSource_PreviewMouseLeftButtonDown);
this.DragSource.PreviewMouseMove += new MouseEventHandler(DragSource_PreviewMouseMove);
}
To prevent from starting a false drag & drop operation where the user accidentally drags, you can use SystemParameters.MinimumHorizontalDragDistance and SystemParameters.MinimumVerticalDragDistance.
void DragSource_PreviewMouseMove(object sender, MouseEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed && !IsDragging)
{
Point position = e.GetPosition(null);
if (Math.Abs(position.X - _startPoint.X) > SystemParameters.MinimumHorizontalDragDistance ||
Math.Abs(position.Y - _startPoint.Y) > SystemParameters.MinimumVerticalDragDistance)
{
StartDrag(e);
}
}
}
void DragSource_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
_startPoint = e.GetPosition(null);
}
Now you detect a drag operation, all you need to know is dropping into.
A simple scenario without any effect could be done like this.
private void StartDrag(MouseEventArgs e)
{
IsDragging = true;
DataObject data = new DataObject(System.Windows.DataFormats.Text.ToString(), "abcd");
DragDropEffects de = DragDrop.DoDragDrop(this.DragSource, data, DragDropEffects.Move);
IsDragging = false;
}
I think this can get you started. I really recommend to read the complete post from the link.
https://blogs.msdn.microsoft.com/jaimer/2007/07/12/drag-amp-drop-in-wpf-explained-end-to-end/

Windows Forms MouseEnter not firing after control moved

I want to color the BackColor property of a PictureBox when the mouse enters it.
I turn the BackColor into Yellow when then MouseEnter event fires, and I reset to transparent in MouseLeave.
Then when I click on a PictureBox, I change its position, so I also have a Move event which resets it in transparent.
The problem is, once I moved it, I need to enter the PictureBox twice with the mouse to fire the MouseEnter event!
It's a very graphical problem, so I uploaded a little video to show you what's happening, it surely will explain my problem better than I do.
I tried another way, changing the color not in MouseEnter but in MouseHover. In this case, it works well, except that I have a 500ms delay before firing the Move event, which is obviously not what I want.
I have no viable solution right now.
For the code, it's very simple, for the moment I have :
private void pictureBoxMouseUp(object sender, MouseEventArgs e)
{
    // I move the PictureBox here
}
 
private void pictureBoxMove(object sender, EventArgs e)
{
    (sender as PictureBox).BackColor = Color.Transparent;
}
 
private void pictureBoxMouseEnter(object sender, MouseEventArgs e)
{
    (sender as PictureBox).BackColor = Color.LightYellow;
}
 
private void pictureBoxMouseLeave(object sender, MouseEventArgs e)
{
    (sender as PictureBox).BackColor = Color.Transparent;
}
In the Designer.cs, my events for each PictureBox are like :
this.pictureBox2.MouseDown += new System.Windows.Forms.MouseEventHandler(this.pictureBoxMouseDown);
this.pictureBox2.MouseEnter += new System.EventHandler(this.pictureBoxMouseEnter);
this.pictureBox2.MouseLeave += new System.EventHandler(this.pictureBoxMouseLeave);
this.pictureBox2.MouseUp += new System.Windows.Forms.MouseEventHandler(this.pictureBoxMouseUp);
this.pictureBox2.Move += new System.EventHandler(this.pictureBoxMove);
EDIT : To answer my question, this is the code I use now : (comments are in french)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Diagnostics;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using EmoTEDTherapeute;
namespace ControlSceneImage {
public class SceneImage : PictureBox {
public static readonly int defaultWidth = 100;
public static readonly int defaultHeight = 100;
static readonly int activePbPosY; // Position en Y des scènes actives
static readonly Dictionary<string, Point> scenesPos = null; // Invariant, stocke la position initiale des PictureBox
static readonly List<Point>[] activeScenesPos = null; // Invariant, stocke les positions des PictureBox en fonction du nombre de scènes actives
static List<SceneImage> activeScenes = null;
const int maxActiveScenes = 5;
const int ecart = 80;
const int decalage = 15;
const int panelScenesWidth = 909;
const int panelScenesHeight = 154;
const int panelScenesLocationX = 35;
const int panelScenesLocationY = 36;
bool isActive;
static SceneImage() {
// Constructeur initialisant tous les membres statiques, n'est appelé qu'une seule fois, avant tout le reste
activePbPosY = (panelScenesLocationY + panelScenesHeight - (int)(0.6 * defaultHeight)) / 2;
scenesPos = new Dictionary<string, Point>();
activeScenesPos = new List<Point>[maxActiveScenes];
for (int i = 0; i < maxActiveScenes; i++) {
activeScenesPos[i] = CalcActiveScenesPos(i+1);
}
activeScenes = new List<SceneImage>();
}
public SceneImage() {
MouseEnter += new EventHandler(OnMouseEnter);
MouseDown += new MouseEventHandler(OnMouseDown);
MouseUp += new MouseEventHandler(OnMouseUp);
MouseLeave += new EventHandler(OnMouseLeave);
BorderStyle = BorderStyle.FixedSingle;
Size = new Size(defaultWidth, defaultHeight);
SizeMode = PictureBoxSizeMode.Zoom;
isActive = false;
}
private static List<Point> CalcActiveScenesPos(int nbActiveScenes) {
List<Point> ret = new List<Point>();
for (int i = 0; i < nbActiveScenes; i++) {
ret.Add(new Point((panelScenesLocationX + panelScenesWidth + ecart) / 2 + (int)((ecart + defaultWidth) * (i - nbActiveScenes / 2.0)) + decalage, activePbPosY));
}
return ret;
}
private void UpdateScenesPos() {
for(int i = 0; i < activeScenes.Count; i++) {
activeScenes[i].Location = activeScenesPos[activeScenes.Count - 1][i];
}
}
private void OnMouseEnter(object sender, EventArgs e) {
BackColor = Color.LightYellow;
Cursor = Cursors.Hand;
}
private void OnMouseDown(object sender, MouseEventArgs e) {
BorderStyle = BorderStyle.Fixed3D;
}
private void OnMouseUp(object sender, MouseEventArgs e) {
if (!scenesPos.ContainsKey(Name)) {
// Si ce n'est pas déjà fait, on stocke la position initiale de notre PictureBox
scenesPos.Add(Name, Location);
// Et on crée un Panel vide sous elle
Panel panel = new Panel();
panel.Location = Location;
panel.Size = Size;
panel.BorderStyle = BorderStyle.Fixed3D;
// On ajoute notre panel à notre form
Form1.AddInSeance(panel);
}
if (!isActive) {
activeScenes.Add(this);
} else {
Location = scenesPos[Name];
activeScenes.Remove(this);
}
isActive = !isActive;
UpdateScenesPos();
}
private void OnMouseLeave(object sender, EventArgs e) {
BorderStyle = BorderStyle.FixedSingle;
BackColor = Color.Transparent;
}
}
}
I use the same method as before, and for an unknown reason, now it works.
Thanks to all of you for helping me :)
The problem is that when you relocate the PictureBox, it will not receive the mouse leave event. Maybe you have already noticed that, that's why you set the BackColor in the Move event, too.
After you moved the control, it will not receive a second MouseEnter when you hover it again, only after you moved the mouse off and on again.
Try to send a mouse leave event manually (I haven't tested it):
private const int WM_MOUSELEAVE = 0x02A3;
[DllImport("user32.dll")]
private static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);
private void pictureBoxMouseUp(object sender, MouseEventArgs e)
{
// move the PictureBox...
SendMessage(((PictureBox)sender).Handle, WM_MOUSELEAVE, IntPtr.Zero, IntPtr.Zero);
}
I will avoid to move the PictureBox. Clearly your bug come from that.
When you move the component, the mouse is no more in it but it status is not updated.
You can swim deep in the windows form reference code or you can just says you have N small preview (the pictures on the bottom line) and one big preview (the upper one).
Create N+1 picture box and don't change it. Just change their image property.
When a small preview is clicked, switch it's image property with the big preview.
Also, a good MVC pattern is recommended.

Move Item from one cell to another

I have a tableLayoutPanel with 16 cells. 15 of the cells have controls. I want to be able to move the controls from one cell to another at runtime.
I have used
private void button15_Click(object sender, EventArgs e)
{
tableLayoutPanel1.Controls.Remove(button15);
tableLayoutPanel1.Controls.Add(button15, 3, 3);
}
This works well but i want to know if there is any better way to do this???
In Winforms, you can only move a control inside its parent (of course there are some exceptions to some controls which in fact don't have any Parent). So the idea here is if you want to move a control of your TableLayoutPanel, you have to set its Parent to your Form of another container when mouse is held down, when moving, the position of the control is in the new parent, after mouse is released, we have to set the Parent of the control to the TableLayoutPanel back, of course we have to find the drop-down cell position and use SetCellPosition method to position the control on the TableLayoutPanel, here is the demo code for you (works great), I use 2 Buttons in this demo, you can replace them with any control you want:
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
//This will prevent flicker
typeof(TableLayoutPanel).GetProperty("DoubleBuffered", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).SetValue(tableLayoutPanel1, true, null);
}
Point downPoint;
bool moved;
//This is used to store the CellBounds together with the Cell position
//so that we can find the Cell position later (after releasing mouse).
Dictionary<TableLayoutPanelCellPosition, Rectangle> dict = new Dictionary<TableLayoutPanelCellPosition, Rectangle>();
//MouseDown event handler for all your controls (on the tableLayoutPanel1)
private void Buttons_MouseDown(object sender, MouseEventArgs e) {
Control button = sender as Control;
button.Parent = this;
button.BringToFront();
downPoint = e.Location;
}
//MouseMove event handler for all your controls (on the tableLayoutPanel1)
private void Buttons_MouseMove(object sender, MouseEventArgs e) {
Control button = sender as Control;
if (e.Button == MouseButtons.Left) {
button.Left += e.X - downPoint.X;
button.Top += e.Y - downPoint.Y;
moved = true;
tableLayoutPanel1.Invalidate();
}
}
//MouseUp event handler for all your controls (on the tableLayoutPanel1)
private void Buttons_MouseUp(object sender, MouseEventArgs e) {
Control button = sender as Control;
if (moved) {
SetControl(button, e.Location);
button.Parent = tableLayoutPanel1;
moved = false;
}
}
//This is used to set the control on the tableLayoutPanel after releasing mouse
private void SetControl(Control c, Point position) {
Point localPoint = tableLayoutPanel1.PointToClient(c.PointToScreen(position));
var keyValue = dict.FirstOrDefault(e => e.Value.Contains(localPoint));
if (!keyValue.Equals(default(KeyValuePair<TableLayoutPanelCellPosition, Rectangle>))) {
tableLayoutPanel1.SetCellPosition(c, keyValue.Key);
}
}
//CellPaint event handler for your tableLayoutPanel1
private void tableLayoutPanel1_CellPaint(object sender, TableLayoutCellPaintEventArgs e) {
dict[new TableLayoutPanelCellPosition(e.Column, e.Row)] = e.CellBounds;
if (moved) {
if (e.CellBounds.Contains(tableLayoutPanel1.PointToClient(MousePosition))) {
e.Graphics.FillRectangle(Brushes.Yellow, e.CellBounds);
}
}
}
}
Remove Lock & set dock to none and move!

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