From 69f3ab18034430121e4466a02363cf43ff242dfb Mon Sep 17 00:00:00 2001 From: Birunthan Mohanathas Date: Sun, 28 Aug 2011 10:58:26 +0000 Subject: [PATCH] - Added Manage dialog, which consolidates RainBrowser and RainThemes into a single UI - Updated About dialog - Removed RainBrowser and RainThemes from build --- Library/AboutDialog.cpp | 611 ----------- Library/AboutDialog.h | 32 - Library/Dialog.cpp | 123 +++ Library/Dialog.h | 59 ++ Library/DialogAbout.cpp | 962 +++++++++++++++++ Library/DialogAbout.h | 105 ++ Library/DialogManage.cpp | 1769 +++++++++++++++++++++++++++++++ Library/DialogManage.h | 115 ++ Library/Library.rc | 265 +++-- Library/Library.vcxproj | 27 +- Library/Library.vcxproj.filters | 27 +- Library/Litestep.cpp | 115 +- Library/MeterWindow.cpp | 83 +- Library/MeterWindow.h | 7 +- Library/Rainmeter.cpp | 339 ++---- Library/Rainmeter.h | 34 +- Library/StdAfx.h | 3 +- Library/System.cpp | 62 ++ Library/System.h | 3 + Library/TrayWindow.cpp | 42 +- Library/UpdateCheck.cpp | 6 +- Library/resource.h | 215 ++-- 22 files changed, 3784 insertions(+), 1220 deletions(-) delete mode 100644 Library/AboutDialog.cpp delete mode 100644 Library/AboutDialog.h create mode 100644 Library/Dialog.cpp create mode 100644 Library/Dialog.h create mode 100644 Library/DialogAbout.cpp create mode 100644 Library/DialogAbout.h create mode 100644 Library/DialogManage.cpp create mode 100644 Library/DialogManage.h diff --git a/Library/AboutDialog.cpp b/Library/AboutDialog.cpp deleted file mode 100644 index 08550992..00000000 --- a/Library/AboutDialog.cpp +++ /dev/null @@ -1,611 +0,0 @@ -/* - Copyright (C) 2000 Kimmo Pekkola - - 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include "StdAfx.h" -#include "Rainmeter.h" -#include "System.h" -#include "MeterWindow.h" -#include "Measure.h" -#include "resource.h" -#include "AboutDialog.h" -#include "../Version.h" - -#define LOGTIMER 1 - -#define WM_DELAYED_CLOSE WM_APP + 0 - -extern CRainmeter* Rainmeter; - -INT_PTR CALLBACK AboutProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam); -void UpdateWidgets(); -BOOL OnInitAboutDialog(HWND window); - -HWND g_DialogWin = NULL; -WINDOWPLACEMENT g_DialogPlacement = {0}; - -struct PLUGIN_INFO -{ - std::wstring name; - UINT version; - std::wstring author; -}; -std::vector g_Plugins; - -HWND OpenAboutDialog(HWND hwndOwner, HINSTANCE instance) -{ - if (g_DialogWin == NULL) - { - g_DialogWin = CreateDialog(instance, MAKEINTRESOURCE(IDD_ABOUT_DIALOG), hwndOwner, AboutProc); - - if (g_DialogWin) - { - HICON hIcon = LoadIcon(instance, MAKEINTRESOURCE(IDI_TRAY)); - SendMessage(g_DialogWin, WM_SETICON, ICON_SMALL, (LPARAM)hIcon); - - if (g_DialogPlacement.length == 0) - { - g_DialogPlacement.length = sizeof(WINDOWPLACEMENT); - GetWindowPlacement(g_DialogWin, &g_DialogPlacement); - } - - SetWindowPlacement(g_DialogWin, &g_DialogPlacement); - } - } - else - { - if (!IsZoomed(g_DialogWin)) - { - ShowWindow(g_DialogWin, SW_SHOWNORMAL); - } - } - UpdateAboutStatistics(); - - return g_DialogWin; -} - -void UpdateAboutDialog() -{ - if (g_DialogWin != NULL && IsWindowVisible(g_DialogWin)) - { - WCHAR* selectedItemName = NULL; - - HWND widget; - widget = GetDlgItem(g_DialogWin, IDC_ABOUT_ENTRIES); - int selected = (int)SendMessage(widget, LB_GETCURSEL, 0, 0); - - // Get current selected entry - if (selected != 0 && selected != 1 && selected != LB_ERR) - { - int selectedItemLen = (int)SendMessage(widget, LB_GETTEXTLEN, selected, 0); - - if (selectedItemLen != LB_ERR) - { - selectedItemName = new WCHAR[selectedItemLen + 1]; - - if (LB_ERR != SendMessage(widget, LB_GETTEXT, selected, (LPARAM)selectedItemName)) - { - selectedItemName[selectedItemLen] = L'\0'; - } - else - { - delete [] selectedItemName; - selectedItemName = NULL; - } - } - } - - // Delete all entries - SendMessage(widget, LB_RESETCONTENT, 0, 0); - - // Update all dialog widgets - OnInitAboutDialog(g_DialogWin); - - // Re-select entry - if (selected == 0 || selected == 1) - { - SendMessage(widget, LB_SETCURSEL, selected, 0); - UpdateWidgets(); - } - else if (selectedItemName != NULL) - { - int sel = 3; - - const std::map& windows = Rainmeter->GetAllMeterWindows(); - std::map::const_iterator iter = windows.begin(); - for ( ; iter != windows.end(); ++iter) - { - if (_wcsicmp(selectedItemName, (*iter).first.c_str()) == 0) - { - SendMessage(widget, LB_SETCURSEL, sel, 0); - break; - } - ++sel; - } - - delete [] selectedItemName; - } - } -} - -void UpdateAboutStatistics(LPCTSTR entryName) -{ - if (g_DialogWin != NULL && IsWindowVisible(g_DialogWin)) - { - HWND widget; - widget = GetDlgItem(g_DialogWin, IDC_ABOUT_ENTRIES); - int selected = (int)SendMessage(widget, LB_GETCURSEL, NULL, NULL); - int count = (int)SendMessage(widget, LB_GETCOUNT, NULL, NULL); - - if (selected != LB_ERR) - { - widget = GetDlgItem(g_DialogWin, IDC_STATISTICS); - SendMessage(widget, WM_SETREDRAW, 0, 0); - - if (selected == 0) - { - if (entryName == NULL) - { - int count = ListView_GetItemCount(widget); - - std::list::const_iterator iter = Rainmeter->GetAboutLogData().begin(); - LVITEM vitem; - vitem.mask = LVIF_TEXT; - - int i = 0; - for ( ; iter != Rainmeter->GetAboutLogData().end(); ++iter) - { - if (i < count) - { - ListView_SetItemText(widget, i, 0, (WCHAR*)(*iter).timestamp.c_str()); - } - else - { - vitem.iItem = i; - vitem.iSubItem = 0; - vitem.pszText = (WCHAR*)(*iter).timestamp.c_str(); - ListView_InsertItem(widget, &vitem); - } - ListView_SetItemText(widget, i, 1, (WCHAR*)(*iter).type.c_str()); - ListView_SetItemText(widget, i, 2, (WCHAR*)(*iter).message.c_str()); - - ++i; - } - } - } - else if (selected == 2) - { - HWND widgetEnt; - widgetEnt = GetDlgItem(g_DialogWin, IDC_ABOUT_ENTRIES); - SendMessage(widgetEnt, LB_SETCURSEL, 1, NULL); - UpdateWidgets(); - } - else - { - int current = 3; - - const std::map& windows = Rainmeter->GetAllMeterWindows(); - std::map::const_iterator iter = windows.begin(); - for ( ; iter != windows.end(); ++iter) - { - if (current == selected) - { - if (entryName == NULL || _wcsicmp(entryName, (*iter).first.c_str()) == 0) - { - int count = ListView_GetItemCount(widget); - - CMeterWindow* meterWindow = (*iter).second; - const std::list& measures = meterWindow->GetMeasures(); - - int index = 0; - std::list::const_iterator i = measures.begin(); - for ( ; i != measures.end(); ++i) - { - const WCHAR* name = (*i)->GetName(); - const WCHAR* val = (*i)->GetStats(); - - WCHAR buffer[256]; - double minVal = (*i)->GetMinValue(); - double maxVal = (*i)->GetMaxValue(); - CMeasure::GetScaledValue(AUTOSCALE_ON, 1, minVal, buffer, _countof(buffer)); - std::wstring range = buffer; - range += L" - "; - CMeasure::GetScaledValue(AUTOSCALE_ON, 1, maxVal, buffer, _countof(buffer)); - range += buffer; - - if (name && *name) - { - if (index < count) - { - ListView_SetItemText(widget, index, 0, (WCHAR*)name); - } - else - { - LVITEM vitem; - vitem.mask = LVIF_TEXT; - vitem.iItem = index; - vitem.iSubItem = 0; - vitem.pszText = (WCHAR*)name; - ListView_InsertItem(widget, &vitem); - } - - ListView_SetItemText(widget, index, 1, (WCHAR*)range.c_str()); - if (val) - { - ListView_SetItemText(widget, index, 2, (WCHAR*)val); - } - ++index; - } - } - - if (count > index) - { - // Delete unnecessary items - for (int j = index; j < count; ++j) - { - ListView_DeleteItem(widget, index); - } - } - } - - break; - } - ++current; - } - } - - SendMessage(widget, WM_SETREDRAW, 1, 0); - } - } -} - -void UpdateWidgets() -{ - HWND widget; - widget = GetDlgItem(g_DialogWin, IDC_ABOUT_ENTRIES); - int selected = (int)SendMessage(widget, LB_GETCURSEL, NULL, NULL); - - widget = GetDlgItem(g_DialogWin, IDC_STATISTICS); - ListView_DeleteAllItems(widget); - - if (selected == 0) - { - LVCOLUMN lvc; - lvc.mask = LVCF_TEXT; - lvc.pszText = L"Time"; - ListView_SetColumn(widget, 0, &lvc); - lvc.pszText = L"Type"; - ListView_SetColumn(widget, 1, &lvc); - lvc.pszText = L"Message"; - ListView_SetColumn(widget, 2, &lvc); - } - else if (selected == 1) - { - LVCOLUMN lvc; - lvc.mask = LVCF_TEXT; - lvc.pszText = L"Plugin"; - ListView_SetColumn(widget, 0, &lvc); - lvc.pszText = L"Version"; - ListView_SetColumn(widget, 1, &lvc); - lvc.pszText = L"Author"; - ListView_SetColumn(widget, 2, &lvc); - - // Update the list of plugins - if (g_Plugins.empty()) - { - ScanPlugins(); - } - - std::vector::const_iterator iter = g_Plugins.begin(); - LVITEM vitem; - vitem.mask = LVIF_TEXT; - - int i = 0; - for ( ; iter != g_Plugins.end(); ++iter) - { - if (!(*iter).name.empty()) - { - vitem.iItem = i; - vitem.iSubItem = 0; - vitem.pszText = (WCHAR*)(*iter).name.c_str(); - ListView_InsertItem(widget, &vitem); - } - - if ((*iter).version != 0) - { - WCHAR buffer[64]; - _snwprintf_s(buffer, _TRUNCATE, L"%u.%u", (*iter).version / 1000, (*iter).version % 1000); - ListView_SetItemText(widget, i, 1, buffer); - } - - ListView_SetItemText(widget, i, 2, (WCHAR*)(*iter).author.c_str()); - - ++i; - } - - if (!g_Plugins.empty()) - { - ListView_SetItemState(widget, 0, LVIS_SELECTED, LVIS_SELECTED); - } - } - else - { - LVCOLUMN lvc; - lvc.mask = LVCF_TEXT; - lvc.pszText = L"Measure"; - ListView_SetColumn(widget, 0, &lvc); - lvc.pszText = L"Range"; - ListView_SetColumn(widget, 1, &lvc); - lvc.pszText = L"Value"; - ListView_SetColumn(widget, 2, &lvc); - } -} - -typedef LPCTSTR (*GETPLUGINAUTHOR)(); -typedef UINT (*GETPLUGINVERSION)(); - -void ScanPlugins() -{ - WIN32_FIND_DATA fileData; // Data structure describes the file found - HANDLE hSearch; // Search handle returned by FindFirstFile - - std::wstring files = Rainmeter->GetPluginPath() + L"*.dll"; - - // Start searching for .ini files in the given directory. - hSearch = FindFirstFile(files.c_str(), &fileData); - do - { - if (hSearch == INVALID_HANDLE_VALUE) break; // No more files found - - PLUGIN_INFO info; - info.name = fileData.cFileName; - info.version = 0; - - // Try to get the version and author - std::wstring tmpSz = Rainmeter->GetPluginPath() + fileData.cFileName; - DWORD err = 0; - HMODULE dll = CSystem::RmLoadLibrary(tmpSz.c_str(), &err, true); - if (dll) - { - GETPLUGINAUTHOR GetAuthorFunc = (GETPLUGINAUTHOR)GetProcAddress(dll, "GetPluginAuthor"); - if (GetAuthorFunc) - { - LPCTSTR author = GetAuthorFunc(); - if (author && *author) - { - info.author = author; - } - } - - GETPLUGINVERSION GetVersionFunc = (GETPLUGINVERSION)GetProcAddress(dll, "GetPluginVersion"); - if (GetVersionFunc) - { - info.version = GetVersionFunc(); - } - FreeLibrary(dll); - } - else - { - LogWithArgs(LOG_WARNING, L"Unable to load plugin: \"%s\", ErrorCode=%u", tmpSz.c_str(), err); - } - - g_Plugins.push_back(info); - } - while (FindNextFile(hSearch, &fileData)); - - FindClose(hSearch); -} - -void RepositionControls(HWND hwndDlg) -{ - RECT r, br, ar, sr, wr; - HWND widget; - - GetClientRect(hwndDlg, &r); - GetClientRect(GetDlgItem(hwndDlg, IDOK), &br); - GetClientRect(GetDlgItem(hwndDlg, IDC_STATIC_ABOUT), &ar); - GetClientRect(GetDlgItem(hwndDlg, IDC_VERSION_STRING), &sr); - - // Reposition the statistics widgets - widget = GetDlgItem(hwndDlg, IDC_STATIC_ABOUT); - SetWindowPos(widget, NULL, 0, 0, r.right - 22, ar.bottom, SWP_NOMOVE | SWP_NOZORDER); - widget = GetDlgItem(hwndDlg, IDC_VERSION_STRING); - SetWindowPos(widget, NULL, 0, 0, r.right - 44, sr.bottom, SWP_NOMOVE | SWP_NOZORDER); - widget = GetDlgItem(hwndDlg, IDC_BUILD_STRING); - SetWindowPos(widget, NULL, 0, 0, r.right - 44, sr.bottom, SWP_NOMOVE | SWP_NOZORDER); - widget = GetDlgItem(hwndDlg, IDC_URL_STRING); - SetWindowPos(widget, NULL, 0, 0, r.right - 44, sr.bottom, SWP_NOMOVE | SWP_NOZORDER); - - widget = GetDlgItem(hwndDlg, IDC_DISABLE_VERSION_CHECK); - GetClientRect(widget, &wr); - MapWindowPoints(widget, hwndDlg, (LPPOINT)&wr, 2); - SetWindowPos(widget, NULL, ((r.right - (wr.right - wr.left)) / 2) + 9, wr.top, 0, 0, SWP_NOSIZE | SWP_NOZORDER); - - widget = GetDlgItem(hwndDlg, IDC_ABOUT_ENTRIES); - SetWindowPos(widget, NULL, 0, 0, (r.right < 800) ? ((r.right - 28) / 3) : 257, r.bottom - 170, SWP_NOMOVE | SWP_NOZORDER); - widget = GetDlgItem(hwndDlg, IDOK); - SetWindowPos(widget, NULL, (r.right - br.right) / 2, r.bottom - br.bottom - 9, br.right, br.bottom, SWP_NOZORDER); - - // Set listbox width and adjust third column - widget = GetDlgItem(hwndDlg, IDC_STATISTICS); - SetWindowPos(widget, NULL, (r.right < 800) ? (18 + ((r.right - 28) / 3)) : 275, 130, (r.right < 800) ? (2 * ((r.right - 28) / 3)) : (r.right - 287), r.bottom - 170, SWP_NOZORDER); - - LVCOLUMN lvc; - lvc.mask = LVCF_WIDTH; - lvc.cx = ((r.right < 800) ? (2 * ((r.right - 28) / 3)) : (r.right - 287)) - 200; - ListView_SetColumn(widget, 2, &lvc); -} - -BOOL OnInitAboutDialog(HWND window) -{ - WCHAR tmpSz[256]; - HWND widget; - - widget = GetDlgItem(window, IDC_VERSION_STRING); - _snwprintf_s(tmpSz, _TRUNCATE, L"%s %s%s rev %i %s", APPNAME, APPVERSION, revision_beta ? L" beta" : L"", revision_number, APPBITS); - SetWindowText(widget, tmpSz); - - widget = GetDlgItem(window, IDC_BUILD_STRING); - _snwprintf_s(tmpSz, _TRUNCATE, L"Built on %s", ConvertToWide(__DATE__).c_str()); - SetWindowText(widget, tmpSz); - - CheckDlgButton(window, IDC_DISABLE_VERSION_CHECK, Rainmeter->GetDisableVersionCheck() ? BST_CHECKED : BST_UNCHECKED); - - // Add entries for each config - widget = GetDlgItem(window, IDC_ABOUT_ENTRIES); - const std::map& windows = Rainmeter->GetAllMeterWindows(); - std::map::const_iterator iter = windows.begin(); - for ( ; iter != windows.end(); ++iter) - { - CMeterWindow* meterWindow = (*iter).second; - const std::wstring& skinName = meterWindow->GetSkinName(); - SendMessage(widget, LB_ADDSTRING, NULL, (LPARAM)skinName.c_str()); - size_t namelength = skinName.length(); - - int currwidth = (int)SendMessage(widget, LB_GETHORIZONTALEXTENT, NULL, NULL); - if (6 * (int)namelength > currwidth) - { - SendMessage(widget, LB_SETHORIZONTALEXTENT, 6 * namelength, NULL); - } - } - SendMessage(widget, LB_INSERTSTRING, 0, (LPARAM) L"Log"); - SendMessage(widget, LB_INSERTSTRING, 1, (LPARAM) L"Plugins"); - SendMessage(widget, LB_INSERTSTRING, 2, (LPARAM) L"--------------------"); - - // Select Log entry - SendMessage(widget, LB_SETCURSEL, 0, 0); - SetTimer(window, LOGTIMER, 1000, NULL); - - if (g_DialogWin == NULL) - { - // Add columns to the list view - widget = GetDlgItem(window, IDC_STATISTICS); - - //ListView_SetExtendedListViewStyleEx(widget, LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT); - ListView_SetExtendedListViewStyleEx(widget, LVS_EX_FULLROWSELECT | LVS_EX_DOUBLEBUFFER, LVS_EX_FULLROWSELECT | LVS_EX_DOUBLEBUFFER); - - LVCOLUMN lvc; - lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; - lvc.iSubItem = 0; - lvc.pszText = L"Time"; - lvc.cx = 110; - lvc.fmt = LVCFMT_LEFT; // left-aligned column - ListView_InsertColumn(widget, 0, &lvc); - lvc.iSubItem = 1; - lvc.cx = 85; - lvc.pszText = L"Type"; - ListView_InsertColumn(widget, 1, &lvc); - lvc.iSubItem = 2; - lvc.cx = 170; - lvc.pszText = L"Message"; - ListView_InsertColumn(widget, 2, &lvc); - } - - UpdateWidgets(); - RepositionControls(window); - - return TRUE; -} - -INT_PTR CALLBACK AboutProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam) -{ - switch (message) - { - case WM_INITDIALOG: - return OnInitAboutDialog(hwndDlg); - - case WM_WINDOWPOSCHANGING: - { - WINDOWPOS* pos = (WINDOWPOS*)lParam; - - pos->cx = max(420, pos->cx); - pos->cy = max(340, pos->cy); - } - return TRUE; - - case WM_SIZE: - RepositionControls(hwndDlg); - return TRUE; - - case WM_CLOSE: - PostMessage(hwndDlg, WM_DELAYED_CLOSE, 0, 0); - return TRUE; - - case WM_COMMAND: - switch (LOWORD(wParam)) - { - case IDC_DISABLE_VERSION_CHECK: - if (IsDlgButtonChecked(hwndDlg, IDC_DISABLE_VERSION_CHECK)) - { - Rainmeter->SetDisableVersionCheck(TRUE); - } - else - { - Rainmeter->SetDisableVersionCheck(FALSE); - } - return TRUE; - - case IDOK: - PostMessage(hwndDlg, WM_DELAYED_CLOSE, 0, 0); - return TRUE; - - case IDC_ABOUT_ENTRIES: - if (HIWORD(wParam) == LBN_SELCHANGE) - { - KillTimer(hwndDlg, LOGTIMER); - - HWND widget = GetDlgItem(hwndDlg, IDC_ABOUT_ENTRIES); - if (widget != NULL) - { - if (0 == (int)SendMessage(widget, LB_GETCURSEL, 0, 0)) - { - SetTimer(g_DialogWin, LOGTIMER, 1000, NULL); - } - } - - UpdateWidgets(); - UpdateAboutStatistics(); - return TRUE; - } - break; - } - break; - - case WM_DELAYED_CLOSE: - KillTimer(hwndDlg, LOGTIMER); - Rainmeter->SaveSettings(); - GetWindowPlacement(hwndDlg, &g_DialogPlacement); - if (g_DialogPlacement.showCmd == SW_SHOWMINIMIZED) - { - g_DialogPlacement.showCmd = SW_SHOWNORMAL; - } - DestroyWindow(hwndDlg); - g_DialogWin = NULL; - g_Plugins.clear(); - return TRUE; - - case WM_TIMER: - if (wParam == LOGTIMER) - { - UpdateAboutStatistics(); - return TRUE; - } - break; - } - return FALSE; -} - diff --git a/Library/AboutDialog.h b/Library/AboutDialog.h deleted file mode 100644 index ad727669..00000000 --- a/Library/AboutDialog.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - Copyright (C) 2000 Kimmo Pekkola - - 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#ifndef _ABOUTDIALOG_H_ -#define _ABOUTDIALOG_H_ - -#include "MeterWindow.h" - -#define MAXABOUTLOGLINES 20 - -HWND OpenAboutDialog(HWND hwndOwner, HINSTANCE instance); -void UpdateAboutDialog(); -void UpdateAboutStatistics(LPCTSTR entryName = NULL); -void ScanPlugins(); - -#endif - diff --git a/Library/Dialog.cpp b/Library/Dialog.cpp new file mode 100644 index 00000000..11b17ebc --- /dev/null +++ b/Library/Dialog.cpp @@ -0,0 +1,123 @@ +/* + Copyright (C) 2011 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "StdAfx.h" +#include "Dialog.h" + +/* +** CDialog +** +** Constructor. +** +*/ +CDialog::CDialog(HWND wnd) : + m_Window(wnd), + m_Font(), + m_FontBold() +{ + NONCLIENTMETRICS ncm; + ncm.cbSize = sizeof(NONCLIENTMETRICS) - sizeof(ncm.iPaddedBorderWidth); + SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0); + m_Font = CreateFontIndirect(&ncm.lfMenuFont); + ncm.lfMenuFont.lfWeight = FW_BOLD; + ncm.lfMenuFont.lfHeight -= 2; + m_FontBold = CreateFontIndirect(&ncm.lfMenuFont); +} + +/* +** CDialog +** +** Destructor. +** +*/ +CDialog::~CDialog() +{ + DeleteObject(m_Font); + DeleteObject(m_FontBold); +} + +/* +** SetDialogFont +** +** Sets dialog font to UI font. +** +*/ +void CDialog::SetDialogFont() +{ + EnumChildWindows(m_Window, SetFontProc, (WPARAM)m_Font); +} + +/* +** SetFontProc +** +** Callback for EnumChildWindows(). +** +*/ +BOOL CALLBACK CDialog::SetFontProc(HWND hWnd, LPARAM lParam) +{ + SendMessage(hWnd, WM_SETFONT, (WPARAM)lParam, 0); + return TRUE; +} + +/* +** OnColorDialog +** +** Paints dialog background. +** +*/ +INT_PTR CDialog::OnColorDialog(WPARAM wParam, LPARAM lParam) +{ + return (INT_PTR)GetStockObject(WHITE_BRUSH); +} + +/* +** OnColorStatic +** +** Paints control text and background. +** +*/ +INT_PTR CDialog::OnColorStatic(WPARAM wParam, LPARAM lParam) +{ + HDC hdc = (HDC)wParam; + SetTextColor(hdc, (COLORREF)GetSysColor(COLOR_WINDOWTEXT)); + SetBkMode(hdc, TRANSPARENT); + + return OnColorDialog(wParam, lParam); +} + +/* +** CTab +** +** Constructor. +** +*/ +CTab::CTab(HWND wnd) : CDialog(wnd), + m_Initialized(false) +{ +} + +/* +** CTab +** +** Destructor. +** +*/ +CTab::~CTab() +{ + DestroyWindow(m_Window); +} diff --git a/Library/Dialog.h b/Library/Dialog.h new file mode 100644 index 00000000..7d73431a --- /dev/null +++ b/Library/Dialog.h @@ -0,0 +1,59 @@ +/* + Copyright (C) 2011 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef _DIALOG_H_ +#define _DIALOG_H_ + +class CDialog +{ +public: + HWND GetWindow() { return m_Window; } + +protected: + CDialog(HWND wnd); + virtual ~CDialog(); + + void SetDialogFont(); + + static INT_PTR OnColorDialog(WPARAM wParam, LPARAM lParam); + static INT_PTR OnColorStatic(WPARAM wParam, LPARAM lParam); + + HWND m_Window; + HFONT m_Font; + HFONT m_FontBold; + +private: + static BOOL CALLBACK SetFontProc(HWND hWnd, LPARAM lParam); +}; + +class CTab : public CDialog +{ +public: + bool IsInitialized() { return m_Initialized; } + + virtual void Initialize() {} + virtual void Resize(int w, int h) {} + +protected: + CTab(HWND wnd); + virtual ~CTab(); + + bool m_Initialized; +}; + +#endif diff --git a/Library/DialogAbout.cpp b/Library/DialogAbout.cpp new file mode 100644 index 00000000..74b90888 --- /dev/null +++ b/Library/DialogAbout.cpp @@ -0,0 +1,962 @@ +/* + Copyright (C) 2011 Birunthan Mohanathas, Kimmo Pekkola + + 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "StdAfx.h" +#include "Rainmeter.h" +#include "System.h" +#include "MeterWindow.h" +#include "Measure.h" +#include "resource.h" +#include "DialogAbout.h" +#include "../Version.h" + +#define WM_DELAYED_CLOSE WM_APP + 0 + +extern CRainmeter* Rainmeter; + +WINDOWPLACEMENT CDialogAbout::c_WindowPlacement = {0}; +CDialogAbout* CDialogAbout::c_Dialog = NULL; + +/* +** CDialogAbout +** +** Constructor. +** +*/ +CDialogAbout::CDialogAbout(HWND wnd) : CDialog(wnd), + m_TabLog(), + m_TabMeasures(), + m_TabPlugins() +{ +} + +/* +** ~CDialogAbout +** +** Destructor. +** +*/ +CDialogAbout::~CDialogAbout() +{ + delete m_TabLog; + delete m_TabMeasures; + delete m_TabPlugins; +} + +/* +** Open +** +** Opens the About dialog. +** +*/ +void CDialogAbout::Open(int tab) +{ + if (!c_Dialog) + { + HINSTANCE instance = Rainmeter->GetInstance(); + HWND owner = Rainmeter->GetTrayWindow()->GetWindow(); + if (!CreateDialog(instance, MAKEINTRESOURCE(IDD_ABOUT_DIALOG), owner, DlgProc)) return; + } + else + { + if (!IsZoomed(c_Dialog->m_Window)) + { + ShowWindow(c_Dialog->m_Window, SW_SHOWNORMAL); + } + } + + BringWindowToTop(c_Dialog->m_Window); + + // Fake WM_NOTIFY to change tab + NMHDR nm; + nm.code = TCN_SELCHANGE; + nm.idFrom = IDC_ABOUT_TAB; + nm.hwndFrom = GetDlgItem(c_Dialog->m_Window, IDC_ABOUT_TAB); + TabCtrl_SetCurSel(nm.hwndFrom, tab); + c_Dialog->OnNotify(0, (LPARAM)&nm); +} + +void CDialogAbout::AddLogItem(int level, LPCWSTR time, LPCWSTR message) +{ + if (c_Dialog && c_Dialog->m_TabLog && c_Dialog->m_TabLog->IsInitialized()) + { + c_Dialog->m_TabLog->AddItem(level, time, message); + } +} + +void CDialogAbout::UpdateSkins() +{ + if (c_Dialog && c_Dialog->m_TabMeasures && c_Dialog->m_TabMeasures->IsInitialized()) + { + c_Dialog->m_TabMeasures->UpdateSkinList(); + } +} + +void CDialogAbout::UpdateMeasures(LPCTSTR entryName) +{ + if (c_Dialog && c_Dialog->m_TabMeasures && c_Dialog->m_TabMeasures->IsInitialized()) + { + c_Dialog->m_TabMeasures->UpdateMeasureList(entryName); + } +} + +/* +** DlgProc +** +** Dialog procedure for the About dialog. +** +*/ +INT_PTR CALLBACK CDialogAbout::DlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + if (!c_Dialog) + { + if (uMsg == WM_INITDIALOG) + { + c_Dialog = new CDialogAbout(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_GETMINMAXINFO: + { + MINMAXINFO* mmi = (MINMAXINFO*)lParam; + mmi->ptMinTrackSize.x = 400; + mmi->ptMinTrackSize.y = 250; + } + return TRUE; + + case WM_SIZE: + { + if (wParam != SIZE_MINIMIZED) + { + int w = LOWORD(lParam); + int h = HIWORD(lParam); + RECT r; + + HWND item = GetDlgItem(hWnd, IDC_ABOUT_TAB); + SetWindowPos(item, NULL, 0, 0, w - 18, h - 47, SWP_NOMOVE | SWP_NOZORDER); + + item = GetDlgItem(hWnd, IDC_ABOUT_VERSION_TEXT); + GetClientRect(item, &r); + SetWindowPos(item, NULL, 8, h - r.bottom - 11, 0, 0, SWP_NOSIZE | SWP_NOZORDER); + + item = GetDlgItem(hWnd, IDCLOSE); + GetClientRect(item, &r); + SetWindowPos(item, NULL, w - r.right - 9, h - r.bottom - 8, 0, 0, SWP_NOSIZE | SWP_NOZORDER); + + c_Dialog->m_TabLog->Resize(w - 48, h - 100); + c_Dialog->m_TabMeasures->Resize(w - 48, h - 100); + c_Dialog->m_TabPlugins->Resize(w - 48, h - 100); + } + } + return TRUE; + + case WM_CLOSE: + PostMessage(hWnd, WM_DELAYED_CLOSE, 0, 0); + return TRUE; + + case WM_DESTROY: + delete c_Dialog; + c_Dialog = NULL; + return FALSE; + + case WM_DELAYED_CLOSE: + GetWindowPlacement(hWnd, &c_WindowPlacement); + if (c_WindowPlacement.showCmd == SW_SHOWMINIMIZED) + { + c_WindowPlacement.showCmd = SW_SHOWNORMAL; + } + DestroyWindow(hWnd); + return TRUE; + } + } + + return FALSE; +} + +INT_PTR CDialogAbout::OnInitDialog(WPARAM wParam, LPARAM lParam) +{ + HICON hIcon = LoadIcon(Rainmeter->GetInstance(), MAKEINTRESOURCE(IDI_TRAY)); + SendMessage(m_Window, WM_SETICON, ICON_SMALL, (LPARAM)hIcon); + + if (c_WindowPlacement.length == 0) + { + c_WindowPlacement.length = sizeof(WINDOWPLACEMENT); + GetWindowPlacement(m_Window, &c_WindowPlacement); + } + + SetWindowPlacement(m_Window, &c_WindowPlacement); + + HWND item = GetDlgItem(m_Window, IDC_ABOUT_TAB); + TCITEM tci = {0}; + tci.mask = TCIF_TEXT; + tci.pszText = L"Log"; + TabCtrl_InsertItem(item, 0, &tci); + tci.pszText = L"Measures"; + TabCtrl_InsertItem(item, 1, &tci); + tci.pszText = L"Plugins"; + TabCtrl_InsertItem(item, 2, &tci); + + item = GetDlgItem(m_Window, IDC_ABOUT_VERSION_TEXT); + WCHAR tmpSz[128]; + _snwprintf_s(tmpSz, _TRUNCATE, L"%s %s%s r%i %s (%s)", APPNAME, APPVERSION, revision_beta ? L" beta" : L"", revision_number, APPBITS, APPDATE); + SetWindowText(item, tmpSz); + + HINSTANCE instance = Rainmeter->GetInstance(); + m_TabLog = new CTabLog(CreateDialog(instance, MAKEINTRESOURCE(IDD_ABOUTLOG_DIALOG), m_Window, CDialogAbout::CTabLog::DlgProc)); + m_TabMeasures = new CTabMeasures(CreateDialog(instance, MAKEINTRESOURCE(IDD_ABOUTMEASURES_DIALOG), m_Window, CDialogAbout::CTabMeasures::DlgProc)); + m_TabPlugins = new CTabPlugins(CreateDialog(instance, MAKEINTRESOURCE(IDD_ABOUTPLUGINS_DIALOG), m_Window, CDialogAbout::CTabPlugins::DlgProc)); + + if (CSystem::GetOSPlatform() >= OSPLATFORM_VISTA) + { + // Use UI font (Segoe UI) on Vista+ + SetDialogFont(); + } + + return TRUE; +} + +INT_PTR CDialogAbout::OnCommand(WPARAM wParam, LPARAM lParam) +{ + switch (LOWORD(wParam)) + { + case IDCLOSE: + PostMessage(m_Window, WM_DELAYED_CLOSE, 0, 0); + break; + + default: + return FALSE; + } + + return TRUE; +} + +INT_PTR CDialogAbout::OnNotify(WPARAM wParam, LPARAM lParam) +{ + LPNMHDR nm = (LPNMHDR)lParam; + switch (nm->idFrom) + { + case IDC_ABOUT_TAB: + if (nm->code == TCN_SELCHANGE) + { + CTab* tab; + int sel = TabCtrl_GetCurSel(nm->hwndFrom); + if (sel == 0) + { + tab = m_TabLog; + } + else if (sel == 1) + { + tab = m_TabMeasures; + } + else // if (sel == 2) + { + tab = m_TabPlugins; + } + + if (tab) + { + if (!tab->IsInitialized()) + { + tab->Initialize(); + } + BringWindowToTop(tab->GetWindow()); + } + } + break; + + default: + return FALSE; + } + + return TRUE; +} + +// ----------------------------------------------------------------------------------------------- +// +// Log tab +// +// ----------------------------------------------------------------------------------------------- + +/* +** CTabLog +** +** Constructor. +** +*/ +CDialogAbout::CTabLog::CTabLog(HWND wnd) : CTab(wnd), + m_Error(true), + m_Warning(true), + m_Notice(true), + m_Debug(true) +{ +} + +/* +** Initialize +** +** Called when tab is displayed. +** +*/ +void CDialogAbout::CTabLog::Initialize() +{ + m_Initialized = true; + + // Add columns to the list view + HWND item = GetDlgItem(m_Window, IDC_ABOUTLOG_ITEMS_LISTVIEW); + + ListView_SetExtendedListViewStyleEx(item, LVS_EX_FULLROWSELECT | LVS_EX_DOUBLEBUFFER, LVS_EX_FULLROWSELECT | LVS_EX_DOUBLEBUFFER); + + // Set folder/.ini icons for tree list + HIMAGELIST hImageList = ImageList_Create(16, 16, ILC_COLOR32, 2, 10); + HMODULE hDLL = LoadLibrary(L"user32.dll"); + + HICON hIcon = (HICON)LoadImage(hDLL, MAKEINTRESOURCE(103), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR); + ImageList_AddIcon(hImageList, hIcon); + DeleteObject(hIcon); + + hIcon = (HICON)LoadImage(hDLL, MAKEINTRESOURCE(101), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR); + ImageList_AddIcon(hImageList, hIcon); + DeleteObject(hIcon); + + hIcon = (HICON)LoadImage(hDLL, MAKEINTRESOURCE(104), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR); + ImageList_AddIcon(hImageList, hIcon); + DeleteObject(hIcon); + + FreeLibrary(hDLL); + + ListView_SetImageList(item, (WPARAM)hImageList, LVSIL_SMALL); + + LVCOLUMN lvc; + lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; + lvc.fmt = LVCFMT_LEFT; // left-aligned column + lvc.iSubItem = 0; + lvc.pszText = L"Type"; + lvc.cx = 75; + ListView_InsertColumn(item, 0, &lvc); + lvc.iSubItem = 1; + lvc.cx = 85; + lvc.pszText = L"Time"; + ListView_InsertColumn(item, 1, &lvc); + lvc.iSubItem = 2; + lvc.cx = 370; + lvc.pszText = L"Message"; + ListView_InsertColumn(item, 2, &lvc); + + item = GetDlgItem(m_Window, IDC_ABOUTLOG_ERROR_CHECKBOX); + Button_SetCheck(item, BST_CHECKED); + + item = GetDlgItem(m_Window, IDC_ABOUTLOG_WARNING_CHECKBOX); + Button_SetCheck(item, BST_CHECKED); + + item = GetDlgItem(m_Window, IDC_ABOUTLOG_NOTICE_CHECKBOX); + Button_SetCheck(item, BST_CHECKED); + + item = GetDlgItem(m_Window, IDC_ABOUTLOG_DEBUG_CHECKBOX); + Button_SetCheck(item, BST_CHECKED); +} + +/* +** Resize +** +** Resizes window and repositions controls. +** +*/ +void CDialogAbout::CTabLog::Resize(int w, int h) +{ + SetWindowPos(m_Window, NULL, 0, 0, w, h, SWP_NOMOVE | SWP_NOZORDER); + + HWND item = GetDlgItem(m_Window, IDC_ABOUTLOG_ITEMS_LISTVIEW); + SetWindowPos(item, NULL, 0, 0, w, h - 22, SWP_NOMOVE | SWP_NOZORDER); + + // Adjust third colum + LVCOLUMN lvc; + lvc.mask = LVCF_WIDTH; + lvc.cx = w - 183; + ListView_SetColumn(item, 2, &lvc); + + item = GetDlgItem(m_Window, IDC_ABOUTLOG_ERROR_CHECKBOX); + SetWindowPos(item, NULL, 0, h - 15, 0, 0, SWP_NOSIZE | SWP_NOZORDER); + + item = GetDlgItem(m_Window, IDC_ABOUTLOG_WARNING_CHECKBOX); + SetWindowPos(item, NULL, 75, h - 15, 0, 0, SWP_NOSIZE | SWP_NOZORDER); + + item = GetDlgItem(m_Window, IDC_ABOUTLOG_NOTICE_CHECKBOX); + SetWindowPos(item, NULL, 150, h - 15, 0, 0, SWP_NOSIZE | SWP_NOZORDER); + + item = GetDlgItem(m_Window, IDC_ABOUTLOG_DEBUG_CHECKBOX); + SetWindowPos(item, NULL, 225, h - 15, 0, 0, SWP_NOSIZE | SWP_NOZORDER); +} + +/* +** AddItem +** +** Adds item to log. +** +*/ +void CDialogAbout::CTabLog::AddItem(int level, LPCWSTR time, LPCWSTR message) +{ + LVITEM vitem; + vitem.mask = LVIF_IMAGE | LVIF_TEXT; + vitem.iItem = 0; + vitem.iSubItem = 0; + + switch (level) + { + case LOG_ERROR: + if (!m_Error) return; + vitem.pszText = L"Error"; + vitem.iImage = 0; + break; + + case LOG_WARNING: + if (!m_Error) return; + vitem.pszText = L"Warning"; + vitem.iImage = 1; + break; + + case LOG_NOTICE: + if (!m_Notice) return; + vitem.pszText = L"Notice"; + vitem.iImage = 2; + break; + + case LOG_DEBUG: + if (!m_Debug) return; + vitem.pszText = L"Debug"; + vitem.iImage = -1; + break; + } + + HWND item = GetDlgItem(m_Window, IDC_ABOUTLOG_ITEMS_LISTVIEW); + ListView_InsertItem(item, &vitem); + ListView_SetItemText(item, vitem.iItem, 1, (WCHAR*)time); + ListView_SetItemText(item, vitem.iItem, 2, (WCHAR*)message); + if (!ListView_IsItemVisible(item, 0)) + { + ListView_Scroll(item, 0, 16); + } +} + +/* +** DlgProc +** +** Dialog procedure for the log dialog. +** +*/ +INT_PTR CALLBACK CDialogAbout::CTabLog::DlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) + { + case WM_COMMAND: + return c_Dialog->m_TabLog->OnCommand(wParam, lParam); + + case WM_CTLCOLORDLG: + return OnColorDialog(wParam, lParam); + + case WM_CTLCOLORBTN: + case WM_CTLCOLORSTATIC: + return OnColorStatic(wParam, lParam); + } + + return FALSE; +} + +INT_PTR CDialogAbout::CTabLog::OnCommand(WPARAM wParam, LPARAM lParam) +{ + switch (LOWORD(wParam)) + { + case IDC_ABOUTLOG_ERROR_CHECKBOX: + if (HIWORD(wParam) == BN_CLICKED) + { + m_Error = !m_Error; + } + break; + + case IDC_ABOUTLOG_WARNING_CHECKBOX: + if (HIWORD(wParam) == BN_CLICKED) + { + m_Warning = !m_Warning; + } + break; + + case IDC_ABOUTLOG_NOTICE_CHECKBOX: + if (HIWORD(wParam) == BN_CLICKED) + { + m_Notice = !m_Notice; + } + break; + + case IDC_ABOUTLOG_DEBUG_CHECKBOX: + if (HIWORD(wParam) == BN_CLICKED) + { + m_Debug = !m_Debug; + } + break; + + default: + return FALSE; + } + + return TRUE; +} + +// ----------------------------------------------------------------------------------------------- +// +// Measures tab +// +// ----------------------------------------------------------------------------------------------- + +/* +** CTabMeasures +** +** Constructor. +** +*/ +CDialogAbout::CTabMeasures::CTabMeasures(HWND wnd) : CTab(wnd) +{ +} + +/* +** Initialize +** +** Called when tab is displayed. +** +*/ +void CDialogAbout::CTabMeasures::Initialize() +{ + m_Initialized = true; + + // Add columns to the list view + HWND item = GetDlgItem(m_Window, IDC_ABOUTMEASURES_ITEMS_LISTVIEW); + ListView_SetExtendedListViewStyleEx(item, LVS_EX_FULLROWSELECT | LVS_EX_DOUBLEBUFFER, LVS_EX_FULLROWSELECT | LVS_EX_DOUBLEBUFFER); + + LVCOLUMN lvc; + lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; + lvc.iSubItem = 0; + lvc.pszText = L"Name"; + lvc.cx = 120; + lvc.fmt = LVCFMT_LEFT; // left-aligned column + ListView_InsertColumn(item, 0, &lvc); + lvc.iSubItem = 1; + lvc.cx = 90; + lvc.pszText = L"Range"; + ListView_InsertColumn(item, 1, &lvc); + lvc.iSubItem = 2; + lvc.cx = 160; + lvc.pszText = L"Value"; + ListView_InsertColumn(item, 2, &lvc); + + // Add entries for each config + item = GetDlgItem(m_Window, IDC_ABOUTMEASURES_ITEMS_LISTBOX); + const std::map& windows = Rainmeter->GetAllMeterWindows(); + std::map::const_iterator iter = windows.begin(); + for ( ; iter != windows.end(); ++iter) + { + CMeterWindow* meterWindow = (*iter).second; + const std::wstring& skinName = meterWindow->GetSkinName(); + SendMessage(item, LB_ADDSTRING, NULL, (LPARAM)skinName.c_str()); + size_t namelength = skinName.length(); + + int currwidth = (int)SendMessage(item, LB_GETHORIZONTALEXTENT, NULL, NULL); + if (6 * (int)namelength > currwidth) + { + SendMessage(item, LB_SETHORIZONTALEXTENT, 6 * namelength, NULL); + } + } + + // Select first item + SendMessage(item, LB_SETCURSEL, 0, 0); +} + +/* +** Resize +** +** Resizes window and repositions controls. +** +*/ +void CDialogAbout::CTabMeasures::Resize(int w, int h) +{ + SetWindowPos(m_Window, NULL, 0, 0, w, h, SWP_NOMOVE | SWP_NOZORDER); + + HWND item = GetDlgItem(m_Window, IDC_ABOUTMEASURES_ITEMS_LISTVIEW); + SetWindowPos(item, NULL, 0, 0, w - 160, h, SWP_NOMOVE | SWP_NOZORDER); + + // Adjust third colum + LVCOLUMN lvc; + lvc.mask = LVCF_WIDTH; + lvc.cx = w - 392; + ListView_SetColumn(item, 2, &lvc); + + item = GetDlgItem(m_Window, IDC_ABOUTMEASURES_ITEMS_LISTBOX); + SetWindowPos(item, NULL, 0, 0, 150, h, SWP_NOMOVE | SWP_NOZORDER); +} + +/* +** UpdateSkinList +** +** Updates the list of skins. +** +*/ +void CDialogAbout::CTabMeasures::UpdateSkinList() +{ + WCHAR* selectedItemName = NULL; + + HWND item = GetDlgItem(m_Window, IDC_ABOUTMEASURES_ITEMS_LISTBOX); + int selected = (int)SendMessage(item, LB_GETCURSEL, 0, 0); + + // Get current selected entry + if (selected != LB_ERR) + { + int selectedItemLen = (int)SendMessage(item, LB_GETTEXTLEN, selected, 0); + + if (selectedItemLen != LB_ERR) + { + selectedItemName = new WCHAR[selectedItemLen + 1]; + + if (LB_ERR != SendMessage(item, LB_GETTEXT, selected, (LPARAM)selectedItemName)) + { + selectedItemName[selectedItemLen] = L'\0'; + } + else + { + delete [] selectedItemName; + selectedItemName = NULL; + } + } + } + + // Delete all entries + SendMessage(item, LB_RESETCONTENT, 0, 0); + + // TODO Move following to common + const std::map& windows = Rainmeter->GetAllMeterWindows(); + std::map::const_iterator iter = windows.begin(); + for ( ; iter != windows.end(); ++iter) + { + CMeterWindow* meterWindow = (*iter).second; + const std::wstring& skinName = meterWindow->GetSkinName(); + SendMessage(item, LB_ADDSTRING, NULL, (LPARAM)skinName.c_str()); + size_t namelength = skinName.length(); + + int currwidth = (int)SendMessage(item, LB_GETHORIZONTALEXTENT, NULL, NULL); + if (6 * (int)namelength > currwidth) + { + SendMessage(item, LB_SETHORIZONTALEXTENT, 6 * namelength, NULL); + } + } + + if (selectedItemName != NULL) + { + int sel = 0; + SendMessage(item, LB_SETCURSEL, sel, 0); + + const std::map& windows = Rainmeter->GetAllMeterWindows(); + std::map::const_iterator iter = windows.begin(); + for ( ; iter != windows.end(); ++iter) + { + if (_wcsicmp(selectedItemName, (*iter).first.c_str()) == 0) + { + SendMessage(item, LB_SETCURSEL, sel, 0); + break; + } + ++sel; + } + + delete [] selectedItemName; + } +} + +/* +** UpdateSkinList +** +** Updates the list of measures and values. +** +*/ +void CDialogAbout::CTabMeasures::UpdateMeasureList(LPCTSTR entryName) +{ + HWND item = GetDlgItem(m_Window, IDC_ABOUTMEASURES_ITEMS_LISTBOX); + int selected = (int)SendMessage(item, LB_GETCURSEL, NULL, NULL); + + const std::map& windows = Rainmeter->GetAllMeterWindows(); + std::map::const_iterator iter = windows.begin(); + for (int i = 0; iter != windows.end(); ++i, ++iter) + { + if (i == selected && + (entryName == NULL || _wcsicmp(entryName, (*iter).first.c_str()) == 0)) + { + item = GetDlgItem(m_Window, IDC_ABOUTMEASURES_ITEMS_LISTVIEW); + SendMessage(item, WM_SETREDRAW, 0, 0); + int count = ListView_GetItemCount(item); + int index = 0; + + CMeterWindow* meterWindow = (*iter).second; + const std::list& measures = meterWindow->GetMeasures(); + std::list::const_iterator j = measures.begin(); + for ( ; j != measures.end(); ++j) + { + const WCHAR* name = (*j)->GetName(); + const WCHAR* val = (*j)->GetStats(); + + WCHAR buffer[256]; + double minVal = (*j)->GetMinValue(); + double maxVal = (*j)->GetMaxValue(); + CMeasure::GetScaledValue(AUTOSCALE_ON, 1, minVal, buffer, _countof(buffer)); + std::wstring range = buffer; + range += L" - "; + CMeasure::GetScaledValue(AUTOSCALE_ON, 1, maxVal, buffer, _countof(buffer)); + range += buffer; + + if (name && *name) + { + if (index < count) + { + ListView_SetItemText(item, index, 0, (WCHAR*)name); + } + else + { + LVITEM vitem; + vitem.mask = LVIF_TEXT; + vitem.iItem = index; + vitem.iSubItem = 0; + vitem.pszText = (WCHAR*)name; + ListView_InsertItem(item, &vitem); + } + + ListView_SetItemText(item, index, 1, (WCHAR*)range.c_str()); + if (val) + { + ListView_SetItemText(item, index, 2, (WCHAR*)val); + } + ++index; + } + } + + if (count > index) + { + // Delete unnecessary items + for (int j = index; j < count; ++j) + { + ListView_DeleteItem(item, index); + } + } + + SendMessage(item, WM_SETREDRAW, 1, 0); + break; + } + } +} + +/* +** DlgProc +** +** Dialog procedure for the measures dialog. +** +*/ +INT_PTR CALLBACK CDialogAbout::CTabMeasures::DlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) + { + case WM_COMMAND: + return c_Dialog->m_TabMeasures->OnCommand(wParam, lParam); + + case WM_CTLCOLORDLG: + return OnColorDialog(wParam, lParam); + + case WM_CTLCOLORBTN: + case WM_CTLCOLORSTATIC: + return OnColorStatic(wParam, lParam); + } + + return FALSE; +} + +INT_PTR CDialogAbout::CTabMeasures::OnCommand(WPARAM wParam, LPARAM lParam) +{ + switch (LOWORD(wParam)) + { + case IDC_ABOUTMEASURES_ITEMS_LISTBOX: + if (HIWORD(wParam) == LBN_SELCHANGE) + { + UpdateMeasureList(NULL); + } + break; + + default: + return FALSE; + } + + return TRUE; +} + +// ----------------------------------------------------------------------------------------------- +// +// Plugins tab +// +// ----------------------------------------------------------------------------------------------- + +/* +** CTabPlugins +** +** Constructor. +** +*/ +CDialogAbout::CTabPlugins::CTabPlugins(HWND wnd) : CTab(wnd) +{ +} + +/* +** Initialize +** +** Called when tab is displayed. +** +*/ +void CDialogAbout::CTabPlugins::Initialize() +{ + m_Initialized = true; + + // Add columns to the list view + HWND item = GetDlgItem(m_Window, IDC_ABOUTPLUGINS_ITEMS_LISTVIEW); + + LVCOLUMN lvc; + lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; + lvc.iSubItem = 0; + lvc.pszText = L"Name"; + lvc.cx = 140; + lvc.fmt = LVCFMT_LEFT; // left-aligned column + ListView_InsertColumn(item, 0, &lvc); + lvc.iSubItem = 1; + lvc.cx = 80; + lvc.pszText = L"Version"; + ListView_InsertColumn(item, 1, &lvc); + lvc.iSubItem = 2; + lvc.cx = 310; + lvc.pszText = L"Author"; + ListView_InsertColumn(item, 2, &lvc); + + LVITEM vitem; + vitem.mask = LVIF_TEXT; + vitem.iItem = 0; + vitem.iSubItem = 0; + + // Scan for plugins + WIN32_FIND_DATA fileData; // Data structure describes the file found + HANDLE hSearch; // Search handle returned by FindFirstFile + + std::wstring files = Rainmeter->GetPluginPath() + L"*.dll"; + + // Start searching for .ini files in the given directory. + hSearch = FindFirstFile(files.c_str(), &fileData); + int index = 0; + do + { + if (hSearch == INVALID_HANDLE_VALUE) break; // No more files found + + // Try to get the version and author + std::wstring tmpSz = Rainmeter->GetPluginPath() + fileData.cFileName; + DWORD err = 0; + HMODULE dll = CSystem::RmLoadLibrary(tmpSz.c_str(), &err, true); + if (dll) + { + vitem.iItem = index; + vitem.pszText = fileData.cFileName; + ListView_InsertItem(item, &vitem); + + GETPLUGINVERSION GetVersionFunc = (GETPLUGINVERSION)GetProcAddress(dll, "GetPluginVersion"); + if (GetVersionFunc) + { + UINT version = GetVersionFunc(); + WCHAR buffer[64]; + _snwprintf_s(buffer, _TRUNCATE, L"%u.%u", version / 1000, version % 1000); + ListView_SetItemText(item, vitem.iItem, 1, buffer); + } + + GETPLUGINAUTHOR GetAuthorFunc = (GETPLUGINAUTHOR)GetProcAddress(dll, "GetPluginAuthor"); + if (GetAuthorFunc) + { + LPCTSTR author = GetAuthorFunc(); + if (author && *author) + { + ListView_SetItemText(item, vitem.iItem, 2, (LPWSTR)author); + } + } + + ++index; + FreeLibrary(dll); + } + else + { + LogWithArgs(LOG_ERROR, L"Unable to load plugin: %s (%u)", tmpSz.c_str(), err); + } + } + while (FindNextFile(hSearch, &fileData)); + + FindClose(hSearch); + + LSLog(LOG_ERROR, L"Rainmeter", L"here end"); +} + +/* +** Resize +** +** Resizes window and repositions controls. +** +*/ +void CDialogAbout::CTabPlugins::Resize(int w, int h) +{ + SetWindowPos(m_Window, NULL, 0, 0, w, h, SWP_NOMOVE | SWP_NOZORDER); + + HWND item = GetDlgItem(m_Window, IDC_ABOUTPLUGINS_ITEMS_LISTVIEW); + SetWindowPos(item, NULL, 0, 0, w, h, SWP_NOMOVE | SWP_NOZORDER); + + // Adjust third colum + LVCOLUMN lvc; + lvc.mask = LVCF_WIDTH; + lvc.cx = w - 242; + ListView_SetColumn(item, 2, &lvc); +} + +/* +** DlgProc +** +** Dialog procedure for the Plugins tab. +** +*/ +INT_PTR CALLBACK CDialogAbout::CTabPlugins::DlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) + { + case WM_CTLCOLORDLG: + return OnColorDialog(wParam, lParam); + + case WM_CTLCOLORBTN: + case WM_CTLCOLORSTATIC: + return OnColorStatic(wParam, lParam); + } + + return FALSE; +} diff --git a/Library/DialogAbout.h b/Library/DialogAbout.h new file mode 100644 index 00000000..43aa5c71 --- /dev/null +++ b/Library/DialogAbout.h @@ -0,0 +1,105 @@ +/* + Copyright (C) 2011 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef _DIALOGABOUT_H_ +#define _DIALOGABOUT_H_ + +#include "MeterWindow.h" +#include "TrayWindow.h" +#include "Dialog.h" + +class CDialogAbout : public CDialog +{ +public: + CDialogAbout(HWND window); + virtual ~CDialogAbout(); + + static INT_PTR CALLBACK DlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + INT_PTR OnInitDialog(WPARAM wParam, LPARAM lParam); + INT_PTR OnNotify(WPARAM wParam, LPARAM lParam); + INT_PTR OnCommand(WPARAM wParam, LPARAM lParam); + + static void Open(int tab = 0); + + static void AddLogItem(int level, LPCWSTR time, LPCWSTR message); + static void UpdateSkins(); + static void UpdateMeasures(LPCTSTR entryName = NULL); + + static WINDOWPLACEMENT c_WindowPlacement; + static CDialogAbout* c_Dialog; + +private: + // Log tab + class CTabLog : public CTab + { + public: + CTabLog(HWND window); + + virtual void Initialize(); + virtual void Resize(int w, int h); + + static INT_PTR CALLBACK DlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + INT_PTR OnCommand(WPARAM wParam, LPARAM lParam); + + void AddItem(int level, LPCWSTR time, LPCWSTR message); + + private: + bool m_Error; + bool m_Warning; + bool m_Notice; + bool m_Debug; + }; + + // Measures tab + class CTabMeasures : public CTab + { + public: + CTabMeasures(HWND window); + + virtual void Initialize(); + virtual void Resize(int w, int h); + + static INT_PTR CALLBACK DlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + INT_PTR OnCommand(WPARAM wParam, LPARAM lParam); + + void UpdateSkinList(); + void UpdateMeasureList(LPCTSTR entryName); + }; + + // Plugins tab + class CTabPlugins : public CTab + { + public: + CTabPlugins(HWND window); + + virtual void Initialize(); + virtual void Resize(int w, int h); + + static INT_PTR CALLBACK DlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + + private: + typedef LPCTSTR (*GETPLUGINAUTHOR)(); + typedef UINT (*GETPLUGINVERSION)(); + }; + + CTabLog* m_TabLog; + CTabMeasures* m_TabMeasures; + CTabPlugins* m_TabPlugins; +}; + +#endif diff --git a/Library/DialogManage.cpp b/Library/DialogManage.cpp new file mode 100644 index 00000000..a4b3d273 --- /dev/null +++ b/Library/DialogManage.cpp @@ -0,0 +1,1769 @@ +/* + Copyright (C) 2011 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "StdAfx.h" +#include "Rainmeter.h" +#include "System.h" +#include "MeterWindow.h" +#include "Measure.h" +#include "resource.h" +#include "DialogManage.h" +#include "../Version.h" + +#define WM_DELAYED_CLOSE WM_APP + 0 + +extern CRainmeter* Rainmeter; + +WINDOWPLACEMENT CDialogManage::c_WindowPlacement = {0}; +CDialogManage* CDialogManage::c_Dialog = NULL; + +/* +** CDialogManage +** +** Constructor. +** +*/ +CDialogManage::CDialogManage(HWND wnd) : CDialog(wnd), + m_TabSkins(), + m_TabThemes(), + m_TabSettings() +{ +} + +/* +** ~CDialogManage +** +** Destructor. +** +*/ +CDialogManage::~CDialogManage() +{ + delete m_TabSkins; + delete m_TabThemes; + delete m_TabSettings; +} + +/* +** Open +** +** Opens the Manage dialog. +** +*/ +void CDialogManage::Open(int tab) +{ + if (!c_Dialog) + { + HINSTANCE instance = Rainmeter->GetInstance(); + HWND owner = Rainmeter->GetTrayWindow()->GetWindow(); + if (!CreateDialog(instance, MAKEINTRESOURCE(IDD_MANAGE_DIALOG), owner, DlgProc)) return; + } + else + { + if (!IsZoomed(c_Dialog->m_Window)) + { + ShowWindow(c_Dialog->m_Window, SW_SHOWNORMAL); + } + } + + BringWindowToTop(c_Dialog->m_Window); + + // Fake WM_NOTIFY to change tab + NMHDR nm; + nm.code = TCN_SELCHANGE; + nm.idFrom = IDC_MANAGE_TAB; + nm.hwndFrom = GetDlgItem(c_Dialog->m_Window, IDC_MANAGE_TAB); + TabCtrl_SetCurSel(nm.hwndFrom, tab); + c_Dialog->OnNotify(0, (LPARAM)&nm); +} + +/* +** OpenSkin +** +** Opens the Manage dialog Skins tab with skin selected. +** +*/ +void CDialogManage::OpenSkin(CMeterWindow* meterWindow) +{ + Open(); + + if (c_Dialog && c_Dialog->m_TabSkins) + { + std::wstring name = meterWindow->GetSkinName(); + name += L"\\"; + name += meterWindow->GetSkinIniFile(); + + HWND item = GetDlgItem(c_Dialog->m_TabSkins->GetWindow(), IDC_MANAGESKINS_SKINS_TREEVIEW); + c_Dialog->m_TabSkins->SelectTreeItem(item, TreeView_GetRoot(item), name.c_str()); + } +} + +/* +** UpdateSkins +** +** Updates Skins tab. +** +*/ +void CDialogManage::UpdateSkins(CMeterWindow* meterWindow, bool deleted) +{ + if (c_Dialog && c_Dialog->m_TabSkins && c_Dialog->m_TabSkins->IsInitialized()) + { + c_Dialog->m_TabSkins->Update(meterWindow, deleted); + } +} + +/* +** UpdateThemes +** +** Updates Themes tab. +** +*/ +void CDialogManage::UpdateThemes() +{ + if (c_Dialog && c_Dialog->m_TabThemes && c_Dialog->m_TabThemes->IsInitialized()) + { + c_Dialog->m_TabThemes->Update(); + } +} + +std::wstring GetTreeSelectionPath(HWND tree) +{ + WCHAR buffer[MAX_PATH]; + + // Get current selection name + TVITEM tvi = {0}; + tvi.hItem = TreeView_GetSelection(tree); + tvi.mask = TVIF_TEXT; + tvi.pszText = buffer; + tvi.cchTextMax = MAX_PATH; + TreeView_GetItem(tree, &tvi); + + std::wstring path = buffer; + while ((tvi.hItem = TreeView_GetParent(tree, tvi.hItem)) != NULL) + { + TreeView_GetItem(tree, &tvi); + path.insert(0, L"\\"); + path.insert(0, buffer); + } + + return path; +} + +/* +** DlgProc +** +** Dialog procedure for the Manage dialog. +** +*/ +INT_PTR CALLBACK CDialogManage::DlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + if (!c_Dialog) + { + if (uMsg == WM_INITDIALOG) + { + c_Dialog = new CDialogManage(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: + PostMessage(hWnd, WM_DELAYED_CLOSE, 0, 0); + return TRUE; + + case WM_DESTROY: + delete c_Dialog; + c_Dialog = NULL; + return FALSE; + + case WM_DELAYED_CLOSE: + GetWindowPlacement(hWnd, &c_WindowPlacement); + if (c_WindowPlacement.showCmd == SW_SHOWMINIMIZED) + { + c_WindowPlacement.showCmd = SW_SHOWNORMAL; + } + DestroyWindow(hWnd); + return TRUE; + } + } + + return FALSE; +} + +INT_PTR CDialogManage::OnInitDialog(WPARAM wParam, LPARAM lParam) +{ + HICON hIcon = LoadIcon(Rainmeter->GetInstance(), MAKEINTRESOURCE(IDI_TRAY)); + SendMessage(m_Window, WM_SETICON, ICON_SMALL, (LPARAM)hIcon); + + if (c_WindowPlacement.length == 0) + { + c_WindowPlacement.length = sizeof(WINDOWPLACEMENT); + GetWindowPlacement(m_Window, &c_WindowPlacement); + } + + SetWindowPlacement(m_Window, &c_WindowPlacement); + + HWND item = GetDlgItem(m_Window, IDC_MANAGE_TAB); + TCITEM tci = {0}; + tci.mask = TCIF_TEXT; + tci.pszText = L"Skins"; + TabCtrl_InsertItem(item, 0, &tci); + tci.pszText = L"Themes"; + TabCtrl_InsertItem(item, 1, &tci); + tci.pszText = L"Settings"; + TabCtrl_InsertItem(item, 2, &tci); + + HINSTANCE instance = Rainmeter->GetInstance(); + m_TabSkins = new CTabSkins(CreateDialog(instance, MAKEINTRESOURCE(IDD_MANAGESKINS_DIALOG), m_Window, CTabSkins::DlgProc)); + m_TabThemes = new CTabThemes(CreateDialog(instance, MAKEINTRESOURCE(IDD_MANAGETHEMES_DIALOG), m_Window, CTabThemes::DlgProc)); + m_TabSettings = new CTabSettings(CreateDialog(instance, MAKEINTRESOURCE(IDD_MANAGESETTINGS_DIALOG), m_Window, CTabSettings::DlgProc)); + + if (CSystem::GetOSPlatform() >= OSPLATFORM_VISTA) + { + // Use UI font (Segoe UI) on Vista+ + SetDialogFont(); + + // Use arrows instead of plus/minus in the tree for Vista+ + item = GetDlgItem(m_TabSkins->GetWindow(), IDC_MANAGESKINS_SKINS_TREEVIEW); + SetWindowTheme(item, L"explorer", NULL); + } + + item = GetDlgItem(m_TabSkins->GetWindow(), IDC_MANAGESKINS_FILE_TEXT); + SendMessage(item, WM_SETFONT, (WPARAM)m_FontBold, 0); + + return TRUE; +} + +INT_PTR CDialogManage::OnCommand(WPARAM wParam, LPARAM lParam) +{ + switch (LOWORD(wParam)) + { + case IDC_REFRESHALL_BUTTON: + Rainmeter->RefreshAll(); + break; + + case IDC_EDITSETTINGS_BUTTON: + { + std::wstring command = Rainmeter->GetConfigEditor() + L" \""; + command += Rainmeter->GetIniFile(); + command += L"\""; + LSExecute(Rainmeter->GetTrayWindow()->GetWindow(), command.c_str(), SW_SHOWNORMAL); + } + break; + + case IDC_OPENLOG_BUTTON: + RainmeterAboutWide(); + break; + + case IDCLOSE: + PostMessage(m_Window, WM_DELAYED_CLOSE, 0, 0); + break; + + default: + return FALSE; + } + + return TRUE; +} + +INT_PTR CDialogManage::OnNotify(WPARAM wParam, LPARAM lParam) +{ + LPNMHDR nm = (LPNMHDR)lParam; + switch (nm->idFrom) + { + case IDC_MANAGE_TAB: + if (nm->code == TCN_SELCHANGE) + { + CTab* tab; + int sel = TabCtrl_GetCurSel(nm->hwndFrom); + if (sel == 0) + { + tab = m_TabSkins; + } + else if (sel == 1) + { + tab = m_TabThemes; + } + else // if (sel == 2) + { + tab = m_TabSettings; + } + + if (tab) + { + if (!tab->IsInitialized()) + { + tab->Initialize(); + } + BringWindowToTop(tab->GetWindow()); + } + } + break; + + default: + return FALSE; + } + + return TRUE; +} + +// ----------------------------------------------------------------------------------------------- +// +// Skins tab +// +// ----------------------------------------------------------------------------------------------- + +/* +** CTabSkins +** +** Constructor. +** +*/ +CDialogManage::CTabSkins::CTabSkins(HWND wnd) : CTab(wnd), + m_SkinWindow(), + m_HandleCommands(false), + m_IgnoreUpdate(false) +{ +} + +/* +** Initialize +** +** Called when tab is displayed. +** +*/ +void CDialogManage::CTabSkins::Initialize() +{ + m_Initialized = true; + + HWND item = GetDlgItem(m_Window, IDC_MANAGESKINS_ACTIVESKINS_BUTTON); + SetWindowText(item, L"Active skins \x25BE"); + + // Load folder/.ini icons from shell32 + HIMAGELIST hImageList = ImageList_Create(16, 16, ILC_COLOR32, 2, 10); + HMODULE hDLL = LoadLibrary(L"shell32.dll"); + + HICON hIcon = (HICON)LoadImage(hDLL, MAKEINTRESOURCE(4), IMAGE_ICON, 16, 16, LR_SHARED); + ImageList_AddIcon(hImageList, hIcon); + hIcon = (HICON)LoadImage(hDLL, MAKEINTRESOURCE(151), IMAGE_ICON, 16, 16, LR_SHARED); + ImageList_AddIcon(hImageList, hIcon); + + FreeLibrary(hDLL); + + // Apply icons and populate tree + item = GetDlgItem(m_Window, IDC_MANAGESKINS_SKINS_TREEVIEW); + TreeView_SetImageList(item, hImageList, TVSIL_NORMAL); + + TV_INSERTSTRUCT tvi = {0}; + tvi.hParent = NULL; + tvi.hInsertAfter = TVI_LAST; + tvi.item.mask= TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE; + tvi.item.iImage = tvi.item.iSelectedImage= 0; + PopulateTree(item, tvi, Rainmeter->m_ConfigMenu); + + // Get rid of the EDITTEXT control border + item = GetDlgItem(m_Window, IDC_MANAGESKINS_DESCRIPTION_TEXT); + SetWindowLong(item, GWL_EXSTYLE, GetWindowLong(item, GWL_EXSTYLE) &~ WS_EX_CLIENTEDGE); + SetWindowPos(item, NULL, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER); + + item = GetDlgItem(m_Window, IDC_MANAGESKINS_ADDMETADATA_LINK); + ShowWindow(item, SW_HIDE); + + item = GetDlgItem(m_Window, IDC_MANAGESKINS_DISPLAYMONITOR_BUTTON); + SetWindowText(item, L"Display monitor \x25BE"); + + item = GetDlgItem(m_Window, IDC_MANAGESKINS_TRANSPARENCY_COMBOBOX); + ComboBox_AddString(item, L"0%"); + ComboBox_AddString(item, L"10%"); + ComboBox_AddString(item, L"20%"); + ComboBox_AddString(item, L"30%"); + ComboBox_AddString(item, L"40%"); + ComboBox_AddString(item, L"50%"); + ComboBox_AddString(item, L"60%"); + ComboBox_AddString(item, L"70%"); + ComboBox_AddString(item, L"80%"); + ComboBox_AddString(item, L"90%"); + + item = GetDlgItem(m_Window, IDC_MANAGESKINS_ZPOSITION_COMBOBOX); + ComboBox_AddString(item, L"On desktop"); + ComboBox_AddString(item, L"Bottom"); + ComboBox_AddString(item, L"Normal"); + ComboBox_AddString(item, L"Topmost"); + ComboBox_AddString(item, L"Stay topmost"); + + item = GetDlgItem(m_Window, IDC_MANAGESKINS_ONHOVER_COMBOBOX); + ComboBox_AddString(item, L"Do nothing"); + ComboBox_AddString(item, L"Hide"); + ComboBox_AddString(item, L"Fade in"); + ComboBox_AddString(item, L"Fade out"); + + m_HandleCommands = true; +} + +/* +** Update +** +** Updates metadata and settings when changed. +** +*/ +void CDialogManage::CTabSkins::Update(CMeterWindow* meterWindow, bool deleted) +{ + if (m_IgnoreUpdate) + { + // Changed setting from dialog, no need to update + m_IgnoreUpdate = false; + } + else if (m_SkinWindow && m_SkinWindow == meterWindow) + { + // Update from currently open skin + m_HandleCommands = false; + if (deleted) + { + DisableControls(); + m_SkinWindow = NULL; + } + else + { + SetControls(); + } + m_HandleCommands = true; + } + else if (wcscmp(meterWindow->GetSkinName().c_str(), m_SkinName.c_str()) == 0 && + wcscmp(meterWindow->GetSkinIniFile().c_str(), m_FileName.c_str()) == 0) + { + ReadSkin(); + } +} + +void CDialogManage::CTabSkins::SetControls() +{ + WCHAR buffer[64]; + + HWND item = GetDlgItem(m_Window, IDC_MANAGESKINS_EDIT_BUTTON); + EnableWindow(item, TRUE); + + item = GetDlgItem(m_Window, IDC_MANAGESKINS_LOAD_BUTTON); + EnableWindow(item, TRUE); + + if (m_SkinWindow) + { + SetWindowText(item, L"Unload"); + + item = GetDlgItem(m_Window, IDC_MANAGESKINS_REFRESH_BUTTON); + EnableWindow(item, TRUE); + + item = GetDlgItem(m_Window, IDC_MANAGESKINS_X_TEXT); + EnableWindow(item, TRUE); + _itow(m_SkinWindow->GetX(), buffer, 10); + SetWindowText(item, buffer); + + item = GetDlgItem(m_Window, IDC_MANAGESKINS_Y_TEXT); + EnableWindow(item, TRUE); + _itow(m_SkinWindow->GetY(), buffer, 10); + SetWindowText(item, buffer); + + item = GetDlgItem(m_Window, IDC_MANAGESKINS_DISPLAYMONITOR_BUTTON); + EnableWindow(item, TRUE); + + item = GetDlgItem(m_Window, IDC_MANAGESKINS_DRAGGABLE_CHECKBOX); + if (Rainmeter->GetDisableDragging()) + { + EnableWindow(item, FALSE); + Button_SetCheck(item, BST_UNCHECKED); + } + else + { + EnableWindow(item, TRUE); + Button_SetCheck(item, m_SkinWindow->GetWindowDraggable()); + } + + item = GetDlgItem(m_Window, IDC_MANAGESKINS_CLICKTHROUGH_CHECKBOX); + EnableWindow(item, TRUE); + Button_SetCheck(item, m_SkinWindow->GetClickThrough()); + + item = GetDlgItem(m_Window, IDC_MANAGESKINS_KEEPONSCREEN_CHECKBOX); + EnableWindow(item, TRUE); + Button_SetCheck(item, m_SkinWindow->GetKeepOnScreen()); + + item = GetDlgItem(m_Window, IDC_MANAGESKINS_SAVEPOSITION_CHECKBOX); + EnableWindow(item, TRUE); + Button_SetCheck(item, m_SkinWindow->GetSavePosition()); + + item = GetDlgItem(m_Window, IDC_MANAGESKINS_SNAPTOEDGES_CHECKBOX); + EnableWindow(item, TRUE); + Button_SetCheck(item, m_SkinWindow->GetSnapEdges()); + + item = GetDlgItem(m_Window, IDC_MANAGESKINS_TRANSPARENCY_COMBOBOX); + EnableWindow(item, TRUE); + int value = (int)(10 - m_SkinWindow->GetAlphaValue() / 25.5); + value = min(9, value); + value = max(0, value); + ComboBox_SetCurSel(item, value); + + item = GetDlgItem(m_Window, IDC_MANAGESKINS_ZPOSITION_COMBOBOX); + EnableWindow(item, TRUE); + ComboBox_SetCurSel(item, m_SkinWindow->GetWindowZPosition() + 2); + + item = GetDlgItem(m_Window, IDC_MANAGESKINS_LOADORDER_TEXT); + _itow(Rainmeter->GetLoadOrder(m_SkinName), buffer, 10); + SetWindowText(item, buffer); + + item = GetDlgItem(m_Window, IDC_MANAGESKINS_ONHOVER_COMBOBOX); + EnableWindow(item, TRUE); + ComboBox_SetCurSel(item, m_SkinWindow->GetWindowHide()); + } + else + { + SetWindowText(item, L"Load"); + } +} + +void CDialogManage::CTabSkins::DisableControls(bool clear) +{ + HWND item = GetDlgItem(m_Window, IDC_MANAGESKINS_LOAD_BUTTON); + SetWindowText(item, L"Load"); + + if (clear) + { + EnableWindow(item, FALSE); + + item = GetDlgItem(m_Window, IDC_MANAGESKINS_EDIT_BUTTON); + EnableWindow(item, FALSE); + + item = GetDlgItem(m_Window, IDC_MANAGESKINS_FILE_TEXT); + SetWindowText(item, L"N/A"); + + item = GetDlgItem(m_Window, IDC_MANAGESKINS_CONFIG_TEXT); + SetWindowText(item, L"N/A"); + + item = GetDlgItem(m_Window, IDC_MANAGESKINS_AUTHOR_TEXT); + SetWindowText(item, L""); + + item = GetDlgItem(m_Window, IDC_MANAGESKINS_VERSION_TEXT); + SetWindowText(item, L""); + + item = GetDlgItem(m_Window, IDC_MANAGESKINS_LICENSE_TEXT); + SetWindowText(item, L""); + + item = GetDlgItem(m_Window, IDC_MANAGESKINS_DESCRIPTION_TEXT); + SetWindowText(item, L""); + ShowScrollBar(item, SB_VERT, FALSE); + + item = GetDlgItem(m_Window, IDC_MANAGESKINS_ADDMETADATA_LINK); + ShowWindow(item, SW_HIDE); + } + else + { + EnableWindow(item, TRUE); + } + + item = GetDlgItem(m_Window, IDC_MANAGESKINS_REFRESH_BUTTON); + EnableWindow(item, FALSE); + + item = GetDlgItem(m_Window, IDC_MANAGESKINS_X_TEXT); + SetWindowText(item, L""); + EnableWindow(item, FALSE); + + item = GetDlgItem(m_Window, IDC_MANAGESKINS_Y_TEXT); + SetWindowText(item, L""); + EnableWindow(item, FALSE); + + item = GetDlgItem(m_Window, IDC_MANAGESKINS_DISPLAYMONITOR_BUTTON); + EnableWindow(item, FALSE); + + item = GetDlgItem(m_Window, IDC_MANAGESKINS_DRAGGABLE_CHECKBOX); + EnableWindow(item, FALSE); + Button_SetCheck(item, BST_UNCHECKED); + + item = GetDlgItem(m_Window, IDC_MANAGESKINS_CLICKTHROUGH_CHECKBOX); + EnableWindow(item, FALSE); + Button_SetCheck(item, BST_UNCHECKED); + + item = GetDlgItem(m_Window, IDC_MANAGESKINS_KEEPONSCREEN_CHECKBOX); + EnableWindow(item, FALSE); + Button_SetCheck(item, BST_UNCHECKED); + + item = GetDlgItem(m_Window, IDC_MANAGESKINS_SAVEPOSITION_CHECKBOX); + EnableWindow(item, FALSE); + Button_SetCheck(item, BST_UNCHECKED); + + item = GetDlgItem(m_Window, IDC_MANAGESKINS_SNAPTOEDGES_CHECKBOX); + EnableWindow(item, FALSE); + Button_SetCheck(item, BST_UNCHECKED); + + item = GetDlgItem(m_Window, IDC_MANAGESKINS_TRANSPARENCY_COMBOBOX); + EnableWindow(item, FALSE); + ComboBox_SetCurSel(item, -1); + + item = GetDlgItem(m_Window, IDC_MANAGESKINS_ZPOSITION_COMBOBOX); + EnableWindow(item, FALSE); + ComboBox_SetCurSel(item, -1); + + item = GetDlgItem(m_Window, IDC_MANAGESKINS_LOADORDER_TEXT); + SetWindowText(item, L""); + + item = GetDlgItem(m_Window, IDC_MANAGESKINS_ONHOVER_COMBOBOX); + EnableWindow(item, FALSE); + ComboBox_SetCurSel(item, -1); +} + +void CDialogManage::CTabSkins::ReadSkin() +{ + HWND item = GetDlgItem(m_Window, IDC_MANAGESKINS_FILE_TEXT); + SetWindowText(item, m_FileName.c_str()); + + item = GetDlgItem(m_Window, IDC_MANAGESKINS_CONFIG_TEXT); + SetWindowText(item, m_SkinName.c_str()); + + item = GetDlgItem(m_Window, IDC_MANAGESKINS_EDIT_BUTTON); + EnableWindow(item, TRUE); + + std::wstring file = Rainmeter->GetSkinPath(); + file += m_SkinName; + file += L"\\"; + file += m_FileName; + m_SkinWindow = Rainmeter->GetMeterWindowByINI(file); + if (!m_SkinWindow) + { + DisableControls(); + } + + SetControls(); + + WCHAR buffer[MAX_LINE_LENGTH]; + + item = GetDlgItem(m_Window, IDC_MANAGESKINS_AUTHOR_TEXT); + GetPrivateProfileString(L"Rainmeter", L"Author", NULL, buffer, MAX_LINE_LENGTH, file.c_str()); + SetWindowText(item, buffer); + + item = GetDlgItem(m_Window, IDC_MANAGESKINS_ADDMETADATA_LINK); + if (GetPrivateProfileSection(L"Metadata", buffer, 8, file.c_str()) > 0) + { + ShowWindow(item, SW_HIDE); + + // Set metadata + item = GetDlgItem(m_Window, IDC_MANAGESKINS_VERSION_TEXT); + GetPrivateProfileString(L"Metadata", L"Version", NULL, buffer, MAX_LINE_LENGTH, file.c_str()); + SetWindowText(item, buffer); + + item = GetDlgItem(m_Window, IDC_MANAGESKINS_LICENSE_TEXT); + GetPrivateProfileString(L"Metadata", L"License", NULL, buffer, MAX_LINE_LENGTH, file.c_str()); + SetWindowText(item, buffer); + + item = GetDlgItem(m_Window, IDC_MANAGESKINS_DESCRIPTION_TEXT); + GetPrivateProfileString(L"Metadata", L"Description", NULL, buffer, MAX_LINE_LENGTH, file.c_str()); + std::wstring text = buffer; + + if (GetPrivateProfileString(L"Metadata", L"Instructions", NULL, buffer, MAX_LINE_LENGTH, file.c_str()) > 0) + { + text += L"\r\n\r\n"; + text += buffer; + } + + // Replace | with newline + std::wstring::size_type pos; + while ((pos = text.find_first_of(L'|')) != std::wstring::npos) + { + size_t count = (pos + 1 < text.length() && text[pos + 1] == L' ') ? 2 : 1; + if (text[pos - 1] == L' ') + { + --pos; + count += 1; + } + text.replace(pos, count, L"\r\n"); + } + + SetWindowText(item, text.c_str()); + + int lines = Edit_GetLineCount(item); + ShowScrollBar(item, SB_VERT, (BOOL)(lines > 6)); + } + else + { + ShowWindow(item, SW_SHOWNORMAL); + + item = GetDlgItem(m_Window, IDC_MANAGESKINS_VERSION_TEXT); + SetWindowText(item, L""); + + item = GetDlgItem(m_Window, IDC_MANAGESKINS_LICENSE_TEXT); + SetWindowText(item, L""); + + item = GetDlgItem(m_Window, IDC_MANAGESKINS_DESCRIPTION_TEXT); + SetWindowText(item, L""); + ShowScrollBar(item, SB_VERT, FALSE); + } +} + +/* +** PopulateTree +** +** Populates the treeview with folders and skins. +** +*/ +void CDialogManage::CTabSkins::PopulateTree(HWND tree, TV_INSERTSTRUCT& tvi, const std::vector& configMenuData) +{ + if (!configMenuData.empty()) + { + for (int i = 0, isize = (int)configMenuData.size(); i < isize; ++i) + { + if (configMenuData[i].index == -1) + { + tvi.item.iImage = tvi.item.iSelectedImage = 0; + tvi.item.pszText = const_cast(configMenuData[i].name.c_str()); + HTREEITEM hOldParent = tvi.hParent; + tvi.hParent = (HTREEITEM)SendMessage(tree, TVM_INSERTITEM, 0, (LPARAM)&tvi); + PopulateTree(tree, tvi, configMenuData[i].children); + tvi.hParent = hOldParent; + } + else + { + tvi.item.iImage = tvi.item.iSelectedImage = 1; + //MessageBox(NULL, configMenuData[i].name.c_str(), NULL, MB_TOPMOST | MB_OK); + tvi.item.pszText = const_cast(configMenuData[i].name.c_str()); + SendMessage(tree, TVM_INSERTITEM, 0, (LPARAM)&tvi); + } + } + } +} + +/* +** SelectTreeItem +** +** Selects an item in the treeview. +** +*/ +void CDialogManage::CTabSkins::SelectTreeItem(HWND tree, HTREEITEM item, LPCWSTR name) +{ + WCHAR buffer[MAX_PATH]; + TVITEM tvi = {0}; + tvi.mask = TVIF_TEXT; + tvi.hItem = item; + tvi.pszText = buffer; + tvi.cchTextMax = MAX_PATH; + + std::wstring tmpSz = name; + std::wstring::size_type pos = tmpSz.find_first_of(L'\\'); + if (pos != std::wstring::npos) + { + tmpSz.resize(pos); + + // Find and expand the folder + do + { + TreeView_GetItem(tree, &tvi); + if (wcscmp(buffer, tmpSz.c_str()) == 0) + { + if ((item = TreeView_GetChild(tree, tvi.hItem)) != NULL) + { + TreeView_Expand(tree, tvi.hItem, TVE_EXPAND); + name += tmpSz.length() + 1; + SelectTreeItem(tree, item, name); + } + + break; + } + } + while ((tvi.hItem = TreeView_GetNextSibling(tree, tvi.hItem)) != NULL); + } + else + { + // Find and select the file + do + { + TreeView_GetItem(tree, &tvi); + if (wcscmp(buffer, name) == 0) + { + TreeView_Select(tree, tvi.hItem, TVGN_CARET); + break; + } + } + while ((tvi.hItem = TreeView_GetNextSibling(tree, tvi.hItem)) != NULL); + } +} + +/* +** DlgProc +** +** Dialog procedure for the Skins tab. +** +*/ +INT_PTR CALLBACK CDialogManage::CTabSkins::DlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) + { + case WM_COMMAND: + return c_Dialog->m_TabSkins->OnCommand(wParam, lParam); + + case WM_NOTIFY: + return c_Dialog->m_TabSkins->OnNotify(wParam, lParam); + + case WM_CTLCOLORDLG: + return OnColorDialog(wParam, lParam); + + case WM_CTLCOLORBTN: + case WM_CTLCOLORSTATIC: + return OnColorStatic(wParam, lParam); + } + + return FALSE; +} + +INT_PTR CDialogManage::CTabSkins::OnCommand(WPARAM wParam, LPARAM lParam) +{ + switch (LOWORD(wParam)) + { + case IDC_MANAGESKINS_ACTIVESKINS_BUTTON: + { + HMENU menu = CreatePopupMenu(); + + // Add active skins to menu + std::map::const_iterator iter = Rainmeter->GetAllMeterWindows().begin(); + int index = 0; + for ( ; iter != Rainmeter->GetAllMeterWindows().end(); ++iter) + { + std::wstring name = ((*iter).second)->GetSkinName(); + name += L"\\"; + name += ((*iter).second)->GetSkinIniFile(); + InsertMenu(menu, index, MF_BYPOSITION, ID_CONFIG_FIRST + index, name.c_str()); + ++index; + } + + if (index == 0) + { + InsertMenu(menu, index, MF_BYPOSITION | MF_GRAYED, 0, L"No active skins"); + } + + RECT r; + GetWindowRect((HWND)lParam, &r); + + // Show context menu + TrackPopupMenu( + menu, + TPM_RIGHTBUTTON | TPM_LEFTALIGN, + r.left, + --r.bottom, + 0, + m_Window, + NULL + ); + + DestroyMenu(menu); + } + break; + + case IDC_MANAGESKINS_LOAD_BUTTON: + { + if (!m_SkinWindow) + { + // Skin not active, load + const std::vector& configs = Rainmeter->GetAllConfigs(); + + for (int i = 0, isize = (int)configs.size(); i < isize; ++i) + { + if (_wcsicmp(configs[i].config.c_str(), m_SkinName.c_str()) == 0) + { + for (int j = 0, jsize = (int)configs[i].iniFiles.size(); j < jsize; ++j) + { + if (_wcsicmp(configs[i].iniFiles[j].c_str(), m_FileName.c_str()) == 0) + { + Rainmeter->ActivateConfig(i, j); + + // Fake selection change to update controls + NMHDR nm; + nm.code = TVN_SELCHANGED; + nm.idFrom = IDC_MANAGESKINS_SKINS_TREEVIEW; + nm.hwndFrom = GetDlgItem(m_Window, IDC_MANAGESKINS_SKINS_TREEVIEW); + OnNotify(0, (LPARAM)&nm); + } + } + } + } + } + else + { + m_HandleCommands = false; + Rainmeter->DeactivateConfig(m_SkinWindow, -1); + } + } + break; + + case IDC_MANAGESKINS_REFRESH_BUTTON: + m_SkinWindow->Refresh(false); + break; + + case IDC_MANAGESKINS_EDIT_BUTTON: + { + std::wstring command = Rainmeter->GetConfigEditor() + L" \""; + command += Rainmeter->GetSkinPath(); + command += m_SkinName; + command += L"\\"; + command += m_FileName; + command += L"\""; + + // If the skins are in the program folder start the editor as admin + if (Rainmeter->GetPath() + L"Skins\\" == Rainmeter->GetSkinPath()) + { + LSExecuteAsAdmin(NULL, command.c_str(), SW_SHOWNORMAL); + } + else + { + LSExecute(NULL, command.c_str(), SW_SHOWNORMAL); + } + } + break; + + case IDC_MANAGESKINS_X_TEXT: + if (HIWORD(wParam) == EN_CHANGE) + { + WCHAR buffer[32]; + if (GetWindowText((HWND)lParam, buffer, 32) > 0) + { + m_IgnoreUpdate = true; + int x = _wtoi(buffer); + m_SkinWindow->MoveWindow(x, m_SkinWindow->GetY()); + + if (x > m_SkinWindow->GetX()) + { + _itow(m_SkinWindow->GetX(), buffer, 10); + Edit_SetText((HWND)lParam, buffer); + } + } + } + break; + + case IDC_MANAGESKINS_Y_TEXT: + if (HIWORD(wParam) == EN_CHANGE) + { + WCHAR buffer[32]; + if (GetWindowText((HWND)lParam, buffer, 32) > 0) + { + m_IgnoreUpdate = true; + int y = _wtoi(buffer); + m_SkinWindow->MoveWindow(m_SkinWindow->GetX(), y); + + if (y > m_SkinWindow->GetY()) + { + _itow(m_SkinWindow->GetY(), buffer, 10); + Edit_SetText((HWND)lParam, buffer); + } + } + } + break; + + case IDC_MANAGESKINS_DISPLAYMONITOR_BUTTON: + { + HMENU menu = LoadMenu(Rainmeter->GetInstance(), MAKEINTRESOURCE(IDR_SKIN_MENU)); + if (menu) + { + HMENU subMenu = GetSubMenu(menu, 0); // Skin menu + subMenu = GetSubMenu(subMenu, 4); // Settings menu + subMenu = GetSubMenu(subMenu, 0); // Position menu + subMenu = GetSubMenu(subMenu, 0); // Display monitor menu + Rainmeter->CreateMonitorMenu(subMenu, m_SkinWindow); + + RECT r; + GetWindowRect((HWND)lParam, &r); + + // Show context menu + TrackPopupMenu( + subMenu, + TPM_RIGHTBUTTON | TPM_LEFTALIGN, + r.left, + --r.bottom, + 0, + m_Window, + NULL + ); + + DestroyMenu(menu); + } + } + break; + + case IDC_MANAGESKINS_DRAGGABLE_CHECKBOX: + m_IgnoreUpdate = true; + m_SkinWindow->SetWindowDraggable(!m_SkinWindow->GetWindowDraggable()); + break; + + case IDC_MANAGESKINS_CLICKTHROUGH_CHECKBOX: + m_IgnoreUpdate = true; + m_SkinWindow->SetClickThrough(!m_SkinWindow->GetClickThrough()); + break; + + case IDC_MANAGESKINS_KEEPONSCREEN_CHECKBOX: + m_IgnoreUpdate = true; + m_SkinWindow->SetKeepOnScreen(!m_SkinWindow->GetKeepOnScreen()); + break; + + case IDC_MANAGESKINS_SAVEPOSITION_CHECKBOX: + m_IgnoreUpdate = true; + m_SkinWindow->SetSavePosition(!m_SkinWindow->GetSavePosition()); + break; + + case IDC_MANAGESKINS_SNAPTOEDGES_CHECKBOX: + m_IgnoreUpdate = true; + m_SkinWindow->SetSnapEdges(!m_SkinWindow->GetSnapEdges()); + break; + + case IDC_MANAGESKINS_ZPOSITION_COMBOBOX: + if (HIWORD(wParam) == CBN_SELCHANGE) + { + m_IgnoreUpdate = true; + ZPOSITION zpos = (ZPOSITION)(ComboBox_GetCurSel((HWND)lParam) - 2); + m_SkinWindow->ChangeZPos(zpos); + } + break; + + case IDC_MANAGESKINS_TRANSPARENCY_COMBOBOX: + if (HIWORD(wParam) == CBN_SELCHANGE) + { + m_IgnoreUpdate = true; + int sel = ComboBox_GetCurSel((HWND)lParam) + ID_CONTEXT_SKINMENU_TRANSPARENCY_0; + SendMessage(m_SkinWindow->GetWindow(), WM_COMMAND, sel, 0); + } + break; + + case IDC_MANAGESKINS_ONHOVER_COMBOBOX: + if (HIWORD(wParam) == CBN_SELCHANGE) + { + m_IgnoreUpdate = true; + HIDEMODE hide = (HIDEMODE)ComboBox_GetCurSel((HWND)lParam); + m_SkinWindow->SetWindowHide(hide); + } + break; + + case ID_CONTEXT_MANAGESKINSMENU_EXPAND: + { + HWND tree = GetDlgItem(m_Window, IDC_MANAGESKINS_SKINS_TREEVIEW); + HTREEITEM item = TreeView_GetSelection(tree); + TreeView_Expand(tree, item, TVE_TOGGLE); + } + break; + + case ID_CONTEXT_MANAGESKINSMENU_OPENFOLDER: + { + HWND tree = GetDlgItem(m_Window, IDC_MANAGESKINS_SKINS_TREEVIEW); + std::wstring command = L"\"" + Rainmeter->GetSkinPath(); + command += GetTreeSelectionPath(tree); + command += L"\""; + LSExecute(NULL, command.c_str(), SW_SHOWNORMAL); + } + break; + + default: + if (wParam >= ID_CONFIG_FIRST && wParam <= ID_CONFIG_LAST) + { + std::map::const_iterator iter = Rainmeter->GetAllMeterWindows().begin(); + int index = (int)wParam - ID_CONFIG_FIRST; + int i = 0; + for ( ; iter != Rainmeter->GetAllMeterWindows().end(); ++iter) + { + if (i == index) + { + std::wstring name = ((*iter).second)->GetSkinName(); + name += L"\\"; + name += ((*iter).second)->GetSkinIniFile(); + + HWND item = GetDlgItem(m_Window, IDC_MANAGESKINS_SKINS_TREEVIEW); + SelectTreeItem(item, TreeView_GetRoot(item), name.c_str()); + break; + } + + ++i; + } + } + else if (wParam == ID_CONTEXT_SKINMENU_MONITOR_AUTOSELECT || + wParam == ID_CONTEXT_SKINMENU_MONITOR_PRIMARY || + wParam >= ID_MONITOR_FIRST && wParam <= ID_MONITOR_LAST) + { + SendMessage(m_SkinWindow->GetWindow(), WM_COMMAND, wParam, 0); + break; + } + + return FALSE; + } + + return TRUE; +} + +INT_PTR CDialogManage::CTabSkins::OnNotify(WPARAM wParam, LPARAM lParam) +{ + LPNMHDR nm = (LPNMHDR)lParam; + switch (nm->code) + { + case NM_CLICK: + if (nm->idFrom == IDC_MANAGESKINS_ADDMETADATA_LINK) + { + std::wstring file = Rainmeter->GetSkinPath(); + file += m_SkinName; + file += L"\\"; + file += m_FileName; + WritePrivateProfileString(L"Rainmeter", L"\r\n[Metadata]\r\nDescription=\r\nLicense=\r\nVersion", L"", file.c_str()); + SendMessage(m_Window, WM_COMMAND, MAKEWPARAM(IDC_MANAGESKINS_EDIT_BUTTON, 0), 0); + ShowWindow(nm->hwndFrom, SW_HIDE); + } + break; + + case NM_DBLCLK: + if (nm->idFrom == IDC_MANAGESKINS_SKINS_TREEVIEW && !m_FileName.empty()) + { + OnCommand(MAKEWPARAM(IDC_MANAGESKINS_LOAD_BUTTON, 0), 0); + } + break; + + case NM_RCLICK: + if (nm->idFrom == IDC_MANAGESKINS_SKINS_TREEVIEW) + { + POINT pt; + GetCursorPos(&pt); + + TVHITTESTINFO ht; + ht.pt = pt; + ScreenToClient(nm->hwndFrom, &ht.pt); + + if (TreeView_HitTest(nm->hwndFrom, &ht) && !(ht.flags & TVHT_NOWHERE)) + { + TreeView_SelectItem(nm->hwndFrom, ht.hItem); + + TVITEM tvi = {0}; + tvi.hItem = TreeView_GetSelection(nm->hwndFrom); + tvi.mask = TVIF_STATE; + + HMENU menu = LoadMenu(Rainmeter->GetInstance(), MAKEINTRESOURCE(IDR_MANAGESKINS_MENU)); + if (menu && TreeView_GetItem(nm->hwndFrom, &tvi)) + { + HMENU subMenu; + + if (m_FileName.empty()) + { + // It's a folder + subMenu = GetSubMenu(menu, 0); + SetMenuDefaultItem(subMenu, ID_CONTEXT_MANAGESKINSMENU_EXPAND, MF_BYCOMMAND); + + if (tvi.state & TVIS_EXPANDED) + { + MENUITEMINFO mii = {0}; + mii.cbSize = sizeof(MENUITEMINFO); + mii.fMask = MIIM_STRING; + mii.dwTypeData = L"Collapse"; + SetMenuItemInfo(subMenu, ID_CONTEXT_MANAGESKINSMENU_EXPAND, MF_BYCOMMAND, &mii); + } + } + else + { + // It's a skin + subMenu = GetSubMenu(menu, 1); + SetMenuDefaultItem(subMenu, ID_CONTEXT_MANAGESKINSMENU_LOAD, MF_BYCOMMAND); + + if (m_SkinWindow) + { + MENUITEMINFO mii = {0}; + mii.cbSize = sizeof(MENUITEMINFO); + mii.fMask = MIIM_STRING; + mii.dwTypeData = L"Unload"; + SetMenuItemInfo(subMenu, ID_CONTEXT_MANAGESKINSMENU_LOAD, MF_BYCOMMAND, &mii); + } + else + { + EnableMenuItem(subMenu, ID_CONTEXT_MANAGESKINSMENU_REFRESH, MF_BYCOMMAND | MF_GRAYED); + } + } + + // Show context menu + TrackPopupMenu( + subMenu, + TPM_RIGHTBUTTON | TPM_LEFTALIGN, + pt.x, + pt.y, + 0, + m_Window, + NULL + ); + + DestroyMenu(menu); + } + } + } + break; + + case TVN_SELCHANGED: + if (nm->idFrom == IDC_MANAGESKINS_SKINS_TREEVIEW) + { + m_SkinWindow = NULL; + m_FileName.clear(); + m_SkinName.clear(); + + // Temporarily disable handling commands + m_HandleCommands = false; + + //LSLog(LOG_DEBUG, L"Rainmeter", L"UPDATE"); + + WCHAR buffer[MAX_PATH]; + + // Get current selection name + TVITEM tvi = {0}; + tvi.hItem = TreeView_GetSelection(nm->hwndFrom); + tvi.mask = TVIF_TEXT | TVIF_CHILDREN; + tvi.pszText = buffer; + tvi.cchTextMax = MAX_PATH; + TreeView_GetItem(nm->hwndFrom, &tvi); + + if (tvi.cChildren == 0) + { + // Current selection is file + m_FileName = buffer; + tvi.mask = TVIF_TEXT; + + // Loop through parents to get config + m_SkinName.clear(); + while ((tvi.hItem = TreeView_GetParent(nm->hwndFrom, tvi.hItem)) != NULL) + { + TreeView_GetItem(nm->hwndFrom, &tvi); + m_SkinName.insert(0, L"\\"); + m_SkinName.insert(0, buffer); + } + + m_SkinName.resize(m_SkinName.length() - 1); // Get rid of trailing slash + + ReadSkin(); + } + else + { + DisableControls(true); + } + + m_HandleCommands = true; + } + break; + + default: + return FALSE; + } + + return TRUE; +} + +// ----------------------------------------------------------------------------------------------- +// +// Themes tab +// +// ----------------------------------------------------------------------------------------------- + +/* +** CTabThemes +** +** Constructor. +** +*/ +CDialogManage::CTabThemes::CTabThemes(HWND wnd) : CTab(wnd), + m_LoadTheme(false) +{ +} + +/* +** Initialize +** +** Called when tab is displayed. +** +*/ +void CDialogManage::CTabThemes::Initialize() +{ + m_Initialized = true; + + HWND item = GetDlgItem(m_Window, IDC_MANAGETHEMES_LIST); + const std::vector& themes = Rainmeter->GetAllThemes(); + for (int i = 0, isize = themes.size(); i < isize; ++i) + { + ListBox_AddString(item, themes[i].c_str()); + } +} + +/* +** Update +** +** Loads new theme. +** +*/ +void CDialogManage::CTabThemes::Update() +{ + if (m_LoadTheme) + { + m_LoadTheme = false; + HWND item = GetDlgItem(m_Window, IDC_MANAGETHEMES_LOAD_BUTTON); + EnableWindow(item, TRUE); + + // Called by ClearDeleteLaterList(), all MeterWindows have been deleted now so + // proceed to loading theme + item = GetDlgItem(m_Window, IDC_MANAGETHEMES_LIST); + int sel = ListBox_GetCurSel(item); + + const std::vector& themes = Rainmeter->GetAllThemes(); + + std::wstring path = Rainmeter->GetSettingsPath() + L"Themes\\"; + path += themes[sel].c_str(); + std::wstring theme = path + L"\\Rainmeter.thm"; + std::wstring wallpaper = path + L"\\RainThemes.bmp"; + + CSystem::CopyFiles(theme, Rainmeter->GetIniFile()); + + if (_waccess(wallpaper.c_str(), 0) != -1) + { + // Set wallpaper + SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, (void*)wallpaper.c_str(), 0); + } + + Rainmeter->ReadGeneralSettings(Rainmeter->GetIniFile()); + + // Create meter windows for active configs + const std::multimap& configOrders = Rainmeter->m_ConfigOrders; + for (std::multimap::const_iterator iter = configOrders.begin(); iter != configOrders.end(); ++iter) + { + const CRainmeter::CONFIG& config = Rainmeter->GetAllConfigs()[(*iter).second]; + if (config.active > 0 && config.active <= (int)config.iniFiles.size()) + { + Rainmeter->ActivateConfig((*iter).second, config.active - 1); + } + } + } +} + +/* +** DlgProc +** +** Dialog procedure for the Themes tab. +** +*/ +INT_PTR CALLBACK CDialogManage::CTabThemes::DlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) + { + case WM_COMMAND: + return c_Dialog->m_TabThemes->OnCommand(wParam, lParam); + + case WM_CTLCOLORDLG: + return OnColorDialog(wParam, lParam); + + case WM_CTLCOLORBTN: + case WM_CTLCOLORSTATIC: + return OnColorStatic(wParam, lParam); + } + + return FALSE; +} + +INT_PTR CDialogManage::CTabThemes::OnCommand(WPARAM wParam, LPARAM lParam) +{ + switch (LOWORD(wParam)) + { + case IDC_MANAGETHEMES_EMPTYTHEME_CHECKBOX: + { + BOOL state = !(Button_GetCheck((HWND)lParam) == BST_CHECKED); + + HWND item = GetDlgItem(m_Window, IDC_MANAGETHEMES_UNUSEDSKINS_CHECKBOX); + EnableWindow(item, state); + Button_SetCheck(item, BST_UNCHECKED); + + item = GetDlgItem(m_Window, IDC_MANAGETHEMES_WALLPAPER_CHECKBOX); + EnableWindow(item, state); + Button_SetCheck(item, BST_UNCHECKED); + } + break; + + case IDC_MANAGETHEMES_NAME_TEXT: + if (HIWORD(wParam) == EN_CHANGE) + { + BOOL state = (Edit_GetTextLength((HWND)lParam) != 0); + EnableWindow(GetDlgItem(m_Window, IDC_MANAGETHEMES_SAVE_BUTTON), state); + } + break; + + case IDC_MANAGETHEMES_LIST: + if (HIWORD(wParam) == LBN_SELCHANGE) + { + // Ignore clicks that don't hit items + if (ListBox_GetCurSel((HWND)lParam) != LB_ERR) + { + HWND item = GetDlgItem(m_Window, IDC_MANAGETHEMES_LOAD_BUTTON); + EnableWindow(item, TRUE); + item = GetDlgItem(m_Window, IDC_MANAGETHEMES_DELETE_BUTTON); + EnableWindow(item, TRUE); + item = GetDlgItem(m_Window, IDC_MANAGETHEMES_EDIT_BUTTON); + EnableWindow(item, TRUE); + + const std::vector& themes = Rainmeter->GetAllThemes(); + item = GetDlgItem(m_Window, IDC_MANAGETHEMES_LIST); + int sel = ListBox_GetCurSel(item); + + item = GetDlgItem(m_Window, IDC_MANAGETHEMES_NAME_TEXT); + Edit_SetText(item, themes[sel].c_str()); + } + } + break; + + case IDC_MANAGETHEMES_SAVE_BUTTON: + { + WCHAR buffer[MAX_PATH]; + HWND item = GetDlgItem(m_Window, IDC_MANAGETHEMES_NAME_TEXT); + Edit_GetText(item, buffer, MAX_PATH); + + std::wstring theme = buffer; + std::wstring path = Rainmeter->GetSettingsPath() + L"Themes\\"; + path += theme; + bool alreadyExists = (_waccess(path.c_str(), 0) != -1); + if (alreadyExists) + { + std::wstring question = L"A theme named \"" + theme; + question += L"\" already exists.\n\nDo you want to replace it?"; + if (MessageBox(NULL, question.c_str(), APPNAME, MB_ICONWARNING | MB_YESNO | MB_TOPMOST) != IDYES) + { + // Cancel + break; + } + } + else + { + // Make sure path exists + CreateDirectory(path.c_str(), NULL); + } + + path += L"\\Rainmeter.thm"; + + item = GetDlgItem(m_Window, IDC_MANAGETHEMES_EMPTYTHEME_CHECKBOX); + if (Button_GetCheck(item) != BST_CHECKED) + { + if (!CSystem::CopyFiles(Rainmeter->GetIniFile(), path)) + { + std::wstring message = L"Unable to save theme at: " + path; + MessageBox(NULL, message.c_str(), APPNAME, MB_OK | MB_TOPMOST | MB_ICONERROR); + break; + } + + // Exclude unused skins + item = GetDlgItem(m_Window, IDC_MANAGETHEMES_UNUSEDSKINS_CHECKBOX); + if (Button_GetCheck(item) == BST_CHECKED) + { + CConfigParser parser; + parser.Initialize(path.c_str(), Rainmeter); + + const std::vector& sections = parser.GetSections(); + std::vector::const_iterator iter = sections.begin(); + + // Remove sections with Active=0 + for ( ; iter != sections.end(); ++iter) + { + if (parser.GetValue(*iter, L"Active", L"") == L"0") + { + WritePrivateProfileString((*iter).c_str(), NULL, NULL, path.c_str()); + } + } + } + + // Save wallpaper + item = GetDlgItem(m_Window, IDC_MANAGETHEMES_WALLPAPER_CHECKBOX); + if (Button_GetCheck(item) == BST_CHECKED) + { + // Get current wallpaper + if (SystemParametersInfo(SPI_GETDESKWALLPAPER, MAX_PATH, &buffer, 0)) + { + std::wstring::size_type pos = path.find_last_of(L'\\'); + path.replace(pos + 1, path.length() - pos - 1, L"RainThemes.bmp"); + CSystem::CopyFiles((std::wstring)buffer, path); + } + } + } + else + { + // Create empty theme + HANDLE file = CreateFile(path.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + if (file == INVALID_HANDLE_VALUE) + { + std::wstring message = L"Unable to save theme at: " + path; + MessageBox(NULL, message.c_str(), APPNAME, MB_OK | MB_TOPMOST | MB_ICONERROR); + break; + } + + CloseHandle(file); + } + + if (!alreadyExists) + { + item = GetDlgItem(m_Window, IDC_MANAGETHEMES_LIST); + ListBox_AddString(item, theme.c_str()); + + // Add theme to vector + std::vector& themes = Rainmeter->m_Themes; + if (!themes.empty()) + { + std::vector::iterator iter = themes.begin(); + for ( ; iter != themes.end(); ++iter) + { + if (wcscmp(theme.c_str(), (*iter).c_str()) < 0) + { + themes.insert(iter, theme); + return TRUE; + } + } + } + + // If themes empty or if name is alphabetically after vector contents + themes.push_back(theme); + } + } + break; + + case IDC_MANAGETHEMES_LOAD_BUTTON: + { + EnableWindow((HWND)lParam, FALSE); + m_LoadTheme = true; + + // Deactivate all skins + std::map& meterWindows = Rainmeter->GetAllMeterWindows(); + if (!meterWindows.empty()) + { + std::map::const_iterator iter = meterWindows.begin(); + for ( ; iter != meterWindows.end(); ++iter) + { + Rainmeter->DeactivateConfig((*iter).second, -1, false); + } + } + else + { + Update(); + } + } + break; + + case IDC_MANAGETHEMES_EDIT_BUTTON: + { + HWND item = GetDlgItem(m_Window, IDC_MANAGETHEMES_LIST); + int sel = ListBox_GetCurSel(item); + const std::vector& themes = Rainmeter->GetAllThemes(); + + std::wstring command = Rainmeter->GetConfigEditor() + L" \""; + command += Rainmeter->GetSettingsPath(); + command += L"Themes\\"; + command += themes[sel].c_str(); + command += L"\\Rainmeter.thm\""; + LSExecute(NULL, command.c_str(), SW_SHOWNORMAL); + } + break; + + case IDC_MANAGETHEMES_DELETE_BUTTON: + { + HWND item = GetDlgItem(m_Window, IDC_MANAGETHEMES_LIST); + int sel = ListBox_GetCurSel(item); + std::vector& themes = const_cast&>(Rainmeter->GetAllThemes()); + + std::wstring question = L"Are you sure you want to delete the \"" + themes[sel]; + question += L"\" theme?"; + if (MessageBox(NULL, question.c_str(), APPNAME, MB_ICONQUESTION | MB_YESNO | MB_TOPMOST) != IDYES) + { + // Cancel + break; + } + + std::wstring folder = Rainmeter->GetSettingsPath() + L"Themes\\"; + folder += themes[sel].c_str(); + + if (CSystem::RemoveFolder(folder)) + { + ListBox_DeleteString(item, sel); + + // Remove theme from vector + std::vector::iterator iter = themes.begin(); + for ( ; iter != themes.end(); ++iter) + { + if (wcscmp(themes[sel].c_str(), (*iter).c_str()) == 0) + { + themes.erase(iter); + break; + } + } + + EnableWindow(GetDlgItem(m_Window, IDC_MANAGETHEMES_LOAD_BUTTON), FALSE); + EnableWindow(GetDlgItem(m_Window, IDC_MANAGETHEMES_DELETE_BUTTON), FALSE); + EnableWindow(GetDlgItem(m_Window, IDC_MANAGETHEMES_EDIT_BUTTON), FALSE); + } + } + break; + + case IDC_MANAGETHEMES_BACKUP_BUTTON: + { + std::wstring command = Rainmeter->GetAddonPath(); + command += L"RainBackup\\RainBackup.exe"; + LSExecute(NULL, command.c_str(), SW_SHOWNORMAL); + } + break; + + default: + return FALSE; + } + + return TRUE; +} + +// ----------------------------------------------------------------------------------------------- +// +// Settings tab +// +// ----------------------------------------------------------------------------------------------- + +/* +** CTabSettings +** +** Constructor. +** +*/ +CDialogManage::CTabSettings::CTabSettings(HWND wnd) : CTab(wnd) +{ +} + +/* +** Initialize +** +** Called when tab is displayed. +** +*/ +void CDialogManage::CTabSettings::Initialize() +{ + m_Initialized = true; + + Button_SetCheck(GetDlgItem(m_Window, IDC_MANAGESETTINGS_CHECKUPDATES_CHECKBOX), !Rainmeter->GetDisableVersionCheck()); + Button_SetCheck(GetDlgItem(m_Window, IDC_MANAGESETTINGS_LOCKSKINS_CHECKBOX), Rainmeter->GetDisableDragging()); + Button_SetCheck(GetDlgItem(m_Window, IDC_MANAGESETTINGS_LOGTOFILE_CHECKBOX), Rainmeter->GetLogging()); + Button_SetCheck(GetDlgItem(m_Window, IDC_MANAGESETTINGS_VERBOSELOGGING_CHECKBOX), Rainmeter->GetDebug()); + + BOOL isLogFile = (_waccess(Rainmeter->GetLogFile().c_str(), 0) != -1); + EnableWindow(GetDlgItem(m_Window, IDC_MANAGESETTINGS_SHOWLOGFILE_BUTTON), isLogFile); + EnableWindow(GetDlgItem(m_Window, IDC_MANAGESETTINGS_DELETELOGFILE_BUTTON), isLogFile); + + WCHAR tmpSz[128]; + _snwprintf_s(tmpSz, _TRUNCATE, L"%s %s%s r%i %s (%s).", APPNAME, APPVERSION, revision_beta ? L" beta" : L"", revision_number, APPBITS, APPDATE); + SetWindowText(GetDlgItem(m_Window, IDC_MANAGESETTINGS_VERSION_LABEL), tmpSz); +} + +/* +** DlgProc +** +** Dialog procedure for the Settings tab. +** +*/ +INT_PTR CALLBACK CDialogManage::CTabSettings::DlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) + { + case WM_COMMAND: + return c_Dialog->m_TabSettings->OnCommand(wParam, lParam); + + case WM_NOTIFY: + return c_Dialog->m_TabSettings->OnNotify(wParam, lParam); + + case WM_CTLCOLORDLG: + return OnColorDialog(wParam, lParam); + + case WM_CTLCOLORBTN: + case WM_CTLCOLORSTATIC: + return OnColorStatic(wParam, lParam); + } + + return FALSE; +} + +INT_PTR CDialogManage::CTabSettings::OnCommand(WPARAM wParam, LPARAM lParam) +{ + switch (LOWORD(wParam)) + { + case IDC_MANAGESETTINGS_CHECKUPDATES_CHECKBOX: + Rainmeter->SetDisableVersionCheck(!Rainmeter->GetDisableVersionCheck()); + break; + + case IDC_MANAGESETTINGS_LOCKSKINS_CHECKBOX: + Rainmeter->SetDisableDragging(!Rainmeter->GetDisableDragging()); + break; + + case IDC_MANAGESETTINGS_RESETSTATISTICS_BUTTON: + Rainmeter->ResetStats(); + break; + + case IDC_MANAGESETTINGS_SHOWLOGFILE_BUTTON: + { + std::wstring command = Rainmeter->GetLogViewer(); + command += Rainmeter->GetLogFile(); + LSExecute(NULL, command.c_str(), SW_SHOWNORMAL); + } + break; + + case IDC_MANAGESETTINGS_DELETELOGFILE_BUTTON: + Rainmeter->DeleteLogFile(); + if (_waccess(Rainmeter->GetLogFile().c_str(), 0) == -1) + { + Button_SetCheck(GetDlgItem(m_Window, IDC_MANAGESETTINGS_LOGTOFILE_CHECKBOX), BST_UNCHECKED); + EnableWindow(GetDlgItem(m_Window, IDC_MANAGESETTINGS_SHOWLOGFILE_BUTTON), FALSE); + EnableWindow(GetDlgItem(m_Window, IDC_MANAGESETTINGS_DELETELOGFILE_BUTTON), FALSE); + } + break; + + case IDC_MANAGESETTINGS_LOGTOFILE_CHECKBOX: + if (Rainmeter->GetLogging()) + { + Rainmeter->StopLogging(); + } + else + { + Rainmeter->StartLogging(); + if (_waccess(Rainmeter->GetLogFile().c_str(), 0) != -1) + { + EnableWindow(GetDlgItem(m_Window, IDC_MANAGESETTINGS_SHOWLOGFILE_BUTTON), TRUE); + EnableWindow(GetDlgItem(m_Window, IDC_MANAGESETTINGS_DELETELOGFILE_BUTTON), TRUE); + } + } + break; + + case IDC_MANAGESETTINGS_VERBOSELOGGING_CHECKBOX: + Rainmeter->SetDebug(!Rainmeter->GetDebug()); + break; + + default: + return FALSE; + } + + return TRUE; +} + +INT_PTR CDialogManage::CTabSettings::OnNotify(WPARAM wParam, LPARAM lParam) +{ + LPNMHDR nm = (LPNMHDR)lParam; + switch (nm->code) + { + case NM_CLICK: + LSExecute(NULL, ((PNMLINK)lParam)->item.szUrl, SW_SHOWNORMAL); + break; + + default: + return FALSE; + } + + return TRUE; +} diff --git a/Library/DialogManage.h b/Library/DialogManage.h new file mode 100644 index 00000000..95c2d6ed --- /dev/null +++ b/Library/DialogManage.h @@ -0,0 +1,115 @@ +/* + Copyright (C) 2011 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef _DIALOGMANAGE_H_ +#define _DIALOGMANAGE_H_ + +#include "MeterWindow.h" +#include "Rainmeter.h" +#include "TrayWindow.h" +#include "Dialog.h" + +class CDialogManage : public CDialog +{ +public: + CDialogManage(HWND window); + virtual ~CDialogManage(); + + static INT_PTR CALLBACK DlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + INT_PTR OnInitDialog(WPARAM wParam, LPARAM lParam); + INT_PTR OnNotify(WPARAM wParam, LPARAM lParam); + INT_PTR OnCommand(WPARAM wParam, LPARAM lParam); + + static void Open(int tab = 0); + static void OpenSkin(CMeterWindow* meterWindow); + + static void UpdateSkins(CMeterWindow* meterWindow, bool deleted = false); + static void UpdateThemes(); + + static WINDOWPLACEMENT c_WindowPlacement; + static CDialogManage* c_Dialog; + +private: + // Skins tab + class CTabSkins : public CTab + { + public: + CTabSkins(HWND window); + + virtual void Initialize(); + + static INT_PTR CALLBACK DlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + INT_PTR OnNotify(WPARAM wParam, LPARAM lParam); + INT_PTR OnCommand(WPARAM wParam, LPARAM lParam); + + void Update(CMeterWindow* meterWindow, bool deleted); + + static void SelectTreeItem(HWND tree, HTREEITEM item, LPCWSTR name); + + private: + void SetControls(); + void DisableControls(bool clear = false); + void ReadSkin(); + + static void PopulateTree(HWND tree, TV_INSERTSTRUCT& tvi, const std::vector& configMenuData); + + std::wstring m_FileName; + std::wstring m_SkinName; + CMeterWindow* m_SkinWindow; + bool m_HandleCommands; + bool m_IgnoreUpdate; + }; + + // Themes tab + class CTabThemes : public CTab + { + public: + CTabThemes(HWND window); + + virtual void Initialize(); + + static INT_PTR CALLBACK DlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + INT_PTR OnNotify(WPARAM wParam, LPARAM lParam); + INT_PTR OnCommand(WPARAM wParam, LPARAM lParam); + + void Update(); + + private: + bool m_LoadTheme; + }; + + // Settings tab + class CTabSettings : public CTab + { + public: + CTabSettings(HWND window); + + virtual void Initialize(); + + static INT_PTR CALLBACK DlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + INT_PTR OnNotify(WPARAM wParam, LPARAM lParam); + INT_PTR OnCommand(WPARAM wParam, LPARAM lParam); + }; + + CTabSkins* m_TabSkins; + CTabThemes* m_TabThemes; + CTabSettings* m_TabSettings; +}; + +#endif + diff --git a/Library/Library.rc b/Library/Library.rc index eb112665..8a22f010 100644 --- a/Library/Library.rc +++ b/Library/Library.rc @@ -1,5 +1,6 @@ // Microsoft Developer Studio generated resource script. // +#include #include "resource.h" #include "../Version.h" @@ -68,50 +69,49 @@ END // Menu // -IDR_CONTEXT_MENU MENU DISCARDABLE +IDR_CONTEXT_MENU MENU BEGIN - POPUP "Rainmeter Menu" + POPUP "Rainmeter" BEGIN - MENUITEM "About...", ID_CONTEXT_ABOUT - MENUITEM "Downloads", ID_CONTEXT_DOWNLOADS + MENUITEM "Manage", ID_CONTEXT_MANAGE + MENUITEM "About", ID_CONTEXT_ABOUT MENUITEM "Help", ID_CONTEXT_SHOW_HELP MENUITEM SEPARATOR - POPUP "Configs" + POPUP "Skins" BEGIN - MENUITEM "No configs available", 0, GRAYED + MENUITEM "No skins available", 0, GRAYED MENUITEM SEPARATOR - MENUITEM "Open Skins' Folder", ID_CONTEXT_OPENSKINSFOLDER - MENUITEM "Disable Dragging", ID_CONTEXT_DISABLEDRAG - MENUITEM "Manage Skins...", ID_CONTEXT_MANAGESKINS + MENUITEM "Open folder", ID_CONTEXT_OPENSKINSFOLDER + MENUITEM "Disable dragging", ID_CONTEXT_DISABLEDRAG END POPUP "Themes" BEGIN - MENUITEM "Manage Themes...", ID_CONTEXT_MANAGETHEMES + MENUITEM "No themes available", 0, GRAYED END MENUITEM SEPARATOR - MENUITEM "Edit Settings...", ID_CONTEXT_EDITCONFIG - MENUITEM "Refresh All", ID_CONTEXT_REFRESH + MENUITEM "Edit settings", ID_CONTEXT_EDITCONFIG + MENUITEM "Refresh all", ID_CONTEXT_REFRESH MENUITEM SEPARATOR POPUP "Logging" BEGIN - MENUITEM "Show Log File...", ID_CONTEXT_SHOWLOGFILE + MENUITEM "Show log file", ID_CONTEXT_SHOWLOGFILE MENUITEM SEPARATOR - MENUITEM "Start Logging", ID_CONTEXT_STARTLOG - MENUITEM "Stop Logging", ID_CONTEXT_STOPLOG + MENUITEM "Start logging", ID_CONTEXT_STARTLOG + MENUITEM "Stop logging", ID_CONTEXT_STOPLOG MENUITEM SEPARATOR - MENUITEM "Delete Log File...", ID_CONTEXT_DELETELOGFILE - MENUITEM "Debug Mode", ID_CONTEXT_DEBUGLOG + MENUITEM "Delete log file", ID_CONTEXT_DELETELOGFILE + MENUITEM "Debug mode", ID_CONTEXT_DEBUGLOG END MENUITEM SEPARATOR MENUITEM "Exit", ID_CONTEXT_QUIT END END -IDR_SKIN_MENU MENU DISCARDABLE +IDR_SKIN_MENU MENU BEGIN - POPUP "Skin Menu" + POPUP "Skin" BEGIN - MENUITEM " ", ID_CONTEXT_SKINMENU_OPENSKINSFOLDER + MENUITEM "", ID_CONTEXT_SKINMENU_OPENSKINSFOLDER MENUITEM SEPARATOR POPUP "Variants" BEGIN @@ -122,7 +122,7 @@ BEGIN BEGIN POPUP "Position" BEGIN - POPUP "Display Monitor" + POPUP "Display monitor" BEGIN MENUITEM "Use default: Primary monitor", ID_CONTEXT_SKINMENU_MONITOR_PRIMARY MENUITEM "@0: Virtual screen", ID_MONITOR_FIRST @@ -131,16 +131,16 @@ BEGIN MENUITEM "Auto-select based on window position", ID_CONTEXT_SKINMENU_MONITOR_AUTOSELECT END MENUITEM SEPARATOR - MENUITEM "Stay Topmost", ID_CONTEXT_SKINMENU_VERYTOPMOST + MENUITEM "Stay topmost", ID_CONTEXT_SKINMENU_VERYTOPMOST MENUITEM "Topmost", ID_CONTEXT_SKINMENU_TOPMOST MENUITEM "Normal", ID_CONTEXT_SKINMENU_NORMAL MENUITEM "Bottom", ID_CONTEXT_SKINMENU_BOTTOM - MENUITEM "On Desktop", ID_CONTEXT_SKINMENU_ONDESKTOP + MENUITEM "On desktop", ID_CONTEXT_SKINMENU_ONDESKTOP MENUITEM SEPARATOR - MENUITEM "From Right", ID_CONTEXT_SKINMENU_FROMRIGHT - MENUITEM "From Bottom", ID_CONTEXT_SKINMENU_FROMBOTTOM - MENUITEM "X as Percentage", ID_CONTEXT_SKINMENU_XPERCENTAGE - MENUITEM "Y as Percentage", ID_CONTEXT_SKINMENU_YPERCENTAGE + MENUITEM "From right", ID_CONTEXT_SKINMENU_FROMRIGHT + MENUITEM "From bottom", ID_CONTEXT_SKINMENU_FROMBOTTOM + MENUITEM "X as percentage", ID_CONTEXT_SKINMENU_XPERCENTAGE + MENUITEM "Y as percentage", ID_CONTEXT_SKINMENU_YPERCENTAGE END POPUP "Transparency" BEGIN @@ -159,89 +159,178 @@ BEGIN MENUITEM "Fade out", ID_CONTEXT_SKINMENU_TRANSPARENCY_FADEOUT END MENUITEM SEPARATOR - MENUITEM "Hide on Mouse Over", ID_CONTEXT_SKINMENU_HIDEONMOUSE + MENUITEM "Hide on mouse over", ID_CONTEXT_SKINMENU_HIDEONMOUSE MENUITEM "Draggable", ID_CONTEXT_SKINMENU_DRAGGABLE - MENUITEM "Save Position", ID_CONTEXT_SKINMENU_REMEMBERPOSITION - MENUITEM "Snap to Edges", ID_CONTEXT_SKINMENU_SNAPTOEDGES - MENUITEM "Click Through", ID_CONTEXT_SKINMENU_CLICKTHROUGH - MENUITEM "Keep on Screen", ID_CONTEXT_SKINMENU_KEEPONSCREEN + MENUITEM "Save position", ID_CONTEXT_SKINMENU_REMEMBERPOSITION + MENUITEM "Snap to edges", ID_CONTEXT_SKINMENU_SNAPTOEDGES + MENUITEM "Click through", ID_CONTEXT_SKINMENU_CLICKTHROUGH + MENUITEM "Keep on screen", ID_CONTEXT_SKINMENU_KEEPONSCREEN END MENUITEM SEPARATOR - MENUITEM "Edit Skin...", ID_CONTEXT_SKINMENU_EDITSKIN - MENUITEM "Refresh Skin", ID_CONTEXT_SKINMENU_REFRESH + MENUITEM "Manage skin", ID_CONTEXT_SKINMENU_MANAGESKIN + MENUITEM "Edit skin", ID_CONTEXT_SKINMENU_EDITSKIN + MENUITEM "Refresh skin", ID_CONTEXT_SKINMENU_REFRESH MENUITEM SEPARATOR - MENUITEM "Close Skin", ID_CONTEXT_CLOSESKIN + MENUITEM "Close skin", ID_CONTEXT_CLOSESKIN END END - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE DISCARDABLE +IDR_MANAGESKINS_MENU MENU BEGIN - "resource.h\0" + POPUP "Folder" + BEGIN + MENUITEM "Expand", ID_CONTEXT_MANAGESKINSMENU_EXPAND + MENUITEM "Open folder", ID_CONTEXT_MANAGESKINSMENU_OPENFOLDER + END + POPUP "Item" + BEGIN + MENUITEM "Load", ID_CONTEXT_MANAGESKINSMENU_LOAD + MENUITEM "Refresh", ID_CONTEXT_MANAGESKINSMENU_REFRESH + MENUITEM "Edit", ID_CONTEXT_MANAGESKINSMENU_EDIT + END END -2 TEXTINCLUDE DISCARDABLE -BEGIN - "#include ""afxres.h""\r\n" - "\0" -END - -3 TEXTINCLUDE DISCARDABLE -BEGIN - "\r\n" - "\0" -END - -#endif // APSTUDIO_INVOKED - - ///////////////////////////////////////////////////////////////////////////// // // Dialog // - -IDD_ABOUT_DIALOG DIALOGEX DISCARDABLE 0, 0, 370, 240 -STYLE DS_SETFONT | DS_CENTER | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME -EXSTYLE WS_EX_APPWINDOW +IDD_ABOUT_DIALOG DIALOGEX 0, 0, 400, 210 +STYLE DS_CENTER | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME +EXSTYLE WS_EX_APPWINDOW| WS_EX_CONTROLPARENT CAPTION "About Rainmeter" FONT 8, "MS Shell Dlg 2", 0, 0, 0x0 BEGIN - GROUPBOX "About",IDC_STATIC_ABOUT,7,7,220,69 - CTEXT "Rainmeter version 0.0",IDC_VERSION_STRING,15,17,300,8 - CTEXT "(Built on ??? ?? ????)",IDC_BUILD_STRING,15,30,300,8 - CTEXT "Get the latest version at www.rainmeter.net",IDC_URL_STRING,15,43,300,8 - CONTROL "Disable check for updates",IDC_DISABLE_VERSION_CHECK, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,67,56,104,10 - LISTBOX IDC_ABOUT_ENTRIES,7,80,130,100,LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP - CONTROL "List1",IDC_STATISTICS,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,118,80,211,100 - DEFPUSHBUTTON "OK",IDOK,91,204,50,14 + CONTROL "", IDC_ABOUT_TAB, "SysTabControl32", TCS_TABS | TCS_FIXEDWIDTH, 6, 6, 388, 181 + LTEXT "", IDC_ABOUT_VERSION_TEXT, 5, 194, 200, 9 + DEFPUSHBUTTON "Close", IDCLOSE, 344, 191, 50, 14 END - -///////////////////////////////////////////////////////////////////////////// -// -// DESIGNINFO -// - -#ifdef APSTUDIO_INVOKED -GUIDELINES DESIGNINFO DISCARDABLE +IDD_ABOUTLOG_DIALOG DIALOGEX 15, 30, 370, 148 +STYLE DS_CONTROL | WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS +FONT 8, "MS Shell Dlg 2", 0, 0, 0x0 BEGIN - IDD_ABOUT_DIALOG, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 227 - TOPMARGIN, 7 - BOTTOMMARGIN, 218 - END + CONTROL "", IDC_ABOUTLOG_ITEMS_LISTVIEW, "SysListView32", LVS_ICON | LVS_REPORT | LVS_SINGLESEL | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP, 0, 0, 368, 135 + AUTOCHECKBOX "Error", IDC_ABOUTLOG_ERROR_CHECKBOX, 0, 139, 50, 9 + AUTOCHECKBOX "Warning", IDC_ABOUTLOG_WARNING_CHECKBOX, 50, 139, 50, 9 + AUTOCHECKBOX "Notice", IDC_ABOUTLOG_NOTICE_CHECKBOX, 100, 139, 50, 9 + AUTOCHECKBOX "Debug", IDC_ABOUTLOG_DEBUG_CHECKBOX, 150, 139, 50, 9 END -#endif // APSTUDIO_INVOKED +IDD_ABOUTMEASURES_DIALOG DIALOGEX 15, 30, 370, 148 +STYLE DS_CONTROL | WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS +FONT 8, "MS Shell Dlg 2", 0, 0, 0x0 +BEGIN + LISTBOX IDC_ABOUTMEASURES_ITEMS_LISTBOX, 0, 0, 100, 148, LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP + CONTROL "", IDC_ABOUTMEASURES_ITEMS_LISTVIEW, "SysListView32", LVS_REPORT | LVS_SINGLESEL | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP, 105, 0, 262, 148 +END + +IDD_ABOUTPLUGINS_DIALOG DIALOGEX 15, 30, 370, 148 +STYLE DS_CONTROL | WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS +FONT 8, "MS Shell Dlg 2", 0, 0, 0x0 +BEGIN + CONTROL "", IDC_ABOUTPLUGINS_ITEMS_LISTVIEW, "SysListView32", LVS_REPORT | LVS_SINGLESEL | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP, 0, 0, 368, 148 +END + +IDD_MANAGE_DIALOG DIALOGEX 0, 0, 500, 322 +STYLE DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU +EXSTYLE WS_EX_APPWINDOW | WS_EX_CONTROLPARENT +CAPTION "Manage Rainmeter" +FONT 8, "MS Shell Dlg 2", 0, 0, 0x0 +BEGIN + CONTROL "", IDC_MANAGE_TAB, "SysTabControl32", TCS_TABS | TCS_FIXEDWIDTH, 6, 6, 488, 293 + PUSHBUTTON "Refresh all", IDC_REFRESHALL_BUTTON, 5, 303, 70, 14 + PUSHBUTTON "Edit settings", IDC_EDITSETTINGS_BUTTON, 79, 303, 70, 14 + PUSHBUTTON "Open log", IDC_OPENLOG_BUTTON, 153, 303, 70, 14 + PUSHBUTTON "Close", IDCLOSE, 444, 303, 50, 14 +END + +IDD_MANAGESKINS_DIALOG DIALOGEX 15, 30, 470, 260 +STYLE DS_CONTROL | WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS +FONT 8, "MS Shell Dlg 2", 0, 0, 0x0 +BEGIN + PUSHBUTTON "", IDC_MANAGESKINS_ACTIVESKINS_BUTTON, 0, 0, 145, 14, WS_TABSTOP + CONTROL "", IDC_MANAGESKINS_SKINS_TREEVIEW, "SysTreeView32", TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT | TVS_SHOWSELALWAYS | WS_BORDER | WS_VSCROLL, 0, 18, 145, 241 + + LTEXT "N/A", IDC_MANAGESKINS_FILE_TEXT, 165, 0, 130, 14, SS_ENDELLIPSIS | SS_NOPREFIX + LTEXT "N/A", IDC_MANAGESKINS_CONFIG_TEXT, 165, 15, 130, 9, SS_ENDELLIPSIS | SS_NOPREFIX + PUSHBUTTON "Load", IDC_MANAGESKINS_LOAD_BUTTON, 310, 0, 50, 14, WS_DISABLED | WS_TABSTOP + PUSHBUTTON "Refresh", IDC_MANAGESKINS_REFRESH_BUTTON, 364, 0, 50, 14, WS_DISABLED | WS_TABSTOP + PUSHBUTTON "Edit", IDC_MANAGESKINS_EDIT_BUTTON, 418, 0, 50, 14, WS_DISABLED | WS_TABSTOP + + LTEXT "Author:", IDC_STATIC, 165, 30, 50, 9 + LTEXT "", IDC_MANAGESKINS_AUTHOR_TEXT, 215, 30, 260, 9, SS_ENDELLIPSIS | SS_NOPREFIX + LTEXT "Version:", IDC_STATIC, 165, 43, 50, 9 + LTEXT "", IDC_MANAGESKINS_VERSION_TEXT, 215, 43, 260, 9, SS_ENDELLIPSIS | SS_NOPREFIX + LTEXT "License:", IDC_STATIC, 165, 57, 50, 9 + LTEXT "", IDC_MANAGESKINS_LICENSE_TEXT, 215, 57, 260, 9, SS_ENDELLIPSIS | SS_NOPREFIX + LTEXT "Description:", IDC_STATIC, 165, 71, 50, 9 + EDITTEXT IDC_MANAGESKINS_DESCRIPTION_TEXT, 213, 71, 253, 64, ES_MULTILINE | ES_READONLY + CONTROL "Add metadata", IDC_MANAGESKINS_ADDMETADATA_LINK, "SysLink", 0x0, 410, 142, 50, 9 + + CONTROL "", IDC_STATIC, STATIC, SS_ETCHEDHORZ | WS_CHILD | WS_VISIBLE, 165, 156, 304, 1 + LTEXT "Coordinates:", IDC_STATIC, 165, 169, 80, 9 + EDITTEXT IDC_MANAGESKINS_X_TEXT, 230, 166, 33, 14, WS_BORDER | WS_TABSTOP | WS_DISABLED + EDITTEXT IDC_MANAGESKINS_Y_TEXT, 267, 166, 33, 14, ES_NUMBER | WS_BORDER | WS_TABSTOP | WS_DISABLED + LTEXT "Position:", IDC_STATIC, 165, 190, 80, 9 + COMBOBOX IDC_MANAGESKINS_ZPOSITION_COMBOBOX, 230, 187, 70, 14, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP | WS_DISABLED + LTEXT "Load order:", IDC_STATIC, 165, 208, 80, 9 + EDITTEXT IDC_MANAGESKINS_LOADORDER_TEXT, 230, 205, 70, 14, ES_NUMBER | WS_BORDER | WS_TABSTOP | WS_DISABLED + LTEXT "Transparency:", IDC_STATIC, 165, 229, 80, 9 + COMBOBOX IDC_MANAGESKINS_TRANSPARENCY_COMBOBOX, 230, 226, 70, 14, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP | WS_DISABLED + LTEXT "On hover:", IDC_STATIC, 165, 247, 80, 9 + COMBOBOX IDC_MANAGESKINS_ONHOVER_COMBOBOX, 230, 244, 70, 14, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP | WS_DISABLED + PUSHBUTTON "", IDC_MANAGESKINS_DISPLAYMONITOR_BUTTON, 330, 166, 90, 14, WS_DISABLED | WS_TABSTOP + AUTOCHECKBOX "Draggable", IDC_MANAGESKINS_DRAGGABLE_CHECKBOX, 330, 190, 70, 9, WS_DISABLED + AUTOCHECKBOX "Click through", IDC_MANAGESKINS_CLICKTHROUGH_CHECKBOX, 330, 203, 70, 9, WS_DISABLED + AUTOCHECKBOX "Keep on screen", IDC_MANAGESKINS_KEEPONSCREEN_CHECKBOX, 330, 216, 70, 9, WS_DISABLED + AUTOCHECKBOX "Save position", IDC_MANAGESKINS_SAVEPOSITION_CHECKBOX, 330, 229, 70, 9, WS_DISABLED + AUTOCHECKBOX "Snap to edges", IDC_MANAGESKINS_SNAPTOEDGES_CHECKBOX, 330, 242, 70, 9, WS_DISABLED +END + +IDD_MANAGETHEMES_DIALOG DIALOGEX 15, 30, 470, 260 +STYLE DS_CONTROL | WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS +FONT 8, "MS Shell Dlg 2", 0, 0, 0x0 +BEGIN + GROUPBOX "Save new theme", IDC_STATIC, 0, 0, 230, 150 + LTEXT "A theme allows you to save the current layout of your Rainmeter skins and restore it at a later time. Themes remember your skins' positions and settings, but restoring an old theme will not undo edits or updates to your skins.", IDC_STATIC, 6, 16, 205, 44 + AUTOCHECKBOX "Save as empty theme", IDC_MANAGETHEMES_EMPTYTHEME_CHECKBOX, 6, 70, 120, 9, WS_TABSTOP + AUTOCHECKBOX "Exclude unused skins", IDC_MANAGETHEMES_UNUSEDSKINS_CHECKBOX, 6, 83, 120, 9, WS_TABSTOP + AUTOCHECKBOX "Include current wallpaper", IDC_MANAGETHEMES_WALLPAPER_CHECKBOX, 6, 96, 120, 9, WS_TABSTOP + LTEXT "Name:", IDC_STATIC, 6, 115, 100, 9 + EDITTEXT IDC_MANAGETHEMES_NAME_TEXT, 6, 128, 160, 14, WS_BORDER | WS_TABSTOP + PUSHBUTTON "Save", IDC_MANAGETHEMES_SAVE_BUTTON, 170, 128, 50, 14, WS_DISABLED | WS_TABSTOP + + GROUPBOX "Saved themes", IDC_STATIC, 238, 0, 230, 150 + LISTBOX IDC_MANAGETHEMES_LIST, 244, 16, 160, 125, LBS_STANDARD | LBS_NOINTEGRALHEIGHT + PUSHBUTTON "Load", IDC_MANAGETHEMES_LOAD_BUTTON, 410, 16, 50, 14, WS_DISABLED + PUSHBUTTON "Delete", IDC_MANAGETHEMES_DELETE_BUTTON, 410, 34, 50, 14, WS_DISABLED + PUSHBUTTON "Edit", IDC_MANAGETHEMES_EDIT_BUTTON, 410, 52, 50, 14, WS_DISABLED + + GROUPBOX "Backup", IDC_STATIC, 0, 200, 468, 60 + LTEXT "A backup allows you to save and fully restore Rainmeter to a prior state, including skins, themes, plugins, addons and statistics. Unlike a theme, installing a backup will replace all edits and updates to your skins since the backup was saved.", IDC_STATIC, 6, 216, 455, 24 + PUSHBUTTON "Backup...", IDC_MANAGETHEMES_BACKUP_BUTTON, 410, 240, 50, 14 +END + +IDD_MANAGESETTINGS_DIALOG DIALOGEX 15, 30, 470, 260 +STYLE DS_CONTROL | WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS +FONT 8, "MS Shell Dlg 2", 0, 0, 0x0 +BEGIN + GROUPBOX "General", IDC_STATIC, 0, 0, 468, 68 + //AUTOCHECKBOX "Run automatically at startup", IDC_MANAGESETTINGS_AUTOSTART_CHECKBOX, 6, 16, 140, 9, WS_DISABLED + AUTOCHECKBOX "Check for updates", IDC_MANAGESETTINGS_CHECKUPDATES_CHECKBOX, 6, 16, 140, 9 + AUTOCHECKBOX "Lock skins into position", IDC_MANAGESETTINGS_LOCKSKINS_CHECKBOX, 6, 29, 140, 9 + PUSHBUTTON "Reset statistics", IDC_MANAGESETTINGS_RESETSTATISTICS_BUTTON, 6, 47, 70, 14 + + GROUPBOX "Logging", IDC_STATIC, 0, 75, 468, 68 + AUTOCHECKBOX "Log to file", IDC_MANAGESETTINGS_LOGTOFILE_CHECKBOX, 6, 91, 140, 9 + AUTOCHECKBOX "Verbose logging (debug mode)", IDC_MANAGESETTINGS_VERBOSELOGGING_CHECKBOX, 6, 104, 140, 9 + PUSHBUTTON "Show log file", IDC_MANAGESETTINGS_SHOWLOGFILE_BUTTON, 6, 122, 70, 14 + PUSHBUTTON "Delete log file", IDC_MANAGESETTINGS_DELETELOGFILE_BUTTON, 80, 122, 70, 14 + + LTEXT "Rainmeter 2.1.0 beta r886 (64-bit). Built on Aug 1 2011.\r\n", IDC_MANAGESETTINGS_VERSION_LABEL, 0, 225, 300, 27 + CONTROL "Get the latest version at rainmeter.net.", IDC_STATIC, "SysLink", 0x0, 0, 238, 300, 9 + CONTROL "Rainmeter is an open source project distributed under the GNU GPL v2 license.", IDC_STATIC, "SysLink", 0x0, 0, 251, 300, 9 +END ///////////////////////////////////////////////////////////////////////////// // diff --git a/Library/Library.vcxproj b/Library/Library.vcxproj index 109f8bc6..3bc31a4f 100644 --- a/Library/Library.vcxproj +++ b/Library/Library.vcxproj @@ -115,7 +115,7 @@ 0x0409 - comctl32.lib;Wininet.lib;Winmm.lib;gdiplus.lib;Iphlpapi.lib;shlwapi.lib;%(AdditionalDependencies) + comctl32.lib;Wininet.lib;UxTheme.lib;Winmm.lib;gdiplus.lib;Iphlpapi.lib;shlwapi.lib;%(AdditionalDependencies) ../TestBench/x32/Debug/Rainmeter.dll true %(AdditionalLibraryDirectories) @@ -158,7 +158,7 @@ 0x0409 - comctl32.lib;Wininet.lib;Winmm.lib;gdiplus.lib;Iphlpapi.lib;shlwapi.lib;%(AdditionalDependencies) + comctl32.lib;Wininet.lib;UxTheme.lib;Winmm.lib;gdiplus.lib;Iphlpapi.lib;shlwapi.lib;%(AdditionalDependencies) ../TestBench/x64/Debug/Rainmeter.dll true %(AdditionalLibraryDirectories) @@ -204,7 +204,7 @@ 0x0409 - comctl32.lib;Wininet.lib;Winmm.lib;gdiplus.lib;Iphlpapi.lib;shlwapi.lib;%(AdditionalDependencies) + comctl32.lib;Wininet.lib;UxTheme.lib;Winmm.lib;gdiplus.lib;Iphlpapi.lib;shlwapi.lib;%(AdditionalDependencies) ../TestBench/x32/Release/Rainmeter.dll true lua/lib;%(AdditionalLibraryDirectories) @@ -252,7 +252,7 @@ /LTCG %(AdditionalOptions) - comctl32.lib;Wininet.lib;Winmm.lib;gdiplus.lib;Iphlpapi.lib;shlwapi.lib;%(AdditionalDependencies) + comctl32.lib;Wininet.lib;UxTheme.lib;Winmm.lib;gdiplus.lib;Iphlpapi.lib;shlwapi.lib;%(AdditionalDependencies) ../TestBench/x64/Release/Rainmeter.dll true %(AdditionalLibraryDirectories) @@ -265,17 +265,6 @@ - - Disabled - EnableFastChecks - Use - Disabled - EnableFastChecks - MaxSpeed - Use - MaxSpeed - Use - Disabled EnableFastChecks @@ -287,6 +276,8 @@ MaxSpeed Use + + Disabled EnableFastChecks @@ -320,6 +311,7 @@ MaxSpeed Use + Disabled EnableFastChecks @@ -833,13 +825,15 @@ - + + + @@ -915,6 +909,7 @@ + diff --git a/Library/Library.vcxproj.filters b/Library/Library.vcxproj.filters index 8ca45976..6e4ae3dc 100644 --- a/Library/Library.vcxproj.filters +++ b/Library/Library.vcxproj.filters @@ -36,9 +36,6 @@ - - Source Files - Source Files @@ -354,6 +351,15 @@ pcre + + Source Files + + + Source Files + + + Source Files + @@ -361,9 +367,6 @@ - - Header Files - Header Files @@ -598,10 +601,22 @@ pcre + + Header Files + + + Header Files + + + Header Files + Resource Files + + Resource Files + \ No newline at end of file diff --git a/Library/Litestep.cpp b/Library/Litestep.cpp index a2d0d669..20eff360 100644 --- a/Library/Litestep.cpp +++ b/Library/Litestep.cpp @@ -339,10 +339,10 @@ HINSTANCE ExecuteCommand(HWND Owner, LPCTSTR szCommand, int nShowCmd, LPCTSTR sz command.erase(0, notwhite); if (command.empty()) return NULL; - size_t quotePos = command.find(L"\""); + size_t quotePos = command.find(L'"'); if (quotePos == 0) { - size_t quotePos2 = command.find(L"\"", quotePos + 1); + size_t quotePos2 = command.find(L'"', quotePos + 1); if (quotePos2 != std::wstring::npos) { args.assign(command, quotePos2 + 1, command.length() - (quotePos2 + 1)); @@ -355,7 +355,7 @@ HINSTANCE ExecuteCommand(HWND Owner, LPCTSTR szCommand, int nShowCmd, LPCTSTR sz } else { - size_t spacePos = command.find(L" "); + size_t spacePos = command.find(L' '); if (spacePos != std::wstring::npos) { args.assign(command, spacePos + 1, command.length() - (spacePos + 1)); @@ -470,11 +470,8 @@ std::string ConvertToAscii(LPCTSTR str) int bufLen = WideCharToMultiByte(CP_ACP, 0, str, strLen, NULL, 0, NULL, NULL); if (bufLen > 0) { - char* tmpSz = new char[bufLen]; - tmpSz[0] = 0; - WideCharToMultiByte(CP_ACP, 0, str, strLen, tmpSz, bufLen, NULL, NULL); - szAscii = tmpSz; - delete [] tmpSz; + szAscii.resize(bufLen - 1); + WideCharToMultiByte(CP_ACP, 0, str, strLen, &szAscii[0], bufLen, NULL, NULL); } } return szAscii; @@ -490,11 +487,8 @@ std::wstring ConvertToWide(LPCSTR str) int bufLen = MultiByteToWideChar(CP_ACP, 0, str, strLen, NULL, 0); if (bufLen > 0) { - WCHAR* wideSz = new WCHAR[bufLen]; - wideSz[0] = 0; - MultiByteToWideChar(CP_ACP, 0, str, strLen, wideSz, bufLen); - szWide = wideSz; - delete [] wideSz; + szWide.resize(bufLen - 1); + MultiByteToWideChar(CP_ACP, 0, str, strLen, &szWide[0], bufLen); } } return szWide; @@ -510,11 +504,8 @@ std::string ConvertToUTF8(LPCWSTR str) int bufLen = WideCharToMultiByte(CP_UTF8, 0, str, strLen, NULL, 0, NULL, NULL); if (bufLen > 0) { - char* tmpSz = new char[bufLen]; - tmpSz[0] = 0; - WideCharToMultiByte(CP_UTF8, 0, str, strLen, tmpSz, bufLen, NULL, NULL); - szAscii = tmpSz; - delete [] tmpSz; + szAscii.resize(bufLen - 1); + WideCharToMultiByte(CP_UTF8, 0, str, strLen, &szAscii[0], bufLen, NULL, NULL); } } return szAscii; @@ -530,30 +521,30 @@ std::wstring ConvertUTF8ToWide(LPCSTR str) int bufLen = MultiByteToWideChar(CP_UTF8, 0, str, strLen, NULL, 0); if (bufLen > 0) { - WCHAR* wideSz = new WCHAR[bufLen]; - wideSz[0] = 0; - MultiByteToWideChar(CP_UTF8, 0, str, strLen, wideSz, bufLen); - szWide = wideSz; - delete [] wideSz; + szWide.resize(bufLen - 1); + MultiByteToWideChar(CP_UTF8, 0, str, strLen, &szWide[0], bufLen); } } return szWide; } -BOOL LSLog(int nLevel, LPCTSTR pszModule, LPCTSTR pszMessage) +BOOL LogInternal(int nLevel, LPCTSTR pszModule, LPCTSTR pszMessage) { - CRainmeter::LOG_INFO logInfo; - logInfo.message = pszMessage; - // Add timestamp static ULONGLONG startTime = CSystem::GetTickCount64(); ULONGLONG time = CSystem::GetTickCount64(); WCHAR buffer[128]; - _snwprintf_s(buffer, _TRUNCATE, L"(%02llu:%02llu:%02llu.%03llu) ", (time - startTime) / (1000 * 60* 60), ((time - startTime) / (1000 * 60)) % 60, ((time - startTime) / 1000) % 60, (time - startTime) % 1000); + _snwprintf_s(buffer, _TRUNCATE, L"%02llu:%02llu:%02llu.%03llu", (time - startTime) / (1000 * 60* 60), ((time - startTime) / (1000 * 60)) % 60, ((time - startTime) / 1000) % 60, (time - startTime) % 1000); - std::wstring message(buffer); - logInfo.timestamp = message; + if (Rainmeter) + { + Rainmeter->AddAboutLogInfo(nLevel, buffer, pszMessage); + } + + std::wstring message = L"("; + message += buffer; + message += L") "; message += pszMessage; #ifdef _DEBUG @@ -561,27 +552,6 @@ BOOL LSLog(int nLevel, LPCTSTR pszModule, LPCTSTR pszMessage) _RPT0(_CRT_WARN, "\n"); #endif - switch(nLevel) - { - case LOG_ERROR: - logInfo.type = L"ERROR"; - break; - case LOG_WARNING: - logInfo.type = L"WARNING"; - break; - case LOG_NOTICE: - logInfo.type = L"NOTICE"; - break; - case LOG_DEBUG: - logInfo.type = L"DEBUG"; - break; - } - - if (Rainmeter) - { - Rainmeter->AddAboutLogInfo(logInfo); - } - // Use the lsapi.dll version of the method if possible if (fpLSLog) { @@ -623,10 +593,29 @@ BOOL LSLog(int nLevel, LPCTSTR pszModule, LPCTSTR pszMessage) FILE* logFile = _wfopen(logfile.c_str(), L"a+, ccs=UTF-8"); if (logFile) { - fputws(logInfo.type.c_str(), logFile); - fputws(L": ", logFile); + message.insert(0, L": "); + + switch (nLevel) + { + case LOG_ERROR: + message.insert(0, L"ERROR"); + break; + + case LOG_WARNING: + message.insert(0, L"WARNING"); + break; + + case LOG_NOTICE: + message.insert(0, L"NOTICE"); + break; + + case LOG_DEBUG: + message.insert(0, L"DEBUG"); + break; + } + + message += L"\n"; fputws(message.c_str(), logFile); - fputws(L"\n", logFile); fclose(logFile); } } @@ -635,14 +624,19 @@ BOOL LSLog(int nLevel, LPCTSTR pszModule, LPCTSTR pszMessage) return TRUE; } -void RmNullCRTInvalidParameterHandler(const wchar_t* expression, const wchar_t* function, const wchar_t* file, unsigned int line, uintptr_t pReserved) +BOOL LSLog(int nLevel, LPCTSTR pszModule, LPCTSTR pszMessage) { - // Do nothing. + if (nLevel != LOG_DEBUG || Rainmeter->GetDebug()) + { + return LogInternal(nLevel, pszModule, pszMessage); + } + + return TRUE; } void Log(int nLevel, const WCHAR* message) { - LSLog(nLevel, L"Rainmeter", message); + LogInternal(nLevel, L"Rainmeter", message); } void LogWithArgs(int nLevel, const WCHAR* format, ... ) @@ -664,8 +658,13 @@ void LogWithArgs(int nLevel, const WCHAR* format, ... ) _set_invalid_parameter_handler(oldHandler); - LSLog(nLevel, L"Rainmeter", buffer); + LogInternal(nLevel, L"Rainmeter", buffer); va_end(args); delete [] buffer; } + +void RmNullCRTInvalidParameterHandler(const wchar_t* expression, const wchar_t* function, const wchar_t* file, unsigned int line, uintptr_t pReserved) +{ + // Do nothing. +} diff --git a/Library/MeterWindow.cpp b/Library/MeterWindow.cpp index da5f746b..57b23c56 100644 --- a/Library/MeterWindow.cpp +++ b/Library/MeterWindow.cpp @@ -24,7 +24,8 @@ #include "Error.h" #include "Meter.h" #include "Measure.h" -#include "AboutDialog.h" +#include "DialogAbout.h" +#include "DialogManage.h" #include "resource.h" #include "Litestep.h" #include "MeasureCalc.h" @@ -200,7 +201,8 @@ CMeterWindow::~CMeterWindow() { BOOL Result; int counter = 0; - do { + do + { // Wait for the window to die Result = UnregisterClass(METERWINDOW_CLASS_NAME, m_Rainmeter->GetInstance()); Sleep(100); @@ -679,7 +681,7 @@ void CMeterWindow::RunBang(BANGCOMMAND bang, const WCHAR* arg) if (!m_Window) return; - switch(bang) + switch (bang) { case BANG_REFRESH: // Refresh needs to be delayed since it crashes if done during Update() @@ -693,7 +695,7 @@ void CMeterWindow::RunBang(BANGCOMMAND bang, const WCHAR* arg) case BANG_UPDATE: KillTimer(m_Window, METERTIMER); // Kill timer temporarily Update(false); - UpdateAboutStatistics(m_SkinName.c_str()); + CDialogAbout::UpdateMeasures(m_SkinName.c_str()); if (m_WindowUpdate >= 0) { SetTimer(m_Window, METERTIMER, m_WindowUpdate, NULL); @@ -768,7 +770,7 @@ void CMeterWindow::RunBang(BANGCOMMAND bang, const WCHAR* arg) case BANG_UPDATEMEASURE: UpdateMeasure(arg); - UpdateAboutStatistics(m_SkinName.c_str()); + CDialogAbout::UpdateMeasures(m_SkinName.c_str()); break; case BANG_DISABLEMEASUREGROUP: @@ -785,7 +787,7 @@ void CMeterWindow::RunBang(BANGCOMMAND bang, const WCHAR* arg) case BANG_UPDATEMEASUREGROUP: UpdateMeasure(arg, true); - UpdateAboutStatistics(m_SkinName.c_str()); + CDialogAbout::UpdateMeasures(m_SkinName.c_str()); break; case BANG_SHOW: @@ -2007,6 +2009,11 @@ void CMeterWindow::WriteConfig(INT setting) WCHAR buffer[32]; const WCHAR* section = m_SkinName.c_str(); + if (setting != SETTING_ALL) + { + CDialogManage::UpdateSkins(this); + } + if (setting & SETTING_WINDOWPOSITION) { // If position needs to be save, do so. @@ -2074,7 +2081,6 @@ void CMeterWindow::WriteConfig(INT setting) } } - /* ** ReadSkin ** @@ -3122,7 +3128,7 @@ LRESULT CMeterWindow::OnTimer(UINT uMsg, WPARAM wParam, LPARAM lParam) if (wParam == METERTIMER) { Update(false); - UpdateAboutStatistics(m_SkinName.c_str()); + CDialogAbout::UpdateMeasures(m_SkinName.c_str()); //if (m_KeepOnScreen) //{ @@ -3331,7 +3337,7 @@ void CMeterWindow::ShowWindowIfAppropriate() { if (!m_Hidden && !inside && !keyDown) { - switch(m_WindowHide) + switch (m_WindowHide) { case HIDEMODE_HIDE: if (m_TransparencyValue == 0 || !IsWindowVisible(m_Window)) @@ -3540,7 +3546,7 @@ LRESULT CMeterWindow::OnMouseMove(UINT uMsg, WPARAM wParam, LPARAM lParam) if (!m_Hidden) { // If Alt, shift or control is down, do not hide the window - switch(m_WindowHide) + switch (m_WindowHide) { case HIDEMODE_HIDE: if (!m_NativeTransparency || m_TransparencyValue == m_AlphaValue) @@ -3655,6 +3661,10 @@ LRESULT CMeterWindow::OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam) LSExecute(NULL, command.c_str(), SW_SHOWNORMAL); } } + else if (wParam == ID_CONTEXT_SKINMENU_REFRESH) + { + Refresh(false); + } else if (wParam == ID_CONTEXT_SKINMENU_OPENSKINSFOLDER) { std::wstring command = L"\"" + m_SkinPath; @@ -3662,9 +3672,9 @@ LRESULT CMeterWindow::OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam) command += L"\""; LSExecute(NULL, command.c_str(), SW_SHOWNORMAL); } - else if (wParam == ID_CONTEXT_SKINMENU_REFRESH) + else if (wParam == ID_CONTEXT_SKINMENU_MANAGESKIN) { - Refresh(false); + CDialogManage::OpenSkin(this); } else if (wParam == ID_CONTEXT_SKINMENU_VERYTOPMOST) { @@ -3705,42 +3715,15 @@ LRESULT CMeterWindow::OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam) } else if (wParam == ID_CONTEXT_SKINMENU_HIDEONMOUSE) { - if (m_WindowHide == HIDEMODE_NONE) - { - m_WindowHide = HIDEMODE_HIDE; - } - else - { - m_WindowHide = HIDEMODE_NONE; - } - WriteConfig(SETTING_HIDEONMOUSEOVER); - UpdateTransparency(m_AlphaValue, false); + SetWindowHide((m_WindowHide == HIDEMODE_NONE) ? HIDEMODE_HIDE : HIDEMODE_NONE); } else if (wParam == ID_CONTEXT_SKINMENU_TRANSPARENCY_FADEIN) { - if (m_WindowHide == HIDEMODE_NONE) - { - m_WindowHide = HIDEMODE_FADEIN; - } - else - { - m_WindowHide = HIDEMODE_NONE; - } - WriteConfig(SETTING_HIDEONMOUSEOVER); - UpdateTransparency(m_AlphaValue, false); + SetWindowHide((m_WindowHide == HIDEMODE_NONE) ? HIDEMODE_FADEIN : HIDEMODE_NONE); } else if (wParam == ID_CONTEXT_SKINMENU_TRANSPARENCY_FADEOUT) { - if (m_WindowHide == HIDEMODE_NONE) - { - m_WindowHide = HIDEMODE_FADEOUT; - } - else - { - m_WindowHide = HIDEMODE_NONE; - } - WriteConfig(SETTING_HIDEONMOUSEOVER); - UpdateTransparency(m_AlphaValue, false); + SetWindowHide((m_WindowHide == HIDEMODE_NONE) ? HIDEMODE_FADEOUT : HIDEMODE_NONE); } else if (wParam == ID_CONTEXT_SKINMENU_REMEMBERPOSITION) { @@ -3954,6 +3937,18 @@ void CMeterWindow::SetSnapEdges(bool b) m_SnapEdges = b; WriteConfig(SETTING_SNAPEDGES); } +/* +** SetWindowHide +** +** Helper function for setting WindowHide +** +*/ +void CMeterWindow::SetWindowHide(HIDEMODE hide) +{ + m_WindowHide = hide; + WriteConfig(SETTING_HIDEONMOUSEOVER); + UpdateTransparency(m_AlphaValue, false); +} /* ** OnSysCommand @@ -4908,7 +4903,6 @@ bool CMeterWindow::DoMoveAction(int x, int y, MOUSE mouse) return false; } - /* ** OnMove ** @@ -5088,7 +5082,7 @@ LRESULT CMeterWindow::OnDelayedMove(UINT uMsg, WPARAM wParam, LPARAM lParam) */ LRESULT CMeterWindow::OnCopyData(UINT uMsg, WPARAM wParam, LPARAM lParam) { - COPYDATASTRUCT* pCopyDataStruct = (COPYDATASTRUCT*) lParam; + COPYDATASTRUCT* pCopyDataStruct = (COPYDATASTRUCT*)lParam; if (pCopyDataStruct && (pCopyDataStruct->dwData == 1) && (pCopyDataStruct->cbData > 0)) { @@ -5246,7 +5240,6 @@ std::wstring CMeterWindow::GetSkinRootPath() return path; } - CMeter* CMeterWindow::GetMeter(const std::wstring& meterName) { std::list::const_iterator j = m_Meters.begin(); diff --git a/Library/MeterWindow.h b/Library/MeterWindow.h index 680ff56a..c92a1e43 100644 --- a/Library/MeterWindow.h +++ b/Library/MeterWindow.h @@ -27,7 +27,7 @@ #include "ConfigParser.h" #include "Group.h" -#define BEGIN_MESSAGEPROC if (Window) { switch(uMsg) { +#define BEGIN_MESSAGEPROC if (Window) { switch (uMsg) { #define MESSAGE(handler, msg) case msg: return Window->handler(uMsg, wParam, lParam); #define REJECT_MESSAGE(msg) case msg: return 0; #define END_MESSAGEPROC } } return DefWindowProc(hWnd, uMsg, wParam, lParam); @@ -204,7 +204,7 @@ public: const std::wstring& GetSkinName() { return m_SkinName; } const std::wstring& GetSkinIniFile() { return m_SkinIniFile; } std::wstring GetSkinRootPath(); - + std::list& GetMeasures() { return m_Measures; } std::list& GetMeters() { return m_Meters; } @@ -247,6 +247,8 @@ public: CMeter* GetMeter(const std::wstring& meterName); CMeasure* GetMeasure(const std::wstring& measureName); + friend class CDialogManage; + protected: static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); @@ -328,6 +330,7 @@ private: void SetWindowDraggable(bool b); void SetSavePosition(bool b); void SetSnapEdges(bool b); + void SetWindowHide(HIDEMODE hide); bool DoAction(int x, int y, MOUSE mouse, bool test); bool DoMoveAction(int x, int y, MOUSE mouse); bool ResizeWindow(bool reset); diff --git a/Library/Rainmeter.cpp b/Library/Rainmeter.cpp index 974c3ede..6a02047d 100644 --- a/Library/Rainmeter.cpp +++ b/Library/Rainmeter.cpp @@ -21,7 +21,8 @@ #include "TrayWindow.h" #include "System.h" #include "Error.h" -#include "AboutDialog.h" +#include "DialogAbout.h" +#include "DialogManage.h" #include "MeasureNet.h" #include "MeterString.h" #include "resource.h" @@ -1428,11 +1429,51 @@ void RainmeterRefreshAppWide() ** Callback for the !RainmeterAbout bang ** */ -void RainmeterAboutWide() +void RainmeterAboutWide(const WCHAR* arg) { if (Rainmeter) { - OpenAboutDialog(Rainmeter->GetTrayWindow()->GetWindow(), Rainmeter->GetInstance()); + int tab = 0; + if (arg) + { + if (_wcsnicmp(arg, L"Measures", 8) == 0) + { + tab = 1; + } + else if (_wcsnicmp(arg, L"Plugins", 7) == 0) + { + tab = 2; + } + } + + CDialogAbout::Open(tab); + } +} + +/* +** RainmeterManagerWide +** +** Callback for the !RainmeterAbout bang +** +*/ +void RainmeterManageWide(const WCHAR* arg) +{ + if (Rainmeter) + { + int tab = 0; + if (arg) + { + if (_wcsnicmp(arg, L"Themes", 6) == 0) + { + tab = 1; + } + else if (_wcsnicmp(arg, L"Settings", 8) == 0) + { + tab = 2; + } + } + + CDialogManage::Open(tab); } } @@ -1668,8 +1709,8 @@ bool CRainmeter::c_Debug = false; */ CRainmeter::CRainmeter() : m_TrayWindow(), - m_DisableVersionCheck(FALSE), - m_NewVersion(FALSE), + m_DisableVersionCheck(false), + m_NewVersion(false), m_DesktopWorkAreaChanged(false), m_DesktopWorkAreaType(false), m_MenuActive(false), @@ -1685,8 +1726,7 @@ CRainmeter::CRainmeter() : CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); - INITCOMMONCONTROLSEX initCtrls = {sizeof(INITCOMMONCONTROLSEX), ICC_LISTVIEW_CLASSES}; - InitCommonControlsEx(&initCtrls); + InitCommonControls(); // Initialize GDI+. GdiplusStartupInput gdiplusStartupInput; @@ -1950,7 +1990,6 @@ int CRainmeter::Initialize(HWND Parent, HINSTANCE Instance, LPCSTR szPath) LogWithArgs(LOG_NOTICE, L"Path: %s", m_Path.c_str()); LogWithArgs(LOG_NOTICE, L"IniFile: %s", m_IniFile.c_str()); LogWithArgs(LOG_NOTICE, L"SkinPath: %s", m_SkinPath.c_str()); - LogWithArgs(LOG_NOTICE, L"PluginPath: %s", m_PluginPath.c_str()); // Extract volume path from program path // E.g.: @@ -1978,12 +2017,6 @@ int CRainmeter::Initialize(HWND Parent, HINSTANCE Instance, LPCSTR szPath) // Test that the Rainmeter.ini file is writable TestSettingsFile(bDefaultIniLocation); - // If the skin folder is somewhere else than in the program path - if (_wcsnicmp(m_Path.c_str(), m_SkinPath.c_str(), m_Path.size()) != 0) - { - CheckSkinVersions(); - } - CSystem::Initialize(Instance); CMeasureNet::InitializeNewApi(); @@ -2116,174 +2149,6 @@ int CRainmeter::Initialize(HWND Parent, HINSTANCE Instance, LPCSTR szPath) return Result; // Alles OK } -/* -** CheckSkinVersions -** -** Checks if any of the skins in the program folder are newer than in the skin folder. -** -*/ -void CRainmeter::CheckSkinVersions() -{ - // List all skins in the program folder - std::wstring strMainSkinsPath = m_Path + L"Skins\\"; - std::vector menu; - ScanForConfigsRecursive(strMainSkinsPath, L"", 0, menu, true); - - for (size_t i = 0, isize = menu.size(); i < isize; ++i) - { - // LogWithArgs(LOG_DEBUG, L"%s", menu[i].name.c_str()); - - // Read the version files - std::wstring strNewVersionFile = strMainSkinsPath + menu[i].name; - strNewVersionFile += L"\\version"; - std::wstring strCurrentVersionFile = m_SkinPath + menu[i].name; - strCurrentVersionFile += L"\\version"; - - std::string strVersion; - std::wstring strVersionNew; - std::wstring strVersionCurrent; - std::wstring strVersionInIni; - - std::ifstream newFile(strNewVersionFile.c_str(), std::ios_base::in); - if (getline(newFile, strVersion)) - { - strVersionNew = ConvertToWide(strVersion.c_str()); - // LogWithArgs(LOG_DEBUG, L"New: %s", strVersionNew.c_str()); - - // Compare with the version entry in the Rainmeter.ini - WCHAR tmpSz[256] = {0}; - GetPrivateProfileString(menu[i].name.c_str(), L"Version", L"", tmpSz, 256, m_IniFile.c_str()); - strVersionInIni = tmpSz; - - // LogWithArgs(LOG_DEBUG, L"In Ini: %s", strVersionInIni.c_str()); - - // Compare with the version file in the skin folder - std::ifstream currentFile(strCurrentVersionFile.c_str(), std::ios_base::in); - if (getline(currentFile, strVersion)) - { - strVersionCurrent = ConvertToWide(strVersion.c_str()); - // LogWithArgs(LOG_DEBUG, L"Current: %s", strVersionCurrent.c_str()); - } - } - - // If the skin doesn't define a version file no need to do anything - if (!strVersionNew.empty()) - { - // Compare the version files - if (CompareVersions(strVersionNew, strVersionInIni) == 1 && - CompareVersions(strVersionNew, strVersionCurrent) == 1) - { - // Check if the old skin exists at all - struct _stat64i32 s; - std::wstring strSkinPath = m_SkinPath + menu[i].name; - if (_wstat(strSkinPath.c_str(), &s) == 0) - { - std::wstring strMessage = L"A new version of config \"" + menu[i].name; - strMessage += L"\" is available.\n\nNew version: "; - strMessage += strVersionNew.empty() ? L"Unknown" : strVersionNew; - strMessage += L"\nCurrent version: "; - strMessage += strVersionCurrent.empty() ? L"Unknown" : strVersionCurrent; - strMessage += L"\n\nDo you want to upgrade?\n\n" - L"(If you select 'Yes' your current config\nwill be moved into the 'Backup' folder)"; - - if (IDYES == MessageBox(NULL, strMessage.c_str(), APPNAME, MB_YESNO | MB_ICONQUESTION)) - { - // Make sure that the folder exists - CreateDirectory(std::wstring(m_SkinPath + L"Backup").c_str(), NULL); - - // Check for illegal characters from the version number - if (strVersionCurrent.find_first_of(L"\\/\"*:?<>|") == std::wstring::npos) - { - std::wstring strTarget = m_SkinPath + L"Backup\\"; - strTarget += menu[i].name; - strTarget += L"-"; - strTarget += strVersionCurrent; - if (CSystem::CopyFiles(m_SkinPath + menu[i].name, strTarget, true)) // Move the folder to "backup" - { - // Upgrade the skin - CSystem::CopyFiles(strMainSkinsPath + menu[i].name, m_SkinPath); - - // TODO: Temporary 'fix': If skin was illustro upgrade the themes too - if (!_wcsicmp(menu[i].name.c_str(), L"illustro")) - { - std::wstring strMainThemes = m_Path + L"Themes"; - std::wstring strCurrentThemes = GetSettingsPath(); - CSystem::CopyFiles(strMainThemes, strCurrentThemes); - } - // End of temporary 'fix' - } - else - { - std::wstring strMessage = L"Failed to upgrade the config.\nUnable to backup the current config."; - MessageBox(NULL, strMessage.c_str(), APPNAME, MB_OK | MB_TOPMOST | MB_ICONERROR); - } - } - else - { - std::wstring strMessage = L"Failed to upgrade the config.\nThe version number contains illegal characters."; - MessageBox(NULL, strMessage.c_str(), APPNAME, MB_OK | MB_TOPMOST | MB_ICONERROR); - } - } - } - else - { - std::wstring strMessage = L"A new version of config \"" + menu[i].name; - strMessage += L"\" is available\n" - L"Do you want to add it to your skin and themes libraries?"; - if (IDYES == MessageBox(NULL, strMessage.c_str(), APPNAME, MB_YESNO | MB_ICONQUESTION)) - { - CSystem::CopyFiles(strMainSkinsPath + menu[i].name, m_SkinPath); - std::wstring strMainThemes = m_Path + L"Themes"; - std::wstring strCurrentThemes = GetSettingsPath(); - CSystem::CopyFiles(strMainThemes, strCurrentThemes); - } - } - - // Even if the user doesn't want to upgrade mark it to the Rainmeter.ini so we don't ask the upgrade question again - WritePrivateProfileString(menu[i].name.c_str(), L"Version", strVersionNew.c_str(), m_IniFile.c_str()); - } - } - } -} - -/* -** CompareVersions -** -** Compares two version strings. Returns 0 if they are equal, 1 if A > B and -1 if A < B. -** -*/ -int CRainmeter::CompareVersions(const std::wstring& strA, const std::wstring& strB) -{ - if (strA.empty() && strB.empty()) return 0; - if (strA.empty()) return -1; - if (strB.empty()) return 1; - - std::vector arrayA = CConfigParser::Tokenize(strA, L"."); - std::vector arrayB = CConfigParser::Tokenize(strB, L"."); - size_t arrayASize = arrayA.size(); - size_t arrayBSize = arrayB.size(); - - size_t len = max(arrayASize, arrayBSize); - for (size_t i = 0; i < len; ++i) - { - int a = 0; - int b = 0; - - if (i < arrayASize) - { - a = _wtoi(arrayA[i].c_str()); - } - if (i < arrayBSize) - { - b = _wtoi(arrayB[i].c_str()); - } - - if (a > b) return 1; - if (a < b) return -1; - } - return 0; -} - /* ** CreateDefaultConfigFile ** @@ -2302,13 +2167,7 @@ void CRainmeter::CreateDefaultConfigFile(const std::wstring& strFile) std::wstring defaultIni = GetPath() + L"Default.ini"; if (_waccess(defaultIni.c_str(), 0) == -1) { - // The default.ini wasn't found -> create new - std::ofstream out(strFile.c_str(), std::ios::out); - if (out) - { - out << std::string("[Rainmeter]\n\n[illustro\\System]\nActive=1\n"); - out.close(); - } + WritePrivateProfileString(L"Rainmeter", L"\r\n[illustro\\System]\r\nActive", L"1", strFile.c_str()); } else { @@ -2318,6 +2177,9 @@ void CRainmeter::CreateDefaultConfigFile(const std::wstring& strFile) void CRainmeter::ReloadSettings() { + // TODO FIXME +// UpdateDialog(); + ScanForConfigs(m_SkinPath); ScanForThemes(GetSettingsPath() + L"Themes"); ReadGeneralSettings(m_IniFile); @@ -2377,7 +2239,7 @@ void CRainmeter::ActivateConfig(int configIndex, int iniIndex) } } -bool CRainmeter::DeactivateConfig(CMeterWindow* meterWindow, int configIndex) +bool CRainmeter::DeactivateConfig(CMeterWindow* meterWindow, int configIndex, bool save) { if (configIndex >= 0 && configIndex < (int)m_ConfigStrings.size()) { @@ -2399,8 +2261,11 @@ bool CRainmeter::DeactivateConfig(CMeterWindow* meterWindow, int configIndex) if (meterWindow) { - // Disable the config in the ini-file - WriteActive(meterWindow->GetSkinName(), -1); + if (save) + { + // Disable the config in the ini-file + WriteActive(meterWindow->GetSkinName(), -1); + } return DeleteMeterWindow(meterWindow, true); } @@ -2423,33 +2288,41 @@ void CRainmeter::CreateMeterWindow(const std::wstring& path, const std::wstring& m_Meters[config] = mw; mw->Initialize(*this); - UpdateAboutDialog(); + CDialogAbout::UpdateSkins(); + CDialogManage::UpdateSkins(mw); } } void CRainmeter::ClearDeleteLaterList() { - while (!m_DelayDeleteList.empty()) + if (!m_DelayDeleteList.empty()) { - CMeterWindow* meterWindow = m_DelayDeleteList.front(); - - // Remove from the delete later list - m_DelayDeleteList.remove(meterWindow); - - // Remove from the meter window list if it is still there - std::map::iterator iter = m_Meters.begin(); - for (; iter != m_Meters.end(); ++iter) + do { - if ((*iter).second == meterWindow) + CMeterWindow* meterWindow = m_DelayDeleteList.front(); + + // Remove from the delete later list + m_DelayDeleteList.remove(meterWindow); + + // Remove from the meter window list if it is still there + std::map::iterator iter = m_Meters.begin(); + for (; iter != m_Meters.end(); ++iter) { - m_Meters.erase(iter); - - UpdateAboutDialog(); - break; + if ((*iter).second == meterWindow) + { + m_Meters.erase(iter); + CDialogManage::UpdateSkins(meterWindow, true); + break; + } } - } - delete meterWindow; + delete meterWindow; + } + while (!m_DelayDeleteList.empty()); + + + CDialogManage::UpdateThemes(); + CDialogAbout::UpdateSkins(); } } @@ -2483,7 +2356,6 @@ bool CRainmeter::DeleteMeterWindow(CMeterWindow* meterWindow, bool bLater) m_Meters.erase(iter); delete meterWindow; - UpdateAboutDialog(); return true; } } @@ -2492,8 +2364,6 @@ bool CRainmeter::DeleteMeterWindow(CMeterWindow* meterWindow, bool bLater) { m_Meters.clear(); } - - UpdateAboutDialog(); } return false; @@ -2835,12 +2705,6 @@ void CRainmeter::ScanForThemes(const std::wstring& path) } } -void CRainmeter::SaveSettings() -{ - WritePrivateProfileString(L"Rainmeter", L"CheckUpdate", NULL , m_IniFile.c_str()); - WritePrivateProfileString(L"Rainmeter", L"DisableVersionCheck", m_DisableVersionCheck ? L"1" : L"0" , m_IniFile.c_str()); -} - BOOL CRainmeter::ExecuteBang(const std::wstring& bang, const std::wstring& arg, CMeterWindow* meterWindow) { // Skip "!Rainmeter" or "!" @@ -3101,7 +2965,11 @@ BOOL CRainmeter::ExecuteBang(const std::wstring& bang, const std::wstring& arg, } else if (_wcsicmp(name, L"About") == 0) { - RainmeterAboutWide(); + RainmeterAboutWide(arg.c_str()); + } + else if (_wcsicmp(name, L"Manage") == 0) + { + RainmeterManageWide(arg.c_str()); } else if (_wcsicmp(name, L"SkinMenu") == 0) { @@ -3865,6 +3733,8 @@ void CRainmeter::ShowContextMenu(POINT pos, CMeterWindow* meterWindow) HMENU subMenu = GetSubMenu(menu, 0); if (subMenu) { + SetMenuDefaultItem(subMenu, ID_CONTEXT_MANAGE, MF_BYCOMMAND); + if (!GetDummyLitestep()) { // Disable Quit/Logging if ran as a Litestep plugin @@ -3918,10 +3788,8 @@ void CRainmeter::ShowContextMenu(POINT pos, CMeterWindow* meterWindow) WCHAR buffer[256]; GetMenuString(menu, 0, buffer, 256, MF_BYPOSITION); - InsertMenu(subMenu, 10, MF_BYPOSITION | MF_POPUP, (UINT_PTR)rainmeterMenu, buffer); - InsertMenu(subMenu, 11, MF_BYPOSITION | MF_SEPARATOR, 0, NULL); - - DeleteMenu(rainmeterMenu, ID_CONTEXT_DOWNLOADS, MF_BYCOMMAND); + InsertMenu(subMenu, 11, MF_BYPOSITION | MF_POPUP, (UINT_PTR)rainmeterMenu, buffer); + InsertMenu(subMenu, 12, MF_BYPOSITION | MF_SEPARATOR, 0, NULL); } else { @@ -3942,9 +3810,9 @@ void CRainmeter::ShowContextMenu(POINT pos, CMeterWindow* meterWindow) // Put Update notifications in the Tray menu if (m_NewVersion) { - InsertMenu(subMenu, 0, MF_BYPOSITION, ID_CONTEXT_NEW_VERSION, L"New Version Available"); + InsertMenu(subMenu, 0, MF_BYPOSITION, ID_CONTEXT_NEW_VERSION, L"Update available"); + HiliteMenuItem(Rainmeter->GetTrayWindow()->GetWindow(), subMenu, 0, MF_BYPOSITION | MF_HILITE); InsertMenu(subMenu, 1, MF_BYPOSITION | MF_SEPARATOR, 0, NULL); - SetMenuDefaultItem(subMenu, ID_CONTEXT_NEW_VERSION, MF_BYCOMMAND); } } @@ -3995,7 +3863,6 @@ void CRainmeter::ShowContextMenu(POINT pos, CMeterWindow* meterWindow) } } - HMENU CRainmeter::CreateConfigMenu(HMENU configMenu, std::vector& configMenuData) { if (!configMenuData.empty()) @@ -4071,7 +3938,7 @@ HMENU CRainmeter::CreateSkinMenu(CMeterWindow* meterWindow, int index, HMENU con HMENU posMenu = GetSubMenu(settingsMenu, 0); if (posMenu) { - switch(meterWindow->GetWindowZPosition()) + switch (meterWindow->GetWindowZPosition()) { case ZPOSITION_ONDESKTOP: CheckMenuItem(posMenu, ID_CONTEXT_SKINMENU_ONDESKTOP, MF_BYCOMMAND | MF_CHECKED); @@ -4387,16 +4254,12 @@ void CRainmeter::DeleteLogFile() } } -void CRainmeter::AddAboutLogInfo(const LOG_INFO& logInfo) +void CRainmeter::AddAboutLogInfo(int level, LPCWSTR time, LPCWSTR message) { + // TODO: Store items in vector + EnterCriticalSection(&m_CsLogData); - - m_LogData.push_front(logInfo); - if (m_LogData.size() > MAXABOUTLOGLINES) - { - m_LogData.pop_back(); - } - + CDialogAbout::AddLogItem(level, time, message); LeaveCriticalSection(&m_CsLogData); } @@ -4418,6 +4281,12 @@ void CRainmeter::SetDisableDragging(bool dragging) WritePrivateProfileString(L"Rainmeter", L"DisableDragging", dragging ? L"1" : L"0", m_IniFile.c_str()); } +void CRainmeter::SetDisableVersionCheck(bool check) +{ + m_DisableVersionCheck = check; + WritePrivateProfileString(L"Rainmeter", L"DisableVersionCheck", check ? L"1" : L"0" , m_IniFile.c_str()); +} + void CRainmeter::TestSettingsFile(bool bDefaultIniLocation) { WritePrivateProfileString(L"Rainmeter", L"WriteTest", L"TRUE", m_IniFile.c_str()); diff --git a/Library/Rainmeter.h b/Library/Rainmeter.h index b358ca30..529b47b6 100644 --- a/Library/Rainmeter.h +++ b/Library/Rainmeter.h @@ -31,10 +31,13 @@ #define APPNAME L"Rainmeter" #ifdef _WIN64 -#define APPBITS L"(64-bit)" +#define APPBITS L"64-bit" #else -#define APPBITS L"(32-bit)" +#define APPBITS L"32-bit" #endif +#define WIDEN2(x) L ## x +#define WIDEN(x) WIDEN2(x) +#define APPDATE WIDEN(__DATE__) // Callbacks for Litestep void RainmeterRefresh(HWND, const char* arg); @@ -117,7 +120,8 @@ void RainmeterDeactivateConfigWide(const WCHAR* arg); void RainmeterToggleConfigWide(const WCHAR* arg); void RainmeterDeactivateConfigGroupWide(const WCHAR* arg); void RainmeterRefreshAppWide(); -void RainmeterAboutWide(); +void RainmeterAboutWide(const WCHAR* arg = NULL); +void RainmeterManageWide(const WCHAR* arg = NULL); void RainmeterSkinMenuWide(const WCHAR* arg); void RainmeterTrayMenuWide(); void RainmeterResetStatsWide(); @@ -156,7 +160,7 @@ public: struct LOG_INFO { - std::wstring type; + int level; std::wstring timestamp; std::wstring message; }; @@ -182,7 +186,7 @@ public: const std::vector& GetAllThemes() { return m_Themes; } void ActivateConfig(int configIndex, int iniIndex); - bool DeactivateConfig(CMeterWindow* meterWindow, int configIndex); + bool DeactivateConfig(CMeterWindow* meterWindow, int configIndex, bool save = true); const std::wstring& GetPath() { return m_Path; } const std::wstring& GetIniFile() { return m_IniFile; } @@ -209,17 +213,16 @@ public: static bool GetDebug() { return c_Debug; } void ReloadSettings(); - void SaveSettings(); void UpdateStats(); void ReadStats(); void WriteStats(bool bForce); void ResetStats(); - BOOL GetDisableVersionCheck() { return m_DisableVersionCheck; } - BOOL GetNewVersion() { return m_NewVersion; } - void SetDisableVersionCheck(BOOL check) { m_DisableVersionCheck = check; } - void SetNewVersion(BOOL NewVer) { m_NewVersion = NewVer; } + bool GetDisableVersionCheck() { return m_DisableVersionCheck; } + void SetDisableVersionCheck(bool check); + bool GetNewVersion() { return m_NewVersion; } + void SetNewVersion(bool newver) { m_NewVersion = newver; } bool GetLogging() { return m_Logging; } void StartLogging(); @@ -231,8 +234,7 @@ public: bool GetDisableDragging() { return m_DisableDragging; } void SetDisableDragging(bool dragging); - void AddAboutLogInfo(const LOG_INFO& logInfo); - const std::list& GetAboutLogData() { return m_LogData; } + void AddAboutLogInfo(int level, LPCWSTR time, LPCWSTR message); void SetDebug(bool debug); @@ -258,6 +260,8 @@ public: static std::wstring ExtractPath(const std::wstring& strFilePath); static void ExpandEnvironmentVariables(std::wstring& strPath); + friend class CDialogManage; + private: void CreateMeterWindow(const std::wstring& path, const std::wstring& config, const std::wstring& iniFile); bool DeleteMeterWindow(CMeterWindow* meterWindow, bool bLater); @@ -278,8 +282,6 @@ private: void CreateDefaultConfigFile(const std::wstring& strFile); void SetLogging(bool logging); void TestSettingsFile(bool bDefaultIniLocation); - void CheckSkinVersions(); - int CompareVersions(const std::wstring& strA, const std::wstring& strB); CTrayWindow* m_TrayWindow; @@ -308,8 +310,8 @@ private: std::wstring m_TrayExecuteDR; std::wstring m_TrayExecuteDM; - BOOL m_DisableVersionCheck; - BOOL m_NewVersion; + bool m_DisableVersionCheck; + bool m_NewVersion; bool m_DesktopWorkAreaChanged; bool m_DesktopWorkAreaType; // If true, DesktopWorkArea is treated as "margin" diff --git a/Library/StdAfx.h b/Library/StdAfx.h index 870bb817..60666e27 100644 --- a/Library/StdAfx.h +++ b/Library/StdAfx.h @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -54,8 +55,6 @@ #include #include #include -#include -#include #include #include diff --git a/Library/System.cpp b/Library/System.cpp index 9fdc380c..98ace236 100644 --- a/Library/System.cpp +++ b/Library/System.cpp @@ -1080,6 +1080,40 @@ void CSystem::ResetWorkingDirectory() } } +/* +** SetClipboardText +** +** Sets clipboard text to given string. +** +*/ +void CSystem::SetClipboardText(const std::wstring& text) +{ + if (OpenClipboard(NULL)) + { + // Include terminating null char + size_t len = text.length() + 1; + + HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE, len * sizeof(WCHAR)); + if (hMem) + { + LPVOID data = GlobalLock(hMem); + if (data) + { + memcpy(data, text.c_str(), len * sizeof(WCHAR)); + GlobalUnlock(hMem); + + EmptyClipboard(); + if (!SetClipboardData(CF_UNICODETEXT, hMem)) + { + GlobalFree(hMem); + } + } + } + + CloseClipboard(); + } +} + /* ** CopyFiles ** @@ -1129,6 +1163,34 @@ bool CSystem::RemoveFile(const std::wstring& file) return (DeleteFile(file.c_str()) != 0); } +/* +** RemoveFolder +** +** Recursively removes folder. +** +*/ +bool CSystem::RemoveFolder(const std::wstring& strFolder) +{ + std::wstring tmpFolder(strFolder); + + // The strings must end with double nul + tmpFolder.append(L"0"); + tmpFolder[tmpFolder.size() - 1] = L'\0'; + + SHFILEOPSTRUCT fo = {0}; + fo.wFunc = FO_DELETE; + fo.pFrom = tmpFolder.c_str(); + fo.fFlags = FOF_NO_UI | FOF_NOCONFIRMATION | FOF_ALLOWUNDO; + + int result = SHFileOperation(&fo); + if (result != 0) + { + LogWithArgs(LOG_ERROR, L"Unable to delete folder %s (%i)", strFolder.c_str(), result); + return false; + } + return true; +} + /* ** GetIniFileMappingList ** diff --git a/Library/System.h b/Library/System.h index de626d1e..e2614564 100644 --- a/Library/System.h +++ b/Library/System.h @@ -75,8 +75,11 @@ public: static HMODULE RmLoadLibrary(LPCWSTR lpLibFileName, DWORD* dwError = NULL, bool ignoreErrors = false); static void ResetWorkingDirectory(); + static void SetClipboardText(const std::wstring& text); + static bool CopyFiles(const std::wstring& strFrom, const std::wstring& strTo, bool bMove = false); static bool RemoveFile(const std::wstring& file); + static bool RemoveFolder(const std::wstring& strFolder); static void GetIniFileMappingList(std::vector& iniFileMappings); static std::wstring GetTemporaryFile(const std::vector& iniFileMappings, const std::wstring& iniFile); diff --git a/Library/TrayWindow.cpp b/Library/TrayWindow.cpp index df9fa473..80f454ab 100644 --- a/Library/TrayWindow.cpp +++ b/Library/TrayWindow.cpp @@ -22,7 +22,8 @@ #include "resource.h" #include "Litestep.h" #include "Rainmeter.h" -#include "AboutDialog.h" +#include "DialogAbout.h" +#include "DialogManage.h" #include "Error.h" #include "RainmeterQuery.h" #include "../Version.h" @@ -411,18 +412,18 @@ LRESULT CALLBACK CTrayWindow::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA } } - switch(uMsg) + switch (uMsg) { case WM_COMMAND: if (Rainmeter && tray) { - if (wParam == ID_CONTEXT_ABOUT) + if (wParam == ID_CONTEXT_MANAGE) { - OpenAboutDialog(tray->GetWindow(), Rainmeter->GetInstance()); + CDialogManage::Open(); } - else if (wParam == ID_CONTEXT_DOWNLOADS) + else if (wParam == ID_CONTEXT_ABOUT) { - LSExecute(NULL, RAINMETER_DOWNLOADS, SW_SHOWNORMAL); + CDialogAbout::Open(); } else if (wParam == ID_CONTEXT_SHOW_HELP) { @@ -474,18 +475,6 @@ LRESULT CALLBACK CTrayWindow::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA command += L"\""; LSExecute(tray->GetWindow(), command.c_str(), SW_SHOWNORMAL); } - else if (wParam == ID_CONTEXT_MANAGETHEMES) - { - std::wstring command = L"\"" + Rainmeter->GetAddonPath(); - command += L"RainThemes\\RainThemes.exe\""; - LSExecute(tray->GetWindow(), command.c_str(), SW_SHOWNORMAL); - } - else if (wParam == ID_CONTEXT_MANAGESKINS) - { - std::wstring command = L"\"" + Rainmeter->GetAddonPath(); - command += L"RainBrowser\\RainBrowser.exe\""; - LSExecute(tray->GetWindow(), command.c_str(), SW_SHOWNORMAL); - } else if (wParam == ID_CONTEXT_QUIT) { if (Rainmeter->GetDummyLitestep()) PostQuitMessage(0); @@ -565,10 +554,9 @@ LRESULT CALLBACK CTrayWindow::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA case WM_TRAY_NOTIFYICON: { UINT uMouseMsg = (UINT)lParam; - std::wstring bang; - switch(uMouseMsg) + switch (uMouseMsg) { case WM_LBUTTONDOWN: bang = Rainmeter->GetTrayExecuteL(); @@ -599,12 +587,16 @@ LRESULT CALLBACK CTrayWindow::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA { Rainmeter->ExecuteCommand(bang.c_str(), NULL); } - else if (uMouseMsg == WM_RBUTTONDOWN) + else if (uMouseMsg == WM_RBUTTONDOWN) { POINT point; GetCursorPos(&point); Rainmeter->ShowContextMenu(point, NULL); } + else if (uMouseMsg == WM_LBUTTONDOWN || uMouseMsg == WM_LBUTTONDBLCLK) + { + CDialogManage::Open(); + } } break; @@ -699,9 +691,9 @@ LRESULT CALLBACK CTrayWindow::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA } else if (wParam == RAINMETER_QUERY_ID_VERSION_CHECK) { - UINT versioncheck = (Rainmeter->GetDisableVersionCheck() * (Rainmeter->GetDisableVersionCheck() + Rainmeter->GetNewVersion())); + UINT versioncheck = ((int)Rainmeter->GetDisableVersionCheck() * ((int)Rainmeter->GetDisableVersionCheck() + (int)Rainmeter->GetNewVersion())); - SendMessage((HWND)lParam, WM_QUERY_RAINMETER_RETURN, (WPARAM)hWnd, (LPARAM) versioncheck); + SendMessage((HWND)lParam, WM_QUERY_RAINMETER_RETURN, (WPARAM)hWnd, (LPARAM)versioncheck); return 0; } @@ -709,7 +701,7 @@ LRESULT CALLBACK CTrayWindow::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA { BOOL debug = Rainmeter->GetDebug(); - SendMessage((HWND)lParam, WM_QUERY_RAINMETER_RETURN, (WPARAM)hWnd, (LPARAM) debug); + SendMessage((HWND)lParam, WM_QUERY_RAINMETER_RETURN, (WPARAM)hWnd, (LPARAM)debug); return 0; } @@ -801,7 +793,7 @@ LRESULT CALLBACK CTrayWindow::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA { BOOL islitestep = !Rainmeter->GetDummyLitestep(); - SendMessage((HWND)lParam, WM_QUERY_RAINMETER_RETURN, (WPARAM)hWnd, (LPARAM) islitestep); + SendMessage((HWND)lParam, WM_QUERY_RAINMETER_RETURN, (WPARAM)hWnd, (LPARAM)islitestep); return 0; } diff --git a/Library/UpdateCheck.cpp b/Library/UpdateCheck.cpp index 80bf880e..5c324cd9 100644 --- a/Library/UpdateCheck.cpp +++ b/Library/UpdateCheck.cpp @@ -71,12 +71,12 @@ void CheckVersion(void* dummy) if (version > RAINMETER_VERSION) { - Rainmeter->SetNewVersion(TRUE); + Rainmeter->SetNewVersion(true); + Log(LOG_NOTICE, L"CheckUpdate: New version available."); } else { - Rainmeter->SetNewVersion(FALSE); - Log(LOG_NOTICE, L"CheckUpdate: No new version available."); + Rainmeter->SetNewVersion(false); } } else diff --git a/Library/resource.h b/Library/resource.h index 02d436b4..57daea90 100644 --- a/Library/resource.h +++ b/Library/resource.h @@ -2,86 +2,139 @@ // Microsoft Visual C++ generated include file. // Used by Library.rc // -#define IDR_CONTEXT_MENU 101 -#define IDD_ABOUT_DIALOG 102 -#define IDR_SKIN_MENU 102 -#define IDI_TRAY 108 -#define IDI_WINDOW 109 -#define IDC_STATISTICS 1000 -#define IDC_BUILD_STRING 1001 -#define IDC_VERSION_STRING 1002 -#define IDC_STATISTICS_STRING 1003 -#define IDC_STATIC_ABOUT 1004 -#define IDC_URL_STRING 1005 -#define IDC_ABOUT_ENTRIES 1006 -#define IDC_AUTHOR_STRING 1007 -#define IDC_DISABLE_VERSION_CHECK 1008 -#define ID_CONTEXT_REFRESH 4001 -#define ID_CONTEXT_QUIT 4002 -#define ID_CONTEXT_DISABLEDRAG 4003 -#define ID_CONTEXT_ABOUT 4004 -#define ID_CONTEXT_DOWNLOADS 4005 -#define ID_CONTEXT_CONFIGS_DEFAULT 4006 -#define ID_CONTEXT_EDITCONFIG 4008 -#define ID_CONTEXT_CLOSESKIN 4009 -#define ID_CONTEXT_SKINMENU_TOPMOST 4010 -#define ID_CONTEXT_SKINMENU_NORMAL 4011 -#define ID_CONTEXT_SKINMENU_BOTTOM 4012 -#define ID_CONTEXT_SKINMENU_TRANSPARENCY_0 4014 -#define ID_CONTEXT_SKINMENU_TRANSPARENCY_10 4015 -#define ID_CONTEXT_SKINMENU_TRANSPARENCY_20 4016 -#define ID_CONTEXT_SKINMENU_TRANSPARENCY_30 4017 -#define ID_CONTEXT_SKINMENU_TRANSPARENCY_40 4018 -#define ID_CONTEXT_SKINMENU_TRANSPARENCY_50 4019 -#define ID_CONTEXT_SKINMENU_TRANSPARENCY_60 4020 -#define ID_CONTEXT_SKINMENU_TRANSPARENCY_70 4021 -#define ID_CONTEXT_SKINMENU_TRANSPARENCY_80 4022 -#define ID_CONTEXT_SKINMENU_TRANSPARENCY_90 4023 -#define ID_CONTEXT_SKINMENU_REFRESH 4024 -#define ID_CONTEXT_SKINMENU_HIDEONMOUSE 4025 -#define ID_CONTEXT_SKINMENU_DRAGGABLE 4026 -#define ID_CONTEXT_SKINMENU_REMEMBERPOSITION 4027 -#define ID_CONTEXT_SKINMENU_SNAPTOEDGES 4028 -#define ID_CONTEXT_SKINMENU_CLICKTHROUGH 4029 -#define ID_CONTEXT_SKINMENU_EDITSKIN 4030 -#define ID_CONTEXT_SKINMENU_VERYTOPMOST 4031 -#define ID_CONTEXT_SKINMENU_ONDESKTOP 4032 -#define ID_CONTEXT_SHOW_HELP 4034 -#define ID_CONTEXT_SHOWLOGFILE 4035 -#define ID_CONTEXT_SKINMENU_TRANSPARENCY_FADEIN 4037 -#define ID_CONTEXT_SKINMENU_TRANSPARENCY_FADEOUT 4038 -#define ID_CONTEXT_SKINMENU_KEEPONSCREEN 4039 -#define ID_CONTEXT_SKINMENU_FROMRIGHT 4040 -#define ID_CONTEXT_SKINMENU_FROMBOTTOM 4041 -#define ID_CONTEXT_SKINMENU_XPERCENTAGE 4042 -#define ID_CONTEXT_SKINMENU_YPERCENTAGE 4043 -#define ID_CONTEXT_OPENSKINSFOLDER 4044 -#define ID_CONTEXT_SKINMENU_OPENSKINSFOLDER 4045 -#define ID_CONTEXT_MANAGETHEMES 4046 -#define ID_CONTEXT_MANAGESKINS 4047 -#define ID_CONTEXT_SKINMENU_MONITOR_PRIMARY 4048 -#define ID_CONTEXT_SKINMENU_MONITOR_AUTOSELECT 4049 -#define ID_CONTEXT_NEW_VERSION 4050 -#define ID_CONTEXT_STARTLOG 4051 -#define ID_CONTEXT_STOPLOG 4052 -#define ID_CONTEXT_DEBUGLOG 4053 -#define ID_CONTEXT_DELETELOGFILE 4054 +#define IDC_STATIC -1 +#define IDI_TRAY 100 +#define IDI_WINDOW 101 +#define IDR_CONTEXT_MENU 102 +#define IDR_SKIN_MENU 103 +#define IDR_MANAGESKINS_MENU 104 +#define IDD_ABOUT_DIALOG 105 +#define IDD_ABOUTLOG_DIALOG 106 +#define IDD_ABOUTMEASURES_DIALOG 107 +#define IDD_ABOUTPLUGINS_DIALOG 108 +//#define IDD_ABOUTINFO_DIALOG 109 +#define IDD_MANAGE_DIALOG 110 +#define IDD_MANAGESKINS_DIALOG 111 +#define IDD_MANAGETHEMES_DIALOG 112 +#define IDD_MANAGESETTINGS_DIALOG 113 -#define ID_CONFIG_EDIT 30000 -#define ID_CONFIG_FIRST 30001 -#define ID_CONFIG_LAST 40000 -#define ID_THEME_FIRST 40001 -#define ID_THEME_LAST 43000 -#define ID_MONITOR_FIRST 43001 -#define ID_MONITOR_LAST 44000 +#define IDC_ABOUT_TAB 1000 +#define IDC_ABOUT_VERSION_TEXT 1001 +#define IDC_ABOUTLOG_ITEMS_LISTVIEW 1002 +#define IDC_ABOUTLOG_ERROR_CHECKBOX 1003 +#define IDC_ABOUTLOG_WARNING_CHECKBOX 1004 +#define IDC_ABOUTLOG_NOTICE_CHECKBOX 1005 +#define IDC_ABOUTLOG_DEBUG_CHECKBOX 1006 +#define IDC_ABOUTMEASURES_ITEMS_LISTBOX 1007 +#define IDC_ABOUTMEASURES_ITEMS_LISTVIEW 1008 +#define IDC_ABOUTPLUGINS_ITEMS_LISTVIEW 1009 -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 110 -#define _APS_NEXT_COMMAND_VALUE 4040 -#define _APS_NEXT_CONTROL_VALUE 1013 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif +#define IDC_MANAGE_TAB 1017 +#define IDC_REFRESHALL_BUTTON 1018 +#define IDC_EDITSETTINGS_BUTTON 1019 +#define IDC_OPENLOG_BUTTON 1020 +#define IDC_MANAGESKINS_ACTIVESKINS_BUTTON 1021 +#define IDC_MANAGESKINS_SKINS_TREEVIEW 1022 +#define IDC_MANAGESKINS_FILE_TEXT 1023 +#define IDC_MANAGESKINS_CONFIG_TEXT 1024 +#define IDC_MANAGESKINS_LOAD_BUTTON 4056 // ID_CONTEXT_MANAGESKINSMENU_LOAD +#define IDC_MANAGESKINS_REFRESH_BUTTON 4057 // ID_CONTEXT_MANAGESKINSMENU_REFRESH +#define IDC_MANAGESKINS_EDIT_BUTTON 4058 // ID_CONTEXT_MANAGESKINSMENU_EDIT +#define IDC_MANAGESKINS_AUTHOR_TEXT 1025 +#define IDC_MANAGESKINS_VERSION_TEXT 1026 +#define IDC_MANAGESKINS_LICENSE_TEXT 1027 +#define IDC_MANAGESKINS_DESCRIPTION_TEXT 1028 +#define IDC_MANAGESKINS_ADDMETADATA_LINK 1029 +#define IDC_MANAGESKINS_X_TEXT 1030 +#define IDC_MANAGESKINS_Y_TEXT 1031 +#define IDC_MANAGESKINS_ZPOSITION_COMBOBOX 1032 +#define IDC_MANAGESKINS_LOADORDER_TEXT 1033 +#define IDC_MANAGESKINS_ONHOVER_COMBOBOX 1034 +#define IDC_MANAGESKINS_TRANSPARENCY_COMBOBOX 1035 +#define IDC_MANAGESKINS_DISPLAYMONITOR_BUTTON 1036 +#define IDC_MANAGESKINS_DRAGGABLE_CHECKBOX 1037 +#define IDC_MANAGESKINS_CLICKTHROUGH_CHECKBOX 1038 +#define IDC_MANAGESKINS_KEEPONSCREEN_CHECKBOX 1039 +#define IDC_MANAGESKINS_SAVEPOSITION_CHECKBOX 1040 +#define IDC_MANAGESKINS_SNAPTOEDGES_CHECKBOX 1041 +#define IDC_MANAGETHEMES_LIST 1042 +#define IDC_MANAGETHEMES_LOAD_BUTTON 1043 +#define IDC_MANAGETHEMES_DELETE_BUTTON 1044 +#define IDC_MANAGETHEMES_EDIT_BUTTON 1045 +#define IDC_MANAGETHEMES_SAVE_BUTTON 1046 +#define IDC_MANAGETHEMES_EMPTYTHEME_CHECKBOX 1047 +#define IDC_MANAGETHEMES_UNUSEDSKINS_CHECKBOX 1048 +#define IDC_MANAGETHEMES_WALLPAPER_CHECKBOX 1049 +#define IDC_MANAGETHEMES_NAME_TEXT 1050 +#define IDC_MANAGETHEMES_BACKUP_BUTTON 1051 +#define IDC_MANAGESETTINGS_CHECKUPDATES_CHECKBOX 1052 +#define IDC_MANAGESETTINGS_LOCKSKINS_CHECKBOX 1053 +#define IDC_MANAGESETTINGS_RESETSTATISTICS_BUTTON 1054 +#define IDC_MANAGESETTINGS_LOGTOFILE_CHECKBOX 1055 +#define IDC_MANAGESETTINGS_VERBOSELOGGING_CHECKBOX 1056 +#define IDC_MANAGESETTINGS_SHOWLOGFILE_BUTTON 1057 +#define IDC_MANAGESETTINGS_DELETELOGFILE_BUTTON 1058 +#define IDC_MANAGESETTINGS_VERSION_LABEL 1059 + +#define ID_CONTEXT_REFRESH 4001 +#define ID_CONTEXT_QUIT 4002 +#define ID_CONTEXT_DISABLEDRAG 4003 +#define ID_CONTEXT_MANAGE 4004 +#define ID_CONTEXT_ABOUT 4005 +#define ID_CONTEXT_CONFIGS_DEFAULT 4006 +#define ID_CONTEXT_EDITCONFIG 4008 +#define ID_CONTEXT_CLOSESKIN 4009 +#define ID_CONTEXT_SKINMENU_TOPMOST 4010 +#define ID_CONTEXT_SKINMENU_NORMAL 4011 +#define ID_CONTEXT_SKINMENU_BOTTOM 4012 +#define ID_CONTEXT_SKINMENU_TRANSPARENCY_0 4014 +#define ID_CONTEXT_SKINMENU_TRANSPARENCY_10 4015 +#define ID_CONTEXT_SKINMENU_TRANSPARENCY_20 4016 +#define ID_CONTEXT_SKINMENU_TRANSPARENCY_30 4017 +#define ID_CONTEXT_SKINMENU_TRANSPARENCY_40 4018 +#define ID_CONTEXT_SKINMENU_TRANSPARENCY_50 4019 +#define ID_CONTEXT_SKINMENU_TRANSPARENCY_60 4020 +#define ID_CONTEXT_SKINMENU_TRANSPARENCY_70 4021 +#define ID_CONTEXT_SKINMENU_TRANSPARENCY_80 4022 +#define ID_CONTEXT_SKINMENU_TRANSPARENCY_90 4023 +#define ID_CONTEXT_SKINMENU_REFRESH 4024 +#define ID_CONTEXT_SKINMENU_HIDEONMOUSE 4025 +#define ID_CONTEXT_SKINMENU_DRAGGABLE 4026 +#define ID_CONTEXT_SKINMENU_REMEMBERPOSITION 4027 +#define ID_CONTEXT_SKINMENU_SNAPTOEDGES 4028 +#define ID_CONTEXT_SKINMENU_CLICKTHROUGH 4029 +#define ID_CONTEXT_SKINMENU_EDITSKIN 4030 +#define ID_CONTEXT_SKINMENU_VERYTOPMOST 4031 +#define ID_CONTEXT_SKINMENU_ONDESKTOP 4032 +#define ID_CONTEXT_SHOW_HELP 4034 +#define ID_CONTEXT_SHOWLOGFILE 4035 +#define ID_CONTEXT_SKINMENU_TRANSPARENCY_FADEIN 4037 +#define ID_CONTEXT_SKINMENU_TRANSPARENCY_FADEOUT 4038 +#define ID_CONTEXT_SKINMENU_KEEPONSCREEN 4039 +#define ID_CONTEXT_SKINMENU_FROMRIGHT 4040 +#define ID_CONTEXT_SKINMENU_FROMBOTTOM 4041 +#define ID_CONTEXT_SKINMENU_XPERCENTAGE 4042 +#define ID_CONTEXT_SKINMENU_YPERCENTAGE 4043 +#define ID_CONTEXT_OPENSKINSFOLDER 4044 +#define ID_CONTEXT_SKINMENU_OPENSKINSFOLDER 4045 +#define ID_CONTEXT_SKINMENU_MONITOR_PRIMARY 4046 +#define ID_CONTEXT_SKINMENU_MONITOR_AUTOSELECT 4047 +#define ID_CONTEXT_NEW_VERSION 4048 +#define ID_CONTEXT_STARTLOG 4049 +#define ID_CONTEXT_STOPLOG 4050 +#define ID_CONTEXT_DEBUGLOG 4051 +#define ID_CONTEXT_DELETELOGFILE 4052 +#define ID_CONTEXT_SKINMENU_MANAGESKIN 4053 +#define ID_CONTEXT_MANAGESKINSMENU_EXPAND 4054 +#define ID_CONTEXT_MANAGESKINSMENU_OPENFOLDER 4055 +#define ID_CONTEXT_MANAGESKINSMENU_LOAD 4056 +#define ID_CONTEXT_MANAGESKINSMENU_REFRESH 4057 +#define ID_CONTEXT_MANAGESKINSMENU_EDIT 4058 + +#define ID_CONFIG_EDIT 30000 +#define ID_CONFIG_FIRST 30001 +#define ID_CONFIG_LAST 40000 +#define ID_THEME_FIRST 40001 +#define ID_THEME_LAST 43000 +#define ID_MONITOR_FIRST 43001 +#define ID_MONITOR_LAST 44000