我有一个传统的基于 Win32 C++ 的 Windows 桌面应用程序。在窗口中,我使用 Ctrl+V 来处理粘贴的内容。同一窗口还处理将键入的字符添加到我管理的内容中的击键。这一切都很好!
但是,如果用户按 Win+V 从 云剪贴板 粘贴,或按 Win+. 使用 Emoji 面板 键入,这些弹出窗口不会位于我的窗口附近的任何位置,即使尽管它是具有输入焦点的活动窗口。
是否有我应该调用的 API,或者我需要响应的 Windows 消息,以便通知操作系统我的窗口希望面板在附近打开,最好是沿着它的边界,或者我提供的矩形?
SetCaretPos()
,但这种行为没有任何影响。我看到周围的 API 都是剪贴板查看器,但那是针对想要观察剪贴板内容更改的窗口,而不是像我这样接受输入的普通窗口。
我只想让操作系统弹出窗口靠近我的窗口,就像常见的
Edit
或 Combo
控件在输入焦点时发生的那样。
一些截图来说明:
运行对话框中的所需位置:
用 MFC 测试程序复制的错误:
要自己复制错误,请使用
Edit > Paste
加速器创建一个支持标准 ID_EDIT_PASTE
菜单项的 MFC 应用程序。将其映射到如下所示的 OnEditPaste
处理程序(仅在 MessageBox 中显示任何 CF_TEXT
):
void TestView::OnEditPaste()
{
if (OpenClipboard()) {
if (auto hText = ::GetClipboardData(CF_TEXT); hText != NULL) {
if (auto pData = ::GlobalLock(hText); pData) {
std::string msg{(char*)pData, ::GlobalSize(hText)};
::MessageBoxA(GetSafeHwnd(), msg.c_str(), "Pasted", MB_OK);
::GlobalUnlock(hText);
}
}
CloseClipboard();
}
}
运行您的应用程序并激活视图。然后按Win+V,云剪贴板远远打开;这就是我迫切想要解决的问题。
我在这里找到了答案:How to set Emoji popup position in Win32
WM_IME_REQUEST
消息,具体来说,IMR_QUERYCHARPOSITION
查询。
如果你正在使用 MFC,你会想要这样的东西。这只是将提示放在窗口的左上角,但你应该明白了。
class TestView : public CView
{
. . .
afx_msg LRESULT OnImeRequest(WPARAM wParam, LPARAM lParam);
}
BEGIN_MESSAGE_MAP(TestView, CView)
. . .
ON_MESSAGE(WM_IME_REQUEST, OnImeRequest)
END_MESSAGE_MAP()
LRESULT TestView::OnImeRequest(WPARAM wParam, LPARAM lParam)
{
switch (wParam) {
case IMR_QUERYCHARPOSITION: {
RECT rcWindow{};
GetWindowRect(&rcWindow);
IMECHARPOSITION* charPos = (IMECHARPOSITION*)lParam;
charPos->dwSize = sizeof(IMECHARPOSITION);
charPos->pt.x = rcWindow.left;
charPos->pt.y = rcWindow.top;
charPos->cLineHeight = 10;
GetClientRect(&charPos->rcDocument);
return 1;
}
}
return 0;
}