mirror of
https://github.com/clangen/musikcube.git
synced 2025-03-29 19:20:28 +00:00
A couple changes to support "single instance" mode in win32.
This commit is contained in:
parent
a60f33fa19
commit
2e2ee29cbb
@ -44,6 +44,21 @@
|
||||
<Filter Include="src\i18n">
|
||||
<UniqueIdentifier>{a8776591-b7ad-4f6f-a927-c4bfaaa1e8c8}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="src\sdk\audio">
|
||||
<UniqueIdentifier>{fe28fe15-6cf7-40e0-bec5-9ca46932d279}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="src\sdk\vis">
|
||||
<UniqueIdentifier>{dd68aae0-9c01-4915-a4b3-c5e5b5ff8058}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="src\sdk\io">
|
||||
<UniqueIdentifier>{578b0af6-0dc3-4a69-a784-5e0293a5708a}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="src\sdk\library">
|
||||
<UniqueIdentifier>{a39a447a-65ad-465c-839d-b96cc4a8e2e9}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="src\sdk\indexer">
|
||||
<UniqueIdentifier>{d35af273-0f2b-4669-aa83-d7eee8c2c5c5}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="pch.cpp">
|
||||
@ -201,30 +216,6 @@
|
||||
<ClInclude Include="audio\Player.h">
|
||||
<Filter>src\audio</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="sdk\IDecoder.h">
|
||||
<Filter>src\sdk</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="sdk\IDecoderFactory.h">
|
||||
<Filter>src\sdk</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="sdk\IDSP.h">
|
||||
<Filter>src\sdk</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="sdk\IOutput.h">
|
||||
<Filter>src\sdk</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="sdk\IAnalyzer.h">
|
||||
<Filter>src\sdk</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="sdk\IBuffer.h">
|
||||
<Filter>src\sdk</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="sdk\IDataStream.h">
|
||||
<Filter>src\sdk</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="sdk\IDataStreamFactory.h">
|
||||
<Filter>src\sdk</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="io\LocalFileStream.h">
|
||||
<Filter>src\io</Filter>
|
||||
</ClInclude>
|
||||
@ -258,15 +249,9 @@
|
||||
<ClInclude Include="plugin\PluginFactory.h">
|
||||
<Filter>src\plugin</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="sdk\IMetadataReader.h">
|
||||
<Filter>src\sdk</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="sdk\IPlugin.h">
|
||||
<Filter>src\sdk</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="sdk\IBufferProvider.h">
|
||||
<Filter>src\sdk</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="debug.h">
|
||||
<Filter>src</Filter>
|
||||
</ClInclude>
|
||||
@ -294,36 +279,15 @@
|
||||
<ClInclude Include="support\PreferenceKeys.h">
|
||||
<Filter>src\support</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="sdk\IPcmVisualizer.h">
|
||||
<Filter>src\sdk</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="sdk\ISpectrumVisualizer.h">
|
||||
<Filter>src\sdk</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="audio\Visualizer.h">
|
||||
<Filter>src\audio</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="sdk\IVisualizer.h">
|
||||
<Filter>src\sdk</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="sdk\IPlaybackRemote.h">
|
||||
<Filter>src\sdk</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="sdk\IPlaybackService.h">
|
||||
<Filter>src\sdk</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="sdk\ITrack.h">
|
||||
<Filter>src\sdk</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="utfutil.h">
|
||||
<Filter>src</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="sdk\constants.h">
|
||||
<Filter>src\sdk</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="sdk\IRetainedTrack.h">
|
||||
<Filter>src\sdk</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="library\track\RetainedTrack.h">
|
||||
<Filter>src\library\track</Filter>
|
||||
</ClInclude>
|
||||
@ -366,21 +330,9 @@
|
||||
<ClInclude Include="library\track\TrackList.h">
|
||||
<Filter>src\library\track</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="sdk\ITrackListEditor.h">
|
||||
<Filter>src\sdk</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="sdk\ITrackList.h">
|
||||
<Filter>src\sdk</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="sdk\IPreferences.h">
|
||||
<Filter>src\sdk</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="sdk\IMetadataValue.h">
|
||||
<Filter>src\sdk</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="sdk\IMetadataValueList.h">
|
||||
<Filter>src\sdk</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="library\query\local\CategoryTrackListQuery.h">
|
||||
<Filter>src\library\query\local</Filter>
|
||||
</ClInclude>
|
||||
@ -405,9 +357,6 @@
|
||||
<ClInclude Include="library\query\local\CategoryListQuery.h">
|
||||
<Filter>src\library\query\local</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="sdk\ISimpleDataProvider.h">
|
||||
<Filter>src\sdk</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Library\query\local\LocalQueryBase.h">
|
||||
<Filter>src\library\query\local</Filter>
|
||||
</ClInclude>
|
||||
@ -417,15 +366,6 @@
|
||||
<ClInclude Include="plugin\Plugins.h">
|
||||
<Filter>src\plugin</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="sdk\IMetadataMapList.h">
|
||||
<Filter>src\sdk</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="sdk\IMetadataMap.h">
|
||||
<Filter>src\sdk</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="sdk\ITrackWriter.h">
|
||||
<Filter>src\sdk</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="library\metadata\MetadataMapList.h">
|
||||
<Filter>src\library\metadata</Filter>
|
||||
</ClInclude>
|
||||
@ -438,23 +378,98 @@
|
||||
<ClInclude Include="i18n\Locale.h">
|
||||
<Filter>src\i18n</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="sdk\IIndexerSource.h">
|
||||
<Filter>src\sdk</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="sdk\IRetainedTrackWriter.h">
|
||||
<Filter>src\sdk</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="library\query\local\TrackMetadataQuery.h">
|
||||
<Filter>src\library\query\local</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="sdk\IIndexerWriter.h">
|
||||
<Filter>src\sdk</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="sdk\IIndexerNotifier.h">
|
||||
<Filter>src\sdk</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="sdk\IEnvironment.h">
|
||||
<Filter>src\sdk</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="sdk\IDSP.h">
|
||||
<Filter>src\sdk\audio</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="sdk\IDecoderFactory.h">
|
||||
<Filter>src\sdk\audio</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="sdk\IDecoder.h">
|
||||
<Filter>src\sdk\audio</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="sdk\IOutput.h">
|
||||
<Filter>src\sdk\audio</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="sdk\IBuffer.h">
|
||||
<Filter>src\sdk\audio</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="sdk\IBufferProvider.h">
|
||||
<Filter>src\sdk\audio</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="sdk\IDataStreamFactory.h">
|
||||
<Filter>src\sdk\io</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="sdk\IDataStream.h">
|
||||
<Filter>src\sdk\io</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="sdk\IVisualizer.h">
|
||||
<Filter>src\sdk\vis</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="sdk\IPcmVisualizer.h">
|
||||
<Filter>src\sdk\vis</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="sdk\ISpectrumVisualizer.h">
|
||||
<Filter>src\sdk\vis</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="sdk\ISimpleDataProvider.h">
|
||||
<Filter>src\sdk\library</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="sdk\IPlaybackRemote.h">
|
||||
<Filter>src\sdk\audio</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="sdk\IMetadataReader.h">
|
||||
<Filter>src\sdk\library</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="sdk\IPlaybackService.h">
|
||||
<Filter>src\sdk\audio</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="sdk\IAnalyzer.h">
|
||||
<Filter>src\sdk\audio</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="sdk\IIndexerNotifier.h">
|
||||
<Filter>src\sdk\indexer</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="sdk\IIndexerSource.h">
|
||||
<Filter>src\sdk\indexer</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="sdk\IIndexerWriter.h">
|
||||
<Filter>src\sdk\indexer</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="sdk\ITrackWriter.h">
|
||||
<Filter>src\sdk\library</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="sdk\ITrackListEditor.h">
|
||||
<Filter>src\sdk\library</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="sdk\ITrackList.h">
|
||||
<Filter>src\sdk\library</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="sdk\ITrack.h">
|
||||
<Filter>src\sdk\library</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="sdk\IRetainedTrackWriter.h">
|
||||
<Filter>src\sdk\library</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="sdk\IRetainedTrack.h">
|
||||
<Filter>src\sdk\library</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="sdk\IMetadataMap.h">
|
||||
<Filter>src\sdk\library</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="sdk\IMetadataMapList.h">
|
||||
<Filter>src\sdk\library</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="sdk\IMetadataValue.h">
|
||||
<Filter>src\sdk\library</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="sdk\IMetadataValueList.h">
|
||||
<Filter>src\sdk\library</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -143,6 +143,7 @@ int main(int argc, char* argv[]) {
|
||||
|
||||
#ifdef WIN32
|
||||
app.SetIcon(IDI_ICON1);
|
||||
app.SetSingleInstanceId("musikbox");
|
||||
#endif
|
||||
/* fire up the indexer if configured to run on startup */
|
||||
if (prefs->GetBool(musik::core::prefs::keys::SyncOnStartup, true)) {
|
||||
|
@ -64,24 +64,27 @@ static const char* KEY_PASSWORD = "password";
|
||||
#define DEFAULT_HEIGHT 17
|
||||
#define DEFAULT_WIDTH 45
|
||||
|
||||
#define STYLE_OVERLAY_LABEL(x) \
|
||||
x->SetContentColor(CURSESPP_OVERLAY_CONTENT);
|
||||
static void applyLabelOverlayStyle(TextLabel& label) {
|
||||
label.SetContentColor(CURSESPP_OVERLAY_CONTENT);
|
||||
}
|
||||
|
||||
#define STYLE_OVERLAY_CHECKBOX(x) \
|
||||
x->SetContentColor(CURSESPP_OVERLAY_CONTENT); \
|
||||
x->SetFocusedContentColor(CURSESPP_OVERLAY_TEXT_FOCUSED);
|
||||
static void applyCheckboxOverlayStyle(Checkbox& cb) {
|
||||
cb.SetContentColor(CURSESPP_OVERLAY_CONTENT);
|
||||
cb.SetFocusedContentColor(CURSESPP_OVERLAY_TEXT_FOCUSED);
|
||||
}
|
||||
|
||||
#define STYLE_OVERLAY_INPUT(x) \
|
||||
if (x->GetStyle() == TextInput::StyleBox) { \
|
||||
x->SetFrameColor(CURSESPP_OVERLAY_FRAME); \
|
||||
x->SetContentColor(CURSESPP_OVERLAY_CONTENT); \
|
||||
x->SetFocusedFrameColor(CURSESPP_OVERLAY_INPUT_FRAME); \
|
||||
x->SetFocusedContentColor(CURSESPP_OVERLAY_CONTENT); \
|
||||
} \
|
||||
else { \
|
||||
x->SetContentColor(CURSESPP_OVERLAY_CONTENT); \
|
||||
x->SetFocusedContentColor(CURSESPP_OVERLAY_TEXT_FOCUSED); \
|
||||
static void applyInputOverlayStyle(TextInput& input) {
|
||||
if (input.GetStyle() == TextInput::StyleBox) {
|
||||
input.SetFrameColor(CURSESPP_OVERLAY_FRAME);
|
||||
input.SetContentColor(CURSESPP_OVERLAY_CONTENT);
|
||||
input.SetFocusedFrameColor(CURSESPP_OVERLAY_INPUT_FRAME);
|
||||
input.SetFocusedContentColor(CURSESPP_OVERLAY_CONTENT);
|
||||
}
|
||||
else {
|
||||
input.SetContentColor(CURSESPP_OVERLAY_CONTENT);
|
||||
input.SetFocusedContentColor(CURSESPP_OVERLAY_TEXT_FOCUSED);
|
||||
}
|
||||
}
|
||||
|
||||
#define RIGHT(x) (x->GetX() + x->GetWidth())
|
||||
#define TEXT_WIDTH(x) ((int) u8cols(x->GetText()))
|
||||
@ -183,18 +186,18 @@ void ServerOverlay::InitViews() {
|
||||
this->pwInput.reset(new TextInput(TextInput::StyleLine, IInput::InputPassword));
|
||||
|
||||
/* style 'em */
|
||||
STYLE_OVERLAY_LABEL(this->titleLabel);
|
||||
STYLE_OVERLAY_CHECKBOX(this->enableWssCb);
|
||||
STYLE_OVERLAY_LABEL(this->wssPortLabel);
|
||||
STYLE_OVERLAY_INPUT(this->wssPortInput);
|
||||
STYLE_OVERLAY_CHECKBOX(this->enableHttpCb);
|
||||
STYLE_OVERLAY_LABEL(this->httpPortLabel);
|
||||
STYLE_OVERLAY_INPUT(this->httpPortInput);
|
||||
STYLE_OVERLAY_CHECKBOX(this->enableSyncTransCb);
|
||||
STYLE_OVERLAY_LABEL(this->transCacheLabel);
|
||||
STYLE_OVERLAY_INPUT(this->transCacheInput);
|
||||
STYLE_OVERLAY_LABEL(this->pwLabel);
|
||||
STYLE_OVERLAY_INPUT(this->pwInput);
|
||||
applyLabelOverlayStyle(*this->titleLabel);
|
||||
applyCheckboxOverlayStyle(*this->enableWssCb);
|
||||
applyLabelOverlayStyle(*this->wssPortLabel);
|
||||
applyInputOverlayStyle(*this->wssPortInput);
|
||||
applyCheckboxOverlayStyle(*this->enableHttpCb);
|
||||
applyLabelOverlayStyle(*this->httpPortLabel);
|
||||
applyInputOverlayStyle(*this->httpPortInput);
|
||||
applyCheckboxOverlayStyle(*this->enableSyncTransCb);
|
||||
applyLabelOverlayStyle(*this->transCacheLabel);
|
||||
applyInputOverlayStyle(*this->transCacheInput);
|
||||
applyLabelOverlayStyle(*this->pwLabel);
|
||||
applyInputOverlayStyle(*this->pwInput);
|
||||
|
||||
/* add 'em */
|
||||
this->AddWindow(this->titleLabel);
|
||||
|
@ -137,6 +137,10 @@ void App::SetIcon(int resourceId) {
|
||||
win32::SetIcon(resourceId);
|
||||
}
|
||||
}
|
||||
|
||||
void App::SetSingleInstanceId(const std::string& uniqueId) {
|
||||
this->uniqueId = uniqueId;
|
||||
}
|
||||
#endif
|
||||
|
||||
void App::SetMinimizeToTray(bool minimizeToTray) {
|
||||
@ -183,6 +187,17 @@ void App::OnResized() {
|
||||
}
|
||||
|
||||
void App::Run(ILayoutPtr layout) {
|
||||
#ifdef WIN32
|
||||
if (this->uniqueId.size()) {
|
||||
win32::EnableSingleInstance(uniqueId);
|
||||
|
||||
if (win32::AlreadyRunning()) {
|
||||
win32::ShowOtherInstance();
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
Colors::Init(this->colorMode);
|
||||
|
||||
if (this->colorTheme.size()) {
|
||||
|
@ -62,6 +62,7 @@ namespace cursespp {
|
||||
|
||||
#ifdef WIN32
|
||||
void SetIcon(int resourceId);
|
||||
void SetSingleInstanceId(const std::string& uniqueId);
|
||||
#endif
|
||||
|
||||
void Run(ILayoutPtr layout);
|
||||
@ -110,6 +111,7 @@ namespace cursespp {
|
||||
|
||||
#ifdef WIN32
|
||||
int iconId;
|
||||
std::string uniqueId;
|
||||
#endif
|
||||
};
|
||||
}
|
||||
|
@ -35,6 +35,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "Win32Util.h"
|
||||
#include <Windows.h>
|
||||
#include <Commctrl.h>
|
||||
#include <shellapi.h>
|
||||
@ -42,6 +43,7 @@
|
||||
#ifdef WIN32
|
||||
|
||||
#define WM_TRAYICON (WM_USER + 2000)
|
||||
#define WM_SHOW_OTHER_INSTANCE (WM_USER + 2001)
|
||||
|
||||
static std::basic_string<TCHAR> className = L"Curses_App";
|
||||
static HWND mainWindow = nullptr;
|
||||
@ -50,8 +52,10 @@ static std::unique_ptr<NOTIFYICONDATA> trayIcon;
|
||||
static bool minimizeToTray = false, minimizedToTray = false;
|
||||
static std::string appTitle;
|
||||
static HICON icon16 = nullptr, icon32 = nullptr;
|
||||
static HANDLE runningMutex;
|
||||
static DWORD runningMutexLastError = 0;
|
||||
|
||||
static void findMainWindow() {
|
||||
static HWND findThisProcessMainWindow() {
|
||||
static TCHAR buffer[256];
|
||||
|
||||
if (mainWindow == nullptr) {
|
||||
@ -64,12 +68,39 @@ static void findMainWindow() {
|
||||
GetClassName(hWnd, buffer, sizeof(buffer));
|
||||
if (className == std::basic_string<TCHAR>(buffer)) {
|
||||
mainWindow = hWnd;
|
||||
return;
|
||||
return hWnd;
|
||||
}
|
||||
}
|
||||
hWnd = GetNextWindow(hWnd, GW_HWNDNEXT);
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static HWND findOtherProcessMainWindow() {
|
||||
static TCHAR buffer[256];
|
||||
|
||||
DWORD dwProcID = GetCurrentProcessId();
|
||||
HWND hWnd = GetTopWindow(GetDesktopWindow());
|
||||
|
||||
while (hWnd) {
|
||||
DWORD dwWndProcID = 0;
|
||||
GetWindowThreadProcessId(hWnd, &dwWndProcID);
|
||||
if (dwWndProcID != dwProcID) { /* not in this process */
|
||||
GetClassName(hWnd, buffer, sizeof(buffer));
|
||||
if (className == std::basic_string<TCHAR>(buffer)) {
|
||||
::GetWindowText(hWnd, buffer, sizeof(buffer));
|
||||
if (appTitle == u16to8(buffer)) { /* title must match*/
|
||||
return hWnd;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hWnd = GetNextWindow(hWnd, GW_HWNDNEXT);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static HICON loadIcon(int resourceId, int size) {
|
||||
@ -97,6 +128,19 @@ static void initTrayIcon(HWND hwnd) {
|
||||
}
|
||||
}
|
||||
|
||||
static void restoreFromTray(HWND hwnd) {
|
||||
Shell_NotifyIcon(NIM_DELETE, trayIcon.get());
|
||||
minimizedToTray = false;
|
||||
ShowWindow(hwnd, SW_SHOWNORMAL);
|
||||
|
||||
}
|
||||
|
||||
static void resetMutex() {
|
||||
CloseHandle(runningMutex);
|
||||
runningMutex = nullptr;
|
||||
runningMutexLastError = 0;
|
||||
}
|
||||
|
||||
static LRESULT CALLBACK wndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, UINT_PTR id, DWORD_PTR data) {
|
||||
if (minimizeToTray) {
|
||||
if ((msg == WM_SIZE && wparam == SIZE_MINIMIZED) ||
|
||||
@ -117,41 +161,49 @@ static LRESULT CALLBACK wndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpara
|
||||
|
||||
if (msg == WM_TRAYICON) {
|
||||
if (LOWORD(lparam) == WM_LBUTTONUP) {
|
||||
Shell_NotifyIcon(NIM_DELETE, trayIcon.get());
|
||||
minimizedToTray = false;
|
||||
ShowWindow(hwnd, SW_SHOWNORMAL);
|
||||
restoreFromTray(hwnd);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (msg == WM_SHOW_OTHER_INSTANCE) {
|
||||
cursespp::win32::ShowMainWindow();
|
||||
restoreFromTray(hwnd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (msg == WM_QUIT) {
|
||||
resetMutex();
|
||||
}
|
||||
|
||||
return DefSubclassProc(hwnd, msg, wparam, lparam);
|
||||
}
|
||||
|
||||
namespace cursespp {
|
||||
namespace win32 {
|
||||
void ShowMainWindow() {
|
||||
findMainWindow();
|
||||
findThisProcessMainWindow();
|
||||
if (mainWindow) {
|
||||
ShowWindow(mainWindow, SW_SHOWNORMAL);
|
||||
}
|
||||
}
|
||||
|
||||
void HideMainWindow() {
|
||||
findMainWindow();
|
||||
findThisProcessMainWindow();
|
||||
if (mainWindow) {
|
||||
ShowWindow(mainWindow, SW_HIDE);
|
||||
}
|
||||
}
|
||||
|
||||
void Minimize() {
|
||||
findMainWindow();
|
||||
findThisProcessMainWindow();
|
||||
if (mainWindow) {
|
||||
ShowWindow(mainWindow, SW_SHOWMINIMIZED);
|
||||
}
|
||||
}
|
||||
|
||||
HWND GetMainWindow() {
|
||||
findMainWindow();
|
||||
findThisProcessMainWindow();
|
||||
return mainWindow;
|
||||
}
|
||||
|
||||
@ -177,6 +229,29 @@ namespace cursespp {
|
||||
void SetAppTitle(const std::string& title) {
|
||||
appTitle = title;
|
||||
}
|
||||
|
||||
bool AlreadyRunning() {
|
||||
return !IsDebuggerPresent() && (runningMutexLastError == ERROR_ALREADY_EXISTS);
|
||||
}
|
||||
|
||||
void ShowOtherInstance() {
|
||||
HWND otherHwnd = findOtherProcessMainWindow();
|
||||
if (otherHwnd) {
|
||||
SendMessage(otherHwnd, WM_SHOW_OTHER_INSTANCE, 0, 0);
|
||||
::SetForegroundWindow(otherHwnd);
|
||||
}
|
||||
}
|
||||
|
||||
void EnableSingleInstance(const std::string& uniqueId) {
|
||||
if (uniqueId.size() && !runningMutex) {
|
||||
std::string mutexName = "cursespp::" + uniqueId;
|
||||
runningMutex = CreateMutexA(nullptr, false, mutexName.c_str());
|
||||
runningMutexLastError = GetLastError();
|
||||
}
|
||||
else {
|
||||
resetMutex();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -48,6 +48,9 @@ namespace cursespp {
|
||||
void SetIcon(int resourceId);
|
||||
void SetAppTitle(const std::string& title);
|
||||
void SetMinimizeToTray(bool enabled);
|
||||
void EnableSingleInstance(const std::string& uniqueId);
|
||||
bool AlreadyRunning();
|
||||
void ShowOtherInstance();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -95,7 +95,7 @@ abstract class PlayerWrapper {
|
||||
|
||||
if (preDuckGlobalVolume != DUCK_NONE) {
|
||||
preDuckGlobalVolume = volume
|
||||
volume = volume * DUCK_COEF
|
||||
volume *= DUCK_COEF
|
||||
}
|
||||
|
||||
if (volume != globalVolume) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user