diff --git a/server/2015Remote/2015Remote.rc b/server/2015Remote/2015Remote.rc index fa0539c..e9b9c5c 100644 Binary files a/server/2015Remote/2015Remote.rc and b/server/2015Remote/2015Remote.rc differ diff --git a/server/2015Remote/CDlgFileSend.cpp b/server/2015Remote/CDlgFileSend.cpp index c866a5f..b101330 100644 --- a/server/2015Remote/CDlgFileSend.cpp +++ b/server/2015Remote/CDlgFileSend.cpp @@ -27,6 +27,7 @@ void CDlgFileSend::DoDataExchange(CDataExchange* pDX) BEGIN_MESSAGE_MAP(CDlgFileSend, CDialog) ON_WM_CLOSE() + ON_WM_TIMER() ON_MESSAGE(WM_UPDATEFILEPROGRESS, &CDlgFileSend::OnUpdateFileProgress) ON_MESSAGE(WM_FINISHFILESEND, &CDlgFileSend::OnFinishFileSend) END_MESSAGE_MAP() @@ -83,6 +84,7 @@ LRESULT CDlgFileSend::OnUpdateFileProgress(WPARAM wParam, LPARAM lParam) ShowWindow(SW_SHOW); BringWindowToTop(); SetForegroundWindow(); + if (percent>=100.) SetTimer(1, 3000, NULL); delete pChunk; delete pFile; @@ -128,3 +130,10 @@ void CDlgFileSend::OnClose() DialogBase::OnClose(); } + +void CDlgFileSend::OnTimer(UINT_PTR nIDEvent) { + if (nIDEvent == 1) { + KillTimer(1); + PostMessageA(WM_CLOSE, 0, 0); + } +} diff --git a/server/2015Remote/CDlgFileSend.h b/server/2015Remote/CDlgFileSend.h index 14c7233..bf7fa7b 100644 --- a/server/2015Remote/CDlgFileSend.h +++ b/server/2015Remote/CDlgFileSend.h @@ -37,4 +37,5 @@ public: CProgressCtrl m_Progress; virtual BOOL OnInitDialog(); afx_msg void OnClose(); + afx_msg void OnTimer(UINT_PTR nIDEvent); }; diff --git a/server/2015Remote/IOCPServer.h b/server/2015Remote/IOCPServer.h index 6a4dde2..c451999 100644 --- a/server/2015Remote/IOCPServer.h +++ b/server/2015Remote/IOCPServer.h @@ -121,6 +121,7 @@ public: bool m_bIsProcessing; HICON m_hIcon; BOOL m_bConnected; + uint64_t m_nDisconnectTime = 0; CDialogBase(UINT nIDTemplate, CWnd* pParent, Server* pIOCPServer, CONTEXT_OBJECT* pContext, int nIcon) : m_bIsClosed(false), m_bIsProcessing(false), m_ContextObject(pContext), @@ -128,12 +129,14 @@ public: CDialog(nIDTemplate, pParent) { m_bConnected = TRUE; + m_nDisconnectTime = 0; m_IPAddress = pContext->GetPeerName().c_str(); m_hIcon = nIcon > 0 ? LoadIcon(AfxGetInstanceHandle(), MAKEINTRESOURCE(nIcon)) : NULL; } int UpdateContext(CONTEXT_OBJECT* pContext) { m_bConnected = TRUE; + m_nDisconnectTime = 0; m_ContextObject = pContext; m_iocpServer = pContext->GetServer(); m_ContextObject->hDlg = this; diff --git a/server/2015Remote/ScreenSpyDlg.cpp b/server/2015Remote/ScreenSpyDlg.cpp index 52c4dcd..ac274ca 100644 --- a/server/2015Remote/ScreenSpyDlg.cpp +++ b/server/2015Remote/ScreenSpyDlg.cpp @@ -342,6 +342,7 @@ VOID CScreenSpyDlg::OnClose() afx_msg LRESULT CScreenSpyDlg::OnDisconnect(WPARAM wParam, LPARAM lParam) { m_bConnected = FALSE; + m_nDisconnectTime = GetTickCount64(); // Close the dialog if reconnect not succeed in 15 seconds SetTimer(2, 15000, NULL); PostMessage(WM_PAINT); @@ -594,7 +595,7 @@ void CScreenSpyDlg::OnPaint() NULL, DI_NORMAL | DI_COMPAT ); - if (!m_bConnected) { + if (!m_bConnected && GetTickCount64()-m_nDisconnectTime>2000) { DrawTipString("正在重连......", 2); } } @@ -1126,9 +1127,14 @@ void CScreenSpyDlg::EnterFullScreen() if (!m_pToolbar) { m_pToolbar = new CToolbarDlg(this); m_pToolbar->Create(IDD_TOOLBAR_DLG, this); - int cx = GetSystemMetrics(SM_CXSCREEN); - int cy = GetSystemMetrics(SM_CYSCREEN); - m_pToolbar->SetWindowPos(&wndTopMost, 0, -40, cx, 40, SWP_HIDEWINDOW); + // OnInitDialog() 会根据 m_bLocked 和 m_bOnTop 设置正确的位置和可见性 + // 如果未锁定,初始隐藏在屏幕外 + if (!m_pToolbar->m_bLocked) { + int cx = GetSystemMetrics(SM_CXSCREEN); + int cy = GetSystemMetrics(SM_CYSCREEN); + int y = m_pToolbar->m_bOnTop ? -40 : cy; // 根据位置设置隐藏在上方或下方 + m_pToolbar->SetWindowPos(&wndTopMost, 0, y, cx, 40, SWP_HIDEWINDOW); + } } // 7. 标记全屏模式 diff --git a/server/2015Remote/ToolbarDlg.cpp b/server/2015Remote/ToolbarDlg.cpp index 27aa0df..918b69f 100644 --- a/server/2015Remote/ToolbarDlg.cpp +++ b/server/2015Remote/ToolbarDlg.cpp @@ -1,5 +1,6 @@ #include "stdafx.h" #include "ToolbarDlg.h" +#include "2015Remote.h" #include "2015RemoteDlg.h" #include @@ -24,28 +25,62 @@ BEGIN_MESSAGE_MAP(CToolbarDlg, CDialogEx) ON_BN_CLICKED(CONTROL_BTN_ID, &CToolbarDlg::OnBnClickedCtrl) ON_BN_CLICKED(IDC_BTN_MINIMIZE, &CToolbarDlg::OnBnClickedMinimize) ON_BN_CLICKED(IDC_BTN_CLOSE, &CToolbarDlg::OnBnClickedClose) + ON_BN_CLICKED(IDC_BTN_LOCK, &CToolbarDlg::OnBnClickedLock) + ON_BN_CLICKED(IDC_BTN_POSITION, &CToolbarDlg::OnBnClickedPosition) + ON_BN_CLICKED(IDC_BTN_OPACITY, &CToolbarDlg::OnBnClickedOpacity) + ON_BN_CLICKED(IDC_BTN_SCREENSHOT, &CToolbarDlg::OnBnClickedScreenshot) ON_WM_ERASEBKGND() END_MESSAGE_MAP() void CToolbarDlg::CheckMousePosition() { + // 如果父窗口最小化,隐藏工具栏 + CWnd* pParent = GetParent(); + if (pParent && pParent->IsIconic()) { + if (m_bVisible) { + ShowWindow(SW_HIDE); + m_bVisible = false; + } + return; + } + + // 如果工具栏已锁定,确保它可见(处理最小化恢复等情况) + if (m_bLocked) { + if (!m_bVisible) { + SlideIn(); + } + return; + } + CPoint pt; GetCursorPos(&pt); int cxScreen = GetSystemMetrics(SM_CXSCREEN); + int cyScreen = GetSystemMetrics(SM_CYSCREEN); - // 计算按钮群的总宽度 (4个按钮 + 间距) - int totalWidth = 80 * 4 + 10 * 3; + // 计算按钮群的总宽度 (8个按钮 + 间距) + int totalWidth = 80 * 8 + 10 * 7; int leftBound = (cxScreen - totalWidth) / 2; int rightBound = (cxScreen + totalWidth) / 2; - // 只有在按钮对应的横向范围内从下往上扫到顶端才弹出 - if (pt.y <= 2 && pt.x >= leftBound && pt.x <= rightBound) { - if (!m_bVisible) SlideIn(); - } - // 鼠标离开工具栏范围(或者在工具栏左右两侧)时隐藏 - else if (pt.y > m_nHeight + 10 || pt.x < leftBound - 50 || pt.x > rightBound + 50) { - if (m_bVisible) SlideOut(); + if (m_bOnTop) { + // 工具栏在上方: 鼠标移到顶端时弹出 + if (pt.y <= 2 && pt.x >= leftBound && pt.x <= rightBound) { + if (!m_bVisible) SlideIn(); + } + // 鼠标离开工具栏范围时隐藏 + else if (pt.y > m_nHeight + 10 || pt.x < leftBound - 50 || pt.x > rightBound + 50) { + if (m_bVisible) SlideOut(); + } + } else { + // 工具栏在下方: 鼠标移到底端时弹出 + if (pt.y >= cyScreen - 2 && pt.x >= leftBound && pt.x <= rightBound) { + if (!m_bVisible) SlideIn(); + } + // 鼠标离开工具栏范围时隐藏 + else if (pt.y < cyScreen - m_nHeight - 10 || pt.x < leftBound - 50 || pt.x > rightBound + 50) { + if (m_bVisible) SlideOut(); + } } } @@ -54,31 +89,46 @@ void CToolbarDlg::SlideIn() if (m_bVisible) return; m_bVisible = true; - // 获取屏幕宽度,确保位置正确 + // 获取屏幕尺寸 int cx = GetSystemMetrics(SM_CXSCREEN); + int cy = GetSystemMetrics(SM_CYSCREEN); - // 动画:从 -m_nHeight 移动到 0 - // 步进加大(10像素),等待时间极短(10-15ms) - for (int i = -m_nHeight; i <= 0; i += 10) { - // 使用 SWP_NOACTIVATE 极其重要,防止夺取焦点导致的界面闪烁 - SetWindowPos(&wndTopMost, 0, i, cx, m_nHeight, SWP_SHOWWINDOW | SWP_NOACTIVATE); - - // 强制窗口立即重绘按钮,否则背景会是一片漆黑直到动画结束 - UpdateWindow(); - - Sleep(10); // 10ms 是人眼感知的流畅极限 + if (m_bOnTop) { + // 从上方滑入: 从 -m_nHeight 移动到 0 + for (int i = -m_nHeight; i <= 0; i += 10) { + SetWindowPos(&wndTopMost, 0, i, cx, m_nHeight, SWP_SHOWWINDOW | SWP_NOACTIVATE); + UpdateWindow(); + Sleep(10); + } + SetWindowPos(&wndTopMost, 0, 0, cx, m_nHeight, SWP_NOACTIVATE); + } else { + // 从下方滑入: 从 cy 移动到 cy - m_nHeight + for (int i = cy; i >= cy - m_nHeight; i -= 10) { + SetWindowPos(&wndTopMost, 0, i, cx, m_nHeight, SWP_SHOWWINDOW | SWP_NOACTIVATE); + UpdateWindow(); + Sleep(10); + } + SetWindowPos(&wndTopMost, 0, cy - m_nHeight, cx, m_nHeight, SWP_NOACTIVATE); } - - // 确保最终位置精准在 0 - SetWindowPos(&wndTopMost, 0, 0, cx, m_nHeight, SWP_NOACTIVATE); } void CToolbarDlg::SlideOut() { int cx = GetSystemMetrics(SM_CXSCREEN); - for (int y = 0; y >= -m_nHeight; y -= 8) { - SetWindowPos(&wndTopMost, 0, y, cx, m_nHeight, SWP_NOACTIVATE); - Sleep(50); + int cy = GetSystemMetrics(SM_CYSCREEN); + + if (m_bOnTop) { + // 向上滑出 + for (int y = 0; y >= -m_nHeight; y -= 8) { + SetWindowPos(&wndTopMost, 0, y, cx, m_nHeight, SWP_NOACTIVATE); + Sleep(50); + } + } else { + // 向下滑出 + for (int y = cy - m_nHeight; y <= cy; y += 8) { + SetWindowPos(&wndTopMost, 0, y, cx, m_nHeight, SWP_NOACTIVATE); + Sleep(50); + } } ShowWindow(SW_HIDE); m_bVisible = false; @@ -107,20 +157,21 @@ BOOL CToolbarDlg::OnInitDialog() { CDialogEx::OnInitDialog(); + // 加载用户设置 + LoadSettings(); + // 1. 设置分层窗口样式 ModifyStyleEx(0, WS_EX_LAYERED); - // 2. 关键设置:使用 LWA_COLORKEY 和 LWA_ALPHA 混合 - // RGB(255, 0, 255) 是品红色,我们将它定义为“透明色” - // 255 代表按钮部分完全不透明(如果你想要按钮也半透明,可以改成 150-200) - SetLayeredWindowAttributes(RGB(255, 0, 255), 255, LWA_COLORKEY | LWA_ALPHA); + // 2. 应用透明度设置 + ApplyOpacity(); - // --- 按钮布局代码 (保持不变) --- + // --- 按钮布局代码 (8个按钮) --- int cx = GetSystemMetrics(SM_CXSCREEN); int btnWidth = 80; int btnHeight = 28; int btnSpacing = 10; - int totalWidth = btnWidth * 4 + btnSpacing * 3; + int totalWidth = btnWidth * 8 + btnSpacing * 7; int startX = (cx - totalWidth) / 2; int y = (m_nHeight - btnHeight) / 2; @@ -130,7 +181,19 @@ BOOL CToolbarDlg::OnInitDialog() GetDlgItem(CONTROL_BTN_ID)->SetWindowPos(NULL, nextX, y, btnWidth, btnHeight, SWP_NOZORDER); nextX += btnWidth + btnSpacing; - GetDlgItem(IDC_BTN_MINIMIZE)->SetWindowPos(NULL, nextX, y, btnWidth, btnHeight, SWP_NOZORDER); // 放置最小化按钮 + GetDlgItem(IDC_BTN_LOCK)->SetWindowPos(NULL, nextX, y, btnWidth, btnHeight, SWP_NOZORDER); + + nextX += btnWidth + btnSpacing; + GetDlgItem(IDC_BTN_POSITION)->SetWindowPos(NULL, nextX, y, btnWidth, btnHeight, SWP_NOZORDER); + + nextX += btnWidth + btnSpacing; + GetDlgItem(IDC_BTN_OPACITY)->SetWindowPos(NULL, nextX, y, btnWidth, btnHeight, SWP_NOZORDER); + + nextX += btnWidth + btnSpacing; + GetDlgItem(IDC_BTN_SCREENSHOT)->SetWindowPos(NULL, nextX, y, btnWidth, btnHeight, SWP_NOZORDER); + + nextX += btnWidth + btnSpacing; + GetDlgItem(IDC_BTN_MINIMIZE)->SetWindowPos(NULL, nextX, y, btnWidth, btnHeight, SWP_NOZORDER); nextX += btnWidth + btnSpacing; GetDlgItem(IDC_BTN_CLOSE)->SetWindowPos(NULL, nextX, y, btnWidth, btnHeight, SWP_NOZORDER); @@ -139,6 +202,29 @@ BOOL CToolbarDlg::OnInitDialog() CScreenSpyDlg* pParent = (CScreenSpyDlg*)GetParent(); GetDlgItem(CONTROL_BTN_ID)->SetWindowTextA(pParent->m_bIsCtrl ? "暂停控制" : "控制屏幕"); + // 设置锁定按钮文本 + GetDlgItem(IDC_BTN_LOCK)->SetWindowTextA(m_bLocked ? "解锁" : "锁定"); + + // 设置位置按钮文本 + GetDlgItem(IDC_BTN_POSITION)->SetWindowTextA(m_bOnTop ? "放下面" : "放上面"); + + // 设置透明度按钮文本 + GetDlgItem(IDC_BTN_OPACITY)->SetWindowTextA(GetOpacityText()); + + // 设置截图按钮文本 + GetDlgItem(IDC_BTN_SCREENSHOT)->SetWindowTextA("截图"); + + // 如果是锁定状态,立即显示工具栏(否则锁定时无法触发显示) + if (m_bLocked) { + m_bVisible = true; + int cy = GetSystemMetrics(SM_CYSCREEN); + if (m_bOnTop) { + SetWindowPos(&wndTopMost, 0, 0, cx, m_nHeight, SWP_SHOWWINDOW | SWP_NOACTIVATE); + } else { + SetWindowPos(&wndTopMost, 0, cy - m_nHeight, cx, m_nHeight, SWP_SHOWWINDOW | SWP_NOACTIVATE); + } + } + return TRUE; } @@ -158,3 +244,83 @@ BOOL CToolbarDlg::OnEraseBkgnd(CDC* pDC) pDC->FillSolidRect(rect, RGB(255, 0, 255)); return TRUE; } + +void CToolbarDlg::OnBnClickedLock() +{ + m_bLocked = !m_bLocked; + GetDlgItem(IDC_BTN_LOCK)->SetWindowTextA(m_bLocked ? "解锁" : "锁定"); + SaveSettings(); +} + +void CToolbarDlg::OnBnClickedPosition() +{ + m_bOnTop = !m_bOnTop; + GetDlgItem(IDC_BTN_POSITION)->SetWindowTextA(m_bOnTop ? "放下面" : "放上面"); + UpdatePosition(); + SaveSettings(); +} + +void CToolbarDlg::UpdatePosition() +{ + int cx = GetSystemMetrics(SM_CXSCREEN); + int cy = GetSystemMetrics(SM_CYSCREEN); + + if (m_bOnTop) { + // 移动到屏幕上方 + SetWindowPos(&wndTopMost, 0, 0, cx, m_nHeight, SWP_NOACTIVATE); + } else { + // 移动到屏幕下方 + SetWindowPos(&wndTopMost, 0, cy - m_nHeight, cx, m_nHeight, SWP_NOACTIVATE); + } +} + +void CToolbarDlg::LoadSettings() +{ + m_bLocked = THIS_CFG.GetInt("toolbar", "Locked", 0) != 0; + m_bOnTop = THIS_CFG.GetInt("toolbar", "OnTop", 1) != 0; + m_nOpacityLevel = THIS_CFG.GetInt("toolbar", "OpacityLevel", 0) % 3; +} + +void CToolbarDlg::SaveSettings() +{ + THIS_CFG.SetInt("toolbar", "Locked", m_bLocked ? 1 : 0); + THIS_CFG.SetInt("toolbar", "OnTop", m_bOnTop ? 1 : 0); + THIS_CFG.SetInt("toolbar", "OpacityLevel", m_nOpacityLevel); +} + +void CToolbarDlg::ApplyOpacity() +{ + // 透明度级别: 0=100%(255), 1=75%(191), 2=50%(128) + BYTE opacity; + switch (m_nOpacityLevel) { + case 1: opacity = 191; break; // 75% + case 2: opacity = 128; break; // 50% + default: opacity = 255; break; // 100% + } + SetLayeredWindowAttributes(RGB(255, 0, 255), opacity, LWA_COLORKEY | LWA_ALPHA); +} + +CString CToolbarDlg::GetOpacityText() +{ + switch (m_nOpacityLevel) { + case 1: return "透明75%"; + case 2: return "透明50%"; + default: return "透明度"; + } +} + +void CToolbarDlg::OnBnClickedOpacity() +{ + m_nOpacityLevel = (m_nOpacityLevel + 1) % 3; + ApplyOpacity(); + GetDlgItem(IDC_BTN_OPACITY)->SetWindowTextA(GetOpacityText()); + SaveSettings(); +} + +void CToolbarDlg::OnBnClickedScreenshot() +{ + CScreenSpyDlg* pParent = (CScreenSpyDlg*)GetParent(); + if (pParent) { + pParent->SaveSnapshot(); + } +} diff --git a/server/2015Remote/ToolbarDlg.h b/server/2015Remote/ToolbarDlg.h index 4732801..d5aa980 100644 --- a/server/2015Remote/ToolbarDlg.h +++ b/server/2015Remote/ToolbarDlg.h @@ -15,10 +15,18 @@ public: int m_nHeight = 40; bool m_bVisible = false; + bool m_bLocked = false; // 是否锁定工具栏 + bool m_bOnTop = true; // 是否在屏幕上方 (默认上方) + int m_nOpacityLevel = 0; // 透明度级别 (0=100%, 1=75%, 2=50%) void SlideIn(); void SlideOut(); void CheckMousePosition(); + void UpdatePosition(); // 更新工具栏位置 + void LoadSettings(); // 从注册表加载设置 + void SaveSettings(); // 保存设置到注册表 + void ApplyOpacity(); // 应用透明度 + CString GetOpacityText(); // 获取透明度按钮文本 protected: virtual void DoDataExchange(CDataExchange* pDX); @@ -29,6 +37,10 @@ public: afx_msg void OnBnClickedCtrl(); afx_msg void OnBnClickedMinimize(); afx_msg void OnBnClickedClose(); + afx_msg void OnBnClickedLock(); + afx_msg void OnBnClickedPosition(); + afx_msg void OnBnClickedOpacity(); + afx_msg void OnBnClickedScreenshot(); afx_msg BOOL OnEraseBkgnd(CDC* pDC); virtual BOOL OnInitDialog(); }; diff --git a/server/2015Remote/resource.h b/server/2015Remote/resource.h index 6585381..f6ee344 100644 --- a/server/2015Remote/resource.h +++ b/server/2015Remote/resource.h @@ -434,6 +434,10 @@ #define IDC_STATIC_CURRENTPERCENT 2216 #define IDC_EDIT_INSTALL_DIR 2216 #define IDC_EDIT_INSTALL_NAME 2217 +#define IDC_BTN_LOCK 2218 +#define IDC_BTN_POSITION 2219 +#define IDC_BTN_OPACITY 2220 +#define IDC_BTN_SCREENSHOT 2221 #define ID_ONLINE_UPDATE 32772 #define ID_ONLINE_MESSAGE 32773 #define ID_ONLINE_DELETE 32775 @@ -620,7 +624,7 @@ #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 322 #define _APS_NEXT_COMMAND_VALUE 32995 -#define _APS_NEXT_CONTROL_VALUE 2218 +#define _APS_NEXT_CONTROL_VALUE 2222 #define _APS_NEXT_SYMED_VALUE 105 #endif #endif