Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/283.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在窗体打开时将光标更改为十字(代码段工具)_C#_Winforms - Fatal编程技术网

C# 在窗体打开时将光标更改为十字(代码段工具)

C# 在窗体打开时将光标更改为十字(代码段工具),c#,winforms,C#,Winforms,我正在尝试实现一个像“Gyazo”这样的软件,一个截图的代码片段工具。程序开始(屏幕上没有显示任何内容,除了光标更改),用户单击点A,然后拖动到点B(绘制一个透明矩形),释放鼠标,然后保存屏幕截图并关闭程序 我画那个透明矩形的方法是,我重新调整一个透明度为30%的窗体的大小和位置。所以光标永远不会在表单上!为了更改光标,因为它位于表单之外,我尝试使用: [DllImport("user32.dll")] static extern bool SetSystemCursor(IntPtr hcur

我正在尝试实现一个像“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);
我在这段代码中遇到的问题是它确实有缺陷。当窗体关闭时,光标不会变回正常状态。我不知道如何正确地还原光标。另外,当表单从任务管理器关闭时,不可能恢复光标,对吗

在这种情况下,您建议用什么其他方式将光标更改为十字


编辑:我只是想澄清一下,因为之前我试着问了一个类似的问题,这个问题被标记为重复的,我把它删除了,我想做的是类似的,但有很多不同,因为在这个问题提供的答案中,答案中提供的解决方案是制作一个全屏无边界表单,将桌面的屏幕截图设置为该窗体的背景,然后从中裁剪出一个矩形。首先,该解决方案会“冻结”屏幕,因为在裁剪过程中,您只会看到桌面的一张照片;其次,以这种方式处理多显示器设置几乎是不可能的。另外,它会做额外的和不必要的工作。

在退出应用程序之前将光标设置为默认值将解决此问题。这可以在
表单中实现。关闭
事件如下:

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);
}

编辑:通过任务管理器中的“终止任务”选项终止进程将触发
窗体。关闭
事件。需要截获一个
TerminateProcess()
调用,该调用与“Kill Process”选项一起使用。

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

我会给你一个例子,你只需要添加两个表单,而不需要做任何设计

表单_屏幕截图

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();
    }

}
现在是半透明的选择窗体

表格透明选择

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;
    }
}

试着把这个放到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);
    }
}
每当应用程序结束或崩溃时,这将使其恢复正常

所以,就像从法线更改为十字一样,您可以更改要指向箭头的任何光标


当您停止应用程序(Ctrl+F5)时,它将不起作用,因为这将跳过所有行。但在发布应用程序后将完全起作用。

我建议100%不透明度,并将屏幕复制到表单中,使其看起来不明显(也没有边框)。它似乎覆盖了所有的角落。这看起来和你一天前发布的问题一模一样,你已经得到了很多反馈。不要介意删除并重新发布完全相同的问题是多么粗鲁,是什么让你认为在回答方式上会有实质性的不同?在过去的24小时里,编程的状态并没有发生显著的变化。@YoryeNathan这不会达到我想做的,因为如果在拍摄屏幕时“冻结”屏幕,并且几乎不可能处理多监视器设置。我在很久以前看到过您建议的解决方案,以供将来参考:如果您不同意“关闭为重复”的处理方式,正确的后续行动是编辑该问题,详细解释您的问题实际上不是重复的原因,然后建议重新打开该问题。如果社区同意,问题将重新开始,不会丢失到目前为止的所有讨论,并且随着问题本身的改进(这显然不是在这里发生的……我们现在又回到了问题的起点)。就目前情况而言,出于同样的原因,你面临着这个问题再次被关闭的风险。“更多的工作”是一个无效的理由,因为选择做更少的工作会导致一个未解决的问题,否则你不会来这里。处理多屏幕设置也可以这样做(是的,它需要更多的工作)。以60帧/秒的速度刷新它也可以完成(虽然不是很多,但还需要做更多的工作)。如果这不适合您,您可能需要寻找一种不同于C的技术。当用户从任务管理器关闭应用程序时,不会触发该事件,因此我想完全避免这种情况,因为正如我在问题中所说,
SetSystemCursor(…)
可能是一段超级错误的代码,这可能会导致用户重新启动整个计算机,将光标恢复为normal@Shiro:需要澄清的是:
SetSystemCursor()
函数本身并不是“超级错误”,我很抱歉,但我在我的问题中提到,我不想通过拍摄背景截图来实现这一点,是不是因为要在多个监视器中使用?如果是这样,你可以在连接的监视器数量上使用0个不透明表格,这将更改所有监视器上的光标,然后进行裁剪。你想对这样的东西进行编辑吗?而且还可以防止UI冻结。但在完成拖动之前,您不能执行任何其他操作。但是0.01可以。看起来几乎是零透明度。我必须更改
加载
,并将所有游标设置为
交叉
,然后如何恢复它们,因为它们都被覆盖为
交叉
?您已删除我的游标..:-(现在我所有的游标都乱七八糟了,我找到了解决游标问题的方法。有一个函数可以将所有游标重置回旧状态。当你停止应用程序时,它将不起作用