我尝试将正在使用的Windows桌面应用程序中的文本放置到剪贴板上,但出现了一些我不理解的行为。
我使用的函数如下:
bool Clipboard::CopyText(const XStringW& txt)
{
size_t memsize = sizeof(wchar_t) * (txt.Length() + 1);
HGLOBAL glob = GlobalAlloc(GMEM_MOVEABLE, memsize);
if (glob != NULL)
{
void* mem = GlobalLock(glob);
if (mem != NULL)
{
memcpy(mem, (LPCWSTR) txt, memsize);
GlobalUnlock(glob);
HANDLE handle = NULL;
if (OpenClipboard(NULL))
{
EmptyClipboard();
handle = SetClipboardData(CF_UNICODETEXT, glob);
ASSERT(handle != NULL);
CloseClipboard();
}
return handle != NULL;
}
else
字符串else
之后发生的事情并不特别重要。
如果我执行上面的代码块,一切实际上都像它应该的那样工作。这对我来说很奇怪,因为根据documentation:
如果应用程序在hwnd设置为NULL的情况下调用OpenClipboard,则EmptyClipboard将剪贴板所有者设置为NULL;这导致SetClipboardData失败。
但我发现它的工作,因为它应该。
但是,我只是添加了EmptyClipboard()
作为实验。在此之前,我的代码无法正常工作。假设我从Word文档中放置文本"Hello"
。然后我从应用程序中复制了一个数字999
。如果我尝试粘贴到Excel或Word(例如),它会粘贴"Hello"
。但是,如果我在Excel中选择"Paste Special"
并粘贴为文本,它将粘贴"999"
。因此,它将工作,但只有当使用非默认粘贴。
如果我添加EmptyClipboard()
(按照我上面的代码),它可以完美地工作。它清除了之前存在的东西。但根据文件,应该不会。
有人能帮我理解吗?
2条答案
按热度按时间mlmc2os51#
我不知道该如何回答这个问题,除了:
“因为文件上是这么说的。”tm
就这样吧文档和其中提供的示例明确指出,您必须调用,以便 *(伪代码):
字符串
上面还写着:“在调用OpenClipboard * 之前,请先使用窗口的适当句柄 * 调用EmptyClipboard *”。
做不到这一点,然后想知道为什么它不起作用是一个挫折的练习。
::OpenClipboard
,但在此不适用。m528fe3b2#
这更像是一个猜测,而不是一个正确的答案,但我做了几个测试,发现了有趣的结果。我有一个假设,它的工作方式取决于你调用它的线程类型。
例如,如果您从无窗口线程/进程调用
OpenClipboard(NULL)
,它应该仍然工作,并给予您访问剪贴板。这是合乎逻辑的,因为您实际上不能传递任何有效的HWND
,因为您没有任何有效的HWND
。但是如果你试图从一个实际上有活动的、可见的窗口的线程/进程调用
OpenClipboard(NULL)
,它 * 应该 * 失败,因为你只是懒惰而没有传递你手上肯定有的HWND
。这是它应该工作的方式,正如我所看到的。然而,看起来,即使他们最初有这个计划,在某些时候,Windows开发人员只是因为一些未公开的原因而放弃了它,并使
OpenClipboard(NULL)
工作,不管你是否有Windows,没有更新文档。