Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion TrafficMonitor/CommonData.h
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,12 @@ struct GeneralSettingData
hardware_monitor_item &= ~item_type;
}

StringSet connections_hide; //用于保存哪些网络要从“选择网络连接”子菜单项中隐藏
StringSet connections_hide; //用于保存哪些网络要从”选择网络连接”子菜单项中隐藏

// Global hotkey
bool hotkey_enabled{ true }; // 全局热键功能开关
UINT hotkey_modifiers{ MOD_CONTROL | MOD_SHIFT }; // 热键修饰键(MOD_ALT | MOD_CONTROL | MOD_SHIFT | MOD_WIN)
UINT hotkey_vk{ VK_F11 }; // 热键虚拟键码
};

//定义监控时间间隔有效的最大值和最小值
Expand Down
119 changes: 118 additions & 1 deletion TrafficMonitor/GeneralSettingsDlg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ void CGeneralSettingsDlg::DoDataExchange(CDataExchange* pDX)
DDX_Control(pDX, IDC_SELECT_CPU_COMBO, m_select_cpu_combo);
DDX_Control(pDX, IDC_PLUGIN_MANAGE_BUTTON, m_plugin_manager_btn);
DDX_Control(pDX, IDC_SELECT_CONNECTIONS_BUTTON, m_select_connection_btn);
DDX_Control(pDX, IDC_HOTKEY_BUTTON, m_hotkey_button);
}

void CGeneralSettingsDlg::SetControlEnable()
Expand All @@ -215,6 +216,7 @@ void CGeneralSettingsDlg::SetControlEnable()
EnableDlgCtrl(IDC_RESET_AUTO_RUN_BUTTON, m_data.auto_run);
EnableDlgCtrl(IDC_AUTO_RUN_METHOD_REGESTRY_RADIO, m_data.auto_run);
EnableDlgCtrl(IDC_AUTO_RUN_METHOD_TASK_SCHEDULE_RADIO, m_data.auto_run);
m_hotkey_button.EnableWindow(m_data.hotkey_enabled);
}


Expand Down Expand Up @@ -248,6 +250,8 @@ BEGIN_MESSAGE_MAP(CGeneralSettingsDlg, CTabDlg)
ON_MESSAGE(WM_SPIN_EDIT_POS_CHANGED, &CGeneralSettingsDlg::OnSpinEditPosChanged)
ON_BN_CLICKED(IDC_AUTO_RUN_METHOD_REGESTRY_RADIO, &CGeneralSettingsDlg::OnBnClickedAutoRunMethodRegestryRadio)
ON_BN_CLICKED(IDC_AUTO_RUN_METHOD_TASK_SCHEDULE_RADIO, &CGeneralSettingsDlg::OnBnClickedAutoRunMethodTaskScheduleRadio)
ON_BN_CLICKED(IDC_HOTKEY_ENABLE_CHECK, &CGeneralSettingsDlg::OnBnClickedHotkeyEnableCheck)
ON_BN_CLICKED(IDC_HOTKEY_BUTTON, &CGeneralSettingsDlg::OnBnClickedHotkeyButton)
END_MESSAGE_MAP()


Expand Down Expand Up @@ -442,6 +446,11 @@ BOOL CGeneralSettingsDlg::OnInitDialog()
m_plugin_manager_btn.SetIcon(theApp.GetMenuIcon(IDI_PLUGINS));
m_select_connection_btn.SetIcon(theApp.GetMenuIcon(IDI_CONNECTION));

//初始化热键控件
CheckDlgButton(IDC_HOTKEY_ENABLE_CHECK, m_data.hotkey_enabled);
SetHotKeyButtonText();
m_hotkey_button.EnableWindow(m_data.hotkey_enabled);

return TRUE; // return TRUE unless you set the focus to a control
// 异常: OCX 属性页应返回 FALSE
}
Expand Down Expand Up @@ -567,13 +576,121 @@ void CGeneralSettingsDlg::OnBnClickedShowAllConnectionCheck()

BOOL CGeneralSettingsDlg::PreTranslateMessage(MSG* pMsg)
{
// TODO: 在此添加专用代码和/或调用基类
// 热键捕获模式
if (m_hotkey_capturing)
{
if (pMsg->message == WM_KEYDOWN || pMsg->message == WM_SYSKEYDOWN)
{
UINT vk = static_cast<UINT>(pMsg->wParam);

// ESC 取消捕获
if (vk == VK_ESCAPE)
{
EndHotKeyCapture(true);
return TRUE;
}

// 过滤纯修饰键
if (vk != VK_CONTROL && vk != VK_MENU && vk != VK_SHIFT &&
vk != VK_LWIN && vk != VK_RWIN &&
vk != VK_LCONTROL && vk != VK_RCONTROL &&
vk != VK_LMENU && vk != VK_RMENU &&
vk != VK_LSHIFT && vk != VK_RSHIFT)
{
// 获取当前修饰键状态
UINT modifiers = 0;
if (GetKeyState(VK_CONTROL) & 0x8000) modifiers |= MOD_CONTROL;
if (GetKeyState(VK_MENU) & 0x8000) modifiers |= MOD_ALT;
if (GetKeyState(VK_SHIFT) & 0x8000) modifiers |= MOD_SHIFT;
if (GetKeyState(VK_LWIN) & 0x8000 || GetKeyState(VK_RWIN) & 0x8000)
modifiers |= MOD_WIN;

if (modifiers != 0)
{
OnHotKeyCaptured(modifiers, vk);
return TRUE;
}
}
return TRUE; // 捕获期间拦截所有按键
}
// 点击按钮外区域取消捕获
if (pMsg->message == WM_LBUTTONDOWN || pMsg->message == WM_RBUTTONDOWN)
{
HWND hwndButton = m_hotkey_button.GetSafeHwnd();
if (pMsg->hwnd != hwndButton)
{
EndHotKeyCapture(true);
}
}
}

if (pMsg->message == WM_MOUSEMOVE)
m_toolTip.RelayEvent(pMsg);

return CTabDlg::PreTranslateMessage(pMsg);
}

void CGeneralSettingsDlg::SetHotKeyButtonText()
{
CString text;

if (m_data.hotkey_modifiers & MOD_CONTROL) text += _T("Ctrl+");
if (m_data.hotkey_modifiers & MOD_ALT) text += _T("Alt+");
if (m_data.hotkey_modifiers & MOD_SHIFT) text += _T("Shift+");
if (m_data.hotkey_modifiers & MOD_WIN) text += _T("Win+");

// 使用 MapVirtualKey + GetKeyNameText 获取按键名称
UINT scan_code = MapVirtualKeyW(m_data.hotkey_vk, MAPVK_VK_TO_VSC);
if (m_data.hotkey_vk == VK_INSERT || m_data.hotkey_vk == VK_DELETE ||
m_data.hotkey_vk == VK_HOME || m_data.hotkey_vk == VK_END ||
m_data.hotkey_vk == VK_PRIOR || m_data.hotkey_vk == VK_NEXT ||
m_data.hotkey_vk == VK_LEFT || m_data.hotkey_vk == VK_RIGHT ||
m_data.hotkey_vk == VK_UP || m_data.hotkey_vk == VK_DOWN)
{
scan_code |= 0x100; // 扩展键标志
}
wchar_t key_name_buf[64]{};
GetKeyNameTextW(scan_code << 16, key_name_buf, 64);

text += key_name_buf;
m_hotkey_button.SetWindowText(text);
}

void CGeneralSettingsDlg::StartHotKeyCapture()
{
m_hotkey_capturing = true;
m_hotkey_button.GetWindowText(m_hotkey_original_text);
m_hotkey_button.SetWindowText(CCommon::LoadText(IDS_PRESS_HOTKEY, _T("Press a key combination...")));
m_hotkey_button.SetFocus();
}

void CGeneralSettingsDlg::EndHotKeyCapture(bool cancelled)
{
m_hotkey_capturing = false;
if (cancelled)
m_hotkey_button.SetWindowText(m_hotkey_original_text);
else
SetHotKeyButtonText();
}

void CGeneralSettingsDlg::OnHotKeyCaptured(UINT modifiers, UINT vk)
{
m_data.hotkey_modifiers = modifiers;
m_data.hotkey_vk = vk;
EndHotKeyCapture(false);
}

void CGeneralSettingsDlg::OnBnClickedHotkeyButton()
{
StartHotKeyCapture();
}

void CGeneralSettingsDlg::OnBnClickedHotkeyEnableCheck()
{
m_data.hotkey_enabled = (IsDlgButtonChecked(IDC_HOTKEY_ENABLE_CHECK) != 0);
SetControlEnable();
}

afx_msg LRESULT CGeneralSettingsDlg::OnSpinEditPosChanged(WPARAM wParam, LPARAM lParam)
{
CSpinButtonCtrl* pSpin = (CSpinButtonCtrl*)wParam;
Expand Down
10 changes: 10 additions & 0 deletions TrafficMonitor/GeneralSettingsDlg.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ class CGeneralSettingsDlg : public CTabDlg
CGeneralSettingsDlg(CWnd* pParent = NULL); // standard constructor
virtual ~CGeneralSettingsDlg();

void SetHotKeyButtonText();
void StartHotKeyCapture();
void EndHotKeyCapture(bool cancelled);
void OnHotKeyCaptured(UINT modifiers, UINT vk);

static void CheckTaskbarDisplayItem();

//选项设置数据
Expand Down Expand Up @@ -52,6 +57,9 @@ class CGeneralSettingsDlg : public CTabDlg
CComboBox2 m_select_cpu_combo;
CButton m_plugin_manager_btn;
CButton m_select_connection_btn;
CButton m_hotkey_button;
bool m_hotkey_capturing{ false };
CString m_hotkey_original_text;

virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support

Expand Down Expand Up @@ -102,6 +110,8 @@ class CGeneralSettingsDlg : public CTabDlg
afx_msg void OnBnClickedSelectConnectionsButton();
afx_msg void OnBnClickedResetAutoRunButton();
afx_msg void OnEnChangeMonitorSpanEdit();
afx_msg void OnBnClickedHotkeyEnableCheck();
afx_msg void OnBnClickedHotkeyButton();
protected:
public:
afx_msg void OnBnClickedAutoRunMethodRegestryRadio();
Expand Down
97 changes: 80 additions & 17 deletions TrafficMonitor/SkinFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,12 @@ CSkinFile::CSkinFile()

CSkinFile::~CSkinFile()
{
SAFE_DELETE(m_background_png_s);
SAFE_DELETE(m_background_png_l);
for (auto* img : m_background_png_s)
SAFE_DELETE(img);
m_background_png_s.clear();
for (auto* img : m_background_png_l)
SAFE_DELETE(img);
m_background_png_l.clear();
}

static CSkinFile::LayoutItem LayoutItemFromXmlNode(tinyxml2::XMLElement* ele)
Expand Down Expand Up @@ -127,21 +131,60 @@ bool CSkinFile::Load(const wstring& skin_name)

wstring path_dir = file_path_helper.GetDir();

//载入png背景图
//载入png背景图(支持多帧动画)
m_is_png = true;
//先尝试加载png格式,失败则加载bmp格式
SAFE_DELETE(m_background_png_s);
m_background_png_s = new Gdiplus::Image((path_dir + BACKGROUND_IMAGE_S_PNG).c_str());
if (m_background_png_s->GetLastStatus() != Gdiplus::Ok)
//先清理旧帧
for (auto* img : m_background_png_s)
SAFE_DELETE(img);
m_background_png_s.clear();
for (auto* img : m_background_png_l)
SAFE_DELETE(img);
m_background_png_l.clear();
m_animation_start_time = GetTickCount64();

// 辅助lambda:尝试加载多帧PNG(background_0.png, background_1.png, ...)
// 若background_0.png不存在则回退到background.png单帧
auto LoadMultiFramePng = [&](const wstring& base_name, std::vector<Gdiplus::Image*>& out_frames) -> bool
{
// 先尝试多帧格式 background_0.png
wstring frame0_path = path_dir + base_name + L"_0.png";
if (CCommon::FileExist(frame0_path.c_str()))
{
for (int i = 0; ; i++)
{
wstring frame_path = path_dir + base_name + L"_" + std::to_wstring(i) + L".png";
if (!CCommon::FileExist(frame_path.c_str()))
break;
auto* img = new Gdiplus::Image(frame_path.c_str());
if (img->GetLastStatus() == Gdiplus::Ok)
out_frames.push_back(img);
else
{
delete img;
break;
}
}
return !out_frames.empty();
}
// 回退到单帧 background.png
wstring single_path = path_dir + base_name + L".png";
if (CCommon::FileExist(single_path.c_str()))
{
auto* img = new Gdiplus::Image(single_path.c_str());
if (img->GetLastStatus() == Gdiplus::Ok)
{
out_frames.push_back(img);
return true;
}
delete img;
}
return false;
};

if (!LoadMultiFramePng(L"background", m_background_png_s))
m_is_png = false;
}
SAFE_DELETE(m_background_png_l);
m_background_png_l = new Gdiplus::Image((path_dir + BACKGROUND_IMAGE_L_PNG).c_str());
if (m_background_png_l->GetLastStatus() != Gdiplus::Ok)
{
if (!LoadMultiFramePng(L"background_l", m_background_png_l))
m_is_png = false;
}

//png背景图加载失败,使用bmp背景图
if (!m_is_png)
Expand Down Expand Up @@ -398,6 +441,23 @@ void CSkinFile::SetAlpha(int alpha)
m_alpha = alpha;
}

Gdiplus::Image* CSkinFile::GetCurrentBackgroundFrame(bool show_more_info)
{
auto& frames = show_more_info ? m_background_png_l : m_background_png_s;
if (frames.empty())
return nullptr;
if (frames.size() == 1)
return frames.front();

// 基于时间戳选择帧,帧率 10fps,独立于数据刷新率
ULONGLONG now = GetTickCount64();
if (m_animation_start_time == 0)
m_animation_start_time = now;
ULONGLONG elapsed = now - m_animation_start_time;
size_t frame_idx = static_cast<size_t>(elapsed / 33) % frames.size();
return frames[frame_idx];
}

void CSkinFile::SetSettingData(const SkinSettingData& setting_data)
{
//如果字体有变化,则重新创建字体
Expand Down Expand Up @@ -429,8 +489,10 @@ void CSkinFile::DrawPreview(CDC* pDC, CRect rect)
if (IsPNG()) //png背景使用GDI+绘制
{
CDrawCommonEx gdiplus_drawer(pDC);
gdiplus_drawer.DrawImage(m_background_png_s, rect_s.TopLeft(), rect_s.Size(), IDrawCommon::StretchMode::STRETCH);
gdiplus_drawer.DrawImage(m_background_png_l, rect_l.TopLeft(), rect_l.Size(), IDrawCommon::StretchMode::STRETCH);
Gdiplus::Image* preview_s = m_background_png_s.empty() ? nullptr : m_background_png_s.front();
Gdiplus::Image* preview_l = m_background_png_l.empty() ? nullptr : m_background_png_l.front();
if (preview_s) gdiplus_drawer.DrawImage(preview_s, rect_s.TopLeft(), rect_s.Size(), IDrawCommon::StretchMode::STRETCH);
if (preview_l) gdiplus_drawer.DrawImage(preview_l, rect_l.TopLeft(), rect_l.Size(), IDrawCommon::StretchMode::STRETCH);
}
else
{
Expand Down Expand Up @@ -576,8 +638,9 @@ void CSkinFile::DrawInfo(CDC* pDC, bool show_more_info)
//绘制背景
CDrawCommonEx gdiplus_drawer;
gdiplus_drawer.Create(CDC::FromHandle(hdcMemory));
Gdiplus::Image* background_image{ show_more_info ? m_background_png_l : m_background_png_s };
gdiplus_drawer.DrawImage(background_image, CPoint(0, 0), rect.Size(), CDrawCommon::StretchMode::FILL);
Gdiplus::Image* background_image{ GetCurrentBackgroundFrame(show_more_info) };
if (background_image)
gdiplus_drawer.DrawImage(background_image, CPoint(0, 0), rect.Size(), CDrawCommon::StretchMode::FILL);

//保存完全透明的像素点
std::set<DrawCommonHelper::Point> alpha_points;
Expand Down
8 changes: 6 additions & 2 deletions TrafficMonitor/SkinFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,9 @@ class CSkinFile

static void DrawSkinText(IDrawCommon& drawer, DrawStr draw_str, CRect rect, COLORREF color, Alignment align);

// 获取当前应显示的背景帧(按帧序列循环)
Gdiplus::Image* GetCurrentBackgroundFrame(bool show_more_info);

//绘制主界面中除背景图外所有显示项目
void DrawItemsInfo(IDrawCommon& drawer, Layout& layout, CFont& font) const;

Expand All @@ -151,8 +154,9 @@ class CSkinFile
CImage m_background_s;
CImage m_background_l;
bool m_is_png{};
Gdiplus::Image* m_background_png_s{};
Gdiplus::Image* m_background_png_l{};
std::vector<Gdiplus::Image*> m_background_png_s; // 小布局背景帧(至少1帧)
std::vector<Gdiplus::Image*> m_background_png_l; // 大布局背景帧(至少1帧)
ULONGLONG m_animation_start_time{}; // 动画起始时间戳
int m_alpha{ 255 }; //不透明度,仅当背景为png时有效
SkinSettingData m_setting_data;
bool m_is_error{ false };
Expand Down
10 changes: 10 additions & 0 deletions TrafficMonitor/TrafficMonitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,11 @@ void CTrafficMonitorApp::LoadConfig()
ini.GetStringList(L"general", L"connections_hide", connections_hide, std::vector<std::wstring>{});
m_general_data.connections_hide.FromVector(connections_hide);

//Global hotkey
m_general_data.hotkey_enabled = ini.GetBool(L"general", L"hotkey_enabled", true);
m_general_data.hotkey_modifiers = static_cast<UINT>(ini.GetInt(L"general", L"hotkey_modifiers", MOD_CONTROL | MOD_SHIFT));
m_general_data.hotkey_vk = static_cast<UINT>(ini.GetInt(L"general", L"hotkey_vk", VK_F11));

//Windows10颜色模式设置
bool is_windows10_light_theme = CWindowsSettingHelper::IsWindows10LightTheme();
if (is_windows10_light_theme)
Expand Down Expand Up @@ -303,6 +308,11 @@ void CTrafficMonitorApp::SaveConfig()
ini.WriteInt(L"general", L"hardware_monitor_item", m_general_data.hardware_monitor_item);
ini.WriteStringList(L"general", L"connections_hide", m_general_data.connections_hide.ToVector());

//Global hotkey
ini.WriteBool(L"general", L"hotkey_enabled", m_general_data.hotkey_enabled);
ini.WriteInt(L"general", L"hotkey_modifiers", static_cast<int>(m_general_data.hotkey_modifiers));
ini.WriteInt(L"general", L"hotkey_vk", static_cast<int>(m_general_data.hotkey_vk));

//主窗口设置
ini.WriteInt(L"config", L"transparency", m_cfg_data.m_transparency);
ini.WriteBool(L"config", L"always_on_top", m_main_wnd_data.m_always_on_top);
Expand Down
Binary file modified TrafficMonitor/TrafficMonitor.rc
Binary file not shown.
Loading