C# 在窗体打开时将光标更改为十字(代码段工具)
我正在尝试实现一个像“Gyazo”这样的软件,一个截图的代码片段工具。程序开始(屏幕上没有显示任何内容,除了光标更改),用户单击点A,然后拖动到点B(绘制一个透明矩形),释放鼠标,然后保存屏幕截图并关闭程序 我画那个透明矩形的方法是,我重新调整一个透明度为30%的窗体的大小和位置。所以光标永远不会在表单上!为了更改光标,因为它位于表单之外,我尝试使用:C# 在窗体打开时将光标更改为十字(代码段工具),c#,winforms,C#,Winforms,我正在尝试实现一个像“Gyazo”这样的软件,一个截图的代码片段工具。程序开始(屏幕上没有显示任何内容,除了光标更改),用户单击点A,然后拖动到点B(绘制一个透明矩形),释放鼠标,然后保存屏幕截图并关闭程序 我画那个透明矩形的方法是,我重新调整一个透明度为30%的窗体的大小和位置。所以光标永远不会在表单上!为了更改光标,因为它位于表单之外,我尝试使用: [DllImport("user32.dll")] static extern bool SetSystemCursor(IntPtr hcur
[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可以。看起来几乎是零透明度。我必须更改点
,手
,加载
,并将所有游标设置为交叉
,然后如何恢复它们,因为它们都被覆盖为交叉
?您已删除我的游标..:-(现在我所有的游标都乱七八糟了,我找到了解决游标问题的方法。有一个函数可以将所有游标重置回旧状态。当你停止应用程序时,它将不起作用