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));
|
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)
|
void CMy2015RemoteDlg::DoDataExchange(CDataExchange* pDX)
|
||||||
{
|
{
|
||||||
__super::DoDataExchange(pDX);
|
__super::DoDataExchange(pDX);
|
||||||
@@ -928,6 +988,8 @@ BEGIN_MESSAGE_MAP(CMy2015RemoteDlg, CDialogEx)
|
|||||||
ON_COMMAND(ID_MENU_UNCOMPRESS, &CMy2015RemoteDlg::OnMenuUncompress)
|
ON_COMMAND(ID_MENU_UNCOMPRESS, &CMy2015RemoteDlg::OnMenuUncompress)
|
||||||
ON_COMMAND(ID_UNINSTALL_SOFTWARE, &CMy2015RemoteDlg::OnUninstallSoftware)
|
ON_COMMAND(ID_UNINSTALL_SOFTWARE, &CMy2015RemoteDlg::OnUninstallSoftware)
|
||||||
ON_COMMAND(ID_VIEW_HIDE_LOG, &CMy2015RemoteDlg::OnViewHideLog)
|
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()
|
END_MESSAGE_MAP()
|
||||||
|
|
||||||
|
|
||||||
@@ -1347,6 +1409,10 @@ VOID CMy2015RemoteDlg::InitControl()
|
|||||||
m_CList_Message.SetExtendedStyle(style);
|
m_CList_Message.SetExtendedStyle(style);
|
||||||
m_CList_Message.ModifyStyle(WS_HSCROLL, 0);
|
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
|
// 不在这里调 ApplyThumbnailSettings —— 调用方在 LoadThumbnailSettingsFromCfg
|
||||||
// 之后统一 Apply(避免"先用默认值 Apply 一次,再读 INI 后再 Apply 一次"的双绘)。
|
// 之后统一 Apply(避免"先用默认值 Apply 一次,再读 INI 后再 Apply 一次"的双绘)。
|
||||||
}
|
}
|
||||||
@@ -3119,6 +3185,9 @@ void CMy2015RemoteDlg::OnSize(UINT nType, int cx, int cy)
|
|||||||
lastType = nType;
|
lastType = nType;
|
||||||
|
|
||||||
BOOL hideLog = THIS_CFG.GetInt("settings", "HideMsg", 0) == 1;
|
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);
|
EnterCriticalSection(&m_cs);
|
||||||
if (m_CList_Online.m_hWnd!=NULL) { //(控件也是窗口因此也有句柄)
|
if (m_CList_Online.m_hWnd!=NULL) { //(控件也是窗口因此也有句柄)
|
||||||
@@ -3126,7 +3195,7 @@ void CMy2015RemoteDlg::OnSize(UINT nType, int cx, int cy)
|
|||||||
rc.left = 1; //列表的左坐标
|
rc.left = 1; //列表的左坐标
|
||||||
rc.top = m_ToolBar.IsVisible() ? 80:1; //列表的上坐标
|
rc.top = m_ToolBar.IsVisible() ? 80:1; //列表的上坐标
|
||||||
rc.right = cx-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);
|
m_GroupTab.MoveWindow(rc);
|
||||||
|
|
||||||
CRect rcInside;
|
CRect rcInside;
|
||||||
@@ -3143,16 +3212,25 @@ void CMy2015RemoteDlg::OnSize(UINT nType, int cx, int cy)
|
|||||||
}
|
}
|
||||||
LeaveCriticalSection(&m_cs);
|
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 (m_CList_Message.m_hWnd!=NULL) {
|
||||||
if (hideLog) {
|
if (hideLog) {
|
||||||
m_CList_Message.ShowWindow(SW_HIDE);
|
m_CList_Message.ShowWindow(SW_HIDE);
|
||||||
} else {
|
} else {
|
||||||
m_CList_Message.ShowWindow(SW_SHOW);
|
m_CList_Message.ShowWindow(SW_SHOW);
|
||||||
CRect rc;
|
CRect rc;
|
||||||
rc.left = 1; //列表的左坐标
|
rc.left = 1;
|
||||||
rc.top = cy-160; //列表的上坐标
|
rc.top = cy-20-splitPos;
|
||||||
rc.right = cx-1; //列表的右坐标
|
rc.right = cx-1;
|
||||||
rc.bottom = cy-20; //列表的下坐标
|
rc.bottom = cy-20;
|
||||||
m_CList_Message.MoveWindow(rc);
|
m_CList_Message.MoveWindow(rc);
|
||||||
if (needRefresh) {
|
if (needRefresh) {
|
||||||
m_CList_Message.RedrawWindow(NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_UPDATENOW);
|
m_CList_Message.RedrawWindow(NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_UPDATENOW);
|
||||||
@@ -11168,3 +11246,23 @@ void CMy2015RemoteDlg::OnViewHideLog()
|
|||||||
GetClientRect(&rc);
|
GetClientRect(&rc);
|
||||||
OnSize(SIZE_RESTORED, rc.Width(), rc.Height());
|
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::map<uint64_t, PendingTransferV2> g_pendingTransfersV2;
|
||||||
extern std::mutex g_pendingTransfersV2Mtx;
|
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 对话框
|
// CMy2015RemoteDlg 对话框
|
||||||
class CMy2015RemoteDlg : public CDialogLangEx
|
class CMy2015RemoteDlg : public CDialogLangEx
|
||||||
{
|
{
|
||||||
@@ -319,6 +333,8 @@ public:
|
|||||||
std::vector<int> m_PendingOffline; // 存储端口号
|
std::vector<int> m_PendingOffline; // 存储端口号
|
||||||
CListCtrlEx m_CList_Online;
|
CListCtrlEx m_CList_Online;
|
||||||
CListCtrl m_CList_Message;
|
CListCtrl m_CList_Message;
|
||||||
|
CSplitterBar m_SplitterBar;
|
||||||
|
int m_nSplitPos = 160; // 消息区高度(像素),可拖动调整
|
||||||
std::vector<context*> m_HostList; // 虚拟列表数据源(全部客户端)
|
std::vector<context*> m_HostList; // 虚拟列表数据源(全部客户端)
|
||||||
std::unordered_map<uint64_t, size_t> m_ClientIndex; // clientID -> m_HostList 索引映射
|
std::unordered_map<uint64_t, size_t> m_ClientIndex; // clientID -> m_HostList 索引映射
|
||||||
std::vector<size_t> m_FilteredIndices; // 当前分组过滤后的索引列表
|
std::vector<size_t> m_FilteredIndices; // 当前分组过滤后的索引列表
|
||||||
@@ -612,4 +628,6 @@ public:
|
|||||||
afx_msg void OnMenuUncompress();
|
afx_msg void OnMenuUncompress();
|
||||||
afx_msg void OnUninstallSoftware();
|
afx_msg void OnUninstallSoftware();
|
||||||
afx_msg void OnViewHideLog();
|
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_TRIAL_WAN_IP_ABUSE WM_USER+3037 // 试用版 IP 段检测:OnAccept 发现入站为公网 IP,通知主窗口弹框
|
||||||
#define WM_ACTIVE_LICENSE_NUM WM_USER+3038
|
#define WM_ACTIVE_LICENSE_NUM WM_USER+3038
|
||||||
#define WM_ONLINE_HOSTNUM WM_USER+3039
|
#define WM_ONLINE_HOSTNUM WM_USER+3039
|
||||||
|
#define WM_SPLITTER_MOVED WM_USER+3040
|
||||||
|
#define WM_SPLITTER_RELEASED WM_USER+3041
|
||||||
|
|
||||||
#ifdef _UNICODE
|
#ifdef _UNICODE
|
||||||
#if defined _M_IX86
|
#if defined _M_IX86
|
||||||
|
|||||||
Reference in New Issue
Block a user