(winform)如何实现单个或多个picturebox的框选和拖动

时间:2021-09-29 16:15:48
RT。我现在想实现一个和windows桌面快捷方式图标框选类似的效果。即,我的form上有很多picturebox。用鼠标点击form拖动可以产生虚框,在虚框中的picturebox就算被选中(有选中效果),并能被拖动。此时若点击其他未被选中的picturebox,则选中新的最后一个被点击的picturebox(有选中效果),原来被选中的那些picturebox都恢复为未选中状态(取消选中效果)。总之,就和单个或多个windows桌面图标的选中、框选和拖动效果类似(form相当于桌面,picturebox相当于桌面图标)。请各位达人赐教。PS:表达能力有限,不知道说清楚没有。。。。。。

18 个解决方案

#1



public class MoveablePictureBox : PictureBox
{
    [System.Runtime.InteropServices.DllImport("user32.dll")]
    private static extern IntPtr SendMessage(IntPtr hWnd, int msg, int wparam, int lparam);
    protected override void OnMouseDown(MouseEventArgs e)
    {
        base.OnMouseDown(e);
        if (e.Button == MouseButtons.Left)//按下的是鼠标左键
        {
            Capture = false;//释放鼠标,使能够手动操作
            SendMessage(this.Handle, 0x00A1, 2, 0);//拖动窗体
        }
    }
}


以上代码,随便在你的哪个命名空间粘贴上去。编译一下项目。在工具栏中就多了一个MoveablePictureBox,使用这个,运行时候就可以拖动了。

#2


我是初学,1L的代码看不太懂,试试看,多谢了

#3


1楼代码是错的,那个是拖动窗体

#4


你需要自定义鼠标过程,然后动态绑定每个box的鼠标事件到自定义事件中,事件参数中有sender参数,那个就是你选中的box,然后你在事件中处理拖动效果,以及选中后,在其周围划线的效果

#5


其实移动单个picturebox我已经实现了,只是和1L的方法不同。但如何框选并同时移动多个picturebox呢?(即,移动时,多个被选中的picturebox的相对位置保持不变)

#6


哦。想框选
ControlPaint类下有绘制蚂蚁线的方法。你先自己看看,去吃饭。回来在关注。
拖动记录下鼠标位置,然后和picturebox的边缘求交集,有交集的就参与拖动。是这个意思吧。

#7


引用 6 楼 wuyazhe 的回复:
哦。想框选
ControlPaint类下有绘制蚂蚁线的方法。你先自己看看,去吃饭。回来在关注。
拖动记录下鼠标位置,然后和picturebox的边缘求交集,有交集的就参与拖动。是这个意思吧。

画框也基本实现了,问题是选中后,picturebox要有一个“已被选中”的效果(目前是用改变borderstyle来体现,不是很满意)。以及被选中的多个picturebox同时拖动,没有实现。

#8


等下发一些我现在的代码上来,大家看看怎么弄完善

#9


就按你想的,你吧你现在做好的发出来看看,否则回答的都是你不需要的。

#10


//以下实现单个图片的拖动
private Point downPoint; 
        private void picbox_MouseDown(object sender, MouseEventArgs e)
        {         
            if (e.Button == MouseButtons.Left)         
            downPoint = e.Location;
        }

        private void picbox_MouseMove(object sender, MouseEventArgs e)
        {
            //实现图片随鼠标拖动
            if (e.Button == MouseButtons.Left)
            {
                ((Control)sender).Location = new Point(
                    ((Control)sender).Location.X + e.X - downPoint.X,
                    ((Control)sender).Location.Y + e.Y - downPoint.Y);
            }

#11


//以下实现画蚂蚁线框(黑色头发博客里搜索来的代码)
using System;   
using System.Collections.Generic;   
using System.ComponentModel;   
using System.Data;   
using System.Drawing;   
using System.Text;   
using System.Windows.Forms;   
  
namespace AllTest   
{   
    public partial class Form11 : Form   
    {   
        bool MouseIsDown = false;   
        Rectangle MouseRect = Rectangle.Empty;    
        public Form11()   
        {   
            InitializeComponent();   
            this.MouseDown += new MouseEventHandler(frmMain_MouseDown);   
            this.MouseMove += new MouseEventHandler(frmMain_MouseMove);   
            this.MouseUp += new MouseEventHandler(frmMain_MouseUp);    
        }   
        void frmMain_MouseUp(object sender, MouseEventArgs e)   
        {   
            this.Capture = false;   
            Cursor.Clip = Rectangle.Empty;   
            MouseIsDown = false;   
            DrawRectangle();   
            MouseRect = Rectangle.Empty;   
        }   
        void frmMain_MouseMove(object sender, MouseEventArgs e)   
        {   
            if (MouseIsDown)   
                ResizeToRectangle(e.Location);   
        }   
        void frmMain_MouseDown(object sender, MouseEventArgs e)   
        {   
            MouseIsDown = true;   
            DrawStart(e.Location);   
        }   
        private void ResizeToRectangle(Point p)   
        {   
            DrawRectangle();   
            MouseRect.Width = p.X - MouseRect.Left;   
            MouseRect.Height = p.Y - MouseRect.Top;   
            DrawRectangle();   
        }   
        private void DrawRectangle()   
        {   
            Rectangle rect = this.RectangleToScreen(MouseRect);   
            ControlPaint.DrawReversibleFrame(rect, Color.White, FrameStyle.Dashed);   
        }   
        private void DrawStart(Point StartPoint)   
        {   
            this.Capture = true;   
            Cursor.Clip = this.RectangleToScreen(new Rectangle(0, 0, ClientSize.Width, ClientSize.Height));   
            MouseRect = new Rectangle(StartPoint.X, StartPoint.Y, 0, 0);   
        }    
    }   
}  

#12


最后的问题就是,“已被选中”的效果(试过在picturebox上画半透明长方形使picturebox变成半透明的,但因为我要同时实现picturebox的缩放功能,缩放后,半透明长方形就消失了,所以行不通)。以及被选中的多个picturebox同时拖动,要怎么实现呢?

#13


使用MouseDown MouseUp  和MouseMove 来控制。 
down 记录选中的框,和点击点
move 设置框的位置,跟随鼠标(需要计算鼠标移动的相对距离)
up放置

#14


路过学习,帮顶。

#15


自己顶一下,用手机上网不容易啊,各位大大们帮帮我吧

#16


好像还是没有好的方法,哎。我自己弄弄,改进一下再发代码大家看看

#17


这小哥的结帖率。。。。

#18


该回复于2010-12-20 10:09:01被版主删除

#1



public class MoveablePictureBox : PictureBox
{
    [System.Runtime.InteropServices.DllImport("user32.dll")]
    private static extern IntPtr SendMessage(IntPtr hWnd, int msg, int wparam, int lparam);
    protected override void OnMouseDown(MouseEventArgs e)
    {
        base.OnMouseDown(e);
        if (e.Button == MouseButtons.Left)//按下的是鼠标左键
        {
            Capture = false;//释放鼠标,使能够手动操作
            SendMessage(this.Handle, 0x00A1, 2, 0);//拖动窗体
        }
    }
}


以上代码,随便在你的哪个命名空间粘贴上去。编译一下项目。在工具栏中就多了一个MoveablePictureBox,使用这个,运行时候就可以拖动了。

#2


我是初学,1L的代码看不太懂,试试看,多谢了

#3


1楼代码是错的,那个是拖动窗体

#4


你需要自定义鼠标过程,然后动态绑定每个box的鼠标事件到自定义事件中,事件参数中有sender参数,那个就是你选中的box,然后你在事件中处理拖动效果,以及选中后,在其周围划线的效果

#5


其实移动单个picturebox我已经实现了,只是和1L的方法不同。但如何框选并同时移动多个picturebox呢?(即,移动时,多个被选中的picturebox的相对位置保持不变)

#6


哦。想框选
ControlPaint类下有绘制蚂蚁线的方法。你先自己看看,去吃饭。回来在关注。
拖动记录下鼠标位置,然后和picturebox的边缘求交集,有交集的就参与拖动。是这个意思吧。

#7


引用 6 楼 wuyazhe 的回复:
哦。想框选
ControlPaint类下有绘制蚂蚁线的方法。你先自己看看,去吃饭。回来在关注。
拖动记录下鼠标位置,然后和picturebox的边缘求交集,有交集的就参与拖动。是这个意思吧。

画框也基本实现了,问题是选中后,picturebox要有一个“已被选中”的效果(目前是用改变borderstyle来体现,不是很满意)。以及被选中的多个picturebox同时拖动,没有实现。

#8


等下发一些我现在的代码上来,大家看看怎么弄完善

#9


就按你想的,你吧你现在做好的发出来看看,否则回答的都是你不需要的。

#10


//以下实现单个图片的拖动
private Point downPoint; 
        private void picbox_MouseDown(object sender, MouseEventArgs e)
        {         
            if (e.Button == MouseButtons.Left)         
            downPoint = e.Location;
        }

        private void picbox_MouseMove(object sender, MouseEventArgs e)
        {
            //实现图片随鼠标拖动
            if (e.Button == MouseButtons.Left)
            {
                ((Control)sender).Location = new Point(
                    ((Control)sender).Location.X + e.X - downPoint.X,
                    ((Control)sender).Location.Y + e.Y - downPoint.Y);
            }

#11


//以下实现画蚂蚁线框(黑色头发博客里搜索来的代码)
using System;   
using System.Collections.Generic;   
using System.ComponentModel;   
using System.Data;   
using System.Drawing;   
using System.Text;   
using System.Windows.Forms;   
  
namespace AllTest   
{   
    public partial class Form11 : Form   
    {   
        bool MouseIsDown = false;   
        Rectangle MouseRect = Rectangle.Empty;    
        public Form11()   
        {   
            InitializeComponent();   
            this.MouseDown += new MouseEventHandler(frmMain_MouseDown);   
            this.MouseMove += new MouseEventHandler(frmMain_MouseMove);   
            this.MouseUp += new MouseEventHandler(frmMain_MouseUp);    
        }   
        void frmMain_MouseUp(object sender, MouseEventArgs e)   
        {   
            this.Capture = false;   
            Cursor.Clip = Rectangle.Empty;   
            MouseIsDown = false;   
            DrawRectangle();   
            MouseRect = Rectangle.Empty;   
        }   
        void frmMain_MouseMove(object sender, MouseEventArgs e)   
        {   
            if (MouseIsDown)   
                ResizeToRectangle(e.Location);   
        }   
        void frmMain_MouseDown(object sender, MouseEventArgs e)   
        {   
            MouseIsDown = true;   
            DrawStart(e.Location);   
        }   
        private void ResizeToRectangle(Point p)   
        {   
            DrawRectangle();   
            MouseRect.Width = p.X - MouseRect.Left;   
            MouseRect.Height = p.Y - MouseRect.Top;   
            DrawRectangle();   
        }   
        private void DrawRectangle()   
        {   
            Rectangle rect = this.RectangleToScreen(MouseRect);   
            ControlPaint.DrawReversibleFrame(rect, Color.White, FrameStyle.Dashed);   
        }   
        private void DrawStart(Point StartPoint)   
        {   
            this.Capture = true;   
            Cursor.Clip = this.RectangleToScreen(new Rectangle(0, 0, ClientSize.Width, ClientSize.Height));   
            MouseRect = new Rectangle(StartPoint.X, StartPoint.Y, 0, 0);   
        }    
    }   
}  

#12


最后的问题就是,“已被选中”的效果(试过在picturebox上画半透明长方形使picturebox变成半透明的,但因为我要同时实现picturebox的缩放功能,缩放后,半透明长方形就消失了,所以行不通)。以及被选中的多个picturebox同时拖动,要怎么实现呢?

#13


使用MouseDown MouseUp  和MouseMove 来控制。 
down 记录选中的框,和点击点
move 设置框的位置,跟随鼠标(需要计算鼠标移动的相对距离)
up放置

#14


路过学习,帮顶。

#15


自己顶一下,用手机上网不容易啊,各位大大们帮帮我吧

#16


好像还是没有好的方法,哎。我自己弄弄,改进一下再发代码大家看看

#17


这小哥的结帖率。。。。

#18


该回复于2010-12-20 10:09:01被版主删除