网站首页 > 教程分享 正文
这几天使用winform开发一个小工具,用了datagridview,但是发现当时使用复制时候,会弹出报错。
经过分析,理解 Clipboard并没办法 COM,没办法。
首先想到办法,那就是拦截 复制功能,正常来说,操作都是 按Ctrl +C。
那就直接拦截 按键操作,可是当用户处于编辑状态情况,不能拦截,需要还是正常操作。
首先需要操作剪切板,又不能使用Clipboard ,那唯一办法就是自己写api调用。分析官方文档。然后使用.NET调用
完整代码如下
internal class WindowsClipboard
{
[DllImport("user32.dll", SetLastError = true)]
private static extern bool OpenClipboard(IntPtr hWndNewOwner);
[DllImport("user32.dll", SetLastError = true)]
private static extern bool CloseClipboard();
[DllImport("user32.dll", SetLastError = true)]
private static extern bool EmptyClipboard();
[DllImport("kernel32.dll")]
private static extern IntPtr GlobalAlloc(uint uFlags, UIntPtr dwBytes);
[DllImport("kernel32.dll")]
private static extern IntPtr GlobalLock(IntPtr hMem);
[DllImport("kernel32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool GlobalUnlock(IntPtr hMem);
[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr SetClipboardData(uint uFormat, IntPtr hMem);
private const uint CF_UNICODETEXT = 13;
private const uint GMEM_MOVEABLE = 0x0002;
private const uint GMEM_ZEROINIT = 0x0040;
public static void SetText(string text)
{
if (!OpenClipboard(IntPtr.Zero))
{
throw new Exception(#34;打开剪贴板失败 (错误代码: {Marshal.GetLastWin32Error()})");
}
try
{
EmptyClipboard();
// 计算字节长度(包含终止空字符)
var bufferSize = (text.Length + 1) * 2;
var hGlobal = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, (UIntPtr)bufferSize);
if (hGlobal == IntPtr.Zero)
{
throw new Exception("内存分配失败");
}
try
{
var pGlobal = GlobalLock(hGlobal);
if (pGlobal == IntPtr.Zero)
{
throw new Exception("内存锁定失败");
}
try
{
// 将字符串复制到非托管内存
var bytes = Encoding.Unicode.GetBytes(text);
Marshal.Copy(bytes, 0, pGlobal, bytes.Length);
}
finally
{
GlobalUnlock(hGlobal);
}
if (SetClipboardData(CF_UNICODETEXT, hGlobal) == IntPtr.Zero)
{
throw new Exception(#34;设置剪贴板数据失败 (错误代码: {Marshal.GetLastWin32Error()})");
}
// 成功设置后,hGlobal 所有权已转移给剪贴板
hGlobal = IntPtr.Zero;
}
finally
{
if (hGlobal != IntPtr.Zero)
{
GlobalFree(hGlobal);
}
}
}
finally
{
CloseClipboard();
}
}
[DllImport("kernel32.dll")]
private static extern IntPtr GlobalFree(IntPtr hMem);
}
使用时候即
WindowsClipboard.SetText(clipboardText);
经过测试,aot发布后可以使用
处理DataGridView中的拦截和数据
protected override void OnKeyDown(KeyEventArgs e)
{
if (e.KeyCode == Keys.C && e.Control)
{
if (!this.IsCurrentCellInEditMode)
{
this.EndEdit();
if (this.SelectedCells.Count == 0)
return;
// 获取所有选中的单元格并按行列排序
var clipboardText = string.Join(Environment.NewLine,
this.SelectedCells.Cast<DataGridViewCell>()
.GroupBy(c => c.RowIndex)// 按行分组
.OrderBy(g => g.Key)// 按行号排序
.Select(g => string.Join("\t",
g.OrderBy(c => c.ColumnIndex)
.Select(c => c.FormattedValue?.ToString() ?? "")))); // 使用格式化后的值
WindowsClipboard.SetText(clipboardText);
return;
}
}
base.OnKeyDown(e);
}
保存发布后完全没问题
猜你喜欢
- 2025-05-03 CommunityToolkit.Mvvm:ObservableProperty 属性生成器深度解析
- 2025-05-03 C#操作SQL数据库(c# sqlserver)
- 2025-05-03 DataGridView在真实上位机项目中是如何使用的?
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- css导航条 (66)
- sqlinsert (63)
- js提交表单 (60)
- param (62)
- parentelement (65)
- jquery分享 (62)
- check约束 (64)
- curl_init (68)
- sql if语句 (69)
- import (66)
- chmod文件夹 (71)
- clearinterval (71)
- pythonrange (62)
- 数组长度 (61)
- javafx (59)
- 全局消息钩子 (64)
- sort排序 (62)
- jdbc (69)
- php网页源码 (59)
- assert h (69)
- httpclientjar (60)
- postgresql conf (59)
- winform开发 (59)
- mysql数字类型 (71)
- drawimage (61)
本文暂时没有评论,来添加一个吧(●'◡'●)