mirror of
https://github.com/chibicitiberiu/rainmeter-studio.git
synced 2024-02-24 04:33:31 +00:00
- Added !RainmeterWriteKeyValue. (based on MattKing's code)
!RainmeterWriteKeyValue "Section" "Key" "Value" ("FileSpec"), where "FileSpec" is an optional parameter. If FileSpec is not present, the change is automatically done in the currently running skin file. If the bang is executed from command line, FileSpec is required. - Some improvements of MouseOver/Leave detection. - Fixed the issue that window dragging brings on MouseLeave if "Show window contents while dragging" is not set. - Fixed the issue that window dragging can't be begun by dragging the Button. - Fixed the issue that a reaction of the upper Button penetrates to the lower Buttons or the other window.
This commit is contained in:
parent
d92f4f939d
commit
64888434c9
@ -78,15 +78,11 @@ void CConfigParser::Initialize(LPCTSTR filename, CRainmeter* pRainmeter, CMeterW
|
|||||||
// Set the SCREENAREA/WORKAREA variables for present monitor
|
// Set the SCREENAREA/WORKAREA variables for present monitor
|
||||||
SetAutoSelectedMonitorVariables(meterWindow);
|
SetAutoSelectedMonitorVariables(meterWindow);
|
||||||
|
|
||||||
if (meterWindow)
|
std::vector<std::wstring> iniFileMappings;
|
||||||
{
|
CSystem::GetIniFileMappingList(iniFileMappings);
|
||||||
GetIniFileMappingList();
|
|
||||||
}
|
|
||||||
|
|
||||||
ReadIniFile(m_Filename);
|
ReadIniFile(iniFileMappings, m_Filename);
|
||||||
ReadVariables();
|
ReadVariables();
|
||||||
|
|
||||||
m_IniFileMappings.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -869,7 +865,7 @@ Color CConfigParser::ParseColor(LPCTSTR string)
|
|||||||
**
|
**
|
||||||
** \param iniFile The ini file to be read.
|
** \param iniFile The ini file to be read.
|
||||||
*/
|
*/
|
||||||
void CConfigParser::ReadIniFile(const std::wstring& iniFile, int depth)
|
void CConfigParser::ReadIniFile(const std::vector<std::wstring>& iniFileMappings, const std::wstring& iniFile, int depth)
|
||||||
{
|
{
|
||||||
if (depth > 100) // Is 100 enough to assume the include loop never ends?
|
if (depth > 100) // Is 100 enough to assume the include loop never ends?
|
||||||
{
|
{
|
||||||
@ -885,24 +881,14 @@ void CConfigParser::ReadIniFile(const std::wstring& iniFile, int depth)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Avoid "IniFileMapping"
|
// Avoid "IniFileMapping"
|
||||||
std::wstring iniRead = GetAlternateFileName(iniFile);
|
std::wstring iniRead = CSystem::GetTemporaryFile(iniFileMappings, iniFile);
|
||||||
bool alternate = false;
|
bool temporary = (!iniRead.empty() && iniRead != L"<>");
|
||||||
|
|
||||||
if (!iniRead.empty())
|
if (temporary)
|
||||||
{
|
{
|
||||||
// Copy iniFile to temporary directory
|
if (CRainmeter::GetDebug()) DebugLog(L"Reading file: %s (Temp: %s)", iniFile.c_str(), iniRead.c_str());
|
||||||
if (CRainmeter::CopyFiles(iniFile, iniRead))
|
|
||||||
{
|
|
||||||
if (CRainmeter::GetDebug()) DebugLog(L"Reading file: %s (Alternate: %s)", iniFile.c_str(), iniRead.c_str());
|
|
||||||
alternate = true;
|
|
||||||
}
|
|
||||||
else // copy failed
|
|
||||||
{
|
|
||||||
DeleteFile(iniRead.c_str());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
if (!alternate)
|
|
||||||
{
|
{
|
||||||
if (CRainmeter::GetDebug()) DebugLog(L"Reading file: %s", iniFile.c_str());
|
if (CRainmeter::GetDebug()) DebugLog(L"Reading file: %s", iniFile.c_str());
|
||||||
iniRead = iniFile;
|
iniRead = iniFile;
|
||||||
@ -920,7 +906,7 @@ void CConfigParser::ReadIniFile(const std::wstring& iniFile, int depth)
|
|||||||
if (res == 0) // File not found
|
if (res == 0) // File not found
|
||||||
{
|
{
|
||||||
delete [] items;
|
delete [] items;
|
||||||
if (alternate) DeleteFile(iniRead.c_str());
|
if (temporary) CSystem::RemoveFile(iniRead);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (res < size - 2) break; // Fits in the buffer
|
if (res < size - 2) break; // Fits in the buffer
|
||||||
@ -991,7 +977,7 @@ void CConfigParser::ReadIniFile(const std::wstring& iniFile, int depth)
|
|||||||
// It's a relative path so add the current path as a prefix
|
// It's a relative path so add the current path as a prefix
|
||||||
strIncludeFile = CRainmeter::ExtractPath(iniFile) + strIncludeFile;
|
strIncludeFile = CRainmeter::ExtractPath(iniFile) + strIncludeFile;
|
||||||
}
|
}
|
||||||
ReadIniFile(strIncludeFile, depth + 1);
|
ReadIniFile(iniFileMappings, strIncludeFile, depth + 1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1003,7 +989,7 @@ void CConfigParser::ReadIniFile(const std::wstring& iniFile, int depth)
|
|||||||
}
|
}
|
||||||
delete [] buffer;
|
delete [] buffer;
|
||||||
delete [] items;
|
delete [] items;
|
||||||
if (alternate) DeleteFile(iniRead.c_str());
|
if (temporary) CSystem::RemoveFile(iniRead);
|
||||||
}
|
}
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
@ -1086,83 +1072,3 @@ std::vector<std::wstring> CConfigParser::GetKeys(const std::wstring& strSection)
|
|||||||
|
|
||||||
return std::vector<std::wstring>();
|
return std::vector<std::wstring>();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CConfigParser::GetIniFileMappingList()
|
|
||||||
{
|
|
||||||
HKEY hKey;
|
|
||||||
LONG ret;
|
|
||||||
|
|
||||||
ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\IniFileMapping", 0, KEY_ENUMERATE_SUB_KEYS, &hKey);
|
|
||||||
if (ret == ERROR_SUCCESS)
|
|
||||||
{
|
|
||||||
WCHAR buffer[MAX_PATH];
|
|
||||||
DWORD index = 0, cch = MAX_PATH;
|
|
||||||
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
ret = RegEnumKeyEx(hKey, index++, buffer, &cch, NULL, NULL, NULL, NULL);
|
|
||||||
if (ret == ERROR_NO_MORE_ITEMS) break;
|
|
||||||
|
|
||||||
if (ret == ERROR_SUCCESS)
|
|
||||||
{
|
|
||||||
m_IniFileMappings.push_back(buffer);
|
|
||||||
}
|
|
||||||
cch = MAX_PATH;
|
|
||||||
}
|
|
||||||
RegCloseKey(hKey);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::wstring CConfigParser::GetAlternateFileName(const std::wstring &iniFile)
|
|
||||||
{
|
|
||||||
std::wstring alternate;
|
|
||||||
|
|
||||||
if (!m_IniFileMappings.empty())
|
|
||||||
{
|
|
||||||
std::wstring::size_type pos = iniFile.find_last_of(L'\\');
|
|
||||||
std::wstring filename;
|
|
||||||
|
|
||||||
if (pos != std::wstring::npos)
|
|
||||||
{
|
|
||||||
filename = iniFile.substr(pos + 1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
filename = iniFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < m_IniFileMappings.size(); ++i)
|
|
||||||
{
|
|
||||||
if (wcsicmp(m_IniFileMappings[i].c_str(), filename.c_str()) == 0)
|
|
||||||
{
|
|
||||||
WCHAR buffer[4096];
|
|
||||||
|
|
||||||
GetTempPath(4096, buffer);
|
|
||||||
alternate = buffer;
|
|
||||||
if (GetTempFileName(alternate.c_str(), L"cfg", 0, buffer) != 0)
|
|
||||||
{
|
|
||||||
alternate = buffer;
|
|
||||||
|
|
||||||
std::wstring tmp = GetAlternateFileName(alternate);
|
|
||||||
if (tmp.empty())
|
|
||||||
{
|
|
||||||
return alternate;
|
|
||||||
}
|
|
||||||
else // alternate is reserved
|
|
||||||
{
|
|
||||||
DeleteFile(alternate.c_str());
|
|
||||||
return tmp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else // failed
|
|
||||||
{
|
|
||||||
DebugLog(L"Unable to create a temporary file to: %s", alternate.c_str());
|
|
||||||
alternate.clear();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return alternate;
|
|
||||||
}
|
|
||||||
|
@ -71,16 +71,13 @@ private:
|
|||||||
bool ReplaceVariables(std::wstring& result);
|
bool ReplaceVariables(std::wstring& result);
|
||||||
bool ReplaceMeasures(std::wstring& result);
|
bool ReplaceMeasures(std::wstring& result);
|
||||||
|
|
||||||
void ReadIniFile(const std::wstring& strFileName, int depth = 0);
|
void ReadIniFile(const std::vector<std::wstring>& iniFileMappings, const std::wstring& strFileName, int depth = 0);
|
||||||
void SetValue(const std::wstring& strSection, const std::wstring& strKey, const std::wstring& strValue);
|
void SetValue(const std::wstring& strSection, const std::wstring& strKey, const std::wstring& strValue);
|
||||||
const std::wstring& GetValue(const std::wstring& strSection, const std::wstring& strKey, const std::wstring& strDefault);
|
const std::wstring& GetValue(const std::wstring& strSection, const std::wstring& strKey, const std::wstring& strDefault);
|
||||||
std::vector<std::wstring> GetKeys(const std::wstring& strSection);
|
std::vector<std::wstring> GetKeys(const std::wstring& strSection);
|
||||||
|
|
||||||
void SetAutoSelectedMonitorVariables(CMeterWindow* meterWindow);
|
void SetAutoSelectedMonitorVariables(CMeterWindow* meterWindow);
|
||||||
|
|
||||||
void GetIniFileMappingList();
|
|
||||||
std::wstring GetAlternateFileName(const std::wstring& iniFile);
|
|
||||||
|
|
||||||
static void SetMultiMonitorVariables(bool reset);
|
static void SetMultiMonitorVariables(bool reset);
|
||||||
static void SetMonitorVariable(const std::wstring& strVariable, const std::wstring& strValue);
|
static void SetMonitorVariable(const std::wstring& strVariable, const std::wstring& strValue);
|
||||||
|
|
||||||
@ -96,8 +93,6 @@ private:
|
|||||||
stdext::hash_map<std::wstring, std::vector<std::wstring> > m_Keys;
|
stdext::hash_map<std::wstring, std::vector<std::wstring> > m_Keys;
|
||||||
stdext::hash_map<std::wstring, std::wstring> m_Values;
|
stdext::hash_map<std::wstring, std::wstring> m_Values;
|
||||||
|
|
||||||
std::vector<std::wstring> m_IniFileMappings;
|
|
||||||
|
|
||||||
static std::map<std::wstring, std::wstring> c_MonitorVariables;
|
static std::map<std::wstring, std::wstring> c_MonitorVariables;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@ CMeterButton::CMeterButton(CMeterWindow* meterWindow) : CMeter(meterWindow)
|
|||||||
{
|
{
|
||||||
for (int i = 0; i < BUTTON_FRAMES; ++i)
|
for (int i = 0; i < BUTTON_FRAMES; ++i)
|
||||||
{
|
{
|
||||||
m_Bitmaps[i] = NULL;;
|
m_Bitmaps[i] = NULL;
|
||||||
}
|
}
|
||||||
m_Bitmap = NULL;
|
m_Bitmap = NULL;
|
||||||
m_State = BUTTON_STATE_NORMAL;
|
m_State = BUTTON_STATE_NORMAL;
|
||||||
@ -235,25 +235,59 @@ void CMeterButton::BindMeasure(std::list<CMeasure*>& measures)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CMeterButton::MouseUp(POINT pos, CMeterWindow* window)
|
/*
|
||||||
|
** HitTest2
|
||||||
|
**
|
||||||
|
** Checks if the given point is inside the button.
|
||||||
|
**
|
||||||
|
*/
|
||||||
|
bool CMeterButton::HitTest2(int px, int py, bool checkAlpha)
|
||||||
{
|
{
|
||||||
int x = GetX();
|
int x = GetX();
|
||||||
int y = GetY();
|
int y = GetY();
|
||||||
|
|
||||||
|
if (m_MouseOver &&
|
||||||
|
px >= x && px < x + m_W &&
|
||||||
|
py >= y && py < y + m_H)
|
||||||
|
{
|
||||||
|
if (checkAlpha)
|
||||||
|
{
|
||||||
|
if (m_SolidColor.GetA() > 0 || m_SolidColor2.GetA() > 0)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check transparent pixels
|
||||||
|
if (m_Bitmap)
|
||||||
|
{
|
||||||
|
Color color;
|
||||||
|
Status status = m_Bitmap->GetPixel(px - x + m_W * m_State, py - y, &color);
|
||||||
|
if (status != Ok || color.GetA() > 0)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CMeterButton::MouseUp(POINT pos, CMeterWindow* window)
|
||||||
|
{
|
||||||
if (m_State == BUTTON_STATE_DOWN)
|
if (m_State == BUTTON_STATE_DOWN)
|
||||||
{
|
{
|
||||||
if (m_Clicked &&
|
if (window && m_Clicked && HitTest2(pos.x, pos.y, true))
|
||||||
pos.x >= x && pos.x < x + m_W &&
|
|
||||||
pos.y >= y && pos.y < y + m_H)
|
|
||||||
{
|
{
|
||||||
Color color;
|
// Do a delayed execute or ortherwise !RainmeterRefresh crashes
|
||||||
m_Bitmap->GetPixel(pos.x - x + m_W * m_State, pos.y - y, &color);
|
PostMessage(window->GetWindow(), WM_DELAYED_EXECUTE, (WPARAM)NULL, (LPARAM)m_Command.c_str());
|
||||||
|
|
||||||
if (color.GetA() > 0)
|
|
||||||
{
|
|
||||||
// Do a delayed execute or ortherwise !RainmeterRefresh crashes
|
|
||||||
PostMessage(window->GetWindow(), WM_DELAYED_EXECUTE, (WPARAM)NULL, (LPARAM)m_Command.c_str());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
m_State = BUTTON_STATE_NORMAL;
|
m_State = BUTTON_STATE_NORMAL;
|
||||||
m_Clicked = false;
|
m_Clicked = false;
|
||||||
@ -266,45 +300,25 @@ bool CMeterButton::MouseUp(POINT pos, CMeterWindow* window)
|
|||||||
|
|
||||||
bool CMeterButton::MouseDown(POINT pos)
|
bool CMeterButton::MouseDown(POINT pos)
|
||||||
{
|
{
|
||||||
int x = GetX();
|
if (HitTest2(pos.x, pos.y, true))
|
||||||
int y = GetY();
|
|
||||||
|
|
||||||
if (pos.x >= x && pos.x < x + m_W &&
|
|
||||||
pos.y >= y && pos.y < y + m_H)
|
|
||||||
{
|
{
|
||||||
Color color;
|
m_State = BUTTON_STATE_DOWN;
|
||||||
m_Bitmap->GetPixel(pos.x - x + m_W * m_State, pos.y - y, &color);
|
m_Clicked = true;
|
||||||
|
return true;
|
||||||
if (color.GetA() > 0)
|
|
||||||
{
|
|
||||||
m_State = BUTTON_STATE_DOWN;
|
|
||||||
m_Clicked = true;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CMeterButton::MouseMove(POINT pos)
|
bool CMeterButton::MouseMove(POINT pos)
|
||||||
{
|
{
|
||||||
int x = GetX();
|
|
||||||
int y = GetY();
|
|
||||||
|
|
||||||
if (m_Clicked == true)
|
if (m_Clicked == true)
|
||||||
{
|
{
|
||||||
if (pos.x >= x && pos.x < x + m_W &&
|
if (HitTest2(pos.x, pos.y, true))
|
||||||
pos.y >= y && pos.y < y + m_H)
|
|
||||||
{
|
{
|
||||||
Color color;
|
if (m_State == BUTTON_STATE_NORMAL)
|
||||||
m_Bitmap->GetPixel(pos.x - x + m_W * m_State, pos.y - y, &color);
|
|
||||||
|
|
||||||
if (color.GetA() > 0)
|
|
||||||
{
|
{
|
||||||
if (m_State == BUTTON_STATE_NORMAL)
|
m_State = BUTTON_STATE_DOWN;
|
||||||
{
|
return true;
|
||||||
m_State = BUTTON_STATE_DOWN;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -324,8 +338,7 @@ bool CMeterButton::MouseMove(POINT pos)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (pos.x >= x && pos.x < x + m_W &&
|
if (HitTest2(pos.x, pos.y, false))
|
||||||
pos.y >= y && pos.y < y + m_H)
|
|
||||||
{
|
{
|
||||||
if (m_State == BUTTON_STATE_NORMAL)
|
if (m_State == BUTTON_STATE_NORMAL)
|
||||||
{
|
{
|
||||||
|
@ -41,6 +41,8 @@ public:
|
|||||||
bool MouseDown(POINT pos);
|
bool MouseDown(POINT pos);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool HitTest2(int px, int py, bool checkAlpha);
|
||||||
|
|
||||||
Gdiplus::Bitmap* m_Bitmap; // The bitmap
|
Gdiplus::Bitmap* m_Bitmap; // The bitmap
|
||||||
Gdiplus::CachedBitmap* m_Bitmaps[BUTTON_FRAMES]; // The cached bitmaps
|
Gdiplus::CachedBitmap* m_Bitmaps[BUTTON_FRAMES]; // The cached bitmaps
|
||||||
std::wstring m_ImageName; // Name of the image
|
std::wstring m_ImageName; // Name of the image
|
||||||
|
@ -323,6 +323,9 @@ void CMeterWindow::Refresh(bool init, bool all)
|
|||||||
KillTimer(m_Window, FADETIMER);
|
KillTimer(m_Window, FADETIMER);
|
||||||
KillTimer(m_Window, TRANSITIONTIMER);
|
KillTimer(m_Window, TRANSITIONTIMER);
|
||||||
|
|
||||||
|
m_MouseOver = false;
|
||||||
|
SetMouseLeaveEvent(true);
|
||||||
|
|
||||||
std::list<CMeasure*>::iterator i = m_Measures.begin();
|
std::list<CMeasure*>::iterator i = m_Measures.begin();
|
||||||
for( ; i != m_Measures.end(); ++i)
|
for( ; i != m_Measures.end(); ++i)
|
||||||
{
|
{
|
||||||
@ -417,6 +420,52 @@ void CMeterWindow::Refresh(bool init, bool all)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CMeterWindow::SetMouseLeaveEvent(bool cancel)
|
||||||
|
{
|
||||||
|
if (!cancel && !m_MouseOver) return;
|
||||||
|
|
||||||
|
// Check whether the mouse event is set
|
||||||
|
TRACKMOUSEEVENT tme = {sizeof(TRACKMOUSEEVENT)};
|
||||||
|
tme.hwndTrack = m_Window;
|
||||||
|
tme.dwFlags = TME_QUERY;
|
||||||
|
|
||||||
|
if (TrackMouseEvent(&tme) != 0)
|
||||||
|
{
|
||||||
|
if (cancel)
|
||||||
|
{
|
||||||
|
if (tme.dwFlags == 0) return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (m_WindowDraggable)
|
||||||
|
{
|
||||||
|
if (tme.dwFlags == (TME_LEAVE | TME_NONCLIENT)) return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (tme.dwFlags == TME_LEAVE) return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tme.cbSize = sizeof(TRACKMOUSEEVENT);
|
||||||
|
tme.hwndTrack = m_Window;
|
||||||
|
|
||||||
|
// Cancel the mouse event set before
|
||||||
|
tme.dwFlags |= TME_CANCEL;
|
||||||
|
TrackMouseEvent(&tme);
|
||||||
|
|
||||||
|
if (cancel) return;
|
||||||
|
|
||||||
|
// Set the mouse event
|
||||||
|
tme.dwFlags = TME_LEAVE;
|
||||||
|
if (m_WindowDraggable)
|
||||||
|
{
|
||||||
|
tme.dwFlags |= TME_NONCLIENT;
|
||||||
|
}
|
||||||
|
TrackMouseEvent(&tme);
|
||||||
|
}
|
||||||
|
|
||||||
void CMeterWindow::MapCoordsToScreen(int& x, int& y, int w, int h)
|
void CMeterWindow::MapCoordsToScreen(int& x, int& y, int w, int h)
|
||||||
{
|
{
|
||||||
// Check that the window is inside the screen area
|
// Check that the window is inside the screen area
|
||||||
@ -522,7 +571,7 @@ void CMeterWindow::ChangeZPos(ZPOSITION zPos, bool all)
|
|||||||
if (CSystem::GetShowDesktop())
|
if (CSystem::GetShowDesktop())
|
||||||
{
|
{
|
||||||
// Insert after the tray window temporarily to keep order
|
// Insert after the tray window temporarily to keep order
|
||||||
winPos = Rainmeter->GetTrayWindow()->GetWindow();
|
winPos = m_Rainmeter->GetTrayWindow()->GetWindow();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -2547,40 +2596,35 @@ LRESULT CMeterWindow::OnTimer(WPARAM wParam, LPARAM lParam)
|
|||||||
}
|
}
|
||||||
else if(wParam == MOUSETIMER)
|
else if(wParam == MOUSETIMER)
|
||||||
{
|
{
|
||||||
ShowWindowIfAppropriate();
|
if (!m_Rainmeter->IsMenuActive() && !m_Dragging)
|
||||||
|
|
||||||
POINT pos;
|
|
||||||
GetCursorPos(&pos);
|
|
||||||
MapWindowPoints(NULL, m_Window, &pos, 1);
|
|
||||||
|
|
||||||
if (!m_MouseLeaveAction.empty())
|
|
||||||
{
|
{
|
||||||
// Check mouse leave actions
|
ShowWindowIfAppropriate();
|
||||||
DoAction(pos.x, pos.y, MOUSE_LEAVE, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_WindowZPosition == ZPOSITION_ONTOPMOST)
|
if (m_WindowZPosition == ZPOSITION_ONTOPMOST)
|
||||||
{
|
|
||||||
ChangeZPos(ZPOSITION_ONTOPMOST);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle buttons
|
|
||||||
bool redraw = false;
|
|
||||||
std::list<CMeter*>::const_iterator j = m_Meters.begin();
|
|
||||||
for( ; j != m_Meters.end(); ++j)
|
|
||||||
{
|
|
||||||
// Hidden meters are ignored
|
|
||||||
if ((*j)->IsHidden()) continue;
|
|
||||||
|
|
||||||
CMeterButton* button = dynamic_cast<CMeterButton*>(*j);
|
|
||||||
if (button)
|
|
||||||
{
|
{
|
||||||
redraw |= button->MouseMove(pos);
|
ChangeZPos(ZPOSITION_ONTOPMOST);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_MouseOver)
|
||||||
|
{
|
||||||
|
POINT pos;
|
||||||
|
GetCursorPos(&pos);
|
||||||
|
if (WindowFromPoint(pos) == m_Window)
|
||||||
|
{
|
||||||
|
SetMouseLeaveEvent(false);
|
||||||
|
|
||||||
|
MapWindowPoints(NULL, m_Window, &pos, 1);
|
||||||
|
DoMoveAction(pos.x, pos.y, MOUSE_OVER);
|
||||||
|
|
||||||
|
// Handle buttons
|
||||||
|
HandleButtons(pos, BUTTONPROC_MOVE, NULL, false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Run all mouse leave actions
|
||||||
|
OnMouseLeave(0, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (redraw)
|
|
||||||
{
|
|
||||||
Redraw();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(wParam == FADETIMER)
|
else if(wParam == FADETIMER)
|
||||||
@ -2684,29 +2728,14 @@ void CMeterWindow::ShowWindowIfAppropriate()
|
|||||||
{
|
{
|
||||||
bool inside = false;
|
bool inside = false;
|
||||||
bool keyDown = GetKeyState(VK_CONTROL) & 0x8000 || GetKeyState(VK_SHIFT) & 0x8000 || GetKeyState(VK_MENU) & 0x8000;
|
bool keyDown = GetKeyState(VK_CONTROL) & 0x8000 || GetKeyState(VK_SHIFT) & 0x8000 || GetKeyState(VK_MENU) & 0x8000;
|
||||||
|
|
||||||
POINT pos;
|
POINT pos;
|
||||||
RECT rect;
|
|
||||||
|
|
||||||
GetWindowRect(m_Window, &rect);
|
|
||||||
GetCursorPos(&pos);
|
GetCursorPos(&pos);
|
||||||
|
if (WindowFromPoint(pos) == m_Window)
|
||||||
if(rect.left <= pos.x && rect.right > pos.x &&
|
|
||||||
rect.top <= pos.y && rect.bottom > pos.y)
|
|
||||||
{
|
{
|
||||||
// Check transparent pixels
|
MapWindowPoints(NULL, m_Window, &pos, 1);
|
||||||
if (m_DoubleBuffer)
|
|
||||||
{
|
inside = HitTest(pos.x, pos.y);
|
||||||
Color color;
|
|
||||||
m_DoubleBuffer->GetPixel(pos.x - rect.left, pos.y - rect.top, &color);
|
|
||||||
if (color.GetA() != 0)
|
|
||||||
{
|
|
||||||
inside = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
inside = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_ClickThrough)
|
if (m_ClickThrough)
|
||||||
@ -2765,6 +2794,92 @@ void CMeterWindow::ShowWindowIfAppropriate()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** HitTest
|
||||||
|
**
|
||||||
|
** Checks if the given point is inside the window.
|
||||||
|
**
|
||||||
|
*/
|
||||||
|
bool CMeterWindow::HitTest(int x, int y)
|
||||||
|
{
|
||||||
|
if (x >= 0 && y >= 0 && x < m_WindowW && y < m_WindowH)
|
||||||
|
{
|
||||||
|
// Check transparent pixels
|
||||||
|
if (m_DoubleBuffer)
|
||||||
|
{
|
||||||
|
Color color;
|
||||||
|
Status status = m_DoubleBuffer->GetPixel(x, y, &color);
|
||||||
|
if (status != Ok || color.GetA() > 0)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** HandleButtons
|
||||||
|
**
|
||||||
|
** Handles all buttons and cursor.
|
||||||
|
** Note that meterWindow parameter is used if proc is BUTTONPROC_UP.
|
||||||
|
**
|
||||||
|
*/
|
||||||
|
void CMeterWindow::HandleButtons(POINT pos, BUTTONPROC proc, CMeterWindow* meterWindow, bool changeCursor)
|
||||||
|
{
|
||||||
|
bool redraw = false;
|
||||||
|
bool drawCursor = false;
|
||||||
|
|
||||||
|
std::list<CMeter*>::const_reverse_iterator j = m_Meters.rbegin();
|
||||||
|
for( ; j != m_Meters.rend(); ++j)
|
||||||
|
{
|
||||||
|
// Hidden meters are ignored
|
||||||
|
if ((*j)->IsHidden()) continue;
|
||||||
|
|
||||||
|
CMeterButton* button = dynamic_cast<CMeterButton*>(*j);
|
||||||
|
if (button)
|
||||||
|
{
|
||||||
|
switch (proc)
|
||||||
|
{
|
||||||
|
case BUTTONPROC_DOWN:
|
||||||
|
redraw |= button->MouseDown(pos);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BUTTONPROC_UP:
|
||||||
|
redraw |= button->MouseUp(pos, meterWindow);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BUTTONPROC_MOVE:
|
||||||
|
default:
|
||||||
|
redraw |= button->MouseMove(pos);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changeCursor && !drawCursor)
|
||||||
|
{
|
||||||
|
if ((*j)->HitTest(pos.x, pos.y) && (*j)->HasMouseActionCursor())
|
||||||
|
{
|
||||||
|
drawCursor = ((*j)->HasMouseAction() || button);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (redraw)
|
||||||
|
{
|
||||||
|
Redraw();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changeCursor)
|
||||||
|
{
|
||||||
|
SetCursor(LoadCursor(NULL, drawCursor ? IDC_HAND : IDC_ARROW));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** OnMouseMove
|
** OnMouseMove
|
||||||
@ -2823,44 +2938,35 @@ LRESULT CMeterWindow::OnMouseMove(WPARAM wParam, LPARAM lParam)
|
|||||||
if (m_Message == WM_NCMOUSEMOVE)
|
if (m_Message == WM_NCMOUSEMOVE)
|
||||||
{
|
{
|
||||||
// Map to local window
|
// Map to local window
|
||||||
MapWindowPoints(GetDesktopWindow(), m_Window, &pos, 1);
|
MapWindowPoints(NULL, m_Window, &pos, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
DoAction(pos.x, pos.y, MOUSE_OVER, false);
|
DoMoveAction(pos.x, pos.y, MOUSE_OVER);
|
||||||
|
|
||||||
// Handle buttons
|
// Handle buttons
|
||||||
bool redraw = false;
|
HandleButtons(pos, BUTTONPROC_MOVE, NULL, true);
|
||||||
bool drawCursor = false;
|
|
||||||
std::list<CMeter*>::const_iterator j = m_Meters.begin();
|
|
||||||
for( ; j != m_Meters.end(); ++j)
|
|
||||||
{
|
|
||||||
// Hidden meters are ignored
|
|
||||||
if ((*j)->IsHidden()) continue;
|
|
||||||
|
|
||||||
CMeterButton* button = dynamic_cast<CMeterButton*>(*j);
|
return 0;
|
||||||
if (button)
|
}
|
||||||
{
|
|
||||||
redraw |= button->MouseMove(pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
if((*j)->HitTest(pos.x, pos.y) && (*j)->HasMouseActionCursor())
|
/*
|
||||||
{
|
** OnMouseLeave
|
||||||
drawCursor |= ((*j)->HasMouseAction() || button);
|
**
|
||||||
}
|
** When we get WM_MOUSELEAVE messages, run all leave actions.
|
||||||
}
|
**
|
||||||
|
*/
|
||||||
|
LRESULT CMeterWindow::OnMouseLeave(WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
POINT pos;
|
||||||
|
GetCursorPos(&pos);
|
||||||
|
HWND hWnd = WindowFromPoint(pos);
|
||||||
|
if (!hWnd || (hWnd != m_Window && GetParent(hWnd) != m_Window)) // ignore tooltips
|
||||||
|
{
|
||||||
|
POINT pos = {SHRT_MIN, SHRT_MIN};
|
||||||
|
while (DoMoveAction(pos.x, pos.y, MOUSE_LEAVE)) ; // Leave all forcibly
|
||||||
|
|
||||||
if(drawCursor)
|
// Handle buttons
|
||||||
{
|
HandleButtons(pos, BUTTONPROC_MOVE, NULL, true);
|
||||||
SetCursor(LoadCursor(NULL, IDC_HAND));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SetCursor(LoadCursor(NULL, IDC_ARROW));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (redraw)
|
|
||||||
{
|
|
||||||
Redraw();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -2889,12 +2995,12 @@ LRESULT CMeterWindow::OnCommand(WPARAM wParam, LPARAM lParam)
|
|||||||
{
|
{
|
||||||
if(wParam == ID_CONTEXT_SKINMENU_EDITSKIN)
|
if(wParam == ID_CONTEXT_SKINMENU_EDITSKIN)
|
||||||
{
|
{
|
||||||
std::wstring command = Rainmeter->GetConfigEditor();
|
std::wstring command = m_Rainmeter->GetConfigEditor();
|
||||||
command += L" \"";
|
command += L" \"";
|
||||||
command += m_SkinPath + L"\\" + m_SkinName + L"\\" + m_SkinIniFile + L"\"";
|
command += m_SkinPath + L"\\" + m_SkinName + L"\\" + m_SkinIniFile + L"\"";
|
||||||
|
|
||||||
// If the skins are in the program folder start the editor as admin
|
// If the skins are in the program folder start the editor as admin
|
||||||
if (Rainmeter->GetPath() + L"Skins\\" == Rainmeter->GetSkinPath())
|
if (m_Rainmeter->GetPath() + L"Skins\\" == m_Rainmeter->GetSkinPath())
|
||||||
{
|
{
|
||||||
LSExecuteAsAdmin(NULL, command.c_str(), SW_SHOWNORMAL);
|
LSExecuteAsAdmin(NULL, command.c_str(), SW_SHOWNORMAL);
|
||||||
}
|
}
|
||||||
@ -3154,9 +3260,6 @@ LRESULT CMeterWindow::OnSysCommand(WPARAM wParam, LPARAM lParam)
|
|||||||
m_Dragging = true;
|
m_Dragging = true;
|
||||||
m_Dragged = false;
|
m_Dragged = false;
|
||||||
|
|
||||||
std::wstring startWindowX = m_WindowX;
|
|
||||||
std::wstring startWindowY = m_WindowY;
|
|
||||||
|
|
||||||
// Run the DefWindowProc so the dragging works
|
// Run the DefWindowProc so the dragging works
|
||||||
LRESULT result = DefWindowProc(m_Window, m_Message, wParam, lParam);
|
LRESULT result = DefWindowProc(m_Window, m_Message, wParam, lParam);
|
||||||
|
|
||||||
@ -3169,6 +3272,13 @@ LRESULT CMeterWindow::OnSysCommand(WPARAM wParam, LPARAM lParam)
|
|||||||
{
|
{
|
||||||
WriteConfig();
|
WriteConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
POINT pos;
|
||||||
|
GetCursorPos(&pos);
|
||||||
|
MapWindowPoints(NULL, m_Window, &pos, 1);
|
||||||
|
|
||||||
|
// Handle buttons
|
||||||
|
HandleButtons(pos, BUTTONPROC_UP, NULL, true); // redraw only
|
||||||
}
|
}
|
||||||
else // not dragged
|
else // not dragged
|
||||||
{
|
{
|
||||||
@ -3197,6 +3307,9 @@ LRESULT CMeterWindow::OnEnterSizeMove(WPARAM wParam, LPARAM lParam)
|
|||||||
if (m_Dragging)
|
if (m_Dragging)
|
||||||
{
|
{
|
||||||
m_Dragged = true; // Don't post the WM_NCLBUTTONUP message!
|
m_Dragged = true; // Don't post the WM_NCLBUTTONUP message!
|
||||||
|
|
||||||
|
// Set cursor to default
|
||||||
|
SetCursor(LoadCursor(NULL, IDC_ARROW));
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -3226,7 +3339,7 @@ LRESULT CMeterWindow::OnNcHitTest(WPARAM wParam, LPARAM lParam)
|
|||||||
POINT pos;
|
POINT pos;
|
||||||
pos.x = (SHORT)LOWORD(lParam);
|
pos.x = (SHORT)LOWORD(lParam);
|
||||||
pos.y = (SHORT)HIWORD(lParam);
|
pos.y = (SHORT)HIWORD(lParam);
|
||||||
MapWindowPoints(GetDesktopWindow(), m_Window, &pos, 1);
|
MapWindowPoints(NULL, m_Window, &pos, 1);
|
||||||
|
|
||||||
int x1 = m_DragMargins.GetLeft();
|
int x1 = m_DragMargins.GetLeft();
|
||||||
int x2 = m_WindowW - m_DragMargins.GetRight();
|
int x2 = m_WindowW - m_DragMargins.GetRight();
|
||||||
@ -3406,26 +3519,13 @@ LRESULT CMeterWindow::OnLeftButtonDown(WPARAM wParam, LPARAM lParam)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Handle buttons
|
// Handle buttons
|
||||||
bool redraw = false;
|
HandleButtons(pos, BUTTONPROC_DOWN, NULL, true);
|
||||||
std::list<CMeter*>::const_iterator j = m_Meters.begin();
|
|
||||||
for( ; j != m_Meters.end(); ++j)
|
|
||||||
{
|
|
||||||
// Hidden meters are ignored
|
|
||||||
if ((*j)->IsHidden()) continue;
|
|
||||||
|
|
||||||
CMeterButton* button = dynamic_cast<CMeterButton*>(*j);
|
if (!DoAction(pos.x, pos.y, MOUSE_LMB_DOWN, false) && m_WindowDraggable)
|
||||||
if (button)
|
{
|
||||||
{
|
// Cancel the mouse event beforehand
|
||||||
redraw |= button->MouseDown(pos);
|
SetMouseLeaveEvent(true);
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
if (redraw)
|
|
||||||
{
|
|
||||||
Redraw();
|
|
||||||
}
|
|
||||||
else if(!DoAction(pos.x, pos.y, MOUSE_LMB_DOWN, false) && m_WindowDraggable)
|
|
||||||
{
|
|
||||||
// Run the DefWindowProc so the dragging works
|
// Run the DefWindowProc so the dragging works
|
||||||
return DefWindowProc(m_Window, m_Message, wParam, lParam);
|
return DefWindowProc(m_Window, m_Message, wParam, lParam);
|
||||||
}
|
}
|
||||||
@ -3455,23 +3555,7 @@ LRESULT CMeterWindow::OnLeftButtonUp(WPARAM wParam, LPARAM lParam)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Handle buttons
|
// Handle buttons
|
||||||
bool redraw = false;
|
HandleButtons(pos, BUTTONPROC_UP, this, true);
|
||||||
std::list<CMeter*>::const_iterator j = m_Meters.begin();
|
|
||||||
for( ; j != m_Meters.end(); ++j)
|
|
||||||
{
|
|
||||||
// Hidden meters are ignored
|
|
||||||
if ((*j)->IsHidden()) continue;
|
|
||||||
|
|
||||||
CMeterButton* button = dynamic_cast<CMeterButton*>(*j);
|
|
||||||
if (button)
|
|
||||||
{
|
|
||||||
redraw |= button->MouseUp(pos, this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (redraw)
|
|
||||||
{
|
|
||||||
Redraw();
|
|
||||||
}
|
|
||||||
|
|
||||||
DoAction(pos.x, pos.y, MOUSE_LMB_UP, false);
|
DoAction(pos.x, pos.y, MOUSE_LMB_UP, false);
|
||||||
|
|
||||||
@ -3500,25 +3584,9 @@ LRESULT CMeterWindow::OnLeftButtonDoubleClick(WPARAM wParam, LPARAM lParam)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Handle buttons
|
// Handle buttons
|
||||||
bool redraw = false;
|
HandleButtons(pos, BUTTONPROC_DOWN, NULL, true);
|
||||||
std::list<CMeter*>::iterator j = m_Meters.begin();
|
|
||||||
for( ; j != m_Meters.end(); ++j)
|
|
||||||
{
|
|
||||||
// Hidden meters are ignored
|
|
||||||
if ((*j)->IsHidden()) continue;
|
|
||||||
|
|
||||||
CMeterButton* button = dynamic_cast<CMeterButton*>(*j);
|
if (!DoAction(pos.x, pos.y, MOUSE_LMB_DBLCLK, false))
|
||||||
if (button)
|
|
||||||
{
|
|
||||||
redraw |= button->MouseDown(pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
if (redraw)
|
|
||||||
{
|
|
||||||
Redraw();
|
|
||||||
}
|
|
||||||
else if (!DoAction(pos.x, pos.y, MOUSE_LMB_DBLCLK, false))
|
|
||||||
{
|
{
|
||||||
DoAction(pos.x, pos.y, MOUSE_LMB_DOWN, false);
|
DoAction(pos.x, pos.y, MOUSE_LMB_DOWN, false);
|
||||||
}
|
}
|
||||||
@ -3547,6 +3615,9 @@ LRESULT CMeterWindow::OnRightButtonDown(WPARAM wParam, LPARAM lParam)
|
|||||||
pos.y = pos.y - rect.top;
|
pos.y = pos.y - rect.top;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle buttons
|
||||||
|
HandleButtons(pos, BUTTONPROC_MOVE, NULL, true);
|
||||||
|
|
||||||
DoAction(pos.x, pos.y, MOUSE_RMB_DOWN, false);
|
DoAction(pos.x, pos.y, MOUSE_RMB_DOWN, false);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -3560,7 +3631,14 @@ LRESULT CMeterWindow::OnRightButtonDown(WPARAM wParam, LPARAM lParam)
|
|||||||
*/
|
*/
|
||||||
LRESULT CMeterWindow::OnRightButtonUp(WPARAM wParam, LPARAM lParam)
|
LRESULT CMeterWindow::OnRightButtonUp(WPARAM wParam, LPARAM lParam)
|
||||||
{
|
{
|
||||||
if (!DoAction((SHORT)LOWORD(lParam), (SHORT)HIWORD(lParam), MOUSE_RMB_UP, false))
|
POINT pos;
|
||||||
|
pos.x = (SHORT)LOWORD(lParam);
|
||||||
|
pos.y = (SHORT)HIWORD(lParam);
|
||||||
|
|
||||||
|
// Handle buttons
|
||||||
|
HandleButtons(pos, BUTTONPROC_MOVE, NULL, true);
|
||||||
|
|
||||||
|
if (!DoAction(pos.x, pos.y, MOUSE_RMB_UP, false))
|
||||||
{
|
{
|
||||||
// Run the DefWindowProc so the context menu works
|
// Run the DefWindowProc so the context menu works
|
||||||
return DefWindowProc(m_Window, WM_RBUTTONUP, wParam, lParam);
|
return DefWindowProc(m_Window, WM_RBUTTONUP, wParam, lParam);
|
||||||
@ -3590,6 +3668,9 @@ LRESULT CMeterWindow::OnRightButtonDoubleClick(WPARAM wParam, LPARAM lParam)
|
|||||||
pos.y = pos.y - rect.top;
|
pos.y = pos.y - rect.top;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle buttons
|
||||||
|
HandleButtons(pos, BUTTONPROC_MOVE, NULL, true);
|
||||||
|
|
||||||
if (!DoAction(pos.x, pos.y, MOUSE_RMB_DBLCLK, false))
|
if (!DoAction(pos.x, pos.y, MOUSE_RMB_DBLCLK, false))
|
||||||
{
|
{
|
||||||
DoAction(pos.x, pos.y, MOUSE_RMB_DOWN, false);
|
DoAction(pos.x, pos.y, MOUSE_RMB_DOWN, false);
|
||||||
@ -3619,6 +3700,9 @@ LRESULT CMeterWindow::OnMiddleButtonDown(WPARAM wParam, LPARAM lParam)
|
|||||||
pos.y = pos.y - rect.top;
|
pos.y = pos.y - rect.top;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle buttons
|
||||||
|
HandleButtons(pos, BUTTONPROC_MOVE, NULL, true);
|
||||||
|
|
||||||
DoAction(pos.x, pos.y, MOUSE_MMB_DOWN, false);
|
DoAction(pos.x, pos.y, MOUSE_MMB_DOWN, false);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -3645,6 +3729,9 @@ LRESULT CMeterWindow::OnMiddleButtonUp(WPARAM wParam, LPARAM lParam)
|
|||||||
pos.y = pos.y - rect.top;
|
pos.y = pos.y - rect.top;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle buttons
|
||||||
|
HandleButtons(pos, BUTTONPROC_MOVE, NULL, true);
|
||||||
|
|
||||||
DoAction(pos.x, pos.y, MOUSE_MMB_UP, false);
|
DoAction(pos.x, pos.y, MOUSE_MMB_UP, false);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -3671,6 +3758,9 @@ LRESULT CMeterWindow::OnMiddleButtonDoubleClick(WPARAM wParam, LPARAM lParam)
|
|||||||
pos.y = pos.y - rect.top;
|
pos.y = pos.y - rect.top;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle buttons
|
||||||
|
HandleButtons(pos, BUTTONPROC_MOVE, NULL, true);
|
||||||
|
|
||||||
if (!DoAction(pos.x, pos.y, MOUSE_MMB_DBLCLK, false))
|
if (!DoAction(pos.x, pos.y, MOUSE_MMB_DBLCLK, false))
|
||||||
{
|
{
|
||||||
DoAction(pos.x, pos.y, MOUSE_MMB_DOWN, false);
|
DoAction(pos.x, pos.y, MOUSE_MMB_DOWN, false);
|
||||||
@ -3687,26 +3777,39 @@ LRESULT CMeterWindow::OnMiddleButtonDoubleClick(WPARAM wParam, LPARAM lParam)
|
|||||||
*/
|
*/
|
||||||
LRESULT CMeterWindow::OnContextMenu(WPARAM wParam, LPARAM lParam)
|
LRESULT CMeterWindow::OnContextMenu(WPARAM wParam, LPARAM lParam)
|
||||||
{
|
{
|
||||||
int xPos = (SHORT)LOWORD(lParam);
|
POINT pos;
|
||||||
int yPos = (SHORT)HIWORD(lParam);
|
int x = (SHORT)LOWORD(lParam);
|
||||||
|
int y = (SHORT)HIWORD(lParam);
|
||||||
|
|
||||||
// Transform the point to client rect
|
|
||||||
int x = (INT)(SHORT)LOWORD(lParam);
|
|
||||||
int y = (INT)(SHORT)HIWORD(lParam);
|
|
||||||
RECT rect;
|
RECT rect;
|
||||||
GetWindowRect(m_Window, &rect);
|
GetWindowRect(m_Window, &rect);
|
||||||
x = x - rect.left;
|
|
||||||
y = y - rect.top;
|
|
||||||
|
|
||||||
// If RMB up or RMB down or double-click cause actions, do not show the menu!
|
if (x == -1 && y == -1) // WM_CONTEXTMENU is generated from the keyboard (Shift+F10/VK_APPS)
|
||||||
if (DoAction(x, y, MOUSE_RMB_UP, false) || DoAction(x, y, MOUSE_RMB_DOWN, true) || DoAction(x, y, MOUSE_RMB_DBLCLK, true))
|
|
||||||
{
|
{
|
||||||
return 0;
|
// Set menu position to (0,0) on the window
|
||||||
|
pos.x = rect.left;
|
||||||
|
pos.y = rect.top;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Transform the point to client rect
|
||||||
|
pos.x = x - rect.left;
|
||||||
|
pos.y = y - rect.top;
|
||||||
|
|
||||||
|
// Handle buttons
|
||||||
|
HandleButtons(pos, BUTTONPROC_MOVE, NULL, true);
|
||||||
|
|
||||||
|
// If RMB up or RMB down or double-click cause actions, do not show the menu!
|
||||||
|
if (DoAction(pos.x, pos.y, MOUSE_RMB_UP, false) || DoAction(pos.x, pos.y, MOUSE_RMB_DOWN, true) || DoAction(pos.x, pos.y, MOUSE_RMB_DBLCLK, true))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set menu position to cursor position
|
||||||
|
pos.x = x;
|
||||||
|
pos.y = y;
|
||||||
}
|
}
|
||||||
|
|
||||||
POINT pos;
|
|
||||||
pos.x = xPos;
|
|
||||||
pos.y = yPos;
|
|
||||||
m_Rainmeter->ShowContextMenu(pos, this);
|
m_Rainmeter->ShowContextMenu(pos, this);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -3722,8 +3825,8 @@ LRESULT CMeterWindow::OnContextMenu(WPARAM wParam, LPARAM lParam)
|
|||||||
bool CMeterWindow::DoAction(int x, int y, MOUSE mouse, bool test)
|
bool CMeterWindow::DoAction(int x, int y, MOUSE mouse, bool test)
|
||||||
{
|
{
|
||||||
// Check if the hitpoint was over some meter
|
// Check if the hitpoint was over some meter
|
||||||
std::list<CMeter*>::const_iterator j = m_Meters.begin();
|
std::list<CMeter*>::const_reverse_iterator j = m_Meters.rbegin();
|
||||||
for( ; j != m_Meters.end(); ++j)
|
for( ; j != m_Meters.rend(); ++j)
|
||||||
{
|
{
|
||||||
// Hidden meters are ignored
|
// Hidden meters are ignored
|
||||||
if ((*j)->IsHidden()) continue;
|
if ((*j)->IsHidden()) continue;
|
||||||
@ -3803,60 +3906,11 @@ bool CMeterWindow::DoAction(int x, int y, MOUSE mouse, bool test)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MOUSE_OVER:
|
|
||||||
if (!(*j)->IsMouseOver())
|
|
||||||
{
|
|
||||||
(*j)->SetMouseOver(true);
|
|
||||||
|
|
||||||
if (!((*j)->GetMouseOverAction().empty()))
|
|
||||||
{
|
|
||||||
m_MouseOver = true; // If the mouse is over a meter it's also over the main window
|
|
||||||
if (!test) m_Rainmeter->ExecuteCommand((*j)->GetMouseOverAction().c_str(), this);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (mouse == MOUSE_LEAVE || mouse == MOUSE_OVER)
|
|
||||||
{
|
|
||||||
if ((*j)->IsMouseOver())
|
|
||||||
{
|
|
||||||
(*j)->SetMouseOver(false);
|
|
||||||
|
|
||||||
if (!((*j)->GetMouseLeaveAction().empty()))
|
|
||||||
{
|
|
||||||
if (!test) m_Rainmeter->ExecuteCommand((*j)->GetMouseLeaveAction().c_str(), this);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool inside = false;
|
if (HitTest(x, y))
|
||||||
if (x >= 0 && y >= 0 && x < m_WindowW && y < m_WindowH)
|
|
||||||
{
|
|
||||||
// Check transparent pixels
|
|
||||||
if (m_DoubleBuffer)
|
|
||||||
{
|
|
||||||
Color color;
|
|
||||||
Status status = m_DoubleBuffer->GetPixel(x, y, &color);
|
|
||||||
if (status != Ok || color.GetA() > 0)
|
|
||||||
{
|
|
||||||
inside = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
inside = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (inside)
|
|
||||||
{
|
{
|
||||||
// If no meters caused actions, do the default actions
|
// If no meters caused actions, do the default actions
|
||||||
switch (mouse)
|
switch (mouse)
|
||||||
@ -3932,33 +3986,127 @@ bool CMeterWindow::DoAction(int x, int y, MOUSE mouse, bool test)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
case MOUSE_OVER:
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** DoMoveAction
|
||||||
|
**
|
||||||
|
** Executes the action if such are defined. Returns true, if meter/window which should be processed still may exist.
|
||||||
|
**
|
||||||
|
*/
|
||||||
|
bool CMeterWindow::DoMoveAction(int x, int y, MOUSE mouse, CMeter* upperMeter)
|
||||||
|
{
|
||||||
|
// Check if the hitpoint was over some meter
|
||||||
|
std::list<CMeter*>::const_reverse_iterator j = m_Meters.rbegin();
|
||||||
|
if (upperMeter)
|
||||||
|
{
|
||||||
|
for ( ; j != m_Meters.rend(); ++j)
|
||||||
|
{
|
||||||
|
if ((*j) == upperMeter)
|
||||||
|
{
|
||||||
|
++j;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for( ; j != m_Meters.rend(); ++j)
|
||||||
|
{
|
||||||
|
if (!(*j)->IsHidden() && !upperMeter && (*j)->HitTest(x, y))
|
||||||
|
{
|
||||||
|
if (mouse == MOUSE_OVER)
|
||||||
|
{
|
||||||
|
if (!m_MouseOver)
|
||||||
|
{
|
||||||
|
// If the mouse is over a meter it's also over the main window
|
||||||
|
//DebugLog(L"@Enter: %s", m_SkinName.c_str());
|
||||||
|
m_MouseOver = true;
|
||||||
|
SetMouseLeaveEvent(false);
|
||||||
|
|
||||||
|
if (!m_MouseOverAction.empty())
|
||||||
|
{
|
||||||
|
m_Rainmeter->ExecuteCommand(m_MouseOverAction.c_str(), this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(*j)->IsMouseOver())
|
||||||
|
{
|
||||||
|
if (!((*j)->GetMouseOverAction().empty()) ||
|
||||||
|
!((*j)->GetMouseLeaveAction().empty()) ||
|
||||||
|
dynamic_cast<CMeterButton*>(*j) != NULL)
|
||||||
|
{
|
||||||
|
while (DoMoveAction(x, y, MOUSE_LEAVE, (*j))) ; // Leave all lower meters
|
||||||
|
|
||||||
|
//DebugLog(L"MeterEnter: %s - [%s]", m_SkinName.c_str(), (*j)->GetName());
|
||||||
|
(*j)->SetMouseOver(true);
|
||||||
|
|
||||||
|
if (!((*j)->GetMouseOverAction().empty()))
|
||||||
|
{
|
||||||
|
m_Rainmeter->ExecuteCommand((*j)->GetMouseOverAction().c_str(), this);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((*j)->IsMouseOver())
|
||||||
|
{
|
||||||
|
//DebugLog(L"MeterLeave: %s - [%s]", m_SkinName.c_str(), (*j)->GetName());
|
||||||
|
(*j)->SetMouseOver(false);
|
||||||
|
|
||||||
|
if (!((*j)->GetMouseLeaveAction().empty()))
|
||||||
|
{
|
||||||
|
m_Rainmeter->ExecuteCommand((*j)->GetMouseLeaveAction().c_str(), this);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (upperMeter) return false;
|
||||||
|
|
||||||
|
if (HitTest(x, y))
|
||||||
|
{
|
||||||
|
// If no meters caused actions, do the default actions
|
||||||
|
if (mouse == MOUSE_OVER)
|
||||||
|
{
|
||||||
if (!m_MouseOver)
|
if (!m_MouseOver)
|
||||||
{
|
{
|
||||||
|
//DebugLog(L"Enter: %s", m_SkinName.c_str());
|
||||||
m_MouseOver = true;
|
m_MouseOver = true;
|
||||||
|
SetMouseLeaveEvent(false);
|
||||||
|
|
||||||
if (!m_MouseOverAction.empty())
|
if (!m_MouseOverAction.empty())
|
||||||
{
|
{
|
||||||
if (!test) m_Rainmeter->ExecuteCommand(m_MouseOverAction.c_str(), this);
|
m_Rainmeter->ExecuteCommand(m_MouseOverAction.c_str(), this);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Mouse leave happens when the mouse is outside the window
|
// Mouse leave happens when the mouse is outside the window
|
||||||
if (mouse == MOUSE_LEAVE)
|
if (m_MouseOver)
|
||||||
{
|
{
|
||||||
if (m_MouseOver)
|
//DebugLog(L"Leave: %s", m_SkinName.c_str());
|
||||||
|
m_MouseOver = false;
|
||||||
|
SetMouseLeaveEvent(true);
|
||||||
|
|
||||||
|
if (!m_MouseLeaveAction.empty())
|
||||||
{
|
{
|
||||||
m_MouseOver = false;
|
m_Rainmeter->ExecuteCommand(m_MouseLeaveAction.c_str(), this);
|
||||||
if (!m_MouseLeaveAction.empty())
|
return true;
|
||||||
{
|
|
||||||
if (!test) m_Rainmeter->ExecuteCommand(m_MouseLeaveAction.c_str(), this);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4031,6 +4179,8 @@ LRESULT CALLBACK CMeterWindow::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPAR
|
|||||||
MESSAGE(OnNcHitTest, WM_NCHITTEST)
|
MESSAGE(OnNcHitTest, WM_NCHITTEST)
|
||||||
MESSAGE(OnMouseMove, WM_MOUSEMOVE)
|
MESSAGE(OnMouseMove, WM_MOUSEMOVE)
|
||||||
MESSAGE(OnMouseMove, WM_NCMOUSEMOVE)
|
MESSAGE(OnMouseMove, WM_NCMOUSEMOVE)
|
||||||
|
MESSAGE(OnMouseLeave, WM_MOUSELEAVE)
|
||||||
|
MESSAGE(OnMouseLeave, WM_NCMOUSELEAVE)
|
||||||
MESSAGE(OnContextMenu, WM_CONTEXTMENU)
|
MESSAGE(OnContextMenu, WM_CONTEXTMENU)
|
||||||
MESSAGE(OnRightButtonDown, WM_NCRBUTTONDOWN)
|
MESSAGE(OnRightButtonDown, WM_NCRBUTTONDOWN)
|
||||||
MESSAGE(OnRightButtonDown, WM_RBUTTONDOWN)
|
MESSAGE(OnRightButtonDown, WM_RBUTTONDOWN)
|
||||||
@ -4180,11 +4330,26 @@ LRESULT CMeterWindow::OnCopyData(WPARAM wParam, LPARAM lParam)
|
|||||||
bang = str;
|
bang = str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (wcsicmp(bang.c_str(), L"!RainmeterWriteKeyValue") == 0)
|
||||||
|
{
|
||||||
|
// !RainmeterWriteKeyValue is a special case.
|
||||||
|
if (CRainmeter::ParseString(arg.c_str()).size() < 4)
|
||||||
|
{
|
||||||
|
// Add the current config filepath to the args
|
||||||
|
arg += L" \"";
|
||||||
|
arg += m_SkinPath;
|
||||||
|
arg += m_SkinName;
|
||||||
|
arg += L"\\";
|
||||||
|
arg += m_SkinIniFile;
|
||||||
|
arg += L"\"";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Add the current config name to the args. If it's not defined already
|
// Add the current config name to the args. If it's not defined already
|
||||||
// the bang only affects this config, if there already is a config defined
|
// the bang only affects this config, if there already is a config defined
|
||||||
// another one doesn't matter.
|
// another one doesn't matter.
|
||||||
arg += L" \"";
|
arg += L" \"";
|
||||||
arg += m_SkinName.c_str();
|
arg += m_SkinName;
|
||||||
arg += L"\"";
|
arg += L"\"";
|
||||||
|
|
||||||
return Rainmeter->ExecuteBang(bang, arg, this);
|
return Rainmeter->ExecuteBang(bang, arg, this);
|
||||||
|
@ -54,6 +54,13 @@ enum MOUSE
|
|||||||
MOUSE_LEAVE
|
MOUSE_LEAVE
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum BUTTONPROC
|
||||||
|
{
|
||||||
|
BUTTONPROC_DOWN,
|
||||||
|
BUTTONPROC_UP,
|
||||||
|
BUTTONPROC_MOVE
|
||||||
|
};
|
||||||
|
|
||||||
enum ZPOSITION
|
enum ZPOSITION
|
||||||
{
|
{
|
||||||
ZPOSITION_ONDESKTOP = -2,
|
ZPOSITION_ONDESKTOP = -2,
|
||||||
@ -146,6 +153,8 @@ public:
|
|||||||
void Refresh(bool init, bool all = false);
|
void Refresh(bool init, bool all = false);
|
||||||
void Redraw();
|
void Redraw();
|
||||||
|
|
||||||
|
void SetMouseLeaveEvent(bool cancel);
|
||||||
|
|
||||||
void MoveWindow(int x, int y);
|
void MoveWindow(int x, int y);
|
||||||
void ChangeZPos(ZPOSITION zPos, bool all = false);
|
void ChangeZPos(ZPOSITION zPos, bool all = false);
|
||||||
void FadeWindow(int from, int to);
|
void FadeWindow(int from, int to);
|
||||||
@ -226,6 +235,8 @@ protected:
|
|||||||
LRESULT OnDisplayChange(WPARAM wParam, LPARAM lParam);
|
LRESULT OnDisplayChange(WPARAM wParam, LPARAM lParam);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool HitTest(int x, int y);
|
||||||
|
|
||||||
void CreateRegion(bool clear);
|
void CreateRegion(bool clear);
|
||||||
void GetSkinFolders(const std::wstring& folder);
|
void GetSkinFolders(const std::wstring& folder);
|
||||||
Gdiplus::Bitmap* GrabDesktop(int x, int y, int w, int h);
|
Gdiplus::Bitmap* GrabDesktop(int x, int y, int w, int h);
|
||||||
@ -241,7 +252,9 @@ private:
|
|||||||
void InitializeMeasures();
|
void InitializeMeasures();
|
||||||
void InitializeMeters();
|
void InitializeMeters();
|
||||||
void ShowWindowIfAppropriate();
|
void ShowWindowIfAppropriate();
|
||||||
|
void HandleButtons(POINT pos, BUTTONPROC proc, CMeterWindow* meterWindow, bool changeCursor);
|
||||||
bool DoAction(int x, int y, MOUSE mouse, bool test);
|
bool DoAction(int x, int y, MOUSE mouse, bool test);
|
||||||
|
bool DoMoveAction(int x, int y, MOUSE mouse, CMeter* upperMeter = NULL);
|
||||||
bool ResizeWindow(bool reset);
|
bool ResizeWindow(bool reset);
|
||||||
void IgnoreAeroPeek();
|
void IgnoreAeroPeek();
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ std::wstring CRainmeter::c_CmdLine;
|
|||||||
** Splits the given string into substrings
|
** Splits the given string into substrings
|
||||||
**
|
**
|
||||||
*/
|
*/
|
||||||
std::vector<std::wstring> ParseString(LPCTSTR str)
|
std::vector<std::wstring> CRainmeter::ParseString(LPCTSTR str)
|
||||||
{
|
{
|
||||||
std::vector<std::wstring> result;
|
std::vector<std::wstring> result;
|
||||||
if (str)
|
if (str)
|
||||||
@ -198,7 +198,7 @@ void BangWithArgs(BANGCOMMAND bang, const WCHAR* arg, size_t numOfArgs)
|
|||||||
{
|
{
|
||||||
if(Rainmeter)
|
if(Rainmeter)
|
||||||
{
|
{
|
||||||
std::vector<std::wstring> subStrings = ParseString(arg);
|
std::vector<std::wstring> subStrings = CRainmeter::ParseString(arg);
|
||||||
std::wstring config;
|
std::wstring config;
|
||||||
std::wstring argument;
|
std::wstring argument;
|
||||||
|
|
||||||
@ -271,7 +271,7 @@ void BangGroupWithArgs(BANGCOMMAND bang, const WCHAR* arg, size_t numOfArgs)
|
|||||||
{
|
{
|
||||||
if (Rainmeter)
|
if (Rainmeter)
|
||||||
{
|
{
|
||||||
std::vector<std::wstring> subStrings = ParseString(arg);
|
std::vector<std::wstring> subStrings = CRainmeter::ParseString(arg);
|
||||||
|
|
||||||
if (subStrings.size() > numOfArgs)
|
if (subStrings.size() > numOfArgs)
|
||||||
{
|
{
|
||||||
@ -479,7 +479,7 @@ void RainmeterActivateConfig(HWND, const char* arg)
|
|||||||
{
|
{
|
||||||
if (Rainmeter)
|
if (Rainmeter)
|
||||||
{
|
{
|
||||||
std::vector<std::wstring> subStrings = ParseString(ConvertToWide(arg).c_str());
|
std::vector<std::wstring> subStrings = CRainmeter::ParseString(ConvertToWide(arg).c_str());
|
||||||
|
|
||||||
if (subStrings.size() > 1)
|
if (subStrings.size() > 1)
|
||||||
{
|
{
|
||||||
@ -519,7 +519,7 @@ void RainmeterDeactivateConfig(HWND, const char* arg)
|
|||||||
{
|
{
|
||||||
if (Rainmeter)
|
if (Rainmeter)
|
||||||
{
|
{
|
||||||
std::vector<std::wstring> subStrings = ParseString(ConvertToWide(arg).c_str());
|
std::vector<std::wstring> subStrings = CRainmeter::ParseString(ConvertToWide(arg).c_str());
|
||||||
|
|
||||||
if (subStrings.size() > 0)
|
if (subStrings.size() > 0)
|
||||||
{
|
{
|
||||||
@ -548,7 +548,7 @@ void RainmeterToggleConfig(HWND, const char* arg)
|
|||||||
{
|
{
|
||||||
if (Rainmeter)
|
if (Rainmeter)
|
||||||
{
|
{
|
||||||
std::vector<std::wstring> subStrings = ParseString(ConvertToWide(arg).c_str());
|
std::vector<std::wstring> subStrings = CRainmeter::ParseString(ConvertToWide(arg).c_str());
|
||||||
|
|
||||||
if (subStrings.size() >= 2)
|
if (subStrings.size() >= 2)
|
||||||
{
|
{
|
||||||
@ -777,7 +777,7 @@ void RainmeterDeactivateConfigGroup(HWND, const char* arg)
|
|||||||
{
|
{
|
||||||
if (Rainmeter)
|
if (Rainmeter)
|
||||||
{
|
{
|
||||||
std::vector<std::wstring> subStrings = ParseString(ConvertToWide(arg).c_str());
|
std::vector<std::wstring> subStrings = CRainmeter::ParseString(ConvertToWide(arg).c_str());
|
||||||
|
|
||||||
if (subStrings.size() > 0)
|
if (subStrings.size() > 0)
|
||||||
{
|
{
|
||||||
@ -862,7 +862,7 @@ void RainmeterSkinMenu(HWND, const char* arg)
|
|||||||
{
|
{
|
||||||
if (Rainmeter)
|
if (Rainmeter)
|
||||||
{
|
{
|
||||||
std::vector<std::wstring> subStrings = ParseString(ConvertToWide(arg).c_str());
|
std::vector<std::wstring> subStrings = CRainmeter::ParseString(ConvertToWide(arg).c_str());
|
||||||
|
|
||||||
if (subStrings.size() > 0)
|
if (subStrings.size() > 0)
|
||||||
{
|
{
|
||||||
@ -924,6 +924,140 @@ void RainmeterMoveMeter(HWND, const char* arg)
|
|||||||
BangWithArgs(BANG_MOVEMETER, ConvertToWide(arg).c_str(), 3);
|
BangWithArgs(BANG_MOVEMETER, ConvertToWide(arg).c_str(), 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** RainmeterWriteKeyValue
|
||||||
|
**
|
||||||
|
** Callback for the !RainmeterWriteKeyValue bang
|
||||||
|
**
|
||||||
|
*/
|
||||||
|
void RainmeterWriteKeyValue(HWND, const char* arg)
|
||||||
|
{
|
||||||
|
if (Rainmeter)
|
||||||
|
{
|
||||||
|
std::vector<std::wstring> subStrings = CRainmeter::ParseString(ConvertToWide(arg).c_str());
|
||||||
|
|
||||||
|
if (subStrings.size() > 3)
|
||||||
|
{
|
||||||
|
const std::wstring& iniFile = subStrings[3];
|
||||||
|
|
||||||
|
if (iniFile.find(L"..\\") != std::string::npos || iniFile.find(L"../") != std::string::npos)
|
||||||
|
{
|
||||||
|
DebugLog(L"!RainmeterWriteKeyValue: Illegal characters in path - \"..\\\": %s", iniFile.c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wcsnicmp(iniFile.c_str(), Rainmeter->GetSkinPath().c_str(), Rainmeter->GetSkinPath().size()) != 0 &&
|
||||||
|
wcsnicmp(iniFile.c_str(), Rainmeter->GetPath().c_str(), Rainmeter->GetPath().size()) != 0)
|
||||||
|
{
|
||||||
|
DebugLog(L"!RainmeterWriteKeyValue: Illegal path outside of Rainmeter directories: %s", iniFile.c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify whether the file exists
|
||||||
|
if (_waccess(iniFile.c_str(), 0) == -1)
|
||||||
|
{
|
||||||
|
DebugLog(L"!RainmeterWriteKeyValue: File not found: %s", iniFile.c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify whether the file is read-only
|
||||||
|
DWORD attr = GetFileAttributes(iniFile.c_str());
|
||||||
|
if (attr == -1 || (attr & FILE_ATTRIBUTE_READONLY))
|
||||||
|
{
|
||||||
|
DebugLog(L"!RainmeterWriteKeyValue: File is read-only: %s", iniFile.c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Avoid "IniFileMapping"
|
||||||
|
std::vector<std::wstring> iniFileMappings;
|
||||||
|
CSystem::GetIniFileMappingList(iniFileMappings);
|
||||||
|
std::wstring iniWrite = CSystem::GetTemporaryFile(iniFileMappings, iniFile);
|
||||||
|
if (iniWrite == L"<>") // error occurred
|
||||||
|
{
|
||||||
|
DebugLog(L"!RainmeterWriteKeyValue: Failed to create a temporary file: %s", iniFile.c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool temporary = !iniWrite.empty();
|
||||||
|
|
||||||
|
if (temporary)
|
||||||
|
{
|
||||||
|
if (CRainmeter::GetDebug()) DebugLog(L"!RainmeterWriteKeyValue: Writing file: %s (Temp: %s)", iniFile.c_str(), iniWrite.c_str());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (CRainmeter::GetDebug()) DebugLog(L"!RainmeterWriteKeyValue: Writing file: %s", iniFile.c_str());
|
||||||
|
iniWrite = iniFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::wstring& strSection = subStrings[0];
|
||||||
|
const std::wstring& strKey = subStrings[1];
|
||||||
|
const std::wstring& strValue = subStrings[2];
|
||||||
|
|
||||||
|
int formula = -1;
|
||||||
|
BOOL write = 0;
|
||||||
|
|
||||||
|
if (subStrings.size() > 4)
|
||||||
|
{
|
||||||
|
CMeterWindow* mw = Rainmeter->GetMeterWindow(subStrings[4]);
|
||||||
|
if (mw)
|
||||||
|
{
|
||||||
|
double value;
|
||||||
|
formula = mw->GetParser().ReadFormula(strValue, &value);
|
||||||
|
|
||||||
|
// Formula read fine
|
||||||
|
if (formula != -1)
|
||||||
|
{
|
||||||
|
TCHAR buffer[256];
|
||||||
|
swprintf(buffer, L"%f", value);
|
||||||
|
|
||||||
|
const std::wstring& resultString = buffer;
|
||||||
|
|
||||||
|
write = WritePrivateProfileString(strSection.c_str(), strKey.c_str(), resultString.c_str(), iniWrite.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (formula == -1)
|
||||||
|
{
|
||||||
|
write = WritePrivateProfileString(strSection.c_str(), strKey.c_str(), strValue.c_str(), iniWrite.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (temporary)
|
||||||
|
{
|
||||||
|
if (write != 0)
|
||||||
|
{
|
||||||
|
WritePrivateProfileString(NULL, NULL, NULL, iniWrite.c_str()); // FLUSH
|
||||||
|
|
||||||
|
// Copy the file back
|
||||||
|
if (!CSystem::CopyFiles(iniWrite, iniFile))
|
||||||
|
{
|
||||||
|
DebugLog(L"!RainmeterWriteKeyValue: Failed to copy a temporary file to the original filepath: %s (Temp: %s)", iniFile.c_str(), iniWrite.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // failed
|
||||||
|
{
|
||||||
|
DebugLog(L"!RainmeterWriteKeyValue: Failed to write a value to the file: %s (Temp: %s)", iniFile.c_str(), iniWrite.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove a temporary file
|
||||||
|
CSystem::RemoveFile(iniWrite);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (write == 0) // failed
|
||||||
|
{
|
||||||
|
DebugLog(L"!RainmeterWriteKeyValue: Failed to write a value to the file: %s", iniFile.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DebugLog(L"Unable to parse the arguments for !RainmeterWriteKeyValue");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** RainmeterPluginBang
|
** RainmeterPluginBang
|
||||||
**
|
**
|
||||||
@ -973,6 +1107,8 @@ CRainmeter::CRainmeter()
|
|||||||
|
|
||||||
c_Debug = false;
|
c_Debug = false;
|
||||||
|
|
||||||
|
m_MenuActive = false;
|
||||||
|
|
||||||
m_Logging = false;
|
m_Logging = false;
|
||||||
|
|
||||||
m_DesktopWorkAreaChanged = false;
|
m_DesktopWorkAreaChanged = false;
|
||||||
@ -1178,18 +1314,18 @@ int CRainmeter::Initialize(HWND Parent, HINSTANCE Instance, LPCSTR szPath)
|
|||||||
// Copy the default skin to the Skins folder
|
// Copy the default skin to the Skins folder
|
||||||
std::wstring strFrom(m_Path + L"Skins\\" + L"*.*");
|
std::wstring strFrom(m_Path + L"Skins\\" + L"*.*");
|
||||||
std::wstring strTo(m_SkinPath);
|
std::wstring strTo(m_SkinPath);
|
||||||
CopyFiles(strFrom, strTo);
|
CSystem::CopyFiles(strFrom, strTo);
|
||||||
|
|
||||||
// This shouldn't be copied
|
// This shouldn't be copied
|
||||||
std::wstring strNote = strTo + L"Read me before copying skins to here.txt";
|
std::wstring strNote = strTo + L"Read me before copying skins to here.txt";
|
||||||
DeleteFile(strNote.c_str());
|
CSystem::RemoveFile(strNote);
|
||||||
|
|
||||||
// Copy also the themes to the %APPDATA%
|
// Copy also the themes to the %APPDATA%
|
||||||
strFrom = std::wstring(m_Path + L"Themes\\" + L"*.*");
|
strFrom = std::wstring(m_Path + L"Themes\\" + L"*.*");
|
||||||
strTo = std::wstring(GetSettingsPath() + L"Themes");
|
strTo = std::wstring(GetSettingsPath() + L"Themes");
|
||||||
CreateDirectory(strTo.c_str(), NULL);
|
CreateDirectory(strTo.c_str(), NULL);
|
||||||
strTo += L"\\";
|
strTo += L"\\";
|
||||||
CopyFiles(strFrom, strTo);
|
CSystem::CopyFiles(strFrom, strTo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1338,6 +1474,7 @@ int CRainmeter::Initialize(HWND Parent, HINSTANCE Instance, LPCSTR szPath)
|
|||||||
AddBangCommand("!RainmeterSkinMenu", RainmeterSkinMenu);
|
AddBangCommand("!RainmeterSkinMenu", RainmeterSkinMenu);
|
||||||
AddBangCommand("!RainmeterTrayMenu", RainmeterTrayMenu);
|
AddBangCommand("!RainmeterTrayMenu", RainmeterTrayMenu);
|
||||||
AddBangCommand("!RainmeterResetStats", RainmeterResetStats);
|
AddBangCommand("!RainmeterResetStats", RainmeterResetStats);
|
||||||
|
AddBangCommand("!RainmeterWriteKeyValue", RainmeterWriteKeyValue);
|
||||||
AddBangCommand("!RainmeterPluginBang", RainmeterPluginBang);
|
AddBangCommand("!RainmeterPluginBang", RainmeterPluginBang);
|
||||||
AddBangCommand("!RainmeterQuit", RainmeterQuit);
|
AddBangCommand("!RainmeterQuit", RainmeterQuit);
|
||||||
}
|
}
|
||||||
@ -1433,17 +1570,17 @@ void CRainmeter::CheckSkinVersions()
|
|||||||
if (strVersionCurrent.find_first_of(L"\\/\"*:?<>|") == std::wstring::npos)
|
if (strVersionCurrent.find_first_of(L"\\/\"*:?<>|") == std::wstring::npos)
|
||||||
{
|
{
|
||||||
std::wstring strTarget = m_SkinPath + L"Backup\\" + menu[i].name + L"-" + strVersionCurrent;
|
std::wstring strTarget = m_SkinPath + L"Backup\\" + menu[i].name + L"-" + strVersionCurrent;
|
||||||
if (CopyFiles(m_SkinPath + menu[i].name, strTarget, true)) // Move the folder to "backup"
|
if (CSystem::CopyFiles(m_SkinPath + menu[i].name, strTarget, true)) // Move the folder to "backup"
|
||||||
{
|
{
|
||||||
// Upgrade the skin
|
// Upgrade the skin
|
||||||
CopyFiles(strMainSkinsPath + menu[i].name, m_SkinPath);
|
CSystem::CopyFiles(strMainSkinsPath + menu[i].name, m_SkinPath);
|
||||||
|
|
||||||
// TODO: Temporary 'fix': If this was Enigma upgrade the themes too
|
// TODO: Temporary 'fix': If this was Enigma upgrade the themes too
|
||||||
if (menu[i].name == L"Enigma" || menu[i].name == L"Gnometer")
|
if (menu[i].name == L"Enigma" || menu[i].name == L"Gnometer")
|
||||||
{
|
{
|
||||||
std::wstring strMainThemes = m_Path + L"Themes";
|
std::wstring strMainThemes = m_Path + L"Themes";
|
||||||
std::wstring strCurrentThemes = GetSettingsPath();
|
std::wstring strCurrentThemes = GetSettingsPath();
|
||||||
CopyFiles(strMainThemes, strCurrentThemes);
|
CSystem::CopyFiles(strMainThemes, strCurrentThemes);
|
||||||
}
|
}
|
||||||
// End of temporary 'fix'
|
// End of temporary 'fix'
|
||||||
}
|
}
|
||||||
@ -1466,10 +1603,10 @@ void CRainmeter::CheckSkinVersions()
|
|||||||
strMessage += L"Do you want to add it to your skin and themes libraries?";
|
strMessage += 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))
|
if (IDYES == MessageBox(NULL, strMessage.c_str(), APPNAME, MB_YESNO | MB_ICONQUESTION))
|
||||||
{
|
{
|
||||||
CopyFiles(strMainSkinsPath + menu[i].name, m_SkinPath);
|
CSystem::CopyFiles(strMainSkinsPath + menu[i].name, m_SkinPath);
|
||||||
std::wstring strMainThemes = m_Path + L"Themes";
|
std::wstring strMainThemes = m_Path + L"Themes";
|
||||||
std::wstring strCurrentThemes = GetSettingsPath();
|
std::wstring strCurrentThemes = GetSettingsPath();
|
||||||
CopyFiles(strMainThemes, strCurrentThemes);
|
CSystem::CopyFiles(strMainThemes, strCurrentThemes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1516,37 +1653,6 @@ int CRainmeter::CompareVersions(std::wstring strA, std::wstring strB)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
** CopyFiles
|
|
||||||
**
|
|
||||||
** Copies files and folders from one location to another.
|
|
||||||
**
|
|
||||||
*/
|
|
||||||
bool CRainmeter::CopyFiles(const std::wstring& strFrom, const std::wstring& strTo, bool bMove)
|
|
||||||
{
|
|
||||||
std::wstring tmpFrom(strFrom), tmpTo(strTo);
|
|
||||||
|
|
||||||
// The strings must end with double nul
|
|
||||||
tmpFrom.append(L"0");
|
|
||||||
tmpFrom[tmpFrom.size() - 1] = L'\0';
|
|
||||||
tmpTo.append(L"0");
|
|
||||||
tmpTo[tmpTo.size() - 1] = L'\0';
|
|
||||||
|
|
||||||
SHFILEOPSTRUCT fo = {0};
|
|
||||||
fo.wFunc = bMove ? FO_MOVE : FO_COPY;
|
|
||||||
fo.pFrom = tmpFrom.c_str();
|
|
||||||
fo.pTo = tmpTo.c_str();
|
|
||||||
fo.fFlags = FOF_NO_UI | FOF_NOCONFIRMATION | FOF_ALLOWUNDO;
|
|
||||||
|
|
||||||
int result = SHFileOperation(&fo);
|
|
||||||
if (result != 0)
|
|
||||||
{
|
|
||||||
DebugLog(L"Unable to copy files from %s to %s (%i)", strFrom.c_str(), strTo.c_str(), result);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** CreateDefaultConfigFile
|
** CreateDefaultConfigFile
|
||||||
**
|
**
|
||||||
@ -1576,7 +1682,7 @@ void CRainmeter::CreateDefaultConfigFile(std::wstring strFile)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CopyFiles(defaultIni, GetIniFile());
|
CSystem::CopyFiles(defaultIni, GetIniFile());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2245,6 +2351,10 @@ BOOL CRainmeter::ExecuteBang(const std::wstring& bang, const std::wstring& arg,
|
|||||||
{
|
{
|
||||||
BangWithArgs(BANG_MOVEMETER, arg.c_str(), 3);
|
BangWithArgs(BANG_MOVEMETER, arg.c_str(), 3);
|
||||||
}
|
}
|
||||||
|
else if (wcsicmp(bang.c_str(), L"!RainmeterWriteKeyValue") == 0)
|
||||||
|
{
|
||||||
|
RainmeterWriteKeyValue(NULL, ConvertToAscii(arg.c_str()).c_str());
|
||||||
|
}
|
||||||
else if (wcsicmp(bang.c_str(), L"!RainmeterPluginBang") == 0)
|
else if (wcsicmp(bang.c_str(), L"!RainmeterPluginBang") == 0)
|
||||||
{
|
{
|
||||||
BangWithArgs(BANG_PLUGIN, arg.c_str(), 1);
|
BangWithArgs(BANG_PLUGIN, arg.c_str(), 1);
|
||||||
@ -2937,11 +3047,9 @@ PLATFORM CRainmeter::IsNT()
|
|||||||
*/
|
*/
|
||||||
void CRainmeter::ShowContextMenu(POINT pos, CMeterWindow* meterWindow)
|
void CRainmeter::ShowContextMenu(POINT pos, CMeterWindow* meterWindow)
|
||||||
{
|
{
|
||||||
static bool active = false;
|
if (!m_MenuActive)
|
||||||
|
|
||||||
if (!active)
|
|
||||||
{
|
{
|
||||||
active = true;
|
m_MenuActive = true;
|
||||||
|
|
||||||
// Show context menu, if no actions were executed
|
// Show context menu, if no actions were executed
|
||||||
HMENU menu = LoadMenu(m_Instance, MAKEINTRESOURCE(IDR_CONTEXT_MENU));
|
HMENU menu = LoadMenu(m_Instance, MAKEINTRESOURCE(IDR_CONTEXT_MENU));
|
||||||
@ -2955,7 +3063,7 @@ void CRainmeter::ShowContextMenu(POINT pos, CMeterWindow* meterWindow)
|
|||||||
{
|
{
|
||||||
// Disable Quit/Logging if ran as a Litestep plugin
|
// Disable Quit/Logging if ran as a Litestep plugin
|
||||||
EnableMenuItem(subMenu, ID_CONTEXT_QUIT, MF_BYCOMMAND | MF_GRAYED);
|
EnableMenuItem(subMenu, ID_CONTEXT_QUIT, MF_BYCOMMAND | MF_GRAYED);
|
||||||
EnableMenuItem(subMenu, 6, MF_BYPOSITION | MF_GRAYED);
|
EnableMenuItem(subMenu, 6, MF_BYPOSITION | MF_GRAYED); // "Logging" menu
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -3032,8 +3140,19 @@ void CRainmeter::ShowContextMenu(POINT pos, CMeterWindow* meterWindow)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show context menu
|
HWND hWnd = WindowFromPoint(pos);
|
||||||
HWND hWnd = meterWindow ? meterWindow->GetWindow() : m_TrayWindow->GetWindow();
|
if (hWnd != NULL)
|
||||||
|
{
|
||||||
|
CMeterWindow* mw = GetMeterWindow(hWnd);
|
||||||
|
if (mw)
|
||||||
|
{
|
||||||
|
// Cancel the mouse event beforehand
|
||||||
|
mw->SetMouseLeaveEvent(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the window to foreground
|
||||||
|
hWnd = meterWindow ? meterWindow->GetWindow() : m_TrayWindow->GetWindow();
|
||||||
HWND hWndForeground = GetForegroundWindow();
|
HWND hWndForeground = GetForegroundWindow();
|
||||||
if (hWndForeground != hWnd)
|
if (hWndForeground != hWnd)
|
||||||
{
|
{
|
||||||
@ -3043,6 +3162,8 @@ void CRainmeter::ShowContextMenu(POINT pos, CMeterWindow* meterWindow)
|
|||||||
SetForegroundWindow(hWnd);
|
SetForegroundWindow(hWnd);
|
||||||
AttachThreadInput(currentThreadID, foregroundThreadID, FALSE);
|
AttachThreadInput(currentThreadID, foregroundThreadID, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Show context menu
|
||||||
TrackPopupMenu(
|
TrackPopupMenu(
|
||||||
subMenu,
|
subMenu,
|
||||||
TPM_RIGHTBUTTON | TPM_LEFTALIGN,
|
TPM_RIGHTBUTTON | TPM_LEFTALIGN,
|
||||||
@ -3062,7 +3183,7 @@ void CRainmeter::ShowContextMenu(POINT pos, CMeterWindow* meterWindow)
|
|||||||
DestroyMenu(menu);
|
DestroyMenu(menu);
|
||||||
}
|
}
|
||||||
|
|
||||||
active = false;
|
m_MenuActive = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3183,7 +3304,7 @@ HMENU CRainmeter::CreateSkinMenu(CMeterWindow* meterWindow, int index, HMENU con
|
|||||||
// Tick the transparency
|
// Tick the transparency
|
||||||
if (!meterWindow->GetNativeTransparency())
|
if (!meterWindow->GetNativeTransparency())
|
||||||
{
|
{
|
||||||
EnableMenuItem(settingsMenu, 1, MF_BYPOSITION | MF_GRAYED);
|
EnableMenuItem(settingsMenu, 1, MF_BYPOSITION | MF_GRAYED); // "Transparency" menu
|
||||||
EnableMenuItem(settingsMenu, ID_CONTEXT_SKINMENU_CLICKTHROUGH, MF_BYCOMMAND | MF_GRAYED);
|
EnableMenuItem(settingsMenu, ID_CONTEXT_SKINMENU_CLICKTHROUGH, MF_BYCOMMAND | MF_GRAYED);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -3451,7 +3572,7 @@ void CRainmeter::DeleteLogFile()
|
|||||||
SetLogging(false);
|
SetLogging(false);
|
||||||
ResetLoggingFlag();
|
ResetLoggingFlag();
|
||||||
|
|
||||||
DeleteFile(m_LogFile.c_str());
|
CSystem::RemoveFile(m_LogFile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -96,6 +96,7 @@ void RainmeterAbout(HWND, const char* arg);
|
|||||||
void RainmeterSkinMenu(HWND, const char* arg);
|
void RainmeterSkinMenu(HWND, const char* arg);
|
||||||
void RainmeterTrayMenu(HWND, const char* arg);
|
void RainmeterTrayMenu(HWND, const char* arg);
|
||||||
void RainmeterResetStats(HWND, const char* arg);
|
void RainmeterResetStats(HWND, const char* arg);
|
||||||
|
void RainmeterWriteKeyValue(HWND, const char* arg);
|
||||||
void RainmeterPluginBang(HWND, const char* arg);
|
void RainmeterPluginBang(HWND, const char* arg);
|
||||||
void RainmeterQuit(HWND, const char* arg);
|
void RainmeterQuit(HWND, const char* arg);
|
||||||
|
|
||||||
@ -190,6 +191,7 @@ public:
|
|||||||
|
|
||||||
void SetDebug(bool debug);
|
void SetDebug(bool debug);
|
||||||
|
|
||||||
|
bool IsMenuActive() { return m_MenuActive; }
|
||||||
void ShowContextMenu(POINT pos, CMeterWindow* meterWindow);
|
void ShowContextMenu(POINT pos, CMeterWindow* meterWindow);
|
||||||
|
|
||||||
std::wstring GetTrayExecuteL() { return m_TrayExecuteL; };
|
std::wstring GetTrayExecuteL() { return m_TrayExecuteL; };
|
||||||
@ -207,10 +209,10 @@ public:
|
|||||||
|
|
||||||
void ClearDeleteLaterList();
|
void ClearDeleteLaterList();
|
||||||
|
|
||||||
|
static std::vector<std::wstring> ParseString(LPCTSTR str);
|
||||||
static PLATFORM IsNT();
|
static PLATFORM IsNT();
|
||||||
static std::wstring ExtractPath(const std::wstring& strFilePath);
|
static std::wstring ExtractPath(const std::wstring& strFilePath);
|
||||||
static void ExpandEnvironmentVariables(std::wstring& strPath);
|
static void ExpandEnvironmentVariables(std::wstring& strPath);
|
||||||
static bool CopyFiles(const std::wstring& strFrom, const std::wstring& strTo, bool bMove = false);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void CreateMeterWindow(std::wstring path, std::wstring config, std::wstring iniFile);
|
void CreateMeterWindow(std::wstring path, std::wstring config, std::wstring iniFile);
|
||||||
@ -266,6 +268,8 @@ private:
|
|||||||
std::map<UINT, RECT> m_DesktopWorkAreas;
|
std::map<UINT, RECT> m_DesktopWorkAreas;
|
||||||
std::vector<RECT> m_OldDesktopWorkAreas;
|
std::vector<RECT> m_OldDesktopWorkAreas;
|
||||||
|
|
||||||
|
bool m_MenuActive;
|
||||||
|
|
||||||
bool m_Logging;
|
bool m_Logging;
|
||||||
|
|
||||||
std::wstring m_ConfigEditor;
|
std::wstring m_ConfigEditor;
|
||||||
|
@ -999,3 +999,145 @@ BOOL CSystem::DwmIsCompositionEnabled()
|
|||||||
}
|
}
|
||||||
return fEnabled;
|
return fEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** CopyFiles
|
||||||
|
**
|
||||||
|
** Copies files and folders from one location to another.
|
||||||
|
**
|
||||||
|
*/
|
||||||
|
bool CSystem::CopyFiles(const std::wstring& strFrom, const std::wstring& strTo, bool bMove)
|
||||||
|
{
|
||||||
|
std::wstring tmpFrom(strFrom), tmpTo(strTo);
|
||||||
|
|
||||||
|
// The strings must end with double nul
|
||||||
|
tmpFrom.append(L"0");
|
||||||
|
tmpFrom[tmpFrom.size() - 1] = L'\0';
|
||||||
|
tmpTo.append(L"0");
|
||||||
|
tmpTo[tmpTo.size() - 1] = L'\0';
|
||||||
|
|
||||||
|
SHFILEOPSTRUCT fo = {0};
|
||||||
|
fo.wFunc = bMove ? FO_MOVE : FO_COPY;
|
||||||
|
fo.pFrom = tmpFrom.c_str();
|
||||||
|
fo.pTo = tmpTo.c_str();
|
||||||
|
fo.fFlags = FOF_NO_UI | FOF_NOCONFIRMATION | FOF_ALLOWUNDO;
|
||||||
|
|
||||||
|
int result = SHFileOperation(&fo);
|
||||||
|
if (result != 0)
|
||||||
|
{
|
||||||
|
DebugLog(L"Unable to copy files from %s to %s (%i)", strFrom.c_str(), strTo.c_str(), result);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** RemoveFile
|
||||||
|
**
|
||||||
|
** Removes a file even if a file is read-only.
|
||||||
|
**
|
||||||
|
*/
|
||||||
|
bool CSystem::RemoveFile(const std::wstring& file)
|
||||||
|
{
|
||||||
|
DWORD attr = GetFileAttributes(file.c_str());
|
||||||
|
if (attr == -1 || (attr & FILE_ATTRIBUTE_READONLY))
|
||||||
|
{
|
||||||
|
// Unset read-only
|
||||||
|
SetFileAttributes(file.c_str(), (attr == -1) ? FILE_ATTRIBUTE_NORMAL : attr - FILE_ATTRIBUTE_READONLY);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (DeleteFile(file.c_str()) != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** GetIniFileMappingList
|
||||||
|
**
|
||||||
|
** Retrieves the "IniFileMapping" entries from Registry.
|
||||||
|
**
|
||||||
|
*/
|
||||||
|
void CSystem::GetIniFileMappingList(std::vector<std::wstring>& iniFileMappings)
|
||||||
|
{
|
||||||
|
HKEY hKey;
|
||||||
|
LONG ret;
|
||||||
|
|
||||||
|
ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\IniFileMapping", 0, KEY_ENUMERATE_SUB_KEYS, &hKey);
|
||||||
|
if (ret == ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
WCHAR buffer[MAX_PATH];
|
||||||
|
DWORD index = 0, cch = MAX_PATH;
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
ret = RegEnumKeyEx(hKey, index++, buffer, &cch, NULL, NULL, NULL, NULL);
|
||||||
|
if (ret == ERROR_NO_MORE_ITEMS) break;
|
||||||
|
|
||||||
|
if (ret == ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
iniFileMappings.push_back(buffer);
|
||||||
|
}
|
||||||
|
cch = MAX_PATH;
|
||||||
|
}
|
||||||
|
RegCloseKey(hKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** GetTemporaryFile
|
||||||
|
**
|
||||||
|
** Prepares a temporary file if iniFile is included in the "IniFileMapping" entries.
|
||||||
|
** If iniFile is not included, returns a empty string. If error occurred, returns "<>".
|
||||||
|
** Note that a temporary file must be deleted by caller.
|
||||||
|
**
|
||||||
|
*/
|
||||||
|
std::wstring CSystem::GetTemporaryFile(const std::vector<std::wstring>& iniFileMappings, const std::wstring &iniFile)
|
||||||
|
{
|
||||||
|
std::wstring temporary;
|
||||||
|
|
||||||
|
if (!iniFileMappings.empty())
|
||||||
|
{
|
||||||
|
std::wstring::size_type pos = iniFile.find_last_of(L'\\');
|
||||||
|
std::wstring filename;
|
||||||
|
|
||||||
|
if (pos != std::wstring::npos)
|
||||||
|
{
|
||||||
|
filename = iniFile.substr(pos + 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
filename = iniFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < iniFileMappings.size(); ++i)
|
||||||
|
{
|
||||||
|
if (wcsicmp(iniFileMappings[i].c_str(), filename.c_str()) == 0)
|
||||||
|
{
|
||||||
|
WCHAR buffer[MAX_PATH];
|
||||||
|
|
||||||
|
GetTempPath(MAX_PATH, buffer);
|
||||||
|
temporary = buffer;
|
||||||
|
if (GetTempFileName(temporary.c_str(), L"cfg", 0, buffer) != 0)
|
||||||
|
{
|
||||||
|
temporary = buffer;
|
||||||
|
|
||||||
|
std::wstring tmp = GetTemporaryFile(iniFileMappings, temporary);
|
||||||
|
if (tmp.empty() && CopyFiles(iniFile, temporary))
|
||||||
|
{
|
||||||
|
return temporary;
|
||||||
|
}
|
||||||
|
else // alternate is reserved or failed
|
||||||
|
{
|
||||||
|
RemoveFile(temporary);
|
||||||
|
return tmp.empty() ? L"<>" : tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // failed
|
||||||
|
{
|
||||||
|
DebugLog(L"Unable to create a temporary file to: %s", temporary.c_str());
|
||||||
|
return L"<>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return temporary;
|
||||||
|
}
|
||||||
|
@ -64,6 +64,12 @@ public:
|
|||||||
static HWND GetHelperWindow() { return c_HelperWindow; }
|
static HWND GetHelperWindow() { return c_HelperWindow; }
|
||||||
static void PrepareHelperWindow(HWND WorkerW);
|
static void PrepareHelperWindow(HWND WorkerW);
|
||||||
|
|
||||||
|
static bool CopyFiles(const std::wstring& strFrom, const std::wstring& strTo, bool bMove = false);
|
||||||
|
static bool RemoveFile(const std::wstring& file);
|
||||||
|
|
||||||
|
static void GetIniFileMappingList(std::vector<std::wstring>& iniFileMappings);
|
||||||
|
static std::wstring GetTemporaryFile(const std::vector<std::wstring>& iniFileMappings, const std::wstring& iniFile);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void CALLBACK MyWinEventProc(HWINEVENTHOOK hWinEventHook, DWORD event, HWND hwnd, LONG idObject, LONG idChild, DWORD dwEventThread, DWORD dwmsEventTime);
|
static void CALLBACK MyWinEventProc(HWINEVENTHOOK hWinEventHook, DWORD event, HWND hwnd, LONG idObject, LONG idChild, DWORD dwEventThread, DWORD dwmsEventTime);
|
||||||
static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||||
|
@ -599,9 +599,7 @@ LRESULT CALLBACK CTrayWindow::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
|
|||||||
{
|
{
|
||||||
POINT point;
|
POINT point;
|
||||||
GetCursorPos(&point);
|
GetCursorPos(&point);
|
||||||
SetForegroundWindow(tray->m_Window);
|
|
||||||
Rainmeter->ShowContextMenu(point, NULL);
|
Rainmeter->ShowContextMenu(point, NULL);
|
||||||
SetForegroundWindow(tray->m_Window);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user