Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.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# 什么';OpenClipboard API的意义何在?_C#_.net_Winapi - Fatal编程技术网

C# 什么';OpenClipboard API的意义何在?

C# 什么';OpenClipboard API的意义何在?,c#,.net,winapi,C#,.net,Winapi,在尝试使用剪贴板时,我读取了很多被阻止的剪贴板,然后我尝试直接使用OpenClipboard()来捕获剪贴板,并能够从我的窗口使用它 public partial class Form1 : Form { public Form1() { InitializeComponent(); } [DllImport("user32.dll", SetLastError=true)] private static extern bool OpenClip

在尝试使用剪贴板时,我读取了很多被阻止的剪贴板,然后我尝试直接使用
OpenClipboard()
来捕获剪贴板,并能够从我的窗口使用它

public partial class Form1 : Form {
    public Form1() {
        InitializeComponent();
    }

    [DllImport("user32.dll", SetLastError=true)]
    private static extern bool OpenClipboard(IntPtr hWndNewOwner);
    [DllImport("user32.dll", SetLastError=true)]
    private static extern bool CloseClipboard();

    private int idx = 0;
    private void refresh_Tick(object sender, EventArgs e) {
        switch (idx++) {
        case 0:
                OpenClipboard(Handle);
                break;
        default:
                Clipboard.SetText(" ");
                break;
        }
    }
}
使用
SetText
时,我会得到一个臭名昭著的错误:

System.Windows.Forms.dll中首次出现“System.Runtime.InteropServices.ExternalException”类型的异常
其他信息:请求的剪贴板操作未成功

因此,问题是:

  • OpenClipboard()

  • OpenClipboard()
    的参数是什么?API的其余部分不需要任何窗口的句柄,那么为什么
    OpenClipboard()
    ?换句话说,剪贴板应该在进程之间共享,而不是在窗口之间共享——但我看不到为当前进程锁定剪贴板的方法

  • 我可以调用
    OpenClipboard(IntPtr.Zero)
    ,MSDN说:

    如果此参数为NULL,则打开的剪贴板与当前任务关联

    “任务”是什么意思

  • OpenClipboard()实际工作吗

    OpenClipboard()
    工作正常,但绝对不是您所展示的方式。它是一个原始的Win32 API。这是

    OpenClipboard()的参数是什么

    老实说,我对此不确定。通常我们只传递
    NULL
    aka
    IntPtr.Zero
    ,让它与当前任务关联。我猜它检索创建指定窗口的线程,然后将其与剪贴板关联

    什么是任务?这是我的理解。回到Win16时代,他们使用术语“任务”,而不是“线程”或“进程”。有一个函数用于
    GetCurrentTask()

    然后该函数被替换为
    GetCurrentProcess()
    GetCurrentThread()

    因为一次只有一个线程可以访问共享资源更合理,所以我认为“任务”实际上是指“线程”

    API的其余部分不需要任何窗口的句柄,那么为什么OpenClipboard()需要

    如果我上面的假设是正确的,即一次只能有一个线程访问剪贴板,那么Windows很可能会使用您以前使用
    OpenClipboard()
    指定的线程/窗口,直到您调用
    CloseClipboard()
    或线程/窗口无效。这就是为什么不需要一直指定
    HWND

    换句话说,剪贴板应该在进程之间共享,而不是在窗口之间共享——但我看不到为当前进程锁定剪贴板的方法

    它会锁定,尽管我不确定C#p/Invoke。如果您有权访问Win32/C开发工具包,请编译并运行以下代码:

    #include <conio.h>
    #include <Windows.h>
    
    int main()
    {
        OpenClipboard(GetForegroundWindow());
        _getch();
        return 0;
    }
    
    #包括
    #包括
    int main()
    {
    OpenClipboard(GetForegroundWindow());
    _getch();
    返回0;
    }
    

    并查看在其他程序中使用剪贴板时会发生什么情况。:)关闭控制台窗口进行恢复。

    如果我随意抛出API代码,但它不起作用,那是微软的错吗?这里有一个链接,链接到一个正确使用它的示例。你读它至少是想知道正确的方法吗?是的,OpenClipboard确实可以工作,它每天都在使用剪贴板的每个Windows应用程序中使用,文档精确地解释了如何使用它。参数是打开它的窗口的句柄。仅供参考:绝大多数WinAPI使用HWND。因为框架对您隐藏了这一点,并不意味着它们没有被使用。买佩佐德的书,你得把它扔掉。谷歌“c#剪贴板监听器”学习如何正确操作。阅读文档。它将告诉您将每个对OpenClipboard的调用与对CloseClipboard的调用进行匹配。如果没有阅读文档,您怎么会认为库已损坏?不调用
    CloseClipboard
    是一个相当大的问题。如果您阅读文档,本可以避免这种情况。将.net剪贴板类与原始Win32 API混合也是一个问题。这里有很多错误信息。如果您正在从剪贴板读取,则可以为OpenClipboard提供一个空句柄,但如果您打算写入(例如,
    SetClipboardData
    ),则必须使用您拥有的窗口句柄打开剪贴板。当另一个应用程序请求使用延迟渲染设置的格式时,Windows可能会发出
    WM_RENDERFORMAT
    消息,您需要对此作出响应。有关更多信息,请参阅
    SetClipboardData
    的备注。您不应该打开带有ForegroundWindow句柄的剪贴板,因为这些消息将被错误地发送到那里。