我当前正在尝试在我的应用程序中使用 Windows 剪贴板及其通知。具体来说,我正在尝试订阅WM_CLIPBOARDUPDATE https://learn.microsoft.com/en-us/windows/win32/dataxchg/wm-clipboardupdate窗口消息通过使用AddClipboardFormatListener() https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-addclipboardformatlistener功能。之前,我一直在使用SetClipboardViewer() https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setclipboardviewer函数以便将我的窗口直接添加到剪贴板查看器链中。这一切都很好,我已经收到了相关消息WM_DRAWCLIPBOARD
and WM_DESTROYCLIPBOARD
当预期时。但是,我想避免继续使用剪贴板链,因为它非常不稳定。
我的理解是我完全能够收到WM_CLIPBOARDUPDATE
打电话后AddClipboardFormatListener()
。我还缺少另一个步骤吗?我需要做什么才能确保正确收到此消息?就目前情况而言,我在执行复制操作时没有收到它。
这是我的代码的简短示例:
WNDPROC 覆盖:
LRESULT CALLBACK ClipboardService::CallWndProc(int nCode, WPARAM wParam, LPARAM lParam)
{
switch ( pMsg->message )
{
case WM_DRAWCLIPBOARD:
// Handle clipboard available event and forward message
break;
case WM_CLIPBOARDUPDATE:
// This is never triggered
break;
case WM_DESTROYCLIPBOARD:
// Handle clipboard cleared event and forward message
break;
}
return ::CallNextHookEx( g_Hook, nCode, wParam, lParam );
}
由构造函数调用:
HRESULT ClipboardService::SetOrRefreshWindowsHook()
{
HRESULT hr = S_OK;
try
{
if (!m_bHookSet)
{
g_hwndCurrent = ::CreateWindowEx(0, "Message", "ClipboardMessageWindow", 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL);
m_dwThreadID = ::GetWindowThreadProcessId(g_hwndCurrent, &m_dwProcessID);
_Module.Lock();
SetLastError(0);
g_Hook = ::SetWindowsHookEx(WH_CALLWNDPROC, CallWndProc, 0, m_dwThreadID);
//g_hwndNext = ::SetClipboardViewer(g_hwndCurrent); old way to subscribe
// This is what I expect should subscribe me to WM_CLIPBOARDUPDATE messages
if (!::AddClipboardFormatListener(g_hwndCurrent))
hr_exit(E_UNEXPECTED);
DWORD dwLastError = ::GetLastError();
g_This = this;
m_bHookSet = true;
}
}
catch (...)
{
hr_exit(E_UNEXPECTED);
}
wrapup:
return hr;
}
这是一个由 .NET 包装器调用的 COM 接口,但我认为这两件事与本例中的问题无关(我想添加以防万一)。