789 lines
27 KiB
C++
789 lines
27 KiB
C++
#include "stdafx.h"
|
||
#include "ToolbarDlg.h"
|
||
#include "2015Remote.h"
|
||
#include "2015RemoteDlg.h"
|
||
#include <ScreenSpyDlg.h>
|
||
#include <common/commands.h>
|
||
|
||
IMPLEMENT_DYNAMIC(CToolbarDlg, CDialogEx)
|
||
|
||
CToolbarDlg::CToolbarDlg(CScreenSpyDlg* pParent)
|
||
: CDialogLangEx(IDD_TOOLBAR_DLG, pParent)
|
||
{
|
||
m_pParent = pParent;
|
||
}
|
||
|
||
CToolbarDlg::~CToolbarDlg()
|
||
{
|
||
}
|
||
|
||
void CToolbarDlg::DoDataExchange(CDataExchange* pDX)
|
||
{
|
||
__super::DoDataExchange(pDX);
|
||
}
|
||
|
||
BEGIN_MESSAGE_MAP(CToolbarDlg, CDialogEx)
|
||
ON_BN_CLICKED(IDC_BTN_EXIT_FULLSCREEN, &CToolbarDlg::OnBnClickedExitFullscreen)
|
||
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_SWITCH_SCREEN, &CToolbarDlg::OnBnClickedSwitchScreen)
|
||
ON_BN_CLICKED(IDC_BTN_BLOCK_INPUT, &CToolbarDlg::OnBnClickedBlockInput)
|
||
ON_BN_CLICKED(IDC_BTN_STATUS_INFO, &CToolbarDlg::OnBnClickedStatusInfo)
|
||
ON_BN_CLICKED(IDC_BTN_QUALITY, &CToolbarDlg::OnBnClickedQuality)
|
||
ON_BN_CLICKED(IDC_BTN_RESTORE_CONSOLE, &CToolbarDlg::OnBnClickedRestoreConsole)
|
||
ON_BN_CLICKED(IDC_BTN_X, &CToolbarDlg::OnBnClickedX)
|
||
ON_BN_CLICKED(IDC_BTN_Y, &CToolbarDlg::OnBnClickedY)
|
||
ON_BN_CLICKED(IDC_BTN_Z, &CToolbarDlg::OnBnClickedZ)
|
||
ON_BN_CLICKED(IDC_BTN_SCREENSHOT, &CToolbarDlg::OnBnClickedScreenshot)
|
||
ON_WM_ERASEBKGND()
|
||
END_MESSAGE_MAP()
|
||
|
||
RECT CToolbarDlg::GetParentMonitorRect()
|
||
{
|
||
CWnd* pParent = GetParent();
|
||
if (pParent) {
|
||
HMONITOR hMonitor = MonitorFromWindow(pParent->GetSafeHwnd(), MONITOR_DEFAULTTONEAREST);
|
||
MONITORINFO mi = { sizeof(mi) };
|
||
if (GetMonitorInfo(hMonitor, &mi)) {
|
||
return mi.rcMonitor;
|
||
}
|
||
}
|
||
// 回退到主显示器
|
||
RECT rc = { 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN) };
|
||
return rc;
|
||
}
|
||
|
||
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);
|
||
|
||
RECT rcMonitor = GetParentMonitorRect();
|
||
int monLeft = rcMonitor.left;
|
||
int monRight = rcMonitor.right;
|
||
int monTop = rcMonitor.top;
|
||
int monBottom = rcMonitor.bottom;
|
||
int monWidth = monRight - monLeft;
|
||
int monHeight = monBottom - monTop;
|
||
|
||
int btnSize = 32, btnSpacing = 8, btnCount = 16;
|
||
|
||
if (m_nPosition <= 1) {
|
||
// 水平模式 (上/下)
|
||
int totalWidth = btnSize * btnCount + btnSpacing * (btnCount - 1);
|
||
int leftBound = monLeft + (monWidth - totalWidth) / 2;
|
||
int rightBound = monLeft + (monWidth + totalWidth) / 2;
|
||
|
||
if (m_nPosition == 0) {
|
||
// 工具栏在上方: 鼠标移到顶端时弹出
|
||
if (pt.y <= monTop + 2 && pt.x >= leftBound && pt.x <= rightBound) {
|
||
if (!m_bVisible) SlideIn();
|
||
}
|
||
else if (pt.y > monTop + m_nHeight + 10 || pt.x < leftBound - 50 || pt.x > rightBound + 50) {
|
||
if (m_bVisible) SlideOut();
|
||
}
|
||
} else {
|
||
// 工具栏在下方: 鼠标移到底端时弹出
|
||
if (pt.y >= monBottom - 2 && pt.x >= leftBound && pt.x <= rightBound) {
|
||
if (!m_bVisible) SlideIn();
|
||
}
|
||
else if (pt.y < monBottom - m_nHeight - 10 || pt.x < leftBound - 50 || pt.x > rightBound + 50) {
|
||
if (m_bVisible) SlideOut();
|
||
}
|
||
}
|
||
} else {
|
||
// 垂直模式 (左/右)
|
||
int vw = 40;
|
||
int totalHeight = btnSize * btnCount + btnSpacing * (btnCount - 1);
|
||
int topBound = monTop + (monHeight - totalHeight) / 2;
|
||
int bottomBound = monTop + (monHeight + totalHeight) / 2;
|
||
|
||
if (m_nPosition == 2) {
|
||
// 工具栏在左边: 鼠标移到左端时弹出
|
||
if (pt.x <= monLeft + 2 && pt.y >= topBound && pt.y <= bottomBound) {
|
||
if (!m_bVisible) SlideIn();
|
||
}
|
||
else if (pt.x > monLeft + vw + 10 || pt.y < topBound - 50 || pt.y > bottomBound + 50) {
|
||
if (m_bVisible) SlideOut();
|
||
}
|
||
} else {
|
||
// 工具栏在右边: 鼠标移到右端时弹出
|
||
if (pt.x >= monRight - 2 && pt.y >= topBound && pt.y <= bottomBound) {
|
||
if (!m_bVisible) SlideIn();
|
||
}
|
||
else if (pt.x < monRight - vw - 10 || pt.y < topBound - 50 || pt.y > bottomBound + 50) {
|
||
if (m_bVisible) SlideOut();
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
void CToolbarDlg::SlideIn()
|
||
{
|
||
if (m_bVisible) return;
|
||
m_bVisible = true;
|
||
|
||
RECT rcMonitor = GetParentMonitorRect();
|
||
int monLeft = rcMonitor.left;
|
||
int monTop = rcMonitor.top;
|
||
int monRight = rcMonitor.right;
|
||
int monBottom = rcMonitor.bottom;
|
||
int monWidth = monRight - monLeft;
|
||
int monHeight = monBottom - monTop;
|
||
|
||
int hw = 640; // 水平工具栏宽度 (与垂直高度一致)
|
||
int vw = 40;
|
||
int vh = 640;
|
||
|
||
// 从边缘展开(改变窗口大小),避免多显示器时跑到相邻屏幕
|
||
switch (m_nPosition) {
|
||
case 0: { // 从上方展开: 顶边固定在 monTop, 高度从1增长到 m_nHeight
|
||
int hx = monLeft + (monWidth - hw) / 2;
|
||
for (int h = 1; h <= m_nHeight; h += 10) {
|
||
SetWindowPos(&wndTopMost, hx, monTop, hw, h, SWP_SHOWWINDOW | SWP_NOACTIVATE);
|
||
UpdateWindow();
|
||
Sleep(10);
|
||
}
|
||
SetWindowPos(&wndTopMost, hx, monTop, hw, m_nHeight, SWP_NOACTIVATE);
|
||
break;
|
||
}
|
||
case 1: { // 从下方展开: 底边固定在 monBottom, 高度从1增长到 m_nHeight
|
||
int hx = monLeft + (monWidth - hw) / 2;
|
||
for (int h = 1; h <= m_nHeight; h += 10) {
|
||
SetWindowPos(&wndTopMost, hx, monBottom - h, hw, h, SWP_SHOWWINDOW | SWP_NOACTIVATE);
|
||
UpdateWindow();
|
||
Sleep(10);
|
||
}
|
||
SetWindowPos(&wndTopMost, hx, monBottom - m_nHeight, hw, m_nHeight, SWP_NOACTIVATE);
|
||
break;
|
||
}
|
||
case 2: { // 从左边展开: 左边固定在 monLeft, 宽度从1增长到 vw
|
||
int vy = monTop + (monHeight - vh) / 2;
|
||
for (int w = 1; w <= vw; w += 10) {
|
||
SetWindowPos(&wndTopMost, monLeft, vy, w, vh, SWP_SHOWWINDOW | SWP_NOACTIVATE);
|
||
UpdateWindow();
|
||
Sleep(10);
|
||
}
|
||
SetWindowPos(&wndTopMost, monLeft, vy, vw, vh, SWP_NOACTIVATE);
|
||
break;
|
||
}
|
||
case 3: { // 从右边展开: 右边固定在 monRight, 宽度从1增长到 vw
|
||
int vy = monTop + (monHeight - vh) / 2;
|
||
for (int w = 1; w <= vw; w += 10) {
|
||
SetWindowPos(&wndTopMost, monRight - w, vy, w, vh, SWP_SHOWWINDOW | SWP_NOACTIVATE);
|
||
UpdateWindow();
|
||
Sleep(10);
|
||
}
|
||
SetWindowPos(&wndTopMost, monRight - vw, vy, vw, vh, SWP_NOACTIVATE);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
void CToolbarDlg::SlideOut()
|
||
{
|
||
RECT rcMonitor = GetParentMonitorRect();
|
||
int monLeft = rcMonitor.left;
|
||
int monTop = rcMonitor.top;
|
||
int monRight = rcMonitor.right;
|
||
int monBottom = rcMonitor.bottom;
|
||
int monWidth = monRight - monLeft;
|
||
int monHeight = monBottom - monTop;
|
||
|
||
int hw = 640;
|
||
int vw = 40;
|
||
int vh = 640;
|
||
|
||
CWnd* btns[] = {
|
||
&m_btnExit, &m_btnControl,
|
||
&m_btnLock, &m_btnPosition,
|
||
&m_btnOpacity, &m_btnSwitchScreen,
|
||
&m_btnBlockInput, &m_btnStatusInfo,
|
||
&m_btnQuality, &m_btnRestoreConsole,
|
||
&m_btnX, &m_btnY, &m_btnZ,
|
||
&m_btnScreenshot,
|
||
&m_btnMinimize, &m_btnClose,
|
||
};
|
||
const int N = 16;
|
||
CRect btnRects[N];
|
||
for (int i = 0; i < N; i++) {
|
||
btns[i]->GetWindowRect(&btnRects[i]);
|
||
ScreenToClient(&btnRects[i]);
|
||
}
|
||
|
||
// 向边缘缩回,避免多显示器时跑到相邻屏幕
|
||
switch (m_nPosition) {
|
||
case 0: { // 向上缩回: 顶边固定, 底边从下向上收缩, 按钮跟随上移
|
||
int hx = monLeft + (monWidth - hw) / 2;
|
||
for (int h = m_nHeight; h >= 0; h -= 8) {
|
||
int realH = max(h, 1);
|
||
int offset = m_nHeight - realH;
|
||
for (int i = 0; i < N; i++)
|
||
btns[i]->SetWindowPos(NULL, btnRects[i].left, btnRects[i].top - offset, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
|
||
SetWindowPos(&wndTopMost, hx, monTop, hw, realH, SWP_NOACTIVATE);
|
||
Sleep(50);
|
||
}
|
||
break;
|
||
}
|
||
case 1: { // 向下缩回: 底边固定, 顶边从上向下收缩, 按钮自然跟随
|
||
int hx = monLeft + (monWidth - hw) / 2;
|
||
for (int h = m_nHeight; h >= 0; h -= 8) {
|
||
SetWindowPos(&wndTopMost, hx, monBottom - max(h, 1), hw, max(h, 1), SWP_NOACTIVATE);
|
||
Sleep(50);
|
||
}
|
||
break;
|
||
}
|
||
case 2: { // 向左缩回: 左边固定, 右边从右向左收缩, 按钮跟随左移
|
||
int vy = monTop + (monHeight - vh) / 2;
|
||
for (int w = vw; w >= 0; w -= 8) {
|
||
int realW = max(w, 1);
|
||
int offset = vw - realW;
|
||
for (int i = 0; i < N; i++)
|
||
btns[i]->SetWindowPos(NULL, btnRects[i].left - offset, btnRects[i].top, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
|
||
SetWindowPos(&wndTopMost, monLeft, vy, realW, vh, SWP_NOACTIVATE);
|
||
Sleep(50);
|
||
}
|
||
break;
|
||
}
|
||
case 3: { // 向右缩回: 右边固定, 左边从左向右收缩, 按钮自然跟随
|
||
int vy = monTop + (monHeight - vh) / 2;
|
||
for (int w = vw; w >= 0; w -= 8) {
|
||
SetWindowPos(&wndTopMost, monRight - max(w, 1), vy, max(w, 1), vh, SWP_NOACTIVATE);
|
||
Sleep(50);
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
|
||
// 恢复按钮位置(下次 SlideIn 时位置正确)
|
||
for (int i = 0; i < N; i++)
|
||
btns[i]->SetWindowPos(NULL, btnRects[i].left, btnRects[i].top, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
|
||
ShowWindow(SW_HIDE);
|
||
m_bVisible = false;
|
||
}
|
||
|
||
void CToolbarDlg::OnBnClickedExitFullscreen()
|
||
{
|
||
// 通知父窗口退出全屏
|
||
GetParent()->PostMessage(WM_COMMAND, ID_EXIT_FULLSCREEN, 0);
|
||
}
|
||
|
||
void CToolbarDlg::OnBnClickedCtrl()
|
||
{
|
||
CScreenSpyDlg* pParent = (CScreenSpyDlg*)GetParent();
|
||
pParent->m_bIsCtrl = !pParent->m_bIsCtrl;
|
||
pParent->UpdateCtrlStatus(pParent->m_bIsCtrl);
|
||
UpdateButtonIcons();
|
||
}
|
||
|
||
void CToolbarDlg::OnBnClickedClose()
|
||
{
|
||
GetParent()->PostMessage(WM_CLOSE);
|
||
}
|
||
|
||
BOOL CToolbarDlg::OnInitDialog()
|
||
{
|
||
__super::OnInitDialog();
|
||
|
||
// 加载用户设置
|
||
LoadSettings();
|
||
|
||
// 1. 设置分层窗口样式 (WS_EX_NOACTIVATE 防止工具栏点击时抢夺焦点)
|
||
ModifyStyleEx(0, WS_EX_LAYERED | WS_EX_NOACTIVATE);
|
||
|
||
// 2. 应用透明度设置
|
||
ApplyOpacity();
|
||
|
||
// 3. Subclass dialog buttons as CIconButton
|
||
m_btnExit.SubclassDlgItem(IDC_BTN_EXIT_FULLSCREEN, this);
|
||
m_btnControl.SubclassDlgItem(CONTROL_BTN_ID, this);
|
||
m_btnLock.SubclassDlgItem(IDC_BTN_LOCK, this);
|
||
m_btnPosition.SubclassDlgItem(IDC_BTN_POSITION, this);
|
||
m_btnOpacity.SubclassDlgItem(IDC_BTN_OPACITY, this);
|
||
m_btnSwitchScreen.SubclassDlgItem(IDC_BTN_SWITCH_SCREEN, this);
|
||
m_btnBlockInput.SubclassDlgItem(IDC_BTN_BLOCK_INPUT, this);
|
||
m_btnStatusInfo.SubclassDlgItem(IDC_BTN_STATUS_INFO, this);
|
||
m_btnQuality.SubclassDlgItem(IDC_BTN_QUALITY, this);
|
||
m_btnRestoreConsole.SubclassDlgItem(IDC_BTN_RESTORE_CONSOLE, this);
|
||
m_btnX.SubclassDlgItem(IDC_BTN_X, this);
|
||
m_btnY.SubclassDlgItem(IDC_BTN_Y, this);
|
||
m_btnZ.SubclassDlgItem(IDC_BTN_Z, this);
|
||
m_btnScreenshot.SubclassDlgItem(IDC_BTN_SCREENSHOT, this);
|
||
m_btnMinimize.SubclassDlgItem(IDC_BTN_MINIMIZE, this);
|
||
m_btnClose.SubclassDlgItem(IDC_BTN_CLOSE, this);
|
||
|
||
// Set static icons for buttons that don't change
|
||
m_btnExit.SetIconDrawFunc(CIconButton::DrawIconExitFullscreen);
|
||
m_btnSwitchScreen.SetIconDrawFunc(CIconButton::DrawIconSwitchScreen);
|
||
m_btnQuality.SetIconDrawFunc(CIconButton::DrawIconQuality);
|
||
m_btnRestoreConsole.SetIconDrawFunc(CIconButton::DrawIconRestoreConsole);
|
||
m_btnX.SetIconDrawFunc(CIconButton::DrawIconLetterX); // 切换窗口
|
||
// Y按钮图标在 UpdateButtonIcons 中根据音频状态动态设置
|
||
m_btnZ.SetIconDrawFunc(CIconButton::DrawIconLetterZ); // 预留按钮 Z
|
||
m_btnScreenshot.SetIconDrawFunc(CIconButton::DrawIconScreenshot);
|
||
m_btnMinimize.SetIconDrawFunc(CIconButton::DrawIconMinimize);
|
||
m_btnClose.SetIconDrawFunc(CIconButton::DrawIconClose);
|
||
m_btnClose.SetIsCloseButton(true);
|
||
|
||
// 4. Create tooltip
|
||
m_tooltip.Create(this);
|
||
m_tooltip.Activate(TRUE);
|
||
m_tooltip.SetMaxTipWidth(200);
|
||
|
||
CScreenSpyDlg* pParent = (CScreenSpyDlg*)GetParent();
|
||
m_tooltip.AddTool(&m_btnExit, _TR("退出全屏"));
|
||
m_tooltip.AddTool(&m_btnControl, pParent->m_bIsCtrl ? _TR("暂停控制") : _TR("控制屏幕"));
|
||
m_tooltip.AddTool(&m_btnLock, m_bLocked ? _TR("解锁") : _TR("锁定"));
|
||
m_tooltip.AddTool(&m_btnPosition, _TR("放下面"));
|
||
m_tooltip.AddTool(&m_btnOpacity, _TR("透明度"));
|
||
m_tooltip.AddTool(&m_btnSwitchScreen, _TR("切换屏幕"));
|
||
m_tooltip.AddTool(&m_btnBlockInput, _TR("锁定远程输入"));
|
||
m_tooltip.AddTool(&m_btnStatusInfo, m_bShowStatusInfo ? _TR("隐藏状态信息") : _TR("显示状态信息"));
|
||
m_tooltip.AddTool(&m_btnQuality, _TR("屏幕质量"));
|
||
m_tooltip.AddTool(&m_btnRestoreConsole, _TR("RDP会话归位"));
|
||
m_tooltip.AddTool(&m_btnX, _TR("切换窗口")); // 类似 Alt+Tab
|
||
m_tooltip.AddTool(&m_btnY, pParent->m_Settings.AudioEnabled ? _TR("关闭系统音频") : _TR("打开系统音频"));
|
||
m_tooltip.AddTool(&m_btnZ, _T("Z")); // 预留按钮
|
||
m_tooltip.AddTool(&m_btnScreenshot, _TR("截图"));
|
||
m_tooltip.AddTool(&m_btnMinimize, _TR("最小化"));
|
||
m_tooltip.AddTool(&m_btnClose, _TR("关闭"));
|
||
|
||
// 5. Set state-dependent icons and tooltips
|
||
UpdateButtonIcons();
|
||
|
||
// 6. 布局按钮
|
||
LayoutButtons();
|
||
|
||
// 如果是锁定状态,立即显示工具栏(否则锁定时无法触发显示)
|
||
if (m_bLocked) {
|
||
m_bVisible = true;
|
||
RECT rcMonitor = GetParentMonitorRect();
|
||
int monWidth = rcMonitor.right - rcMonitor.left;
|
||
int monHeight = rcMonitor.bottom - rcMonitor.top;
|
||
|
||
int hw = 640;
|
||
int vw = 40;
|
||
int vh = 640;
|
||
int hx = rcMonitor.left + (monWidth - hw) / 2;
|
||
|
||
switch (m_nPosition) {
|
||
case 0:
|
||
SetWindowPos(&wndTopMost, hx, rcMonitor.top, hw, m_nHeight, SWP_SHOWWINDOW | SWP_NOACTIVATE);
|
||
break;
|
||
case 1:
|
||
SetWindowPos(&wndTopMost, hx, rcMonitor.bottom - m_nHeight, hw, m_nHeight, SWP_SHOWWINDOW | SWP_NOACTIVATE);
|
||
break;
|
||
case 2: {
|
||
int vy = rcMonitor.top + (monHeight - vh) / 2;
|
||
SetWindowPos(&wndTopMost, rcMonitor.left, vy, vw, vh, SWP_SHOWWINDOW | SWP_NOACTIVATE);
|
||
break;
|
||
}
|
||
case 3: {
|
||
int vy = rcMonitor.top + (monHeight - vh) / 2;
|
||
SetWindowPos(&wndTopMost, rcMonitor.right - vw, vy, vw, vh, SWP_SHOWWINDOW | SWP_NOACTIVATE);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
void CToolbarDlg::UpdateButtonIcons()
|
||
{
|
||
CScreenSpyDlg* pParent = (CScreenSpyDlg*)GetParent();
|
||
|
||
// Control button: Play (start control) or Pause (pause control)
|
||
if (pParent->m_bIsCtrl) {
|
||
m_btnControl.SetIconDrawFunc(CIconButton::DrawIconPause);
|
||
m_tooltip.UpdateTipText(_TR("暂停控制"), &m_btnControl);
|
||
} else {
|
||
m_btnControl.SetIconDrawFunc(CIconButton::DrawIconPlay);
|
||
m_tooltip.UpdateTipText(_TR("控制屏幕"), &m_btnControl);
|
||
}
|
||
m_btnControl.Invalidate(FALSE);
|
||
|
||
// Lock button
|
||
if (m_bLocked) {
|
||
m_btnLock.SetIconDrawFunc(CIconButton::DrawIconLock);
|
||
m_tooltip.UpdateTipText(_TR("解锁"), &m_btnLock);
|
||
} else {
|
||
m_btnLock.SetIconDrawFunc(CIconButton::DrawIconUnlock);
|
||
m_tooltip.UpdateTipText(_TR("锁定"), &m_btnLock);
|
||
}
|
||
m_btnLock.Invalidate(FALSE);
|
||
|
||
// Position button: show arrow indicating next position
|
||
switch (m_nPosition) {
|
||
case 0: // currently top, click goes to bottom
|
||
m_btnPosition.SetIconDrawFunc(CIconButton::DrawIconArrowDown);
|
||
m_tooltip.UpdateTipText(_TR("放下面"), &m_btnPosition);
|
||
break;
|
||
case 1: // currently bottom, click goes to left
|
||
m_btnPosition.SetIconDrawFunc(CIconButton::DrawIconArrowLeft);
|
||
m_tooltip.UpdateTipText(_TR("放左边"), &m_btnPosition);
|
||
break;
|
||
case 2: // currently left, click goes to right
|
||
m_btnPosition.SetIconDrawFunc(CIconButton::DrawIconArrowRight);
|
||
m_tooltip.UpdateTipText(_TR("放右边"), &m_btnPosition);
|
||
break;
|
||
default: // currently right, click goes to top
|
||
m_btnPosition.SetIconDrawFunc(CIconButton::DrawIconArrowUp);
|
||
m_tooltip.UpdateTipText(_TR("放上面"), &m_btnPosition);
|
||
break;
|
||
}
|
||
m_btnPosition.Invalidate(FALSE);
|
||
|
||
// Opacity button
|
||
switch (m_nOpacityLevel) {
|
||
case 1:
|
||
m_btnOpacity.SetIconDrawFunc(CIconButton::DrawIconOpacityMedium);
|
||
m_tooltip.UpdateTipText(_TR("透明75%"), &m_btnOpacity);
|
||
break;
|
||
case 2:
|
||
m_btnOpacity.SetIconDrawFunc(CIconButton::DrawIconOpacityLow);
|
||
m_tooltip.UpdateTipText(_TR("透明50%"), &m_btnOpacity);
|
||
break;
|
||
default:
|
||
m_btnOpacity.SetIconDrawFunc(CIconButton::DrawIconOpacityFull);
|
||
m_tooltip.UpdateTipText(_TR("透明度"), &m_btnOpacity);
|
||
break;
|
||
}
|
||
m_btnOpacity.Invalidate(FALSE);
|
||
|
||
// Block input button
|
||
if (m_bBlockInput) {
|
||
m_btnBlockInput.SetIconDrawFunc(CIconButton::DrawIconBlockInput);
|
||
m_tooltip.UpdateTipText(_TR("解除锁定输入"), &m_btnBlockInput);
|
||
} else {
|
||
m_btnBlockInput.SetIconDrawFunc(CIconButton::DrawIconUnblockInput);
|
||
m_tooltip.UpdateTipText(_TR("锁定远程输入"), &m_btnBlockInput);
|
||
}
|
||
m_btnBlockInput.Invalidate(FALSE);
|
||
|
||
// Status info button
|
||
if (m_bShowStatusInfo) {
|
||
m_btnStatusInfo.SetIconDrawFunc(CIconButton::DrawIconInfo);
|
||
m_tooltip.UpdateTipText(_TR("隐藏状态信息"), &m_btnStatusInfo);
|
||
} else {
|
||
m_btnStatusInfo.SetIconDrawFunc(CIconButton::DrawIconInfoHide);
|
||
m_tooltip.UpdateTipText(_TR("显示状态信息"), &m_btnStatusInfo);
|
||
}
|
||
m_btnStatusInfo.Invalidate(FALSE);
|
||
|
||
// Audio button (Y)
|
||
if (pParent->m_Settings.AudioEnabled) {
|
||
m_btnY.SetIconDrawFunc(CIconButton::DrawIconAudioOn);
|
||
m_tooltip.UpdateTipText(_TR("关闭系统音频"), &m_btnY);
|
||
} else {
|
||
m_btnY.SetIconDrawFunc(CIconButton::DrawIconAudioOff);
|
||
m_tooltip.UpdateTipText(_TR("打开系统音频"), &m_btnY);
|
||
}
|
||
m_btnY.Invalidate(FALSE);
|
||
}
|
||
|
||
void CToolbarDlg::LayoutButtons()
|
||
{
|
||
int btnSize = 32;
|
||
int btnSpacing = 8;
|
||
int btnCount = 16;
|
||
|
||
CWnd* btns[] = {
|
||
&m_btnExit,
|
||
&m_btnControl,
|
||
&m_btnLock,
|
||
&m_btnPosition,
|
||
&m_btnOpacity,
|
||
&m_btnSwitchScreen,
|
||
&m_btnBlockInput,
|
||
&m_btnStatusInfo,
|
||
&m_btnQuality,
|
||
&m_btnRestoreConsole,
|
||
&m_btnX, // 预留按钮 X
|
||
&m_btnY, // 预留按钮 Y
|
||
&m_btnZ, // 预留按钮 Z
|
||
&m_btnScreenshot,
|
||
&m_btnMinimize,
|
||
&m_btnClose,
|
||
};
|
||
|
||
int margin = (m_nHeight - btnSize) / 2; // 4px 边距
|
||
|
||
if (m_nPosition <= 1) {
|
||
// 水平布局 (上/下) — 窗口宽度为 320, 按钮从左边距开始排列
|
||
for (int i = 0; i < btnCount; i++) {
|
||
btns[i]->SetWindowPos(NULL, margin + i * (btnSize + btnSpacing), margin, btnSize, btnSize, SWP_NOZORDER);
|
||
}
|
||
} else {
|
||
// 垂直布局 (左/右) — 窗口宽度为 40, 按钮从上边距开始排列
|
||
for (int i = 0; i < btnCount; i++) {
|
||
btns[i]->SetWindowPos(NULL, margin, margin + i * (btnSize + btnSpacing), btnSize, btnSize, SWP_NOZORDER);
|
||
}
|
||
}
|
||
}
|
||
|
||
void CToolbarDlg::OnBnClickedMinimize()
|
||
{
|
||
// 隐藏工具栏自身并最小化父窗口
|
||
ShowWindow(SW_HIDE);
|
||
m_bVisible = false;
|
||
GetParent()->ShowWindow(SW_MINIMIZE);
|
||
}
|
||
|
||
BOOL CToolbarDlg::OnEraseBkgnd(CDC* pDC)
|
||
{
|
||
CRect rect;
|
||
GetClientRect(&rect);
|
||
pDC->FillSolidRect(rect, RGB(40, 40, 40));
|
||
return TRUE;
|
||
}
|
||
|
||
void CToolbarDlg::OnBnClickedLock()
|
||
{
|
||
m_bLocked = !m_bLocked;
|
||
UpdateButtonIcons();
|
||
SaveSettings();
|
||
}
|
||
|
||
void CToolbarDlg::OnBnClickedPosition()
|
||
{
|
||
m_nPosition = (m_nPosition + 1) % 4;
|
||
UpdateButtonIcons();
|
||
LayoutButtons();
|
||
UpdatePosition();
|
||
SaveSettings();
|
||
}
|
||
|
||
void CToolbarDlg::UpdatePosition()
|
||
{
|
||
RECT rcMonitor = GetParentMonitorRect();
|
||
int monWidth = rcMonitor.right - rcMonitor.left;
|
||
int monHeight = rcMonitor.bottom - rcMonitor.top;
|
||
|
||
int hw = 640;
|
||
int vw = 40;
|
||
int vh = 640;
|
||
int hx = rcMonitor.left + (monWidth - hw) / 2;
|
||
|
||
switch (m_nPosition) {
|
||
case 0:
|
||
SetWindowPos(&wndTopMost, hx, rcMonitor.top, hw, m_nHeight, SWP_NOACTIVATE);
|
||
break;
|
||
case 1:
|
||
SetWindowPos(&wndTopMost, hx, rcMonitor.bottom - m_nHeight, hw, m_nHeight, SWP_NOACTIVATE);
|
||
break;
|
||
case 2: {
|
||
int vy = rcMonitor.top + (monHeight - vh) / 2;
|
||
SetWindowPos(&wndTopMost, rcMonitor.left, vy, vw, vh, SWP_NOACTIVATE);
|
||
break;
|
||
}
|
||
case 3: {
|
||
int vy = rcMonitor.top + (monHeight - vh) / 2;
|
||
SetWindowPos(&wndTopMost, rcMonitor.right - vw, vy, vw, vh, SWP_NOACTIVATE);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
void CToolbarDlg::LoadSettings()
|
||
{
|
||
m_bLocked = THIS_CFG.GetInt("toolbar", "Locked", 0) != 0;
|
||
int pos = THIS_CFG.GetInt("toolbar", "Position", 0);
|
||
m_nPosition = (pos >= 0 && pos < 4) ? pos : 0;
|
||
int opa = THIS_CFG.GetInt("toolbar", "OpacityLevel", 0);
|
||
m_nOpacityLevel = (opa >= 0 && opa < 3) ? opa : 0;
|
||
m_bShowStatusInfo = THIS_CFG.GetInt("toolbar", "ShowStatusInfo", 1) != 0;
|
||
}
|
||
|
||
void CToolbarDlg::SaveSettings()
|
||
{
|
||
THIS_CFG.SetInt("toolbar", "Locked", m_bLocked ? 1 : 0);
|
||
THIS_CFG.SetInt("toolbar", "Position", m_nPosition);
|
||
THIS_CFG.SetInt("toolbar", "OpacityLevel", m_nOpacityLevel);
|
||
THIS_CFG.SetInt("toolbar", "ShowStatusInfo", m_bShowStatusInfo ? 1 : 0);
|
||
}
|
||
|
||
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(0, opacity, LWA_ALPHA);
|
||
}
|
||
|
||
void CToolbarDlg::OnBnClickedOpacity()
|
||
{
|
||
m_nOpacityLevel = (m_nOpacityLevel + 1) % 3;
|
||
ApplyOpacity();
|
||
UpdateButtonIcons();
|
||
SaveSettings();
|
||
|
||
// 同步状态信息窗口的透明度
|
||
CScreenSpyDlg* pParent = (CScreenSpyDlg*)GetParent();
|
||
if (pParent && pParent->m_pStatusInfoWnd) {
|
||
pParent->m_pStatusInfoWnd->SetOpacityLevel(m_nOpacityLevel);
|
||
}
|
||
}
|
||
|
||
void CToolbarDlg::OnBnClickedSwitchScreen()
|
||
{
|
||
GetParent()->PostMessage(WM_SYSCOMMAND, IDM_SWITCHSCREEN, 0);
|
||
}
|
||
|
||
void CToolbarDlg::OnBnClickedBlockInput()
|
||
{
|
||
GetParent()->PostMessage(WM_SYSCOMMAND, IDM_BLOCK_INPUT, 0);
|
||
}
|
||
|
||
void CToolbarDlg::OnBnClickedStatusInfo()
|
||
{
|
||
m_bShowStatusInfo = !m_bShowStatusInfo;
|
||
UpdateButtonIcons();
|
||
SaveSettings();
|
||
|
||
// 通知父窗口显示/隐藏状态窗口
|
||
GetParent()->PostMessage(WM_COMMAND,
|
||
m_bShowStatusInfo ? ID_SHOW_STATUS_INFO : ID_HIDE_STATUS_INFO, 0);
|
||
}
|
||
|
||
void CToolbarDlg::OnBnClickedQuality()
|
||
{
|
||
CMenu menu;
|
||
menu.CreatePopupMenu();
|
||
menu.AppendMenuL(MF_STRING, IDM_QUALITY_OFF, "关闭(&O)");
|
||
menu.AppendMenuL(MF_STRING, IDM_ADAPTIVE_QUALITY, "自适应(&A)");
|
||
menu.AppendMenu(MF_SEPARATOR);
|
||
menu.AppendMenuL(MF_STRING, IDM_QUALITY_ULTRA, "Ultra (25FPS, DIFF)");
|
||
menu.AppendMenuL(MF_STRING, IDM_QUALITY_HIGH, "High (20FPS, RGB565)");
|
||
menu.AppendMenuL(MF_STRING, IDM_QUALITY_GOOD, "Good (20FPS, H264)");
|
||
menu.AppendMenuL(MF_STRING, IDM_QUALITY_MEDIUM, "Medium (15FPS, H264)");
|
||
menu.AppendMenuL(MF_STRING, IDM_QUALITY_LOW, "Low (12FPS, H264)");
|
||
menu.AppendMenuL(MF_STRING, IDM_QUALITY_MINIMAL, "Minimal (8FPS, H264)");
|
||
|
||
// 勾选当前质量
|
||
CScreenSpyDlg* pParent = (CScreenSpyDlg*)GetParent();
|
||
if (pParent->m_Settings.QualityLevel == QUALITY_DISABLED) {
|
||
menu.CheckMenuItem(IDM_QUALITY_OFF, MF_CHECKED);
|
||
} else if (pParent->m_AdaptiveQuality.enabled) {
|
||
menu.CheckMenuItem(IDM_ADAPTIVE_QUALITY, MF_CHECKED);
|
||
} else if (pParent->m_AdaptiveQuality.currentLevel >= 0 && pParent->m_AdaptiveQuality.currentLevel < QUALITY_COUNT) {
|
||
menu.CheckMenuItem(IDM_QUALITY_ULTRA + pParent->m_AdaptiveQuality.currentLevel, MF_CHECKED);
|
||
}
|
||
|
||
// 弹出菜单
|
||
CRect rc;
|
||
m_btnQuality.GetWindowRect(&rc);
|
||
UINT cmd = menu.TrackPopupMenu(TPM_RETURNCMD | TPM_NONOTIFY, rc.right, rc.top, this);
|
||
if (cmd) {
|
||
GetParent()->PostMessage(WM_SYSCOMMAND, cmd, 0);
|
||
}
|
||
}
|
||
|
||
void CToolbarDlg::OnBnClickedRestoreConsole()
|
||
{
|
||
CScreenSpyDlg* pParent = (CScreenSpyDlg*)GetParent();
|
||
if (pParent) {
|
||
BeginWaitCursor();
|
||
BYTE bToken = CMD_RESTORE_CONSOLE;
|
||
pParent->m_ContextObject->Send2Client(&bToken, 1);
|
||
Sleep(1000); // 等待会话切换完成
|
||
EndWaitCursor();
|
||
}
|
||
}
|
||
|
||
void CToolbarDlg::OnBnClickedX()
|
||
{
|
||
// 切换窗口(类似 Alt+Tab)
|
||
CScreenSpyDlg* pParent = (CScreenSpyDlg*)GetParent();
|
||
if (pParent && pParent->m_ContextObject) {
|
||
BYTE bToken = CMD_SWITCH_WINDOW;
|
||
pParent->m_ContextObject->Send2Client(&bToken, 1);
|
||
}
|
||
}
|
||
|
||
void CToolbarDlg::OnBnClickedY()
|
||
{
|
||
// 切换系统音频
|
||
CScreenSpyDlg* pParent = (CScreenSpyDlg*)GetParent();
|
||
if (pParent && pParent->m_ContextObject) {
|
||
// 切换音频状态
|
||
pParent->m_Settings.AudioEnabled = !pParent->m_Settings.AudioEnabled;
|
||
// 发送控制命令到客户端
|
||
pParent->SendAudioCtrl(pParent->m_Settings.AudioEnabled ? CYCLEAUDIO_ENABLE : CYCLEAUDIO_DISABLE, 1);
|
||
// 如果关闭音频,停止本地播放
|
||
if (!pParent->m_Settings.AudioEnabled) {
|
||
pParent->StopAudioPlayback();
|
||
}
|
||
// 更新系统菜单勾选状态
|
||
CMenu* SysMenu = pParent->GetSystemMenu(FALSE);
|
||
if (SysMenu) {
|
||
SysMenu->CheckMenuItem(IDM_AUDIO_TOGGLE, pParent->m_Settings.AudioEnabled ? MF_CHECKED : MF_UNCHECKED);
|
||
}
|
||
// 更新工具栏按钮图标
|
||
UpdateButtonIcons();
|
||
}
|
||
}
|
||
|
||
void CToolbarDlg::OnBnClickedZ()
|
||
{
|
||
// TODO: 预留按钮 Z 的响应函数
|
||
}
|
||
|
||
void CToolbarDlg::OnBnClickedScreenshot()
|
||
{
|
||
CScreenSpyDlg* pParent = (CScreenSpyDlg*)GetParent();
|
||
if (pParent) {
|
||
pParent->SaveSnapshot();
|
||
}
|
||
}
|
||
|
||
BOOL CToolbarDlg::PreTranslateMessage(MSG* pMsg)
|
||
{
|
||
if (m_tooltip.GetSafeHwnd()) {
|
||
m_tooltip.RelayEvent(pMsg);
|
||
}
|
||
// 不拦截这些消息,让它们继续传播到父窗口 (ScreenSpyDlg) 处理远程转发
|
||
switch (pMsg->message) {
|
||
case WM_MOUSEWHEEL:
|
||
case WM_MOUSEHWHEEL:
|
||
case WM_KEYDOWN:
|
||
case WM_KEYUP:
|
||
case WM_SYSKEYDOWN:
|
||
case WM_SYSKEYUP:
|
||
return FALSE;
|
||
}
|
||
return __super::PreTranslateMessage(pMsg);
|
||
}
|