mirror of
https://github.com/chibicitiberiu/rainmeter-studio.git
synced 2024-02-24 04:33:31 +00:00
1403 lines
36 KiB
C++
1403 lines
36 KiB
C++
/*
|
|
Copyright (C) 2012 Birunthan Mohanathas
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License
|
|
as published by the Free Software Foundation; either version 2
|
|
of the License, or (at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
#include "StdAfx.h"
|
|
#include "../Common/StringUtil.h"
|
|
#include "SkinInstaller.h"
|
|
#include "DialogPackage.h"
|
|
#include "DialogInstall.h"
|
|
#include "resource.h"
|
|
#include "../Version.h"
|
|
|
|
#define WM_DELAYED_CLOSE WM_APP + 0
|
|
|
|
extern GlobalData g_Data;
|
|
extern OsNameVersion g_OsNameVersions[];
|
|
|
|
DialogPackage* DialogPackage::c_Dialog = nullptr;
|
|
|
|
DialogPackage::DialogPackage(HWND wnd) : Dialog(wnd),
|
|
m_TabInfo(wnd),
|
|
m_TabOptions(wnd),
|
|
m_TabAdvanced(wnd),
|
|
m_LoadLayout(false),
|
|
m_MergeSkins(false),
|
|
m_PackagerThread(),
|
|
m_ZipFile(),
|
|
m_AllowNonAsciiFilenames(false)
|
|
{
|
|
}
|
|
|
|
DialogPackage::~DialogPackage()
|
|
{
|
|
}
|
|
|
|
void DialogPackage::Create(HINSTANCE hInstance, LPWSTR lpCmdLine)
|
|
{
|
|
HANDLE hMutex;
|
|
if (IsRunning(L"Rainmeter Skin Packager", &hMutex))
|
|
{
|
|
HWND hwnd = FindWindow(L"#32770", L"Rainmeter Skin Packager");
|
|
SetForegroundWindow(hwnd);
|
|
}
|
|
else
|
|
{
|
|
DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_PACKAGE_DIALOG), nullptr, (DLGPROC)DlgProc, (LPARAM)lpCmdLine);
|
|
ReleaseMutex(hMutex);
|
|
}
|
|
}
|
|
|
|
Dialog::Tab& DialogPackage::GetActiveTab()
|
|
{
|
|
int sel = TabCtrl_GetCurSel(GetDlgItem(m_Window, IDC_PACKAGE_TAB));
|
|
if (sel == -1)
|
|
{
|
|
return m_TabInfo;
|
|
}
|
|
else if (sel == 0)
|
|
{
|
|
return m_TabOptions;
|
|
}
|
|
else // if (sel == 1)
|
|
{
|
|
return m_TabAdvanced;
|
|
}
|
|
}
|
|
|
|
INT_PTR CALLBACK DialogPackage::DlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
if (!c_Dialog)
|
|
{
|
|
if (uMsg == WM_INITDIALOG)
|
|
{
|
|
c_Dialog = new DialogPackage(hWnd);
|
|
return c_Dialog->OnInitDialog(wParam, lParam);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch (uMsg)
|
|
{
|
|
case WM_COMMAND:
|
|
return c_Dialog->OnCommand(wParam, lParam);
|
|
|
|
case WM_NOTIFY:
|
|
return c_Dialog->OnNotify(wParam, lParam);
|
|
|
|
case WM_CLOSE:
|
|
{
|
|
if (!c_Dialog->m_PackagerThread)
|
|
{
|
|
EndDialog(hWnd, 0);
|
|
}
|
|
}
|
|
return TRUE;
|
|
|
|
case WM_DESTROY:
|
|
delete c_Dialog;
|
|
c_Dialog = nullptr;
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
INT_PTR DialogPackage::OnInitDialog(WPARAM wParam, LPARAM lParam)
|
|
{
|
|
HICON hIcon = (HICON)LoadImage(GetModuleHandle(nullptr), MAKEINTRESOURCE(IDI_SKININSTALLER), IMAGE_ICON, 16, 16, LR_SHARED);
|
|
SendMessage(m_Window, WM_SETICON, ICON_SMALL, (LPARAM)hIcon);
|
|
|
|
if (GetOSPlatform() >= OSPLATFORM_VISTA)
|
|
{
|
|
SetDialogFont();
|
|
}
|
|
|
|
m_TabInfo.Activate();
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
INT_PTR DialogPackage::OnCommand(WPARAM wParam, LPARAM lParam)
|
|
{
|
|
switch (LOWORD(wParam))
|
|
{
|
|
case IDC_PACKAGE_NEXT_BUTTON:
|
|
{
|
|
HWND item = GetDlgItem(m_Window, IDC_PACKAGE_TAB);
|
|
TCITEM tci = {0};
|
|
tci.mask = TCIF_TEXT;
|
|
tci.pszText = L"Options";
|
|
TabCtrl_InsertItem(item, 0, &tci);
|
|
tci.pszText = L"Advanced";
|
|
TabCtrl_InsertItem(item, 1, &tci);
|
|
|
|
item = GetDlgItem(m_Window, IDC_PACKAGE_NEXT_BUTTON);
|
|
ShowWindow(item, SW_HIDE);
|
|
|
|
item = GetDlgItem(m_Window, IDC_PACKAGE_CREATEPACKAGE_BUTTON);
|
|
ShowWindow(item, SW_SHOWNORMAL);
|
|
SendMessage(m_Window, DM_SETDEFID, IDC_PACKAGE_CREATEPACKAGE_BUTTON, 0);
|
|
|
|
ShowWindow(m_TabInfo.GetWindow(), SW_HIDE);
|
|
|
|
m_TabOptions.Activate();
|
|
}
|
|
break;
|
|
|
|
case IDC_PACKAGE_CREATEPACKAGE_BUTTON:
|
|
{
|
|
HWND item = GetDlgItem(m_Window, IDC_PACKAGE_CREATEPACKAGE_BUTTON);
|
|
EnableWindow(item, FALSE);
|
|
|
|
item = GetDlgItem(m_Window, IDCANCEL);
|
|
EnableWindow(item, FALSE);
|
|
|
|
m_TabOptions.Activate();
|
|
item = GetDlgItem(m_Window, IDC_PACKAGE_TAB);
|
|
TabCtrl_SetCurSel(item, 0);
|
|
EnableWindow(item, FALSE);
|
|
EnableWindow(m_TabOptions.GetWindow(), FALSE);
|
|
EnableWindow(m_TabAdvanced.GetWindow(), FALSE);
|
|
|
|
item = GetDlgItem(m_TabOptions.GetWindow(), IDC_INSTALLTAB_CREATING_TEXT);
|
|
ShowWindow(item, SW_SHOWNORMAL);
|
|
|
|
item = GetDlgItem(m_TabOptions.GetWindow(), IDC_INSTALLTAB_CREATING_BAR);
|
|
ShowWindow(item, SW_SHOWNORMAL);
|
|
SendMessage(item, PBM_SETMARQUEE, (WPARAM)TRUE, 0);
|
|
|
|
m_PackagerThread = (HANDLE)_beginthreadex(nullptr, 0, PackagerThreadProc, this, 0, nullptr);
|
|
if (!m_PackagerThread)
|
|
{
|
|
MessageBox(m_Window, L"Unknown error.", L"Rainmeter Skin Packager", MB_ERROR);
|
|
EndDialog(m_Window, 0);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case IDCANCEL:
|
|
if (!m_PackagerThread)
|
|
{
|
|
EndDialog(m_Window, 0);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
INT_PTR DialogPackage::OnNotify(WPARAM wParam, LPARAM lParam)
|
|
{
|
|
LPNMHDR nm = (LPNMHDR)lParam;
|
|
switch (nm->idFrom)
|
|
{
|
|
case IDC_PACKAGE_TAB:
|
|
if (nm->code == TCN_SELCHANGE)
|
|
{
|
|
// Disable all tab windows first
|
|
EnableWindow(m_TabInfo.GetWindow(), FALSE);
|
|
EnableWindow(m_TabOptions.GetWindow(), FALSE);
|
|
EnableWindow(m_TabAdvanced.GetWindow(), FALSE);
|
|
|
|
GetActiveTab().Activate();
|
|
}
|
|
break;
|
|
|
|
default:
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void DialogPackage::SetNextButtonState()
|
|
{
|
|
BOOL state = !(m_Name.empty() || m_Author.empty() || m_SkinFolder.second.empty());
|
|
EnableWindow(GetDlgItem(m_Window, IDC_PACKAGE_NEXT_BUTTON), state);
|
|
}
|
|
|
|
bool DialogPackage::CreatePackage()
|
|
{
|
|
// Create options file
|
|
WCHAR tempFile[MAX_PATH];
|
|
GetTempPath(MAX_PATH, tempFile);
|
|
GetTempFileName(tempFile, L"ini", 0, tempFile);
|
|
|
|
WritePrivateProfileString(L"rmskin", L"Name", m_Name.c_str(), tempFile);
|
|
WritePrivateProfileString(L"rmskin", L"Author", m_Author.c_str(), tempFile);
|
|
WritePrivateProfileString(L"rmskin", L"Version", m_Version.c_str(), tempFile);
|
|
|
|
if (!c_Dialog->m_Load.empty())
|
|
{
|
|
WritePrivateProfileString(L"rmskin", L"LoadType", c_Dialog->m_LoadLayout ? L"Layout" : L"Skin", tempFile);
|
|
WritePrivateProfileString(L"rmskin", L"Load", c_Dialog->m_Load.c_str(), tempFile);
|
|
}
|
|
|
|
if (!c_Dialog->m_VariableFiles.empty())
|
|
{
|
|
WritePrivateProfileString(L"rmskin", L"VariableFiles", m_VariableFiles.c_str(), tempFile);
|
|
}
|
|
|
|
if (c_Dialog->m_MergeSkins)
|
|
{
|
|
WritePrivateProfileString(L"rmskin", L"MergeSkins", L"1", tempFile);
|
|
}
|
|
|
|
WritePrivateProfileString(L"rmskin", L"MinimumRainmeter", m_MinimumRainmeter.c_str(), tempFile);
|
|
WritePrivateProfileString(L"rmskin", L"MinimumWindows", m_MinimumWindows.c_str(), tempFile);
|
|
|
|
// Only Skin Installer in Rainmeter 3.0.1 support UTF-8 filenames.
|
|
m_AllowNonAsciiFilenames = DialogInstall::CompareVersions(m_MinimumRainmeter, L"3.0.1") != -1;
|
|
|
|
// Create archive and add options file and header bitmap
|
|
m_ZipFile = zipOpen(ConvertToAscii(m_TargetFile.c_str()).c_str(), APPEND_STATUS_CREATE);
|
|
|
|
auto cleanup = [&]()->bool
|
|
{
|
|
zipClose(m_ZipFile, nullptr);
|
|
DeleteFile(m_TargetFile.c_str());
|
|
return false;
|
|
};
|
|
|
|
if (!m_ZipFile ||
|
|
(!c_Dialog->m_HeaderFile.empty() && !AddFileToPackage(c_Dialog->m_HeaderFile.c_str(), L"RMSKIN.bmp")) ||
|
|
!AddFileToPackage(tempFile, L"RMSKIN.ini"))
|
|
{
|
|
std::wstring error = L"Unable to create package.";
|
|
error += L"\n\nClick OK to close Packager.";
|
|
MessageBox(m_Window, error.c_str(), L"Rainmeter Skin Packager", MB_OK | MB_ICONERROR);
|
|
DeleteFile(tempFile);
|
|
return cleanup();
|
|
}
|
|
|
|
// Add skin
|
|
{
|
|
std::wstring zipPrefix = L"Skins\\" + m_SkinFolder.first;
|
|
zipPrefix += L'\\';
|
|
if (!AddFolderToPackage(m_SkinFolder.second, L"", zipPrefix.c_str()))
|
|
{
|
|
return cleanup();
|
|
}
|
|
}
|
|
|
|
// Add layouts
|
|
for (auto iter = m_LayoutFolders.cbegin(); iter != m_LayoutFolders.cend(); ++iter)
|
|
{
|
|
std::wstring realPath = (*iter).second + L"Rainmeter.ini";
|
|
std::wstring zipPath = L"Layouts\\" + (*iter).first;
|
|
zipPath += L"\\Rainmeter.ini";
|
|
if (!AddFileToPackage(realPath.c_str(), zipPath.c_str()))
|
|
{
|
|
std::wstring error = L"Error adding layout '";
|
|
error += (*iter).first;
|
|
error += L"'.";
|
|
error += L"\n\nClick OK to close Packager.";
|
|
MessageBox(m_Window, error.c_str(), L"Rainmeter Skin Packager", MB_OK | MB_ICONERROR);
|
|
return cleanup();
|
|
}
|
|
}
|
|
|
|
// Add plugins
|
|
for (auto iter = m_PluginFolders.cbegin(); iter != m_PluginFolders.cend(); ++iter)
|
|
{
|
|
// Add 32bit and 64bit versions
|
|
for (int i = 0; i < 2; ++i)
|
|
{
|
|
const std::wstring& realPath = (i == 0) ? (*iter).second.first : (*iter).second.second;
|
|
std::wstring zipPath = ((i == 0) ? L"Plugins\\32bit\\" : L"Plugins\\64bit\\") + (*iter).first;
|
|
if (!AddFileToPackage(realPath.c_str(), zipPath.c_str()))
|
|
{
|
|
std::wstring error = L"Error adding plugin '";
|
|
error += (*iter).first;
|
|
error += L"'.";
|
|
error += L"\n\nClick OK to close Packager.";
|
|
MessageBox(m_Window, error.c_str(), L"Rainmeter Skin Packager", MB_OK | MB_ICONERROR);
|
|
return cleanup();
|
|
}
|
|
}
|
|
}
|
|
|
|
// Add footer
|
|
FILE* file;
|
|
if (zipClose(m_ZipFile, nullptr) == ZIP_OK &&
|
|
(file = _wfopen(m_TargetFile.c_str(), L"r+b")) != nullptr)
|
|
{
|
|
fseek(file, 0, SEEK_END);
|
|
DialogInstall::PackageFooter footer = { _ftelli64(file), 0, "RMSKIN" };
|
|
fwrite(&footer, sizeof(footer), 1, file);
|
|
fclose(file);
|
|
}
|
|
else
|
|
{
|
|
std::wstring error = L"Unable to create package.";
|
|
error += L"\n\nClick OK to close Packager.";
|
|
MessageBox(m_Window, error.c_str(), L"Rainmeter Skin Packager", MB_OK | MB_ICONERROR);
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
unsigned __stdcall DialogPackage::PackagerThreadProc(void* pParam)
|
|
{
|
|
DialogPackage* dialog = (DialogPackage*)pParam;
|
|
|
|
if (dialog->CreatePackage())
|
|
{
|
|
// Stop the progress bar
|
|
HWND item = GetDlgItem(dialog->m_TabOptions.GetWindow(), IDC_INSTALLTAB_CREATING_BAR);
|
|
SendMessage(item, PBM_SETMARQUEE, (WPARAM)FALSE, 0);
|
|
|
|
FlashWindow(dialog->m_Window, TRUE);
|
|
|
|
std::wstring message = L"The skin package has been successfully created.";
|
|
message += L"\n\nClick OK to close Packager.";
|
|
MessageBox(c_Dialog->GetWindow(), message.c_str(), L"Rainmeter Skin Packager", MB_OK | MB_ICONINFORMATION);
|
|
}
|
|
else
|
|
{
|
|
DeleteFile(dialog->m_TargetFile.c_str());
|
|
}
|
|
|
|
EndDialog(dialog->m_Window, 0);
|
|
|
|
return 0;
|
|
}
|
|
|
|
bool DialogPackage::AddFileToPackage(const WCHAR* filePath, const WCHAR* zipPath)
|
|
{
|
|
std::string zipPathUTF8 = StringUtil::NarrowUTF8(zipPath);
|
|
for (int i = 0, isize = zipPathUTF8.length(); i < isize; ++i)
|
|
{
|
|
if ((zipPathUTF8[i] & 0x80) != 0)
|
|
{
|
|
// UTF-8 lead bit is not zero so the string is non-ASCII.
|
|
if (!m_AllowNonAsciiFilenames)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if (zipPathUTF8[i] == '\\')
|
|
{
|
|
zipPathUTF8[i] = '/';
|
|
}
|
|
}
|
|
|
|
const uLong ZIP_UTF8_FLAG = 1 << 11;
|
|
zip_fileinfo fi = {0};
|
|
if (zipOpenNewFileInZip4(
|
|
m_ZipFile, zipPathUTF8.c_str(), &fi,
|
|
nullptr, 0, nullptr, 0, nullptr, Z_DEFLATED, Z_DEFAULT_COMPRESSION,
|
|
0, -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, NULL, 0, 0, ZIP_UTF8_FLAG) != ZIP_OK)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
bool result = true;
|
|
|
|
if (filePath)
|
|
{
|
|
HANDLE file = CreateFile(filePath, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
|
|
if (file == INVALID_HANDLE_VALUE)
|
|
{
|
|
result = false;
|
|
}
|
|
else
|
|
{
|
|
do
|
|
{
|
|
const DWORD bufferSize = 16 * 1024;
|
|
BYTE buffer[bufferSize];
|
|
DWORD readSize;
|
|
if (!ReadFile(file, buffer, bufferSize, &readSize, nullptr))
|
|
{
|
|
result = false;
|
|
}
|
|
else if (readSize != 0)
|
|
{
|
|
result = zipWriteInFileInZip(m_ZipFile, buffer, (UINT)readSize) == ZIP_OK;
|
|
}
|
|
else
|
|
{
|
|
// EOF
|
|
break;
|
|
}
|
|
}
|
|
while (result);
|
|
|
|
CloseHandle(file);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Directory entry, so nothing needs to be written.
|
|
}
|
|
|
|
return zipCloseFileInZip(m_ZipFile) == ZIP_OK && result;
|
|
}
|
|
|
|
bool DialogPackage::AddFolderToPackage(const std::wstring& path, std::wstring base, const WCHAR* zipPrefix)
|
|
{
|
|
std::wstring currentPath = path + base;
|
|
currentPath += L'*';
|
|
|
|
WIN32_FIND_DATA fd;
|
|
HANDLE hFind = FindFirstFileEx(
|
|
currentPath.c_str(),
|
|
FindExInfoStandard,
|
|
&fd,
|
|
FindExSearchNameMatch,
|
|
nullptr,
|
|
0);
|
|
|
|
if (hFind == INVALID_HANDLE_VALUE)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
currentPath.pop_back(); // Remove *
|
|
|
|
bool result = true;
|
|
bool filesAdded = false;
|
|
std::list<std::wstring> folders;
|
|
do
|
|
{
|
|
if (fd.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)
|
|
{
|
|
// Ignore hidden files and folders
|
|
continue;
|
|
}
|
|
|
|
if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
|
{
|
|
if (!(fd.cFileName[0] == L'.' && (!fd.cFileName[1] || fd.cFileName[1] == L'.' && !fd.cFileName[2])))
|
|
{
|
|
folders.push_back(fd.cFileName);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
std::wstring filePath = currentPath + fd.cFileName;
|
|
std::wstring zipPath = zipPrefix;
|
|
zipPath.append(filePath, path.length(), filePath.length() - path.length());
|
|
|
|
result = AddFileToPackage(filePath.c_str(), zipPath.c_str());
|
|
if (!result)
|
|
{
|
|
std::wstring error = L"Error adding file:\n";
|
|
error += filePath;
|
|
error += L"\n\nClick OK to close Packager.";
|
|
MessageBox(m_Window, error.c_str(), L"Rainmeter Skin Packager", MB_OK | MB_ICONERROR);
|
|
break;
|
|
}
|
|
|
|
filesAdded = true;
|
|
}
|
|
}
|
|
while (FindNextFile(hFind, &fd));
|
|
FindClose(hFind);
|
|
|
|
if (result)
|
|
{
|
|
if (!filesAdded && folders.empty())
|
|
{
|
|
// Add directory entry if folder is empty.
|
|
std::wstring zipPath = zipPrefix;
|
|
zipPath.append(currentPath, path.length(), currentPath.length() - path.length());
|
|
AddFileToPackage(nullptr, zipPath.c_str());
|
|
}
|
|
|
|
std::list<std::wstring>::const_iterator iter = folders.begin();
|
|
for ( ; iter != folders.end(); ++iter)
|
|
{
|
|
std::wstring newBase = base + (*iter);
|
|
newBase += L'\\';
|
|
result = AddFolderToPackage(path, newBase, zipPrefix);
|
|
if (!result) break;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
void DialogPackage::ShowHelp()
|
|
{
|
|
std::wstring url = L"http://rainmeter.net/cms/UsingApplication-SkinPackager";
|
|
if (revision_beta)
|
|
{
|
|
url += L"_beta";
|
|
}
|
|
|
|
ShellExecute(m_Window, L"open", url.c_str(), nullptr, nullptr, SW_SHOWNORMAL);
|
|
}
|
|
|
|
std::wstring DialogPackage::SelectFolder(HWND parent, const std::wstring& existingPath)
|
|
{
|
|
LPCWSTR dialog = MAKEINTRESOURCE(IDD_PACKAGESELECTFOLDER_DIALOG);
|
|
std::wstring folder = existingPath;
|
|
if (DialogBoxParam(GetInstanceHandle(), dialog, parent, SelectFolderDlgProc, (LPARAM)&folder) != 1)
|
|
{
|
|
folder.clear();
|
|
}
|
|
return folder;
|
|
}
|
|
|
|
INT_PTR CALLBACK DialogPackage::SelectFolderDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
switch (uMsg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
{
|
|
EnableThemeDialogTexture(hWnd, ETDT_ENABLETAB);
|
|
c_Dialog->SetDialogFont(hWnd);
|
|
|
|
std::wstring* existingPath = (std::wstring*)lParam;
|
|
SetWindowLongPtr(hWnd, GWLP_USERDATA, lParam);
|
|
|
|
*existingPath += L'*';
|
|
WIN32_FIND_DATA fd;
|
|
HANDLE hFind = FindFirstFileEx(existingPath->c_str(), FindExInfoStandard, &fd, FindExSearchNameMatch, nullptr, 0);
|
|
existingPath->pop_back();
|
|
|
|
if (hFind != INVALID_HANDLE_VALUE)
|
|
{
|
|
const WCHAR* folder = PathFindFileName(existingPath->c_str());
|
|
|
|
HWND item = GetDlgItem(hWnd, IDC_PACKAGESELECTFOLDER_EXISTING_RADIO);
|
|
std::wstring text = L"Add folder from ";
|
|
text.append(folder, wcslen(folder) - 1);
|
|
text += L':';
|
|
SetWindowText(item, text.c_str());
|
|
Button_SetCheck(item, BST_CHECKED);
|
|
|
|
item = GetDlgItem(hWnd, IDC_PACKAGESELECTFOLDER_EXISTING_COMBO);
|
|
|
|
do
|
|
{
|
|
if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY &&
|
|
!(fd.cFileName[0] == L'.' && (!fd.cFileName[1] || fd.cFileName[1] == L'.' && !fd.cFileName[2])) &&
|
|
wcscmp(fd.cFileName, L"Backup") != 0 &&
|
|
wcscmp(fd.cFileName, L"@Backup") != 0)
|
|
{
|
|
ComboBox_InsertString(item, -1, fd.cFileName);
|
|
}
|
|
}
|
|
while (FindNextFile(hFind, &fd));
|
|
|
|
ComboBox_SetCurSel(item, 0);
|
|
|
|
FindClose(hFind);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
switch (LOWORD(wParam))
|
|
{
|
|
case IDC_PACKAGESELECTFOLDER_EXISTING_RADIO:
|
|
{
|
|
HWND item = GetDlgItem(hWnd, IDC_PACKAGESELECTFOLDER_EXISTING_COMBO);
|
|
EnableWindow(item, TRUE);
|
|
int sel = ComboBox_GetCurSel(item);
|
|
item = GetDlgItem(hWnd, IDC_PACKAGESELECTFOLDER_CUSTOM_EDIT);
|
|
EnableWindow(item, FALSE);
|
|
item = GetDlgItem(hWnd, IDC_PACKAGESELECTFOLDER_CUSTOMBROWSE_BUTTON);
|
|
EnableWindow(item, FALSE);
|
|
|
|
item = GetDlgItem(hWnd, IDOK);
|
|
EnableWindow(item, sel != -1);
|
|
}
|
|
break;
|
|
|
|
case IDC_PACKAGESELECTFOLDER_CUSTOM_RADIO:
|
|
{
|
|
HWND item = GetDlgItem(hWnd, IDC_PACKAGESELECTFOLDER_EXISTING_COMBO);
|
|
EnableWindow(item, FALSE);
|
|
item = GetDlgItem(hWnd, IDC_PACKAGESELECTFOLDER_CUSTOM_EDIT);
|
|
EnableWindow(item, TRUE);
|
|
item = GetDlgItem(hWnd, IDC_PACKAGESELECTFOLDER_CUSTOMBROWSE_BUTTON);
|
|
EnableWindow(item, TRUE);
|
|
|
|
SendMessage(hWnd, WM_COMMAND, MAKEWPARAM(IDC_PACKAGESELECTFOLDER_CUSTOM_EDIT, EN_CHANGE), 0);
|
|
}
|
|
break;
|
|
|
|
case IDC_PACKAGESELECTFOLDER_CUSTOM_EDIT:
|
|
if (HIWORD(wParam) == EN_CHANGE)
|
|
{
|
|
WCHAR buffer[MAX_PATH];
|
|
int len = Edit_GetText((HWND)lParam, buffer, MAX_PATH);
|
|
|
|
// Disable Add button if invalid directory
|
|
DWORD attributes = GetFileAttributes(buffer);
|
|
BOOL state = (attributes != INVALID_FILE_ATTRIBUTES &&
|
|
attributes & FILE_ATTRIBUTE_DIRECTORY);
|
|
EnableWindow(GetDlgItem(hWnd, IDOK), state);
|
|
}
|
|
break;
|
|
|
|
case IDC_PACKAGESELECTFOLDER_CUSTOMBROWSE_BUTTON:
|
|
{
|
|
WCHAR buffer[MAX_PATH];
|
|
BROWSEINFO bi = {0};
|
|
bi.hwndOwner = hWnd;
|
|
bi.ulFlags = BIF_USENEWUI | BIF_NONEWFOLDERBUTTON | BIF_RETURNONLYFSDIRS;
|
|
|
|
PIDLIST_ABSOLUTE pidl = SHBrowseForFolder(&bi);
|
|
if (pidl && SHGetPathFromIDList(pidl, buffer))
|
|
{
|
|
HWND item = GetDlgItem(hWnd, IDC_PACKAGESELECTFOLDER_CUSTOM_EDIT);
|
|
SetWindowText(item, buffer);
|
|
CoTaskMemFree(pidl);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case IDOK:
|
|
{
|
|
WCHAR buffer[MAX_PATH];
|
|
HWND item = GetDlgItem(hWnd, IDC_PACKAGESELECTFOLDER_EXISTING_RADIO);
|
|
bool existing = Button_GetCheck(item) == BST_CHECKED;
|
|
|
|
item = GetDlgItem(hWnd, existing ? IDC_PACKAGESELECTFOLDER_EXISTING_COMBO : IDC_PACKAGESELECTFOLDER_CUSTOM_EDIT);
|
|
GetWindowText(item, buffer, _countof(buffer));
|
|
|
|
std::wstring* result = (std::wstring*)GetWindowLongPtr(hWnd, GWLP_USERDATA);
|
|
|
|
if (existing)
|
|
{
|
|
*result += buffer;
|
|
}
|
|
else
|
|
{
|
|
*result = buffer;
|
|
}
|
|
*result += L'\\';
|
|
|
|
EndDialog(hWnd, 1);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case WM_CLOSE:
|
|
EndDialog(hWnd, 0);
|
|
break;
|
|
|
|
default:
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
std::pair<std::wstring, std::wstring> DialogPackage::SelectPlugin(HWND parent)
|
|
{
|
|
LPCWSTR dialog = MAKEINTRESOURCE(IDD_PACKAGESELECTPLUGIN_DIALOG);
|
|
std::pair<std::wstring, std::wstring> plugins;
|
|
if (DialogBoxParam(GetInstanceHandle(), dialog, parent, SelectPluginDlgProc, (LPARAM)&plugins) != 1)
|
|
{
|
|
plugins.first.clear();
|
|
plugins.second.clear();
|
|
}
|
|
return plugins;
|
|
}
|
|
|
|
INT_PTR CALLBACK DialogPackage::SelectPluginDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
switch (uMsg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
{
|
|
EnableThemeDialogTexture(hWnd, ETDT_ENABLETAB);
|
|
c_Dialog->SetDialogFont(hWnd);
|
|
|
|
auto plugins = (std::pair<std::wstring, std::wstring>*)lParam;
|
|
SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)plugins);
|
|
}
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
switch (LOWORD(wParam))
|
|
{
|
|
case IDC_PACKAGESELECTPLUGIN_32BITBROWSE_BUTTON:
|
|
case IDC_PACKAGESELECTPLUGIN_64BITBROWSE_BUTTON:
|
|
{
|
|
WCHAR buffer[MAX_PATH];
|
|
buffer[0] = L'\0';
|
|
|
|
OPENFILENAME ofn = { sizeof(OPENFILENAME) };
|
|
ofn.Flags = OFN_FILEMUSTEXIST;
|
|
ofn.lpstrFilter = L"Plugins (.dll)\0*.dll";
|
|
ofn.lpstrTitle = L"Select plugin file";
|
|
ofn.lpstrDefExt = L"dll";
|
|
ofn.nFilterIndex = 0;
|
|
ofn.lpstrFile = buffer;
|
|
ofn.nMaxFile = _countof(buffer);
|
|
ofn.hwndOwner = c_Dialog->GetWindow();
|
|
|
|
if (!GetOpenFileName(&ofn))
|
|
{
|
|
break;
|
|
}
|
|
|
|
bool x32 = LOWORD(wParam) == IDC_PACKAGESELECTPLUGIN_32BITBROWSE_BUTTON;
|
|
|
|
LOADED_IMAGE* loadedImage = ImageLoad(ConvertToAscii(buffer).c_str(), nullptr);
|
|
if (loadedImage)
|
|
{
|
|
WORD machine = loadedImage->FileHeader->FileHeader.Machine;
|
|
ImageUnload(loadedImage);
|
|
|
|
if ((x32 && machine == IMAGE_FILE_MACHINE_I386) || (!x32 && machine == IMAGE_FILE_MACHINE_AMD64))
|
|
{
|
|
// Check if same name as other DLL
|
|
auto plugins = (std::pair<std::wstring, std::wstring>*)GetWindowLongPtr(hWnd, GWLP_USERDATA);
|
|
const WCHAR* otherName = PathFindFileName(x32 ? plugins->second.c_str() : plugins->first.c_str());
|
|
if (*otherName && _wcsicmp(otherName, PathFindFileName(buffer)) != 0)
|
|
{
|
|
MessageBox(hWnd, L"Plugins must have same name.", L"Rainmeter Skin Packager", MB_OK | MB_TOPMOST);
|
|
break;
|
|
}
|
|
|
|
PathSetDlgItemPath(hWnd, x32 ? IDC_PACKAGESELECTPLUGIN_32BIT_EDIT : IDC_PACKAGESELECTPLUGIN_64BIT_EDIT, buffer);
|
|
|
|
(x32 ? plugins->first : plugins->second) = buffer;
|
|
|
|
if (!plugins->first.empty() && !plugins->second.empty())
|
|
{
|
|
// Enable Add button if both plugins have been selected
|
|
EnableWindow(GetDlgItem(hWnd, IDOK), TRUE);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
MessageBox(hWnd, L"Invalid plugin.", L"Rainmeter Skin Packager", MB_OK | MB_TOPMOST);
|
|
}
|
|
break;
|
|
|
|
case IDOK:
|
|
EndDialog(hWnd, 1);
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case WM_CLOSE:
|
|
EndDialog(hWnd, 0);
|
|
break;
|
|
|
|
default:
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------------------------
|
|
//
|
|
// Info tab
|
|
//
|
|
// -----------------------------------------------------------------------------------------------
|
|
|
|
DialogPackage::TabInfo::TabInfo(HWND wnd) : Tab(GetInstanceHandle(), wnd, IDD_PACKAGEINFO_TAB, DlgProc)
|
|
{
|
|
}
|
|
|
|
void DialogPackage::TabInfo::Initialize()
|
|
{
|
|
m_Initialized = true;
|
|
|
|
HWND item = GetDlgItem(m_Window, IDC_INSTALLTAB_NAME_TEXT);
|
|
Edit_SetCueBannerText(item, L"...");
|
|
|
|
item = GetDlgItem(m_Window, IDC_INSTALLTAB_AUTHOR_TEXT);
|
|
Edit_SetCueBannerText(item, L"...");
|
|
|
|
item = GetDlgItem(m_Window, IDC_INSTALLTAB_VERSION_TEXT);
|
|
Edit_SetCueBannerText(item, L"...");
|
|
|
|
item = GetDlgItem(m_Window, IDC_PACKAGEINFO_COMPONENTS_LIST);
|
|
|
|
DWORD extendedFlags = LVS_EX_LABELTIP | LVS_EX_FULLROWSELECT;
|
|
|
|
if (GetOSPlatform() >= OSPLATFORM_VISTA)
|
|
{
|
|
extendedFlags |= LVS_EX_DOUBLEBUFFER;
|
|
SetWindowTheme(item, L"explorer", nullptr);
|
|
}
|
|
|
|
ListView_EnableGroupView(item, TRUE);
|
|
ListView_SetExtendedListViewStyleEx(item, 0, extendedFlags);
|
|
|
|
// Add columns
|
|
LVCOLUMN lvc;
|
|
lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
|
|
lvc.fmt = LVCFMT_LEFT;
|
|
lvc.iSubItem = 0;
|
|
lvc.cx = 252;
|
|
lvc.pszText = L"Name";
|
|
ListView_InsertColumn(item, 0, &lvc);
|
|
|
|
// Add groups
|
|
LVGROUP lvg;
|
|
lvg.cbSize = sizeof(LVGROUP);
|
|
lvg.mask = LVGF_HEADER | LVGF_GROUPID | LVGF_STATE;
|
|
lvg.state = (GetOSPlatform() >= OSPLATFORM_VISTA) ? LVGS_COLLAPSIBLE : LVGS_NORMAL;
|
|
lvg.iGroupId = 0;
|
|
lvg.pszHeader = L"Skin";
|
|
ListView_InsertGroup(item, -1, &lvg);
|
|
lvg.iGroupId = 1;
|
|
lvg.pszHeader = L"Layouts";
|
|
ListView_InsertGroup(item, -1, &lvg);
|
|
lvg.iGroupId = 2;
|
|
lvg.pszHeader = L"Plugins";
|
|
ListView_InsertGroup(item, -1, &lvg);
|
|
}
|
|
|
|
INT_PTR CALLBACK DialogPackage::TabInfo::DlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
switch (uMsg)
|
|
{
|
|
case WM_COMMAND:
|
|
return c_Dialog->m_TabInfo.OnCommand(wParam, lParam);
|
|
|
|
case WM_NOTIFY:
|
|
return c_Dialog->m_TabInfo.OnNotify(wParam, lParam);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
INT_PTR DialogPackage::TabInfo::OnCommand(WPARAM wParam, LPARAM lParam)
|
|
{
|
|
switch (LOWORD(wParam))
|
|
{
|
|
case IDC_PACKAGEINFO_ADDSKIN_BUTTON:
|
|
{
|
|
c_Dialog->m_SkinFolder.second = SelectFolder(m_Window, g_Data.skinsPath);
|
|
if (!c_Dialog->m_SkinFolder.second.empty())
|
|
{
|
|
c_Dialog->m_SkinFolder.first = PathFindFileName(c_Dialog->m_SkinFolder.second.c_str());
|
|
c_Dialog->m_SkinFolder.first.pop_back(); // Remove slash
|
|
|
|
HWND item = GetDlgItem(m_Window, IDC_PACKAGEINFO_COMPONENTS_LIST);
|
|
LVITEM lvi;
|
|
lvi.mask = LVIF_TEXT | LVIF_GROUPID;
|
|
lvi.iItem = 1;
|
|
lvi.iSubItem = 0;
|
|
lvi.iGroupId = 0;
|
|
lvi.pszText = (WCHAR*)c_Dialog->m_SkinFolder.first.c_str();
|
|
ListView_InsertItem(item, &lvi);
|
|
|
|
EnableWindow((HWND)lParam, FALSE);
|
|
c_Dialog->SetNextButtonState();
|
|
}
|
|
}
|
|
break;
|
|
|
|
case IDC_PACKAGEINFO_ADDTHEME_BUTTON:
|
|
{
|
|
std::wstring folder = SelectFolder(m_Window, g_Data.settingsPath + L"Layouts\\");
|
|
if (!folder.empty())
|
|
{
|
|
std::wstring name = PathFindFileName(folder.c_str());
|
|
name.pop_back(); // Remove slash
|
|
|
|
if (c_Dialog->m_LayoutFolders.insert(std::make_pair(name, folder)).second)
|
|
{
|
|
HWND item = GetDlgItem(m_Window, IDC_PACKAGEINFO_COMPONENTS_LIST);
|
|
LVITEM lvi;
|
|
lvi.mask = LVIF_TEXT | LVIF_GROUPID;
|
|
lvi.iItem = c_Dialog->m_LayoutFolders.size() + 1;
|
|
lvi.iSubItem = 0;
|
|
lvi.iGroupId = 1;
|
|
lvi.pszText = (WCHAR*)name.c_str();
|
|
ListView_InsertItem(item, &lvi);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case IDC_PACKAGEINFO_ADDPLUGIN_BUTTON:
|
|
{
|
|
std::pair<std::wstring, std::wstring> plugins = SelectPlugin(m_Window);
|
|
std::wstring name = PathFindFileName(plugins.first.c_str());
|
|
if (!name.empty() && c_Dialog->m_PluginFolders.insert(std::make_pair(name, plugins)).second)
|
|
{
|
|
HWND item = GetDlgItem(m_Window, IDC_PACKAGEINFO_COMPONENTS_LIST);
|
|
LVITEM lvi;
|
|
lvi.mask = LVIF_TEXT | LVIF_GROUPID;
|
|
lvi.iItem = c_Dialog->m_PluginFolders.size() + 1;
|
|
lvi.iSubItem = 0;
|
|
lvi.iGroupId = 2;
|
|
lvi.pszText = (WCHAR*)name.c_str();
|
|
ListView_InsertItem(item, &lvi);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case IDC_PACKAGEINFO_REMOVE_BUTTON:
|
|
{
|
|
HWND item = GetDlgItem(m_Window, IDC_PACKAGEINFO_COMPONENTS_LIST);
|
|
int sel = ListView_GetNextItem(item, -1, LVNI_FOCUSED | LVNI_SELECTED);
|
|
if (sel != -1)
|
|
{
|
|
WCHAR buffer[MAX_PATH];
|
|
|
|
// Remove unchecked items from the component sets
|
|
LVITEM lvi;
|
|
lvi.mask = LVIF_GROUPID | LVIF_TEXT;
|
|
lvi.iSubItem = 0;
|
|
lvi.iItem = sel;
|
|
lvi.pszText = buffer;
|
|
lvi.cchTextMax = _countof(buffer);
|
|
ListView_GetItem(item, &lvi);
|
|
|
|
ListView_DeleteItem(item, sel);
|
|
|
|
const std::wstring name = buffer;
|
|
switch (lvi.iGroupId)
|
|
{
|
|
case 0:
|
|
{
|
|
item = GetDlgItem(m_Window, IDC_PACKAGEINFO_ADDSKIN_BUTTON);
|
|
EnableWindow(item, TRUE);
|
|
c_Dialog->m_SkinFolder.first.clear();
|
|
c_Dialog->m_SkinFolder.second.clear();
|
|
c_Dialog->SetNextButtonState();
|
|
}
|
|
break;
|
|
|
|
case 1:
|
|
c_Dialog->m_LayoutFolders.erase(c_Dialog->m_LayoutFolders.find(name));
|
|
break;
|
|
|
|
case 2:
|
|
c_Dialog->m_PluginFolders.erase(c_Dialog->m_PluginFolders.find(name));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case IDC_PACKAGEINFO_NAME_EDIT:
|
|
case IDC_PACKAGEINFO_AUTHOR_EDIT:
|
|
case IDC_PACKAGEINFO_VERSION_EDIT:
|
|
if (HIWORD(wParam) == EN_CHANGE)
|
|
{
|
|
WCHAR buffer[64];
|
|
int len = GetWindowText((HWND)lParam, buffer, _countof(buffer));
|
|
if (LOWORD(wParam) == IDC_PACKAGEINFO_NAME_EDIT)
|
|
{
|
|
c_Dialog->m_Name.assign(buffer, len);
|
|
}
|
|
else if (LOWORD(wParam) == IDC_PACKAGEINFO_AUTHOR_EDIT)
|
|
{
|
|
c_Dialog->m_Author.assign(buffer, len);
|
|
}
|
|
else // if (LOWORD(wParam) == IDC_PACKAGEINFO_VERSION_EDIT)
|
|
{
|
|
c_Dialog->m_Version.assign(buffer, len);
|
|
}
|
|
c_Dialog->SetNextButtonState();
|
|
}
|
|
break;
|
|
|
|
|
|
default:
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
INT_PTR DialogPackage::TabInfo::OnNotify(WPARAM wParam, LPARAM lParam)
|
|
{
|
|
LPNMHDR nm = (LPNMHDR)lParam;
|
|
switch (nm->code)
|
|
{
|
|
case LVN_ITEMCHANGED:
|
|
{
|
|
NMLISTVIEW* nmlv = (NMLISTVIEW*)lParam;
|
|
if (nm->idFrom == IDC_PACKAGEINFO_COMPONENTS_LIST)
|
|
{
|
|
BOOL selected = (nmlv->uNewState & LVIS_SELECTED);
|
|
|
|
HWND item = GetDlgItem(m_Window, IDC_PACKAGEINFO_REMOVE_BUTTON);
|
|
EnableWindow(item, selected);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case NM_CLICK:
|
|
{
|
|
if (nm->idFrom == IDC_PACKAGEINFO_WHATIS_LINK)
|
|
{
|
|
c_Dialog->ShowHelp();
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------------------------
|
|
//
|
|
// Options tab
|
|
//
|
|
// -----------------------------------------------------------------------------------------------
|
|
|
|
DialogPackage::TabOptions::TabOptions(HWND wnd) : Tab(GetInstanceHandle(), wnd, IDD_PACKAGEOPTIONS_TAB, DlgProc)
|
|
{
|
|
}
|
|
|
|
void DialogPackage::TabOptions::Initialize()
|
|
{
|
|
m_Initialized = true;
|
|
|
|
WCHAR buffer[MAX_PATH];
|
|
SHGetFolderPath(nullptr, CSIDL_DESKTOPDIRECTORY, nullptr, SHGFP_TYPE_CURRENT, buffer);
|
|
|
|
c_Dialog->m_TargetFile = buffer;
|
|
c_Dialog->m_TargetFile += L'\\';
|
|
int pos = (int)c_Dialog->m_TargetFile.length() + 1;
|
|
c_Dialog->m_TargetFile += c_Dialog->m_Name;
|
|
c_Dialog->m_TargetFile += L'_';
|
|
c_Dialog->m_TargetFile += c_Dialog->m_Version;
|
|
|
|
// Escape reserved chars
|
|
for (int i = pos, isize = (int)c_Dialog->m_TargetFile.length(); i < isize; ++i)
|
|
{
|
|
if (wcschr(L"\\/:*?\"<>|", c_Dialog->m_TargetFile[i]))
|
|
{
|
|
c_Dialog->m_TargetFile[i] = L'_';
|
|
}
|
|
}
|
|
|
|
c_Dialog->m_TargetFile += L".rmskin";
|
|
|
|
HWND item = GetDlgItem(m_Window, IDC_PACKAGEOPTIONS_FILE_EDIT);
|
|
SetWindowText(item,c_Dialog->m_TargetFile.c_str());
|
|
|
|
item = GetDlgItem(m_Window, IDC_PACKAGEOPTIONS_LOADTHEME_RADIO);
|
|
if (c_Dialog->m_LayoutFolders.empty())
|
|
{
|
|
EnableWindow(item, FALSE);
|
|
|
|
item = GetDlgItem(m_Window, IDC_PACKAGEOPTIONS_DONOTHING_RADIO);
|
|
Button_SetCheck(item, BST_CHECKED);
|
|
}
|
|
else
|
|
{
|
|
c_Dialog->m_LoadLayout = true;
|
|
c_Dialog->m_Load = (*c_Dialog->m_LayoutFolders.cbegin()).first;
|
|
|
|
Button_SetCheck(item, BST_CHECKED);
|
|
|
|
item = GetDlgItem(m_Window, IDC_PACKAGEOPTIONS_LOADTHEME_COMBO);
|
|
ShowWindow(item, SW_SHOWNORMAL);
|
|
|
|
for (auto iter = c_Dialog->m_LayoutFolders.cbegin(); iter != c_Dialog->m_LayoutFolders.cend(); ++iter)
|
|
{
|
|
ComboBox_AddString(item, (*iter).first.c_str());
|
|
}
|
|
ComboBox_SetCurSel(item, 0);
|
|
}
|
|
|
|
item = GetDlgItem(m_Window, IDC_PACKAGEOPTIONS_LOADSKIN_EDIT);
|
|
Edit_SetCueBannerText(item, L"Select skin");
|
|
|
|
item = GetDlgItem(m_Window, IDC_PACKAGEOPTIONS_RAINMETERVERSION_EDIT);
|
|
_snwprintf_s(buffer, _TRUNCATE, L"%s.%i", APPVERSION, revision_number);
|
|
SetWindowText(item, buffer);
|
|
c_Dialog->m_MinimumRainmeter = buffer;
|
|
|
|
item = GetDlgItem(m_Window, IDC_PACKAGEOPTIONS_WINDOWSVERSION_COMBO);
|
|
ComboBox_AddString(item, L"XP");
|
|
ComboBox_AddString(item, L"Vista");
|
|
ComboBox_AddString(item, L"7");
|
|
ComboBox_SetCurSel(item, 0);
|
|
c_Dialog->m_MinimumWindows = g_OsNameVersions[0].version;
|
|
}
|
|
|
|
INT_PTR CALLBACK DialogPackage::TabOptions::DlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
switch (uMsg)
|
|
{
|
|
case WM_COMMAND:
|
|
return c_Dialog->m_TabOptions.OnCommand(wParam, lParam);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
INT_PTR DialogPackage::TabOptions::OnCommand(WPARAM wParam, LPARAM lParam)
|
|
{
|
|
switch (LOWORD(wParam))
|
|
{
|
|
case IDC_PACKAGEOPTIONS_FILEBROWSE_BUTTON:
|
|
{
|
|
WCHAR buffer[MAX_PATH];
|
|
HWND item = GetDlgItem(m_Window, IDC_PACKAGEOPTIONS_FILE_EDIT);
|
|
GetWindowText(item, buffer, _countof(buffer));
|
|
|
|
OPENFILENAME ofn = { sizeof(OPENFILENAME) };
|
|
ofn.lpstrFilter = L"Rainmeter skin package (.rmskin)\0*.rmskin";
|
|
ofn.lpstrTitle = L"Select Rainmeter skin package";
|
|
ofn.lpstrDefExt = L"dll";
|
|
ofn.lpstrFile = buffer;
|
|
ofn.nMaxFile = _countof(buffer);
|
|
ofn.hwndOwner = c_Dialog->GetWindow();
|
|
|
|
if (GetOpenFileName(&ofn))
|
|
{
|
|
c_Dialog->m_TargetFile = buffer;
|
|
SetWindowText(item, buffer);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case IDC_PACKAGEOPTIONS_DONOTHING_RADIO:
|
|
{
|
|
HWND item = GetDlgItem(m_Window, IDC_PACKAGEOPTIONS_LOADSKIN_EDIT);
|
|
ShowWindow(item, SW_HIDE);
|
|
item = GetDlgItem(m_Window, IDC_PACKAGEOPTIONS_LOADSKINBROWSE_BUTTON);
|
|
ShowWindow(item, SW_HIDE);
|
|
item = GetDlgItem(m_Window, IDC_PACKAGEOPTIONS_LOADTHEME_COMBO);
|
|
ShowWindow(item, SW_HIDE);
|
|
|
|
c_Dialog->m_Load.clear();
|
|
}
|
|
break;
|
|
|
|
case IDC_PACKAGEOPTIONS_LOADSKIN_RADIO:
|
|
{
|
|
HWND item = GetDlgItem(m_Window, IDC_PACKAGEOPTIONS_LOADSKIN_EDIT);
|
|
ShowWindow(item, SW_SHOWNORMAL);
|
|
|
|
WCHAR buffer[MAX_PATH];
|
|
GetWindowText(item, buffer, _countof(buffer));
|
|
c_Dialog->m_Load = buffer;
|
|
c_Dialog->m_LoadLayout = false;
|
|
|
|
item = GetDlgItem(m_Window, IDC_PACKAGEOPTIONS_LOADSKINBROWSE_BUTTON);
|
|
ShowWindow(item, SW_SHOWNORMAL);
|
|
item = GetDlgItem(m_Window, IDC_PACKAGEOPTIONS_LOADTHEME_COMBO);
|
|
ShowWindow(item, SW_HIDE);
|
|
}
|
|
break;
|
|
|
|
case IDC_PACKAGEOPTIONS_LOADTHEME_RADIO:
|
|
{
|
|
HWND item = GetDlgItem(m_Window, IDC_PACKAGEOPTIONS_LOADSKIN_EDIT);
|
|
ShowWindow(item, SW_HIDE);
|
|
item = GetDlgItem(m_Window, IDC_PACKAGEOPTIONS_LOADSKINBROWSE_BUTTON);
|
|
ShowWindow(item, SW_HIDE);
|
|
item = GetDlgItem(m_Window, IDC_PACKAGEOPTIONS_LOADTHEME_COMBO);
|
|
ShowWindow(item, SW_SHOWNORMAL);
|
|
|
|
WCHAR buffer[MAX_PATH];
|
|
GetWindowText(item, buffer, _countof(buffer));
|
|
c_Dialog->m_Load = buffer;
|
|
c_Dialog->m_LoadLayout = true;
|
|
}
|
|
break;
|
|
|
|
case IDC_PACKAGEOPTIONS_LOADSKINBROWSE_BUTTON:
|
|
{
|
|
WCHAR buffer[MAX_PATH];
|
|
HWND item = GetDlgItem(m_Window, IDC_PACKAGEOPTIONS_LOADSKIN_EDIT);
|
|
GetWindowText(item, buffer, _countof(buffer));
|
|
|
|
OPENFILENAME ofn = { sizeof(OPENFILENAME) };
|
|
ofn.Flags = OFN_FILEMUSTEXIST;
|
|
ofn.FlagsEx = OFN_EX_NOPLACESBAR;
|
|
ofn.lpstrFilter = L"Rainmeter skin file (.ini)\0*.ini";
|
|
ofn.lpstrTitle = L"Select Rainmeter skin file";
|
|
ofn.lpstrDefExt = L"ini";
|
|
ofn.lpstrFile = buffer;
|
|
ofn.nMaxFile = _countof(buffer);
|
|
ofn.lpstrInitialDir = c_Dialog->m_SkinFolder.second.c_str();
|
|
ofn.hwndOwner = c_Dialog->GetWindow();
|
|
|
|
if (GetOpenFileName(&ofn))
|
|
{
|
|
// Make sure user didn't browse to some random folder
|
|
if (_wcsnicmp(ofn.lpstrInitialDir, buffer, c_Dialog->m_SkinFolder.second.length()) == 0)
|
|
{
|
|
// Skip everything before actual skin folder
|
|
const WCHAR* folderPath = buffer + c_Dialog->m_SkinFolder.second.length() - c_Dialog->m_SkinFolder.first.length() - 1;
|
|
SetWindowText(item, folderPath);
|
|
c_Dialog->m_Load = folderPath;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case IDC_PACKAGEOPTIONS_RAINMETERVERSION_EDIT:
|
|
if (HIWORD(wParam) == EN_CHANGE)
|
|
{
|
|
WCHAR buffer[32];
|
|
GetWindowText((HWND)lParam, buffer, _countof(buffer));
|
|
|
|
// Get caret position
|
|
DWORD sel = Edit_GetSel((HWND)lParam);
|
|
|
|
// Only allow numbers and period
|
|
WCHAR* version = buffer;
|
|
while (*version)
|
|
{
|
|
if (iswdigit(*version) || *version == L'.')
|
|
{
|
|
++version;
|
|
}
|
|
else
|
|
{
|
|
*version = L'\0';
|
|
SetWindowText((HWND)lParam, buffer);
|
|
|
|
// Reset caret position
|
|
Edit_SetSel((HWND)lParam, LOWORD(sel), HIWORD(sel));
|
|
break;
|
|
}
|
|
}
|
|
|
|
c_Dialog->m_MinimumRainmeter = buffer;
|
|
}
|
|
break;
|
|
|
|
case IDC_PACKAGEOPTIONS_WINDOWSVERSION_COMBO:
|
|
if (HIWORD(wParam) == CBN_SELCHANGE)
|
|
{
|
|
int sel = ComboBox_GetCurSel((HWND)lParam);
|
|
c_Dialog->m_MinimumWindows = g_OsNameVersions[sel].version;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------------------------
|
|
//
|
|
// Advanced tab
|
|
//
|
|
// -----------------------------------------------------------------------------------------------
|
|
|
|
DialogPackage::TabAdvanced::TabAdvanced(HWND wnd) : Tab(GetInstanceHandle(), wnd, IDD_PACKAGEADVANCED_TAB, DlgProc)
|
|
{
|
|
}
|
|
|
|
void DialogPackage::TabAdvanced::Initialize()
|
|
{
|
|
m_Initialized = true;
|
|
}
|
|
|
|
INT_PTR CALLBACK DialogPackage::TabAdvanced::DlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
switch (uMsg)
|
|
{
|
|
case WM_COMMAND:
|
|
return c_Dialog->m_TabAdvanced.OnCommand(wParam, lParam);
|
|
|
|
case WM_NOTIFY:
|
|
return c_Dialog->m_TabAdvanced.OnNotify(wParam, lParam);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
INT_PTR DialogPackage::TabAdvanced::OnCommand(WPARAM wParam, LPARAM lParam)
|
|
{
|
|
switch (LOWORD(wParam))
|
|
{
|
|
case IDC_PACKAGEADVANCED_HEADERROWSE_BUTTON:
|
|
{
|
|
WCHAR buffer[MAX_PATH];
|
|
HWND item = GetDlgItem(m_Window, IDC_PACKAGEADVANCED_HEADER_EDIT);
|
|
GetWindowText(item, buffer, _countof(buffer));
|
|
|
|
OPENFILENAME ofn = { sizeof(OPENFILENAME) };
|
|
ofn.Flags = OFN_FILEMUSTEXIST;
|
|
ofn.lpstrFilter = L"Bitmap file (.bmp)\0*.bmp";
|
|
ofn.lpstrTitle = L"Select header image";
|
|
ofn.lpstrDefExt = L"bmp";
|
|
ofn.lpstrFile = buffer;
|
|
ofn.nMaxFile = _countof(buffer);
|
|
ofn.hwndOwner = c_Dialog->GetWindow();
|
|
|
|
if (GetOpenFileName(&ofn))
|
|
{
|
|
c_Dialog->m_HeaderFile = buffer;
|
|
SetWindowText(item, buffer);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case IDC_PACKAGEADVANCED_VARIABLEFILES_EDIT:
|
|
if (HIWORD(wParam) == EN_CHANGE)
|
|
{
|
|
int length = GetWindowTextLength((HWND)lParam);
|
|
c_Dialog->m_VariableFiles.resize(length);
|
|
GetWindowText((HWND)lParam, &c_Dialog->m_VariableFiles[0], length + 1);
|
|
}
|
|
break;
|
|
|
|
case IDC_PACKAGEADVANCED_MERGESKINS_CHECK:
|
|
c_Dialog->m_MergeSkins = !c_Dialog->m_MergeSkins;
|
|
break;
|
|
|
|
default:
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
INT_PTR DialogPackage::TabAdvanced::OnNotify(WPARAM wParam, LPARAM lParam)
|
|
{
|
|
LPNMHDR nm = (LPNMHDR)lParam;
|
|
switch (nm->code)
|
|
{
|
|
case NM_CLICK:
|
|
{
|
|
if (nm->idFrom == IDC_PACKAGEADVANCED_HELP_LINK)
|
|
{
|
|
c_Dialog->ShowHelp();
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
} |