265 lines
9.1 KiB
C++
265 lines
9.1 KiB
C++
#include "stdafx.h"
|
|
#include "SettingsPanel.h"
|
|
#include "Resource.h"
|
|
#include <shlobj.h>
|
|
|
|
static std::string wide_to_utf8(const std::wstring& w) {
|
|
if (w.empty()) return {};
|
|
int n = WideCharToMultiByte(CP_UTF8, 0, w.c_str(), (int)w.size(), nullptr, 0, nullptr, nullptr);
|
|
if (n <= 0) return {};
|
|
std::string s(n, '\0');
|
|
WideCharToMultiByte(CP_UTF8, 0, w.c_str(), (int)w.size(), s.data(), n, nullptr, nullptr);
|
|
return s;
|
|
}
|
|
|
|
static std::wstring utf8_to_wide(const std::string& s) {
|
|
if (s.empty()) return {};
|
|
int n = MultiByteToWideChar(CP_UTF8, 0, s.c_str(), (int)s.size(), nullptr, 0);
|
|
if (n <= 0) return {};
|
|
std::wstring w(n, L'\0');
|
|
MultiByteToWideChar(CP_UTF8, 0, s.c_str(), (int)s.size(), w.data(), n);
|
|
return w;
|
|
}
|
|
|
|
static std::wstring get_edit_text(HWND h) {
|
|
int n = ::GetWindowTextLengthW(h);
|
|
if (n <= 0) return {};
|
|
std::wstring w(n + 1, L'\0');
|
|
::GetWindowTextW(h, w.data(), n + 1);
|
|
w.resize(n);
|
|
return w;
|
|
}
|
|
|
|
//////////////////////////////////////////
|
|
// CSettingsView
|
|
//////////////////////////////////////////
|
|
|
|
static BOOL CALLBACK SetChildFont(HWND hwnd, LPARAM lparam)
|
|
{
|
|
::SendMessageW(hwnd, WM_SETFONT, (WPARAM)lparam, TRUE);
|
|
return TRUE;
|
|
}
|
|
|
|
int CSettingsView::OnCreate(CREATESTRUCT&)
|
|
{
|
|
CreateControls();
|
|
|
|
HFONT hFont = static_cast<HFONT>(::GetStockObject(DEFAULT_GUI_FONT));
|
|
EnumChildWindows(GetHwnd(), SetChildFont, (LPARAM)hFont);
|
|
|
|
return 0;
|
|
}
|
|
|
|
void CSettingsView::CreateControls()
|
|
{
|
|
const int x0 = 8, lw = 100, gap = 6;
|
|
const int ew = 140, eh = 22;
|
|
int y = 10;
|
|
HINSTANCE inst = GetModuleHandleW(nullptr);
|
|
|
|
auto label = [&](LPCWSTR text, int yoff = 0) {
|
|
CreateWindowExW(0, L"STATIC", text, WS_CHILD | WS_VISIBLE,
|
|
x0, y + yoff, lw, 18, GetHwnd(), nullptr, inst, nullptr);
|
|
};
|
|
|
|
// Output preset
|
|
label(L"Output preset:");
|
|
m_hPreset = CreateWindowExW(WS_EX_CLIENTEDGE, L"COMBOBOX", L"",
|
|
WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST | CBS_HASSTRINGS,
|
|
x0 + lw + gap, y - 2, ew + 40, 140, GetHwnd(), (HMENU)(UINT_PTR)IDC_COMBO_PRESET_OUT, inst, nullptr);
|
|
::SendMessageW(m_hPreset, CB_ADDSTRING, 0, (LPARAM)L"Next to source");
|
|
::SendMessageW(m_hPreset, CB_ADDSTRING, 0, (LPARAM)L"Next to source (_resized)");
|
|
::SendMessageW(m_hPreset, CB_ADDSTRING, 0, (LPARAM)L"Custom folder");
|
|
::SendMessageW(m_hPreset, CB_SETCURSEL, 0, 0);
|
|
y += 30;
|
|
|
|
// Output directory
|
|
label(L"Output folder:");
|
|
m_hOutDir = CreateWindowExW(WS_EX_CLIENTEDGE, L"EDIT", L"",
|
|
WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL,
|
|
x0 + lw + gap, y, ew, eh, GetHwnd(), (HMENU)(UINT_PTR)IDC_EDIT_OUT_DIR, inst, nullptr);
|
|
m_hBtnBrowse = CreateWindowExW(0, L"BUTTON", L"...",
|
|
WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
|
|
x0 + lw + gap + ew + 4, y, 28, eh, GetHwnd(), (HMENU)(UINT_PTR)IDC_BTN_BROWSE_OUT, inst, nullptr);
|
|
y += 30;
|
|
|
|
// Max width / height
|
|
label(L"Max width:");
|
|
m_hMaxW = CreateWindowExW(WS_EX_CLIENTEDGE, L"EDIT", L"0",
|
|
WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL | ES_NUMBER,
|
|
x0 + lw + gap, y, 60, eh, GetHwnd(), (HMENU)(UINT_PTR)IDC_EDIT_MAX_W, inst, nullptr);
|
|
CreateWindowExW(0, L"STATIC", L"Max height:", WS_CHILD | WS_VISIBLE,
|
|
x0 + lw + gap + 68, y, 80, 18, GetHwnd(), nullptr, inst, nullptr);
|
|
m_hMaxH = CreateWindowExW(WS_EX_CLIENTEDGE, L"EDIT", L"0",
|
|
WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL | ES_NUMBER,
|
|
x0 + lw + gap + 68 + 84, y, 60, eh, GetHwnd(), (HMENU)(UINT_PTR)IDC_EDIT_MAX_H, inst, nullptr);
|
|
y += 30;
|
|
|
|
// Fit
|
|
label(L"Fit:");
|
|
m_hFit = CreateWindowExW(WS_EX_CLIENTEDGE, L"COMBOBOX", L"",
|
|
WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST | CBS_HASSTRINGS,
|
|
x0 + lw + gap, y - 2, ew, 140, GetHwnd(), (HMENU)(UINT_PTR)IDC_COMBO_FIT, inst, nullptr);
|
|
const LPCWSTR fits[] = { L"inside", L"cover", L"contain", L"fill", L"outside" };
|
|
for (auto f : fits) ::SendMessageW(m_hFit, CB_ADDSTRING, 0, (LPARAM)f);
|
|
::SendMessageW(m_hFit, CB_SETCURSEL, 0, 0);
|
|
y += 30;
|
|
|
|
// Quality
|
|
label(L"Quality (1-100):");
|
|
m_hQuality = CreateWindowExW(WS_EX_CLIENTEDGE, L"EDIT", L"85",
|
|
WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL | ES_NUMBER,
|
|
x0 + lw + gap, y, 48, eh, GetHwnd(), (HMENU)(UINT_PTR)IDC_EDIT_QUALITY, inst, nullptr);
|
|
y += 30;
|
|
|
|
// Checkboxes
|
|
m_hEnlarge = CreateWindowExW(0, L"BUTTON", L"Allow enlargement",
|
|
WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX,
|
|
x0, y, 180, 22, GetHwnd(), (HMENU)(UINT_PTR)IDC_CHK_ENLARGE, inst, nullptr);
|
|
y += 24;
|
|
|
|
m_hAutorot = CreateWindowExW(0, L"BUTTON", L"EXIF autorotate",
|
|
WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX,
|
|
x0, y, 180, 22, GetHwnd(), (HMENU)(UINT_PTR)IDC_CHK_AUTOROT, inst, nullptr);
|
|
::SendMessageW(m_hAutorot, BM_SETCHECK, BST_CHECKED, 0);
|
|
y += 24;
|
|
|
|
m_hStrip = CreateWindowExW(0, L"BUTTON", L"Strip metadata on save",
|
|
WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX,
|
|
x0, y, 200, 22, GetHwnd(), (HMENU)(UINT_PTR)IDC_CHK_STRIP, inst, nullptr);
|
|
::SendMessageW(m_hStrip, BM_SETCHECK, BST_CHECKED, 0);
|
|
}
|
|
|
|
void CSettingsView::ReadOptions(media::ResizeOptions& opt, std::string& out_dir) const
|
|
{
|
|
int preset = (int)::SendMessageW(m_hPreset, CB_GETCURSEL, 0, 0);
|
|
opt.output_stem_suffix.clear();
|
|
if (preset == 1) opt.output_stem_suffix = "_resized";
|
|
|
|
out_dir.clear();
|
|
if (preset == 2 || !get_edit_text(m_hOutDir).empty())
|
|
out_dir = wide_to_utf8(get_edit_text(m_hOutDir));
|
|
|
|
wchar_t buf[32]{};
|
|
::GetWindowTextW(m_hMaxW, buf, 32);
|
|
opt.max_width = _wtoi(buf);
|
|
if (opt.max_width < 0) opt.max_width = 0;
|
|
|
|
::GetWindowTextW(m_hMaxH, buf, 32);
|
|
opt.max_height = _wtoi(buf);
|
|
if (opt.max_height < 0) opt.max_height = 0;
|
|
|
|
int fi = (int)::SendMessageW(m_hFit, CB_GETCURSEL, 0, 0);
|
|
const char* fits[] = { "inside", "cover", "contain", "fill", "outside" };
|
|
if (fi >= 0 && fi < 5) opt.fit = fits[fi];
|
|
|
|
::GetWindowTextW(m_hQuality, buf, 32);
|
|
opt.quality = _wtoi(buf);
|
|
if (opt.quality < 1) opt.quality = 1;
|
|
if (opt.quality > 100) opt.quality = 100;
|
|
|
|
opt.without_enlargement = ::SendMessageW(m_hEnlarge, BM_GETCHECK, 0, 0) != BST_CHECKED;
|
|
opt.autorotate = ::SendMessageW(m_hAutorot, BM_GETCHECK, 0, 0) == BST_CHECKED;
|
|
opt.strip_metadata = ::SendMessageW(m_hStrip, BM_GETCHECK, 0, 0) == BST_CHECKED;
|
|
}
|
|
|
|
void CSettingsView::WriteOptions(const media::ResizeOptions& opt, const std::string& out_dir)
|
|
{
|
|
int preset = 0;
|
|
if (!out_dir.empty()) preset = 2;
|
|
else if (opt.output_stem_suffix == "_resized") preset = 1;
|
|
::SendMessageW(m_hPreset, CB_SETCURSEL, preset, 0);
|
|
|
|
::SetWindowTextW(m_hOutDir, utf8_to_wide(out_dir).c_str());
|
|
|
|
wchar_t buf[32]{};
|
|
swprintf_s(buf, L"%d", opt.max_width);
|
|
::SetWindowTextW(m_hMaxW, buf);
|
|
swprintf_s(buf, L"%d", opt.max_height);
|
|
::SetWindowTextW(m_hMaxH, buf);
|
|
swprintf_s(buf, L"%d", opt.quality);
|
|
::SetWindowTextW(m_hQuality, buf);
|
|
|
|
::SendMessageW(m_hEnlarge, BM_SETCHECK, opt.without_enlargement ? BST_UNCHECKED : BST_CHECKED, 0);
|
|
::SendMessageW(m_hAutorot, BM_SETCHECK, opt.autorotate ? BST_CHECKED : BST_UNCHECKED, 0);
|
|
::SendMessageW(m_hStrip, BM_SETCHECK, opt.strip_metadata ? BST_CHECKED : BST_UNCHECKED, 0);
|
|
}
|
|
|
|
void CSettingsView::OnBrowseOutput()
|
|
{
|
|
BROWSEINFOW bi{};
|
|
bi.hwndOwner = GetHwnd();
|
|
bi.lpszTitle = L"Choose output folder";
|
|
bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_NEWDIALOGSTYLE;
|
|
wchar_t dn[MAX_PATH]{};
|
|
bi.pszDisplayName = dn;
|
|
PIDLIST_ABSOLUTE pidl = SHBrowseForFolderW(&bi);
|
|
if (!pidl) return;
|
|
wchar_t path[MAX_PATH * 4]{};
|
|
if (SHGetPathFromIDListW(pidl, path))
|
|
::SetWindowTextW(m_hOutDir, path);
|
|
CoTaskMemFree(pidl);
|
|
}
|
|
|
|
LRESULT CSettingsView::WndProc(UINT msg, WPARAM wparam, LPARAM lparam)
|
|
{
|
|
try {
|
|
if (msg == WM_COMMAND) {
|
|
if (LOWORD(wparam) == IDC_BTN_BROWSE_OUT) {
|
|
OnBrowseOutput();
|
|
return 0;
|
|
}
|
|
}
|
|
return WndProcDefault(msg, wparam, lparam);
|
|
}
|
|
catch (const CException& e) {
|
|
CString s;
|
|
s << e.GetText() << L'\n' << e.GetErrorString();
|
|
::MessageBox(nullptr, s, L"Error", MB_ICONERROR);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
//////////////////////////////////////////
|
|
// CSettingsContainer
|
|
//////////////////////////////////////////
|
|
|
|
CSettingsContainer::CSettingsContainer()
|
|
{
|
|
SetTabText(L"Settings");
|
|
SetDockCaption(L"Resize Settings");
|
|
SetView(m_view);
|
|
}
|
|
|
|
LRESULT CSettingsContainer::WndProc(UINT msg, WPARAM wparam, LPARAM lparam)
|
|
{
|
|
try { return WndProcDefault(msg, wparam, lparam); }
|
|
catch (const CException& e) {
|
|
CString s;
|
|
s << e.GetText() << L'\n' << e.GetErrorString();
|
|
::MessageBox(nullptr, s, L"Error", MB_ICONERROR);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
//////////////////////////////////////////
|
|
// CDockSettings
|
|
//////////////////////////////////////////
|
|
|
|
CDockSettings::CDockSettings()
|
|
{
|
|
SetView(m_container);
|
|
SetBarWidth(8);
|
|
}
|
|
|
|
LRESULT CDockSettings::WndProc(UINT msg, WPARAM wparam, LPARAM lparam)
|
|
{
|
|
try { return WndProcDefault(msg, wparam, lparam); }
|
|
catch (const CException& e) {
|
|
CString s;
|
|
s << e.GetText() << L'\n' << e.GetErrorString();
|
|
::MessageBox(nullptr, s, L"Error", MB_ICONERROR);
|
|
}
|
|
return 0;
|
|
}
|