gpt4 book ai didi

c++ - 正确使用 AddClipboardFormatListener 并订阅 WM_CLIPBOARDUPDATE 消息

转载 作者:行者123 更新时间:2023-12-02 10:22:38 25 4
gpt4 key购买 nike

我目前正在尝试在我的应用程序中使用 Windows 剪贴板及其通知。具体来说,我正在尝试订阅 WM_CLIPBOARDUPDATE 使用 AddClipboardFormatListener() 的窗口消息功能。以前,我一直在使用 SetClipboardViewer() 功能以便将我的窗口直接添加到剪贴板查看器链中。这工作得很好,我收到了相关消息WM_DRAWCLIPBOARDWM_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 接口(interface),但我认为在这种情况下,这两件事中的任何一个都与我的问题无关(我想以防万一)。

最佳答案

你不应该使用 SetWindowsHookEx(WH_CALLWNDPROC)将消息接收到您自己的窗口。使用RegisterClass/Ex()而是注册您自己的自定义窗口类,该类具有您的 WndProc分配给它,然后 CreateWindowEx()可以创建该窗口类的实例。无需 Hook 。

HINSTANCE g_hThisInst = NULL;
HWND g_hwndCurrent = NULL;
//HWND g_hwndNext = NULL;
bool g_AddedListener = false;

BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
g_hThisInst = hinstDLL;
return TRUE;
}


LRESULT CALLBACK ClipboardService::WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_CREATE:
//g_hwndNext = ::SetClipboardViewer(hwnd);
g_AddedListener = ::AddClipboardFormatListener(hwnd);
return g_AddedListener ? 0 : -1;

case WM_DESTROY:
/*
ChangeClipboardChain(hwnd, g_hwndNext);
g_hwndNext = NULL;
*/
if (g_AddedListener)
{
RemoveClipboardFormatListener(hwnd);
g_AddedListener = false;
}
return 0;

/*
case WM_CHANGECBCHAIN:
if (g_hwndNext == (HWND)wParam)
g_hwndNext = (HWND)lParam;
else if (g_hwndNext)
SendMessage(g_hwndNext, uMsg, wParam, lParam);
break;

case WM_DRAWCLIPBOARD:
// Handle clipboard available event
if (g_hwndNext)
SendMessage(g_hwndNext, uMsg, wParam, lParam);
break;
*/

case WM_CLIPBOARDUPDATE:
// Handle clipboard updated event
return 0;

case WM_DESTROYCLIPBOARD:
// Handle clipboard cleared event and forward message
break;
}

return ::DefWindowProc(hwnd, uMsg, wParam, lParam);
}

HRESULT ClipboardService::SetOrRefreshWindowsHook()
{
try
{
if (!g_hwndCurrent)
{
WNDCLASS wndClass = {};
wndClass.lpfnWndProc = &ClipboardService::WndProc;
wndClass.hInstance = g_hThisInst;
wndClass.lpszClassName = TEXT("ClipboardMessageWindow");

if (!::RegisterClass(&wndClass))
{
DWORD dwLastError = ::GetLastError();
if (dwLastError != ERROR_CLASS_ALREADY_EXISTS)
return HRESULT_FROM_WIN32(dwLastError);
}

g_hwndCurrent = ::CreateWindowEx(0, wndClass.lpszClassName, "", 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, g_hThisInst, NULL);
if (!g_hwndCurrent)
{
DWORD dwLastError = ::GetLastError();
return HRESULT_FROM_WIN32(dwLastError);
}

g_This = this;
}
}
catch (...)
{
return E_UNEXPECTED;
}

return S_OK;
}

关于c++ - 正确使用 AddClipboardFormatListener 并订阅 WM_CLIPBOARDUPDATE 消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59460658/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com