首页 文章

在表单打开时将光标更改为交叉(代码段工具)

提问于
浏览
4

我正在尝试实现像“Gyazo”这样的软件,这是一个截图的片段工具 . 程序开始(屏幕上没有任何内容,光标更改除外),用户点击A点,然后拖动到B点(绘制透明矩形),释放鼠标,然后屏幕截图被保存,程序关闭 .

我绘制透明矩形的方式是,我重新调整大小并重新定位具有30%透明度的表单 . 所以光标永远不会在窗体上!为了更改光标,因为它在表单之外,我尝试使用:

[DllImport("user32.dll")]
static extern bool SetSystemCursor(IntPtr hcur, uint id);
[DllImport("user32.dll")]
static extern IntPtr LoadCursor(IntPtr hInstance, int lpCursorName);
private int CROSS = 32515;
private const uint NORMAL = 32512;

//and then calling
SetSystemCursor(LoadCursor(IntPtr.Zero, CROSS), NORMAL);

我对这段代码的问题在于它确实是错误的 . 当窗体关闭时,光标不知道如何正确恢复光标 . 此外,从任务管理器关闭表单时还原光标是不可能的,对吗?

在这种情况下,您建议将光标改为交叉的其他方式是什么?

Edit: 只是为了澄清,因为我试过问一个类似的问题,之前被标记为this question的重复并且我删除了它,我想要做的是类似的,但有很多不同,因为在该问题中提供的答案,解决方案在答案中提供的是制作全屏无边框形式,将桌面的屏幕截图设置为该窗体的背景,然后从中裁剪矩形 . 首先,该解决方案是"freezes"屏幕,因为在裁剪发生时您只能看到桌面照片,其次,几乎不可能以这种方式处理多显示器设置 . 此外,它还有额外的不必要的工作 .

3 回答

  • 1

    尝试将它放在Program.cs文件中

    static class Program
    {
        [DllImport("user32.dll")]
        static extern bool SetSystemCursor(IntPtr hcur, uint id);
        [DllImport("user32.dll")]
        static extern IntPtr LoadCursor(IntPtr hInstance, int lpCursorName);
    
        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        private static extern Int32 SystemParametersInfo(UInt32 uiAction, UInt32
        uiParam, String pvParam, UInt32 fWinIni);
    
        private static uint CROSS = 32515;
        private static uint NORMAL = 32512;
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            SetSystemCursor(LoadCursor(IntPtr.Zero, (int)NORMAL), CROSS);
            //Also other pointers to CROSS if you want
            Application.Run(new Form1());
            SystemParametersInfo(0x0057, 0, null, 0);
        }
    }
    

    这将在应用程序结束或崩溃时将其恢复正常 .

    因此,如从Normal更改为Cross,您可以更改任何想要箭头的光标

    停止应用程序时,它将无法工作(Ctrl F5),因为这将跳过所有行 . 但是在发布应用程序后会完全运行 .

  • 0

    制作两个表格 . 一个用于拍摄全屏快照,另一个用于裁剪所需区域 . 选择区域后,将获取的值传递给包含图像的表单并保存 .

    我将举一个例子,你只需添加两个表单,而无需在设计中做任何事情

    Form_ScreenShot

    public delegate void CROP_PARAMS(Point pnt, Size sz);
    public partial class Form_ScreenShot : Form
    {
        Form_TransparentSelection transpSelect;
        PictureBox pBox;
        public Form_ScreenShot()
        {
            InitializeComponent();
            WindowState = FormWindowState.Maximized;
            FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
            pBox = new PictureBox() { Dock = DockStyle.Fill, Cursor = Cursors.Cross };
            pBox.MouseDown += pBox_MouseDown;
            Controls.Add(pBox);
    
            Bitmap bmp = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
            Graphics grp = Graphics.FromImage(bmp);
            grp.CopyFromScreen(0, 0, 0, 0, new Size(bmp.Width, bmp.Height), CopyPixelOperation.SourceCopy);
            pBox.Image = bmp;
    
        }
    
        void CropImage(Point startPoint, Size size)
        {
            Bitmap bmp = new Bitmap(size.Width, size.Height);
            Graphics grp = Graphics.FromImage(bmp);
            grp.DrawImage(pBox.Image, new Rectangle(0, 0, size.Width, size.Height), new Rectangle(startPoint, size), GraphicsUnit.Pixel);
            pBox.Image = bmp;
            bmp.Save("D:\\Check1.png", System.Drawing.Imaging.ImageFormat.Png);
        }
    
        void pBox_MouseDown(object sender, MouseEventArgs e)
        {
            transpSelect = new Form_TransparentSelection(e) {CropImage = CropImage};
            transpSelect.ShowDialog();
            Close();
        }
    
    }
    

    现在半透明选择表格

    Form_TransparentSelection

    public partial class Form_TransparentSelection : Form
    {
        PictureBox pbSelection;
        Point lastPoint;
        public CROP_PARAMS CropImage { get; set; }
        public Form_TransparentSelection(MouseEventArgs e)
        {
            InitializeComponent();
            WindowState = FormWindowState.Maximized;
            FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
            MouseMove += Form_TransparentSelection_MouseMove;
            MouseUp += Form_TransparentSelection_MouseUp;
            Cursor = Cursors.Cross;
    
            pbSelection = new PictureBox() { Size = MinimumSize = new Size(5, 5), Visible = false, BackColor = Color.LightGreen };
            Controls.Add(pbSelection);
    
            lastPoint = new Point(e.X, e.Y);
            pbSelection.Size = pbSelection.MinimumSize;
            pbSelection.Visible = true;
            pbSelection.Location = lastPoint;
    
            Opacity = .5;
            TransparencyKey = Color.LightGreen;
            BackColor = Color.Black;
        }
    
        void Form_TransparentSelection_MouseUp(object sender, MouseEventArgs e)
        {
            CropImage(pbSelection.Location, pbSelection.Size);
            Close();
        }
    
        void Form_TransparentSelection_MouseMove(object sender, MouseEventArgs e)
        {
            pbSelection.Width = e.X - lastPoint.X;
            pbSelection.Height = e.Y - lastPoint.Y;
        }
    }
    
  • -1

    在退出应用程序之前将光标设置为其默认值将解决该问题 . 这可以在 Form.Closing 事件中实现为:

    private void Form_Closing(object sender, System.ComponentModel.CancelEventArgs e)
    {
        // 'NORMAL' is the same constant that is in your code.
        SetSystemCursor(LoadCursor(IntPtr.Zero, NORMAL), NORMAL);
    }
    

    编辑:通过任务管理器中的"Kill Task"选项终止进程将触发 Form.Closing 事件 . 有no way来拦截一个 TerminateProcess() 调用,该调用与"Kill Process"选项一起使用 .

相关问题