diff --git a/server/2015Remote/2015RemoteDlg.cpp b/server/2015Remote/2015RemoteDlg.cpp index 4e1b041..354821f 100644 --- a/server/2015Remote/2015RemoteDlg.cpp +++ b/server/2015Remote/2015RemoteDlg.cpp @@ -747,6 +747,66 @@ void CMy2015RemoteDlg::RecordDllRequest(const std::string& ip) m_DllRequestTimes[ip].push_back(time(nullptr)); } +// ─── CSplitterBar ──────────────────────────────────────────────────────────── + +BEGIN_MESSAGE_MAP(CSplitterBar, CWnd) + ON_WM_LBUTTONDOWN() + ON_WM_MOUSEMOVE() + ON_WM_LBUTTONUP() + ON_WM_SETCURSOR() + ON_WM_PAINT() +END_MESSAGE_MAP() + +BOOL CSplitterBar::Create(CWnd* pParent) +{ + CString cls = AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW, + ::LoadCursor(NULL, IDC_SIZENS), (HBRUSH)(COLOR_3DFACE + 1)); + return CWnd::Create(cls, NULL, WS_CHILD, CRect(0, 0, 0, 0), pParent, 0); +} + +void CSplitterBar::OnLButtonDown(UINT nFlags, CPoint pt) +{ + m_bDragging = true; + SetCapture(); +} + +void CSplitterBar::OnMouseMove(UINT nFlags, CPoint pt) +{ + if (m_bDragging) { + CPoint screen(pt); + ClientToScreen(&screen); + GetParent()->SendMessage(WM_SPLITTER_MOVED, (WPARAM)screen.y, 0); + } +} + +void CSplitterBar::OnLButtonUp(UINT nFlags, CPoint pt) +{ + if (m_bDragging) { + m_bDragging = false; + ReleaseCapture(); + GetParent()->SendMessage(WM_SPLITTER_RELEASED, 0, 0); + } +} + +BOOL CSplitterBar::OnSetCursor(CWnd*, UINT, UINT) +{ + SetCursor(::LoadCursor(NULL, IDC_SIZENS)); + return TRUE; +} + +void CSplitterBar::OnPaint() +{ + CPaintDC dc(this); + CRect rc; + GetClientRect(&rc); + // 中央一条细线作为视觉提示 + int mid = rc.Height() / 2; + dc.FillSolidRect(&rc, GetSysColor(COLOR_3DFACE)); + dc.FillSolidRect(rc.left + 4, mid, rc.Width() - 8, 1, GetSysColor(COLOR_3DSHADOW)); +} + +// ───────────────────────────────────────────────────────────────────────────── + void CMy2015RemoteDlg::DoDataExchange(CDataExchange* pDX) { __super::DoDataExchange(pDX); @@ -928,6 +988,8 @@ BEGIN_MESSAGE_MAP(CMy2015RemoteDlg, CDialogEx) ON_COMMAND(ID_MENU_UNCOMPRESS, &CMy2015RemoteDlg::OnMenuUncompress) ON_COMMAND(ID_UNINSTALL_SOFTWARE, &CMy2015RemoteDlg::OnUninstallSoftware) ON_COMMAND(ID_VIEW_HIDE_LOG, &CMy2015RemoteDlg::OnViewHideLog) + ON_MESSAGE(WM_SPLITTER_MOVED, &CMy2015RemoteDlg::OnSplitterMoved) + ON_MESSAGE(WM_SPLITTER_RELEASED, &CMy2015RemoteDlg::OnSplitterReleased) END_MESSAGE_MAP() @@ -1347,6 +1409,10 @@ VOID CMy2015RemoteDlg::InitControl() m_CList_Message.SetExtendedStyle(style); m_CList_Message.ModifyStyle(WS_HSCROLL, 0); + m_nSplitPos = THIS_CFG.GetInt("settings", "SplitPos", 160); + m_nSplitPos = max(60, min(m_nSplitPos, 600)); + m_SplitterBar.Create(this); + // 不在这里调 ApplyThumbnailSettings —— 调用方在 LoadThumbnailSettingsFromCfg // 之后统一 Apply(避免"先用默认值 Apply 一次,再读 INI 后再 Apply 一次"的双绘)。 } @@ -3119,6 +3185,9 @@ void CMy2015RemoteDlg::OnSize(UINT nType, int cx, int cy) lastType = nType; BOOL hideLog = THIS_CFG.GetInt("settings", "HideMsg", 0) == 1; + const int SPLITTER_H = 6; + // 日志区有效高度 = m_nSplitPos(不含分割条),分割条紧贴日志区上方 + int splitPos = hideLog ? 0 : m_nSplitPos; EnterCriticalSection(&m_cs); if (m_CList_Online.m_hWnd!=NULL) { //(控件也是窗口因此也有句柄) @@ -3126,7 +3195,7 @@ void CMy2015RemoteDlg::OnSize(UINT nType, int cx, int cy) rc.left = 1; //列表的左坐标 rc.top = m_ToolBar.IsVisible() ? 80:1; //列表的上坐标 rc.right = cx-1; //列表的右坐标 - rc.bottom = hideLog ? cy-20 : cy-160; //隐藏日志时扩展到状态栏 + rc.bottom = hideLog ? cy-20 : cy-20-splitPos-SPLITTER_H; m_GroupTab.MoveWindow(rc); CRect rcInside; @@ -3143,16 +3212,25 @@ void CMy2015RemoteDlg::OnSize(UINT nType, int cx, int cy) } LeaveCriticalSection(&m_cs); + if (m_SplitterBar.m_hWnd != NULL) { + if (hideLog) { + m_SplitterBar.ShowWindow(SW_HIDE); + } else { + m_SplitterBar.ShowWindow(SW_SHOW); + m_SplitterBar.MoveWindow(1, cy-20-splitPos-SPLITTER_H, cx-2, SPLITTER_H); + } + } + if (m_CList_Message.m_hWnd!=NULL) { if (hideLog) { m_CList_Message.ShowWindow(SW_HIDE); } else { m_CList_Message.ShowWindow(SW_SHOW); CRect rc; - rc.left = 1; //列表的左坐标 - rc.top = cy-160; //列表的上坐标 - rc.right = cx-1; //列表的右坐标 - rc.bottom = cy-20; //列表的下坐标 + rc.left = 1; + rc.top = cy-20-splitPos; + rc.right = cx-1; + rc.bottom = cy-20; m_CList_Message.MoveWindow(rc); if (needRefresh) { m_CList_Message.RedrawWindow(NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_UPDATENOW); @@ -11168,3 +11246,23 @@ void CMy2015RemoteDlg::OnViewHideLog() GetClientRect(&rc); OnSize(SIZE_RESTORED, rc.Width(), rc.Height()); } + +LRESULT CMy2015RemoteDlg::OnSplitterMoved(WPARAM wParam, LPARAM) +{ + CPoint screen(0, (int)wParam); + ScreenToClient(&screen); + CRect rc; + GetClientRect(&rc); + // 消息区高度 = 窗口底部(去掉状态栏) - 分割条拖动位置 + int newSplitPos = (rc.bottom - 20) - screen.y; + newSplitPos = max(40, min(newSplitPos, rc.Height() - 120)); + m_nSplitPos = newSplitPos; + OnSize(SIZE_RESTORED, rc.Width(), rc.Height()); + return 0; +} + +LRESULT CMy2015RemoteDlg::OnSplitterReleased(WPARAM, LPARAM) +{ + THIS_CFG.SetInt("settings", "SplitPos", m_nSplitPos); + return 0; +} diff --git a/server/2015Remote/2015RemoteDlg.h b/server/2015Remote/2015RemoteDlg.h index f4fab04..e97624d 100644 --- a/server/2015Remote/2015RemoteDlg.h +++ b/server/2015Remote/2015RemoteDlg.h @@ -118,6 +118,20 @@ struct PendingTransferV2 { extern std::map g_pendingTransfersV2; extern std::mutex g_pendingTransfersV2Mtx; + +class CSplitterBar : public CWnd { +public: + BOOL Create(CWnd* pParent); + DECLARE_MESSAGE_MAP() +protected: + bool m_bDragging = false; + afx_msg void OnLButtonDown(UINT nFlags, CPoint pt); + afx_msg void OnMouseMove(UINT nFlags, CPoint pt); + afx_msg void OnLButtonUp(UINT nFlags, CPoint pt); + afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message); + afx_msg void OnPaint(); +}; + // CMy2015RemoteDlg 对话框 class CMy2015RemoteDlg : public CDialogLangEx { @@ -319,6 +333,8 @@ public: std::vector m_PendingOffline; // 存储端口号 CListCtrlEx m_CList_Online; CListCtrl m_CList_Message; + CSplitterBar m_SplitterBar; + int m_nSplitPos = 160; // 消息区高度(像素),可拖动调整 std::vector m_HostList; // 虚拟列表数据源(全部客户端) std::unordered_map m_ClientIndex; // clientID -> m_HostList 索引映射 std::vector m_FilteredIndices; // 当前分组过滤后的索引列表 @@ -612,4 +628,6 @@ public: afx_msg void OnMenuUncompress(); afx_msg void OnUninstallSoftware(); afx_msg void OnViewHideLog(); + afx_msg LRESULT OnSplitterMoved(WPARAM wParam, LPARAM lParam); + afx_msg LRESULT OnSplitterReleased(WPARAM wParam, LPARAM lParam); }; diff --git a/server/2015Remote/stdafx.h b/server/2015Remote/stdafx.h index 699adab..ac87250 100644 --- a/server/2015Remote/stdafx.h +++ b/server/2015Remote/stdafx.h @@ -107,6 +107,8 @@ #define WM_TRIAL_WAN_IP_ABUSE WM_USER+3037 // 试用版 IP 段检测:OnAccept 发现入站为公网 IP,通知主窗口弹框 #define WM_ACTIVE_LICENSE_NUM WM_USER+3038 #define WM_ONLINE_HOSTNUM WM_USER+3039 +#define WM_SPLITTER_MOVED WM_USER+3040 +#define WM_SPLITTER_RELEASED WM_USER+3041 #ifdef _UNICODE #if defined _M_IX86