Feature: Support copy text from remote with Ctrl+V
This commit is contained in:
@@ -494,6 +494,8 @@ BEGIN_MESSAGE_MAP(CMy2015RemoteDlg, CDialogEx)
|
||||
ON_COMMAND(ID_EXECUTE_DOWNLOAD, &CMy2015RemoteDlg::OnExecuteDownload)
|
||||
ON_COMMAND(ID_EXECUTE_UPLOAD, &CMy2015RemoteDlg::OnExecuteUpload)
|
||||
ON_COMMAND(ID_MACHINE_LOGOUT, &CMy2015RemoteDlg::OnMachineLogout)
|
||||
ON_WM_DESTROY()
|
||||
ON_MESSAGE(WM_SESSION_ACTIVATED, &CMy2015RemoteDlg::OnSessionActivatedMsg)
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
|
||||
@@ -962,6 +964,9 @@ BOOL CMy2015RemoteDlg::OnInitDialog()
|
||||
{
|
||||
AUTO_TICK(500);
|
||||
CDialogEx::OnInitDialog();
|
||||
|
||||
g_hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, AfxGetInstanceHandle(), 0);
|
||||
|
||||
m_GroupList = {"default"};
|
||||
// Grid 容器
|
||||
int size = THIS_CFG.GetInt("settings", "VideoWallSize");
|
||||
@@ -3428,3 +3433,142 @@ void CMy2015RemoteDlg::OnExecuteUpload()
|
||||
{
|
||||
TODO_NOTICE;
|
||||
}
|
||||
|
||||
|
||||
void CMy2015RemoteDlg::OnDestroy()
|
||||
{
|
||||
if (g_hKeyboardHook)
|
||||
{
|
||||
UnhookWindowsHookEx(g_hKeyboardHook);
|
||||
g_hKeyboardHook = NULL;
|
||||
}
|
||||
CDialogEx::OnDestroy();
|
||||
}
|
||||
|
||||
CString GetClipboardText()
|
||||
{
|
||||
if (!OpenClipboard(nullptr)) return _T("");
|
||||
|
||||
#ifdef UNICODE
|
||||
HANDLE hData = GetClipboardData(CF_UNICODETEXT);
|
||||
#else
|
||||
HANDLE hData = GetClipboardData(CF_TEXT);
|
||||
#endif
|
||||
|
||||
if (!hData) { CloseClipboard(); return _T(""); }
|
||||
|
||||
#ifdef UNICODE
|
||||
wchar_t* pszText = static_cast<wchar_t*>(GlobalLock(hData));
|
||||
#else
|
||||
char* pszText = static_cast<char*>(GlobalLock(hData));
|
||||
#endif
|
||||
|
||||
CString strText = pszText ? pszText : _T("");
|
||||
GlobalUnlock(hData);
|
||||
CloseClipboard();
|
||||
return strText;
|
||||
}
|
||||
|
||||
void SetClipboardText(const CString& text)
|
||||
{
|
||||
if (!OpenClipboard(nullptr)) return;
|
||||
EmptyClipboard();
|
||||
|
||||
#ifdef UNICODE
|
||||
HGLOBAL hGlob = GlobalAlloc(GMEM_MOVEABLE, (text.GetLength() + 1) * sizeof(wchar_t));
|
||||
wchar_t* p = static_cast<wchar_t*>(GlobalLock(hGlob));
|
||||
if (p) wcscpy_s(p, text.GetLength() + 1, text);
|
||||
#else
|
||||
HGLOBAL hGlob = GlobalAlloc(GMEM_MOVEABLE, (text.GetLength() + 1) * sizeof(char));
|
||||
char* p = static_cast<char*>(GlobalLock(hGlob));
|
||||
if (p) strcpy_s(p, text.GetLength() + 1, CT2A(text)); // CT2A 宏把 CString 转成 char*
|
||||
#endif
|
||||
|
||||
GlobalUnlock(hGlob);
|
||||
#ifdef UNICODE
|
||||
SetClipboardData(CF_UNICODETEXT, hGlob);
|
||||
#else
|
||||
SetClipboardData(CF_TEXT, hGlob);
|
||||
#endif
|
||||
CloseClipboard();
|
||||
}
|
||||
|
||||
CDialogBase* CMy2015RemoteDlg::GetRemoteWindow(HWND hWnd)
|
||||
{
|
||||
if (!::IsWindow(hWnd)) return FALSE;
|
||||
EnterCriticalSection(&m_cs);
|
||||
auto find = m_RemoteWnds.find(hWnd);
|
||||
auto ret = find == m_RemoteWnds.end() ? NULL : find->second;
|
||||
LeaveCriticalSection(&m_cs);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void CMy2015RemoteDlg::RemoveRemoteWindow(HWND wnd) {
|
||||
EnterCriticalSection(&m_cs);
|
||||
m_RemoteWnds.erase(wnd);
|
||||
LeaveCriticalSection(&m_cs);
|
||||
}
|
||||
|
||||
LRESULT CALLBACK CMy2015RemoteDlg::LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
if (nCode == HC_ACTION)
|
||||
{
|
||||
do {
|
||||
static CDialogBase* operateWnd = nullptr;
|
||||
KBDLLHOOKSTRUCT* pKey = (KBDLLHOOKSTRUCT*)lParam;
|
||||
|
||||
// 只在按下时处理
|
||||
if (wParam == WM_KEYDOWN)
|
||||
{
|
||||
// 检测 Ctrl+C / Ctrl+X
|
||||
if ((GetAsyncKeyState(VK_CONTROL) & 0x8000) && (pKey->vkCode == 'C' || pKey->vkCode == 'X')) {
|
||||
HWND hFore = ::GetForegroundWindow();
|
||||
operateWnd = g_2015RemoteDlg->GetRemoteWindow(hFore);
|
||||
if (!operateWnd)
|
||||
g_2015RemoteDlg->m_pActiveSession = nullptr;
|
||||
}
|
||||
// 检测 Ctrl+V
|
||||
else if ((GetAsyncKeyState(VK_CONTROL) & 0x8000) && pKey->vkCode == 'V')
|
||||
{
|
||||
HWND hFore = ::GetForegroundWindow();
|
||||
CDialogBase* dlg = g_2015RemoteDlg->GetRemoteWindow(hFore);
|
||||
if (dlg)
|
||||
{
|
||||
if (dlg == operateWnd)break;
|
||||
// [1] 本地 -> 远程
|
||||
CString strText = GetClipboardText();
|
||||
if (!strText.IsEmpty()) {
|
||||
BYTE* szBuffer = new BYTE[strText.GetLength() + 1];
|
||||
szBuffer[0] = COMMAND_SCREEN_SET_CLIPBOARD;
|
||||
memcpy(szBuffer + 1, strText.GetString(), strText.GetLength());
|
||||
dlg->m_ContextObject->Send2Client(szBuffer, strText.GetLength() + 1);
|
||||
Mprintf("【Ctrl+V】 从本地拷贝到远程 \n");
|
||||
SAFE_DELETE_ARRAY(szBuffer);
|
||||
}
|
||||
}
|
||||
else if (g_2015RemoteDlg->m_pActiveSession)
|
||||
{
|
||||
// [2] 远程 -> 本地
|
||||
BYTE bToken = COMMAND_SCREEN_GET_CLIPBOARD;
|
||||
g_2015RemoteDlg->m_pActiveSession->m_ContextObject->Send2Client(&bToken, sizeof(bToken));
|
||||
Mprintf("【Ctrl+V】 从远程拷贝到本地 \n");
|
||||
}
|
||||
else
|
||||
{
|
||||
Mprintf("[Ctrl+V] 没有活动的远程桌面会话 \n");
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (0);
|
||||
}
|
||||
|
||||
// 允许消息继续传递
|
||||
return CallNextHookEx(g_2015RemoteDlg->g_hKeyboardHook, nCode, wParam, lParam);
|
||||
}
|
||||
|
||||
LRESULT CMy2015RemoteDlg::OnSessionActivatedMsg(WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
CDialogBase* pSession = reinterpret_cast<CDialogBase*>(wParam);
|
||||
m_pActiveSession = pSession;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -185,6 +185,8 @@ public:
|
||||
|
||||
ContextObject->hWnd = Dlg->GetSafeHwnd();
|
||||
ContextObject->hDlg = Dlg;
|
||||
if(id == IDD_DIALOG_SCREEN_SPY)
|
||||
m_RemoteWnds[Dlg->GetSafeHwnd()]=(CDialogBase*)Dlg;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -230,6 +232,13 @@ public:
|
||||
CMenu m_MainMenu;
|
||||
CBitmap m_bmOnline[18];
|
||||
uint64_t m_superID;
|
||||
std::map<HWND, CDialogBase *> m_RemoteWnds;
|
||||
CDialogBase* GetRemoteWindow(HWND hWnd);
|
||||
void RemoveRemoteWindow(HWND wnd);
|
||||
CDialogBase* m_pActiveSession = nullptr; // <20><>ǰ<EFBFBD><EFBFBD>Ự<EFBFBD><E1BBB0><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8> / NULL <20><>ʾ<EFBFBD><CABE>
|
||||
afx_msg LRESULT OnSessionActivatedMsg(WPARAM wParam, LPARAM lParam);
|
||||
static LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam);
|
||||
HHOOK g_hKeyboardHook = NULL;
|
||||
enum {
|
||||
STATUS_UNKNOWN = -1,
|
||||
STATUS_RUN = 0,
|
||||
@@ -330,4 +339,5 @@ public:
|
||||
afx_msg void OnExecuteUpload();
|
||||
afx_msg void OnMachineLogout();
|
||||
void MachineManage(MachineCommand type);
|
||||
afx_msg void OnDestroy();
|
||||
};
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <imm.h>
|
||||
#include <WinUser.h>
|
||||
#include "CGridDialog.h"
|
||||
#include "2015RemoteDlg.h"
|
||||
|
||||
|
||||
// CScreenSpyDlg 对话框
|
||||
@@ -130,6 +131,7 @@ BEGIN_MESSAGE_MAP(CScreenSpyDlg, CDialog)
|
||||
ON_WM_KILLFOCUS()
|
||||
ON_WM_SIZE()
|
||||
ON_WM_LBUTTONDBLCLK()
|
||||
ON_WM_ACTIVATE()
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
|
||||
@@ -218,6 +220,9 @@ VOID CScreenSpyDlg::OnClose()
|
||||
CWnd* parent = GetParent();
|
||||
if (parent)
|
||||
parent->SendMessage(WM_CHILD_CLOSED, (WPARAM)this, 0);
|
||||
extern CMy2015RemoteDlg *g_2015RemoteDlg;
|
||||
if(g_2015RemoteDlg)
|
||||
g_2015RemoteDlg->RemoveRemoteWindow(GetSafeHwnd());
|
||||
|
||||
// 等待数据处理完毕
|
||||
if (IsProcessing()) {
|
||||
@@ -861,3 +866,17 @@ void CScreenSpyDlg::OnSize(UINT nType, int cx, int cy)
|
||||
m_wZoom = ((double)m_BitmapInfor_Full->bmiHeader.biWidth) / ((double)(m_CRect.Width()));
|
||||
m_hZoom = ((double)m_BitmapInfor_Full->bmiHeader.biHeight) / ((double)(m_CRect.Height()));
|
||||
}
|
||||
|
||||
void CScreenSpyDlg::OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized)
|
||||
{
|
||||
CDialogBase::OnActivate(nState, pWndOther, bMinimized);
|
||||
|
||||
CWnd* pMain = AfxGetMainWnd();
|
||||
if (!pMain)
|
||||
return;
|
||||
|
||||
if (nState != WA_INACTIVE){
|
||||
// 通知主窗口:远程窗口获得焦点
|
||||
::PostMessage(pMain->GetSafeHwnd(), WM_SESSION_ACTIVATED, (WPARAM)this, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,6 +109,7 @@ public:
|
||||
afx_msg void OnMouseLeave();
|
||||
afx_msg void OnKillFocus(CWnd* pNewWnd);
|
||||
afx_msg void OnSize(UINT nType, int cx, int cy);
|
||||
afx_msg void OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized);
|
||||
|
||||
protected:
|
||||
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV ֧<><D6A7>
|
||||
|
||||
@@ -84,6 +84,7 @@
|
||||
#define WM_PASSWORDCHECK WM_USER+3021
|
||||
#define WM_SHOWMESSAGE WM_USER+3022
|
||||
#define WM_SHOWERRORMSG WM_USER+3023
|
||||
#define WM_SESSION_ACTIVATED WM_USER+3024
|
||||
|
||||
#ifdef _UNICODE
|
||||
#if defined _M_IX86
|
||||
|
||||
Reference in New Issue
Block a user