Feat: draggable splitter bar to resize host list and message log proportions
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -118,6 +118,20 @@ struct PendingTransferV2 {
|
||||
extern std::map<uint64_t, PendingTransferV2> 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<int> m_PendingOffline; // 存储端口号
|
||||
CListCtrlEx m_CList_Online;
|
||||
CListCtrl m_CList_Message;
|
||||
CSplitterBar m_SplitterBar;
|
||||
int m_nSplitPos = 160; // 消息区高度(像素),可拖动调整
|
||||
std::vector<context*> m_HostList; // 虚拟列表数据源(全部客户端)
|
||||
std::unordered_map<uint64_t, size_t> m_ClientIndex; // clientID -> m_HostList 索引映射
|
||||
std::vector<size_t> 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);
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user