Feature: add menu-driven compress/extract via custom file+folder picker
This commit is contained in:
Binary file not shown.
@@ -637,7 +637,8 @@ CMy2015RemoteDlg::CMy2015RemoteDlg(CWnd* pParent): CDialogLangEx(CMy2015RemoteDl
|
|||||||
m_bmOnline[52].LoadBitmap(IDB_BITMAP_WEBDESKTOP);
|
m_bmOnline[52].LoadBitmap(IDB_BITMAP_WEBDESKTOP);
|
||||||
m_bmOnline[53].LoadBitmap(IDB_BITMAP_PLUGINCONFIG);
|
m_bmOnline[53].LoadBitmap(IDB_BITMAP_PLUGINCONFIG);
|
||||||
m_bmOnline[54].LoadBitmap(IDB_BITMAP_SNAPSHOT); // "播放快照" 菜单的眼睛图标
|
m_bmOnline[54].LoadBitmap(IDB_BITMAP_SNAPSHOT); // "播放快照" 菜单的眼睛图标
|
||||||
|
m_bmOnline[55].LoadBitmap(IDB_BITMAP_COMPRESS);
|
||||||
|
m_bmOnline[56].LoadBitmap(IDB_BITMAP_UNCOMPRESS);
|
||||||
for (int i = 0; i < PAYLOAD_MAXTYPE; i++) {
|
for (int i = 0; i < PAYLOAD_MAXTYPE; i++) {
|
||||||
m_ServerDLL[i] = nullptr;
|
m_ServerDLL[i] = nullptr;
|
||||||
m_ServerBin[i] = nullptr;
|
m_ServerBin[i] = nullptr;
|
||||||
@@ -919,6 +920,8 @@ BEGIN_MESSAGE_MAP(CMy2015RemoteDlg, CDialogEx)
|
|||||||
ON_COMMAND(ID_WEB_REMOTE_CONTROL, &CMy2015RemoteDlg::OnWebRemoteControl)
|
ON_COMMAND(ID_WEB_REMOTE_CONTROL, &CMy2015RemoteDlg::OnWebRemoteControl)
|
||||||
ON_COMMAND(ID_PROXY_PORT_AUTORUN, &CMy2015RemoteDlg::OnProxyPortAutorun)
|
ON_COMMAND(ID_PROXY_PORT_AUTORUN, &CMy2015RemoteDlg::OnProxyPortAutorun)
|
||||||
ON_COMMAND(ID_SCREENPREVIEW_LOOP, &CMy2015RemoteDlg::OnScreenpreviewLoop)
|
ON_COMMAND(ID_SCREENPREVIEW_LOOP, &CMy2015RemoteDlg::OnScreenpreviewLoop)
|
||||||
|
ON_COMMAND(ID_MENU_COMPRESS, &CMy2015RemoteDlg::OnMenuCompress)
|
||||||
|
ON_COMMAND(ID_MENU_UNCOMPRESS, &CMy2015RemoteDlg::OnMenuUncompress)
|
||||||
END_MESSAGE_MAP()
|
END_MESSAGE_MAP()
|
||||||
|
|
||||||
|
|
||||||
@@ -989,6 +992,8 @@ VOID CMy2015RemoteDlg::CreateSolidMenu()
|
|||||||
m_MainMenu.SetMenuItemBitmaps(ID_MAIN_NETWORK, MF_BYCOMMAND, &m_bmOnline[29], &m_bmOnline[29]);
|
m_MainMenu.SetMenuItemBitmaps(ID_MAIN_NETWORK, MF_BYCOMMAND, &m_bmOnline[29], &m_bmOnline[29]);
|
||||||
m_MainMenu.SetMenuItemBitmaps(ID_TRIGGER_SETTINGS, MF_BYCOMMAND, &m_bmOnline[51], &m_bmOnline[51]);
|
m_MainMenu.SetMenuItemBitmaps(ID_TRIGGER_SETTINGS, MF_BYCOMMAND, &m_bmOnline[51], &m_bmOnline[51]);
|
||||||
m_MainMenu.SetMenuItemBitmaps(ID_MAIN_EXIT, MF_BYCOMMAND, &m_bmOnline[26], &m_bmOnline[26]);
|
m_MainMenu.SetMenuItemBitmaps(ID_MAIN_EXIT, MF_BYCOMMAND, &m_bmOnline[26], &m_bmOnline[26]);
|
||||||
|
m_MainMenu.SetMenuItemBitmaps(ID_MENU_COMPRESS, MF_BYCOMMAND, &m_bmOnline[55], &m_bmOnline[55]);
|
||||||
|
m_MainMenu.SetMenuItemBitmaps(ID_MENU_UNCOMPRESS, MF_BYCOMMAND, &m_bmOnline[56], &m_bmOnline[56]);
|
||||||
// Tools menu
|
// Tools menu
|
||||||
m_MainMenu.SetMenuItemBitmaps(ID_TOOL_INPUT_PASSWORD, MF_BYCOMMAND, &m_bmOnline[30], &m_bmOnline[30]);
|
m_MainMenu.SetMenuItemBitmaps(ID_TOOL_INPUT_PASSWORD, MF_BYCOMMAND, &m_bmOnline[30], &m_bmOnline[30]);
|
||||||
m_MainMenu.SetMenuItemBitmaps(ID_TOOL_IMPORT_LICENSE, MF_BYCOMMAND, &m_bmOnline[31], &m_bmOnline[31]);
|
m_MainMenu.SetMenuItemBitmaps(ID_TOOL_IMPORT_LICENSE, MF_BYCOMMAND, &m_bmOnline[31], &m_bmOnline[31]);
|
||||||
@@ -10915,3 +10920,112 @@ void CMy2015RemoteDlg::OnScreenpreviewLoop()
|
|||||||
ShowMessage(_TR("提示"), msg);
|
ShowMessage(_TR("提示"), msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ===== ZSTA 压缩 / 解压 =====
|
||||||
|
#include "ZstdArchive.h"
|
||||||
|
#include "ZstaPickerDlg.h"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
// 把一组源路径压缩为单个 .zsta 文件(弹出保存对话框选择输出)
|
||||||
|
// 调用者只负责传路径,输出路径与压缩过程由本函数处理
|
||||||
|
void CompressPathsToZsta(CWnd* parent, const std::vector<std::string>& srcPaths)
|
||||||
|
{
|
||||||
|
if (srcPaths.empty()) return;
|
||||||
|
|
||||||
|
// 默认输出文件名:第一个源的 basename 或 archive
|
||||||
|
std::string defaultName;
|
||||||
|
{
|
||||||
|
std::string first = srcPaths[0];
|
||||||
|
while (!first.empty() && (first.back() == '/' || first.back() == '\\'))
|
||||||
|
first.pop_back();
|
||||||
|
size_t pos = first.find_last_of("/\\");
|
||||||
|
defaultName = (pos == std::string::npos) ? first : first.substr(pos + 1);
|
||||||
|
if (srcPaths.size() > 1) defaultName = "archive";
|
||||||
|
defaultName += ".zsta";
|
||||||
|
}
|
||||||
|
|
||||||
|
CFileDialog saveDlg(FALSE, _T("zsta"), CString(defaultName.c_str()),
|
||||||
|
OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
|
||||||
|
_T("ZSTA Files (*.zsta)|*.zsta|All Files (*.*)|*.*||"),
|
||||||
|
parent);
|
||||||
|
CString saveTitle = _TR("选择压缩输出文件");
|
||||||
|
saveDlg.m_ofn.lpstrTitle = saveTitle;
|
||||||
|
if (saveDlg.DoModal() != IDOK) return;
|
||||||
|
|
||||||
|
std::string outPath = std::string(CT2A(saveDlg.GetPathName().GetString()));
|
||||||
|
auto err = zsta::CZstdArchive::Compress(srcPaths, outPath, 3);
|
||||||
|
if (err == zsta::Error::Success) {
|
||||||
|
Mprintf("ZSTA 压缩成功: %u 项 -> %s\n",
|
||||||
|
(unsigned)srcPaths.size(), outPath.c_str());
|
||||||
|
CString msg;
|
||||||
|
msg.FormatL("压缩成功 (%u 项):\n%s",
|
||||||
|
(unsigned)srcPaths.size(), outPath.c_str());
|
||||||
|
parent->MessageBox(msg, _TR("提示"), MB_OK | MB_ICONINFORMATION);
|
||||||
|
} else {
|
||||||
|
Mprintf("ZSTA 压缩失败 [%s]: -> %s\n",
|
||||||
|
zsta::CZstdArchive::GetErrorString(err), outPath.c_str());
|
||||||
|
CString msg;
|
||||||
|
msg.FormatL("压缩失败: %s", zsta::CZstdArchive::GetErrorString(err));
|
||||||
|
parent->MessageBox(msg, _TR("错误"), MB_OK | MB_ICONERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
void CMy2015RemoteDlg::OnMenuCompress()
|
||||||
|
{
|
||||||
|
CZstaPickerDlg picker(this);
|
||||||
|
if (picker.DoModal() != IDOK) return;
|
||||||
|
if (picker.m_Paths.empty()) {
|
||||||
|
MessageBoxL("未选择任何文件或文件夹", "提示", MB_OK | MB_ICONINFORMATION);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
CompressPathsToZsta(this, picker.m_Paths);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMy2015RemoteDlg::OnMenuUncompress()
|
||||||
|
{
|
||||||
|
const DWORD MAX_BUF = 64 * 1024;
|
||||||
|
std::vector<TCHAR> buf(MAX_BUF, 0);
|
||||||
|
CFileDialog dlg(TRUE, _T("zsta"), NULL,
|
||||||
|
OFN_ALLOWMULTISELECT | OFN_EXPLORER |
|
||||||
|
OFN_HIDEREADONLY | OFN_FILEMUSTEXIST,
|
||||||
|
_T("ZSTA Files (*.zsta)|*.zsta|All Files (*.*)|*.*||"), this);
|
||||||
|
dlg.m_ofn.lpstrFile = buf.data();
|
||||||
|
dlg.m_ofn.nMaxFile = MAX_BUF;
|
||||||
|
CString title = _TR("请选择要解压的 ZSTA 文件 (可多选)");
|
||||||
|
dlg.m_ofn.lpstrTitle = title;
|
||||||
|
if (dlg.DoModal() != IDOK) return;
|
||||||
|
|
||||||
|
int ok = 0, fail = 0;
|
||||||
|
POSITION pos = dlg.GetStartPosition();
|
||||||
|
while (pos) {
|
||||||
|
CString cpath = dlg.GetNextPathName(pos);
|
||||||
|
std::string src(CT2A(cpath.GetString()));
|
||||||
|
|
||||||
|
// 目标目录:去掉 .zsta 后缀;若无该后缀则追加 _extract
|
||||||
|
std::string dst;
|
||||||
|
if (src.size() >= 5) {
|
||||||
|
std::string ext = src.substr(src.size() - 5);
|
||||||
|
for (char& c : ext) c = (char)tolower((unsigned char)c);
|
||||||
|
if (ext == ".zsta") dst = src.substr(0, src.size() - 5);
|
||||||
|
}
|
||||||
|
if (dst.empty()) dst = src + "_extract";
|
||||||
|
|
||||||
|
auto err = zsta::CZstdArchive::Extract(src, dst);
|
||||||
|
if (err == zsta::Error::Success) {
|
||||||
|
++ok;
|
||||||
|
Mprintf("ZSTA 解压成功: %s -> %s\n", src.c_str(), dst.c_str());
|
||||||
|
} else {
|
||||||
|
++fail;
|
||||||
|
Mprintf("ZSTA 解压失败 [%s]: %s\n",
|
||||||
|
zsta::CZstdArchive::GetErrorString(err), src.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CString msg;
|
||||||
|
msg.FormatL("解压完成: 成功 %d, 失败 %d", ok, fail);
|
||||||
|
MessageBox(msg, _TR("提示"),
|
||||||
|
MB_OK | (fail > 0 ? MB_ICONWARNING : MB_ICONINFORMATION));
|
||||||
|
}
|
||||||
|
|||||||
@@ -364,7 +364,7 @@ public:
|
|||||||
bool IsDllRequestLimited(const std::string& ip);
|
bool IsDllRequestLimited(const std::string& ip);
|
||||||
void RecordDllRequest(const std::string& ip);
|
void RecordDllRequest(const std::string& ip);
|
||||||
CMenu m_MainMenu;
|
CMenu m_MainMenu;
|
||||||
CBitmap m_bmOnline[55]; // 21 original + 4 context menu + 2 tray menu + 23 main menu + 3 new menu icons + 1 snapshot
|
CBitmap m_bmOnline[57]; // 21 original + 4 context menu + 2 tray menu + 25 main menu + 3 new menu icons + 1 snapshot
|
||||||
uint64_t m_superID;
|
uint64_t m_superID;
|
||||||
std::map<HWND, CDialogBase *> m_RemoteWnds;
|
std::map<HWND, CDialogBase *> m_RemoteWnds;
|
||||||
FileTransformCmd m_CmdList;
|
FileTransformCmd m_CmdList;
|
||||||
@@ -604,4 +604,6 @@ public:
|
|||||||
afx_msg void OnWebRemoteControl();
|
afx_msg void OnWebRemoteControl();
|
||||||
afx_msg void OnProxyPortAutorun();
|
afx_msg void OnProxyPortAutorun();
|
||||||
afx_msg void OnScreenpreviewLoop();
|
afx_msg void OnScreenpreviewLoop();
|
||||||
|
afx_msg void OnMenuCompress();
|
||||||
|
afx_msg void OnMenuUncompress();
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -334,6 +334,7 @@
|
|||||||
<ClInclude Include="HideScreenSpyDlg.h" />
|
<ClInclude Include="HideScreenSpyDlg.h" />
|
||||||
<ClInclude Include="HostInfo.h" />
|
<ClInclude Include="HostInfo.h" />
|
||||||
<ClInclude Include="InputDlg.h" />
|
<ClInclude Include="InputDlg.h" />
|
||||||
|
<ClInclude Include="ZstaPickerDlg.h" />
|
||||||
<ClInclude Include="IOCPKCPServer.h" />
|
<ClInclude Include="IOCPKCPServer.h" />
|
||||||
<ClInclude Include="IOCPServer.h" />
|
<ClInclude Include="IOCPServer.h" />
|
||||||
<ClInclude Include="IOCPUDPServer.h" />
|
<ClInclude Include="IOCPUDPServer.h" />
|
||||||
@@ -459,6 +460,7 @@
|
|||||||
<ClCompile Include="file\CFileTransferModeDlg.cpp" />
|
<ClCompile Include="file\CFileTransferModeDlg.cpp" />
|
||||||
<ClCompile Include="HideScreenSpyDlg.cpp" />
|
<ClCompile Include="HideScreenSpyDlg.cpp" />
|
||||||
<ClCompile Include="InputDlg.cpp" />
|
<ClCompile Include="InputDlg.cpp" />
|
||||||
|
<ClCompile Include="ZstaPickerDlg.cpp" />
|
||||||
<ClCompile Include="IOCPKCPServer.cpp" />
|
<ClCompile Include="IOCPKCPServer.cpp" />
|
||||||
<ClCompile Include="IOCPServer.cpp" />
|
<ClCompile Include="IOCPServer.cpp" />
|
||||||
<ClCompile Include="IOCPUDPServer.cpp" />
|
<ClCompile Include="IOCPUDPServer.cpp" />
|
||||||
@@ -525,7 +527,9 @@
|
|||||||
<Image Include="res\Bitmap\AuthGen.bmp" />
|
<Image Include="res\Bitmap\AuthGen.bmp" />
|
||||||
<Image Include="res\Bitmap\authorize.bmp" />
|
<Image Include="res\Bitmap\authorize.bmp" />
|
||||||
<Image Include="res\Bitmap\Backup.bmp" />
|
<Image Include="res\Bitmap\Backup.bmp" />
|
||||||
|
<Image Include="res\bitmap\bitmap9.bmp" />
|
||||||
<Image Include="res\Bitmap\CancelShare.bmp" />
|
<Image Include="res\Bitmap\CancelShare.bmp" />
|
||||||
|
<Image Include="res\bitmap\compress.bmp" />
|
||||||
<Image Include="res\Bitmap\delete.bmp" />
|
<Image Include="res\Bitmap\delete.bmp" />
|
||||||
<Image Include="res\Bitmap\DxgiDesktop.bmp" />
|
<Image Include="res\Bitmap\DxgiDesktop.bmp" />
|
||||||
<Image Include="res\Bitmap\EditGroup.bmp" />
|
<Image Include="res\Bitmap\EditGroup.bmp" />
|
||||||
@@ -569,6 +573,7 @@
|
|||||||
<Image Include="res\Bitmap\Trial.bmp" />
|
<Image Include="res\Bitmap\Trial.bmp" />
|
||||||
<Image Include="res\Bitmap\Trigger.bmp" />
|
<Image Include="res\Bitmap\Trigger.bmp" />
|
||||||
<Image Include="res\Bitmap\unauthorize.bmp" />
|
<Image Include="res\Bitmap\unauthorize.bmp" />
|
||||||
|
<Image Include="res\bitmap\uncompress.bmp" />
|
||||||
<Image Include="res\Bitmap\update.bmp" />
|
<Image Include="res\Bitmap\update.bmp" />
|
||||||
<Image Include="res\Bitmap\VirtualDesktop.bmp" />
|
<Image Include="res\Bitmap\VirtualDesktop.bmp" />
|
||||||
<Image Include="res\Bitmap\Wallet.bmp" />
|
<Image Include="res\Bitmap\Wallet.bmp" />
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
<ClCompile Include="FileTransferModeDlg.cpp" />
|
<ClCompile Include="FileTransferModeDlg.cpp" />
|
||||||
<ClCompile Include="HideScreenSpyDlg.cpp" />
|
<ClCompile Include="HideScreenSpyDlg.cpp" />
|
||||||
<ClCompile Include="InputDlg.cpp" />
|
<ClCompile Include="InputDlg.cpp" />
|
||||||
|
<ClCompile Include="ZstaPickerDlg.cpp" />
|
||||||
<ClCompile Include="IOCPServer.cpp" />
|
<ClCompile Include="IOCPServer.cpp" />
|
||||||
<ClCompile Include="KeyBoardDlg.cpp" />
|
<ClCompile Include="KeyBoardDlg.cpp" />
|
||||||
<ClCompile Include="Loader.c" />
|
<ClCompile Include="Loader.c" />
|
||||||
@@ -107,6 +108,7 @@
|
|||||||
<ClInclude Include="FileTransferModeDlg.h" />
|
<ClInclude Include="FileTransferModeDlg.h" />
|
||||||
<ClInclude Include="HideScreenSpyDlg.h" />
|
<ClInclude Include="HideScreenSpyDlg.h" />
|
||||||
<ClInclude Include="InputDlg.h" />
|
<ClInclude Include="InputDlg.h" />
|
||||||
|
<ClInclude Include="ZstaPickerDlg.h" />
|
||||||
<ClInclude Include="IOCPServer.h" />
|
<ClInclude Include="IOCPServer.h" />
|
||||||
<ClInclude Include="KeyBoardDlg.h" />
|
<ClInclude Include="KeyBoardDlg.h" />
|
||||||
<ClInclude Include="proxy\HPSocket.h" />
|
<ClInclude Include="proxy\HPSocket.h" />
|
||||||
@@ -275,6 +277,9 @@
|
|||||||
<Image Include="res\Bitmap\Trigger.bmp" />
|
<Image Include="res\Bitmap\Trigger.bmp" />
|
||||||
<Image Include="res\Bitmap\WebDesktop.bmp" />
|
<Image Include="res\Bitmap\WebDesktop.bmp" />
|
||||||
<Image Include="res\Bitmap\PluginConfig.bmp" />
|
<Image Include="res\Bitmap\PluginConfig.bmp" />
|
||||||
|
<Image Include="res\bitmap\bitmap9.bmp" />
|
||||||
|
<Image Include="res\bitmap\compress.bmp" />
|
||||||
|
<Image Include="res\bitmap\uncompress.bmp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="..\..\Release\ghost.exe" />
|
<None Include="..\..\Release\ghost.exe" />
|
||||||
|
|||||||
260
server/2015Remote/ZstaPickerDlg.cpp
Normal file
260
server/2015Remote/ZstaPickerDlg.cpp
Normal file
@@ -0,0 +1,260 @@
|
|||||||
|
#include "stdafx.h"
|
||||||
|
#include "ZstaPickerDlg.h"
|
||||||
|
#include "LangManager.h"
|
||||||
|
#include <shobjidl.h>
|
||||||
|
#include <atlconv.h>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
#define new DEBUG_NEW
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
bool IsDirectoryPath(const std::string& p)
|
||||||
|
{
|
||||||
|
DWORD attr = GetFileAttributesA(p.c_str());
|
||||||
|
return (attr != INVALID_FILE_ATTRIBUTES) && (attr & FILE_ATTRIBUTE_DIRECTORY);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构造一个无控件的 DLGTEMPLATE:cdit=0,控件由 OnInitDialog 动态创建。
|
||||||
|
void BuildDialogTemplate(std::vector<BYTE>& out, LPCWSTR caption,
|
||||||
|
short cx, short cy)
|
||||||
|
{
|
||||||
|
out.clear();
|
||||||
|
auto append = [&](const void* p, size_t n) {
|
||||||
|
const BYTE* b = (const BYTE*)p;
|
||||||
|
out.insert(out.end(), b, b + n);
|
||||||
|
};
|
||||||
|
auto appendW = [&](WORD v) {
|
||||||
|
out.push_back((BYTE)(v & 0xFF));
|
||||||
|
out.push_back((BYTE)((v >> 8) & 0xFF));
|
||||||
|
};
|
||||||
|
auto appendWStr = [&](LPCWSTR s) {
|
||||||
|
size_t n = wcslen(s);
|
||||||
|
append(s, (n + 1) * sizeof(WCHAR));
|
||||||
|
};
|
||||||
|
|
||||||
|
DLGTEMPLATE dt = { 0 };
|
||||||
|
dt.style = DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER |
|
||||||
|
WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME;
|
||||||
|
dt.dwExtendedStyle = 0;
|
||||||
|
dt.cdit = 0;
|
||||||
|
dt.x = 0; dt.y = 0;
|
||||||
|
dt.cx = cx; dt.cy = cy;
|
||||||
|
append(&dt, sizeof(dt));
|
||||||
|
appendW(0); // no menu
|
||||||
|
appendW(0); // default dialog class
|
||||||
|
appendWStr(caption); // caption
|
||||||
|
appendW(8); // font point size
|
||||||
|
appendWStr(L"MS Shell Dlg"); // typeface
|
||||||
|
|
||||||
|
while (out.size() % 4) out.push_back(0); // DWORD align
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
|
||||||
|
CZstaPickerDlg::CZstaPickerDlg(CWnd* parent)
|
||||||
|
: CDialog((LPCTSTR)NULL, parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
BEGIN_MESSAGE_MAP(CZstaPickerDlg, CDialog)
|
||||||
|
ON_BN_CLICKED(IDC_ZSTA_ADDFILES, &CZstaPickerDlg::OnAddFiles)
|
||||||
|
ON_BN_CLICKED(IDC_ZSTA_ADDFOLDERS, &CZstaPickerDlg::OnAddFolders)
|
||||||
|
ON_BN_CLICKED(IDC_ZSTA_REMOVE, &CZstaPickerDlg::OnRemove)
|
||||||
|
ON_WM_SIZE()
|
||||||
|
END_MESSAGE_MAP()
|
||||||
|
|
||||||
|
INT_PTR CZstaPickerDlg::DoModal()
|
||||||
|
{
|
||||||
|
CString title = _TR("选择要压缩的文件 / 文件夹");
|
||||||
|
USES_CONVERSION;
|
||||||
|
BuildDialogTemplate(m_Template, T2CW(title), 360, 220);
|
||||||
|
InitModalIndirect((LPCDLGTEMPLATE)m_Template.data());
|
||||||
|
return CDialog::DoModal();
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL CZstaPickerDlg::OnInitDialog()
|
||||||
|
{
|
||||||
|
CDialog::OnInitDialog();
|
||||||
|
|
||||||
|
CRect cli;
|
||||||
|
GetClientRect(&cli);
|
||||||
|
|
||||||
|
// 占位 rect,真正布局在 LayoutControls 里
|
||||||
|
CRect r0(0, 0, 10, 10);
|
||||||
|
|
||||||
|
m_List.Create(WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP |
|
||||||
|
LVS_REPORT | LVS_SHOWSELALWAYS,
|
||||||
|
r0, this, IDC_ZSTA_LIST);
|
||||||
|
m_List.SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);
|
||||||
|
m_List.InsertColumn(0, _TR("类型"), LVCFMT_LEFT, 60);
|
||||||
|
m_List.InsertColumn(1, _TR("路径"), LVCFMT_LEFT, 400);
|
||||||
|
|
||||||
|
auto mkBtn = [&](CButton& b, LPCTSTR text, int id, DWORD extra = 0) {
|
||||||
|
b.Create(text,
|
||||||
|
WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON | extra,
|
||||||
|
r0, this, id);
|
||||||
|
};
|
||||||
|
mkBtn(m_BtnAddFiles, _TR("添加文件..."), IDC_ZSTA_ADDFILES);
|
||||||
|
mkBtn(m_BtnAddFolders, _TR("添加文件夹..."), IDC_ZSTA_ADDFOLDERS);
|
||||||
|
mkBtn(m_BtnRemove, _TR("移除选中"), IDC_ZSTA_REMOVE);
|
||||||
|
mkBtn(m_BtnOK, _TR("确定"), IDOK, BS_DEFPUSHBUTTON);
|
||||||
|
mkBtn(m_BtnCancel, _TR("取消"), IDCANCEL);
|
||||||
|
|
||||||
|
// 子控件继承对话框的字体 (DS_SETFONT)
|
||||||
|
HFONT hFont = (HFONT)::SendMessage(GetSafeHwnd(), WM_GETFONT, 0, 0);
|
||||||
|
if (hFont) {
|
||||||
|
m_List.SendMessage(WM_SETFONT, (WPARAM)hFont, MAKELPARAM(TRUE, 0));
|
||||||
|
m_BtnAddFiles.SendMessage(WM_SETFONT, (WPARAM)hFont, MAKELPARAM(TRUE, 0));
|
||||||
|
m_BtnAddFolders.SendMessage(WM_SETFONT, (WPARAM)hFont, MAKELPARAM(TRUE, 0));
|
||||||
|
m_BtnRemove.SendMessage(WM_SETFONT, (WPARAM)hFont, MAKELPARAM(TRUE, 0));
|
||||||
|
m_BtnOK.SendMessage(WM_SETFONT, (WPARAM)hFont, MAKELPARAM(TRUE, 0));
|
||||||
|
m_BtnCancel.SendMessage(WM_SETFONT, (WPARAM)hFont, MAKELPARAM(TRUE, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
LayoutControls(cli.Width(), cli.Height());
|
||||||
|
RefreshList();
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CZstaPickerDlg::OnSize(UINT nType, int cx, int cy)
|
||||||
|
{
|
||||||
|
CDialog::OnSize(nType, cx, cy);
|
||||||
|
if (m_List.GetSafeHwnd()) LayoutControls(cx, cy);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CZstaPickerDlg::LayoutControls(int cx, int cy)
|
||||||
|
{
|
||||||
|
const int margin = 10;
|
||||||
|
const int btnW = 120;
|
||||||
|
const int btnH = 26;
|
||||||
|
const int gap = 6;
|
||||||
|
|
||||||
|
int listRight = cx - margin - btnW - margin;
|
||||||
|
if (listRight < margin + 100) listRight = margin + 100;
|
||||||
|
|
||||||
|
m_List.MoveWindow(margin, margin, listRight - margin, cy - margin * 2);
|
||||||
|
|
||||||
|
int x = listRight + margin;
|
||||||
|
int y = margin;
|
||||||
|
m_BtnAddFiles.MoveWindow(x, y, btnW, btnH); y += btnH + gap;
|
||||||
|
m_BtnAddFolders.MoveWindow(x, y, btnW, btnH); y += btnH + gap;
|
||||||
|
m_BtnRemove.MoveWindow(x, y, btnW, btnH);
|
||||||
|
|
||||||
|
int bottomY = cy - margin - btnH;
|
||||||
|
m_BtnCancel.MoveWindow(x, bottomY, btnW, btnH);
|
||||||
|
m_BtnOK.MoveWindow(x, bottomY - btnH - gap, btnW, btnH);
|
||||||
|
|
||||||
|
// 让"路径"列填满剩余宽度
|
||||||
|
if (m_List.GetSafeHwnd()) {
|
||||||
|
CRect lr;
|
||||||
|
m_List.GetClientRect(&lr);
|
||||||
|
int w0 = m_List.GetColumnWidth(0);
|
||||||
|
int w1 = lr.Width() - w0 - GetSystemMetrics(SM_CXVSCROLL) - 4;
|
||||||
|
if (w1 > 100) m_List.SetColumnWidth(1, w1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CZstaPickerDlg::AddPath(const std::string& path)
|
||||||
|
{
|
||||||
|
if (path.empty()) return;
|
||||||
|
if (std::find(m_Paths.begin(), m_Paths.end(), path) == m_Paths.end()) {
|
||||||
|
m_Paths.push_back(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CZstaPickerDlg::RefreshList()
|
||||||
|
{
|
||||||
|
m_List.DeleteAllItems();
|
||||||
|
for (size_t i = 0; i < m_Paths.size(); ++i) {
|
||||||
|
bool isDir = IsDirectoryPath(m_Paths[i]);
|
||||||
|
m_List.InsertItem((int)i, isDir ? _TR("文件夹") : _TR("文件"));
|
||||||
|
m_List.SetItemText((int)i, 1, CString(m_Paths[i].c_str()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CZstaPickerDlg::OnAddFiles()
|
||||||
|
{
|
||||||
|
const DWORD MAX_BUF = 64 * 1024;
|
||||||
|
std::vector<TCHAR> buf(MAX_BUF, 0);
|
||||||
|
CFileDialog dlg(TRUE, NULL, NULL,
|
||||||
|
OFN_ALLOWMULTISELECT | OFN_EXPLORER |
|
||||||
|
OFN_HIDEREADONLY | OFN_FILEMUSTEXIST,
|
||||||
|
_T("All Files (*.*)|*.*||"), this);
|
||||||
|
dlg.m_ofn.lpstrFile = buf.data();
|
||||||
|
dlg.m_ofn.nMaxFile = MAX_BUF;
|
||||||
|
CString title = _TR("选择文件 (可多选)");
|
||||||
|
dlg.m_ofn.lpstrTitle = title;
|
||||||
|
if (dlg.DoModal() != IDOK) return;
|
||||||
|
|
||||||
|
POSITION pos = dlg.GetStartPosition();
|
||||||
|
while (pos) {
|
||||||
|
CString p = dlg.GetNextPathName(pos);
|
||||||
|
AddPath(std::string(CT2A(p.GetString())));
|
||||||
|
}
|
||||||
|
RefreshList();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CZstaPickerDlg::OnAddFolders()
|
||||||
|
{
|
||||||
|
IFileOpenDialog* pfd = nullptr;
|
||||||
|
HRESULT hr = CoCreateInstance(CLSID_FileOpenDialog, NULL,
|
||||||
|
CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pfd));
|
||||||
|
if (FAILED(hr) || !pfd) return;
|
||||||
|
|
||||||
|
DWORD flags = 0;
|
||||||
|
pfd->GetOptions(&flags);
|
||||||
|
pfd->SetOptions(flags | FOS_PICKFOLDERS | FOS_ALLOWMULTISELECT |
|
||||||
|
FOS_PATHMUSTEXIST | FOS_FORCEFILESYSTEM);
|
||||||
|
|
||||||
|
USES_CONVERSION;
|
||||||
|
CString title = _TR("选择文件夹 (可多选)");
|
||||||
|
pfd->SetTitle(T2CW(title));
|
||||||
|
|
||||||
|
if (SUCCEEDED(pfd->Show(GetSafeHwnd()))) {
|
||||||
|
IShellItemArray* psia = nullptr;
|
||||||
|
if (SUCCEEDED(pfd->GetResults(&psia)) && psia) {
|
||||||
|
DWORD count = 0;
|
||||||
|
psia->GetCount(&count);
|
||||||
|
for (DWORD i = 0; i < count; ++i) {
|
||||||
|
IShellItem* psi = nullptr;
|
||||||
|
if (SUCCEEDED(psia->GetItemAt(i, &psi)) && psi) {
|
||||||
|
PWSTR wpath = nullptr;
|
||||||
|
if (SUCCEEDED(psi->GetDisplayName(SIGDN_FILESYSPATH, &wpath)) && wpath) {
|
||||||
|
int n = WideCharToMultiByte(CP_ACP, 0, wpath, -1,
|
||||||
|
NULL, 0, NULL, NULL);
|
||||||
|
if (n > 1) {
|
||||||
|
std::string s(n - 1, '\0');
|
||||||
|
WideCharToMultiByte(CP_ACP, 0, wpath, -1,
|
||||||
|
&s[0], n, NULL, NULL);
|
||||||
|
AddPath(s);
|
||||||
|
}
|
||||||
|
CoTaskMemFree(wpath);
|
||||||
|
}
|
||||||
|
psi->Release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
psia->Release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pfd->Release();
|
||||||
|
RefreshList();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CZstaPickerDlg::OnRemove()
|
||||||
|
{
|
||||||
|
std::vector<int> indices;
|
||||||
|
POSITION pos = m_List.GetFirstSelectedItemPosition();
|
||||||
|
while (pos) indices.push_back(m_List.GetNextSelectedItem(pos));
|
||||||
|
|
||||||
|
std::sort(indices.begin(), indices.end(), std::greater<int>());
|
||||||
|
for (int idx : indices) {
|
||||||
|
if (idx >= 0 && idx < (int)m_Paths.size()) {
|
||||||
|
m_Paths.erase(m_Paths.begin() + idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
RefreshList();
|
||||||
|
}
|
||||||
52
server/2015Remote/ZstaPickerDlg.h
Normal file
52
server/2015Remote/ZstaPickerDlg.h
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <afxwin.h>
|
||||||
|
#include <afxcmn.h>
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
// 让用户在同一个对话框里累加要压缩的"文件 + 文件夹"组合:
|
||||||
|
// [添加文件...] 调出多选文件对话框
|
||||||
|
// [添加文件夹...] 调出多选文件夹对话框 (IFileOpenDialog + FOS_PICKFOLDERS)
|
||||||
|
// [移除选中] 从列表里删除
|
||||||
|
// DoModal() 返回 IDOK 时,m_Paths 即为结果 (ANSI/MBCS 路径,与 ZSTA 管道一致)。
|
||||||
|
class CZstaPickerDlg : public CDialog
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit CZstaPickerDlg(CWnd* parent = nullptr);
|
||||||
|
|
||||||
|
virtual INT_PTR DoModal();
|
||||||
|
|
||||||
|
std::vector<std::string> m_Paths;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual BOOL OnInitDialog();
|
||||||
|
|
||||||
|
afx_msg void OnAddFiles();
|
||||||
|
afx_msg void OnAddFolders();
|
||||||
|
afx_msg void OnRemove();
|
||||||
|
afx_msg void OnSize(UINT nType, int cx, int cy);
|
||||||
|
|
||||||
|
DECLARE_MESSAGE_MAP()
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum CtrlId {
|
||||||
|
IDC_ZSTA_LIST = 1001,
|
||||||
|
IDC_ZSTA_ADDFILES = 1002,
|
||||||
|
IDC_ZSTA_ADDFOLDERS = 1003,
|
||||||
|
IDC_ZSTA_REMOVE = 1004,
|
||||||
|
};
|
||||||
|
|
||||||
|
CListCtrl m_List;
|
||||||
|
CButton m_BtnAddFiles;
|
||||||
|
CButton m_BtnAddFolders;
|
||||||
|
CButton m_BtnRemove;
|
||||||
|
CButton m_BtnOK;
|
||||||
|
CButton m_BtnCancel;
|
||||||
|
|
||||||
|
std::vector<BYTE> m_Template; // in-memory DLGTEMPLATE bytes
|
||||||
|
|
||||||
|
void AddPath(const std::string& path);
|
||||||
|
void RefreshList();
|
||||||
|
void LayoutControls(int cx, int cy);
|
||||||
|
};
|
||||||
@@ -1894,3 +1894,33 @@ FRPC Զ
|
|||||||
创建AVI文件失败=Create AVI file failed
|
创建AVI文件失败=Create AVI file failed
|
||||||
启用 H264 硬编码=Enable HW H264 Encoding
|
启用 H264 硬编码=Enable HW H264 Encoding
|
||||||
启用 AV1 硬编码=Enable HW AV1 Encoding
|
启用 AV1 硬编码=Enable HW AV1 Encoding
|
||||||
|
; ZSTA Compress / Picker Dialog - English Translation
|
||||||
|
; Format: Simplified Chinese=English
|
||||||
|
|
||||||
|
; --- Picker dialog (CZstaPickerDlg) ---
|
||||||
|
选择要压缩的文件 / 文件夹=Select Files / Folders to Compress
|
||||||
|
添加文件...=Add Files...
|
||||||
|
添加文件夹...=Add Folders...
|
||||||
|
移除选中=Remove Selected
|
||||||
|
类型=Type
|
||||||
|
路径=Path
|
||||||
|
文件=File
|
||||||
|
文件夹=Folder
|
||||||
|
选择文件 (可多选)=Select Files (multi-select)
|
||||||
|
选择文件夹 (可多选)=Select Folders (multi-select)
|
||||||
|
|
||||||
|
; --- Compress / Extract handlers (CMy2015RemoteDlg) ---
|
||||||
|
未选择任何文件或文件夹=No file or folder selected
|
||||||
|
选择压缩输出文件=Choose Output Archive
|
||||||
|
请选择要解压的 ZSTA 文件 (可多选)=Choose ZSTA File(s) to Extract (multi-select)
|
||||||
|
压缩成功 (%u 项):\n%s=Compression succeeded (%u item(s)):\n%s
|
||||||
|
压缩失败: %s=Compression failed: %s
|
||||||
|
解压完成: 成功 %d, 失败 %d=Extraction complete: %d succeeded, %d failed
|
||||||
|
|
||||||
|
; --- Common (likely already present in en_US.ini; included for completeness) ---
|
||||||
|
确定=OK
|
||||||
|
取消=Cancel
|
||||||
|
提示=Notice
|
||||||
|
错误=Error
|
||||||
|
压缩(&C)=&Compress
|
||||||
|
解压缩(&U)=&Uncompress
|
||||||
|
|||||||
@@ -1885,3 +1885,33 @@ FRPC Զ
|
|||||||
创建AVI文件失败=创建AVI文件失败
|
创建AVI文件失败=创建AVI文件失败
|
||||||
启用 H264 硬编码=启用 H264 硬编码
|
启用 H264 硬编码=启用 H264 硬编码
|
||||||
启用 AV1 硬编码=启用 AV1 硬编码
|
启用 AV1 硬编码=启用 AV1 硬编码
|
||||||
|
; ZSTA Compress / Picker Dialog - Traditional Chinese Translation
|
||||||
|
; Format: Simplified Chinese=Traditional Chinese
|
||||||
|
|
||||||
|
; --- Picker dialog (CZstaPickerDlg) ---
|
||||||
|
选择要压缩的文件 / 文件夹=選擇要壓縮的檔案 / 資料夾
|
||||||
|
添加文件...=新增檔案...
|
||||||
|
添加文件夹...=新增資料夾...
|
||||||
|
移除选中=移除選取項
|
||||||
|
类型=類型
|
||||||
|
路径=路徑
|
||||||
|
文件=檔案
|
||||||
|
文件夹=資料夾
|
||||||
|
选择文件 (可多选)=選擇檔案 (可多選)
|
||||||
|
选择文件夹 (可多选)=選擇資料夾 (可多選)
|
||||||
|
|
||||||
|
; --- Compress / Extract handlers (CMy2015RemoteDlg) ---
|
||||||
|
未选择任何文件或文件夹=未選擇任何檔案或資料夾
|
||||||
|
选择压缩输出文件=選擇壓縮輸出檔案
|
||||||
|
请选择要解压的 ZSTA 文件 (可多选)=請選擇要解壓縮的 ZSTA 檔案 (可多選)
|
||||||
|
压缩成功 (%u 项):\n%s=壓縮成功 (%u 項):\n%s
|
||||||
|
压缩失败: %s=壓縮失敗: %s
|
||||||
|
解压完成: 成功 %d, 失败 %d=解壓縮完成: 成功 %d, 失敗 %d
|
||||||
|
|
||||||
|
; --- Common (likely already present in zh_TW.ini; included for completeness) ---
|
||||||
|
确定=確定
|
||||||
|
取消=取消
|
||||||
|
提示=提示
|
||||||
|
错误=錯誤
|
||||||
|
压缩(&C)=壓縮(&C)
|
||||||
|
解压缩(&U)=解壓縮(&U)
|
||||||
|
|||||||
BIN
server/2015Remote/res/Bitmap/compress.bmp
Normal file
BIN
server/2015Remote/res/Bitmap/compress.bmp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 822 B |
BIN
server/2015Remote/res/Bitmap/uncompress.bmp
Normal file
BIN
server/2015Remote/res/Bitmap/uncompress.bmp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 822 B |
@@ -263,6 +263,9 @@
|
|||||||
#define IDR_WEB_XTERM_CSS 383
|
#define IDR_WEB_XTERM_CSS 383
|
||||||
#define IDR_WEB_XTERM_FIT_JS 384
|
#define IDR_WEB_XTERM_FIT_JS 384
|
||||||
#define IDR_WEB_INDEX_HTML 385
|
#define IDR_WEB_INDEX_HTML 385
|
||||||
|
#define IDB_BITMAP_COMPRESS 386
|
||||||
|
#define IDB_BITMAP9 387
|
||||||
|
#define IDB_BITMAP_UNCOMPRESS 387
|
||||||
#define IDC_MESSAGE 1000
|
#define IDC_MESSAGE 1000
|
||||||
#define IDC_ONLINE 1001
|
#define IDC_ONLINE 1001
|
||||||
#define IDC_STATIC_TIPS 1002
|
#define IDC_STATIC_TIPS 1002
|
||||||
@@ -985,14 +988,19 @@
|
|||||||
#define ID_PARAM_THUMBNAIL_PREVIEW 33050
|
#define ID_PARAM_THUMBNAIL_PREVIEW 33050
|
||||||
#define ID_LICENSE_AUTO_FRP 33051
|
#define ID_LICENSE_AUTO_FRP 33051
|
||||||
#define ID_LICENSE_REVOKE_FRP 33052
|
#define ID_LICENSE_REVOKE_FRP 33052
|
||||||
|
#define ID_Menu 33053
|
||||||
|
#define ID_33054 33054
|
||||||
|
#define ID_MENU_COMPRESS 33055
|
||||||
|
#define ID_33056 33056
|
||||||
|
#define ID_MENU_UNCOMPRESS 33057
|
||||||
#define ID_EXIT_FULLSCREEN 40001
|
#define ID_EXIT_FULLSCREEN 40001
|
||||||
|
|
||||||
// Next default values for new objects
|
// Next default values for new objects
|
||||||
//
|
//
|
||||||
#ifdef APSTUDIO_INVOKED
|
#ifdef APSTUDIO_INVOKED
|
||||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||||
#define _APS_NEXT_RESOURCE_VALUE 386
|
#define _APS_NEXT_RESOURCE_VALUE 388
|
||||||
#define _APS_NEXT_COMMAND_VALUE 33053
|
#define _APS_NEXT_COMMAND_VALUE 33058
|
||||||
#define _APS_NEXT_CONTROL_VALUE 2542
|
#define _APS_NEXT_CONTROL_VALUE 2542
|
||||||
#define _APS_NEXT_SYMED_VALUE 105
|
#define _APS_NEXT_SYMED_VALUE 105
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user