#include "stdafx.h" #include "SettingsPanel.h" #include "Resource.h" #include 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(::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; }