-
Notifications
You must be signed in to change notification settings - Fork 20
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add ability to start the application minimised to tray by specifying …
…`--tray` launch option. Addresses Issue #1.
- Loading branch information
mini)(ant
committed
Sep 17, 2018
1 parent
42c054b
commit 1ca396b
Showing
14 changed files
with
427 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
#include "OStreamSink.h" | ||
|
||
using namespace miniant::Spdlog; | ||
|
||
OStreamSink::OStreamSink(std::shared_ptr<std::ostream> outputStream, bool forceFlush): | ||
m_outputStream(std::move(outputStream)), | ||
m_forceFlush(forceFlush) {} | ||
|
||
std::mutex& OStreamSink::GetMutex() { | ||
return mutex_; | ||
} | ||
|
||
void OStreamSink::sink_it_(const spdlog::details::log_msg& message) { | ||
fmt::memory_buffer formattedMessage; | ||
sink::formatter_->format(message, formattedMessage); | ||
m_outputStream->write(formattedMessage.data(), static_cast<std::streamsize>(formattedMessage.size())); | ||
if (m_forceFlush) | ||
m_outputStream->flush(); | ||
} | ||
|
||
void OStreamSink::flush_() { | ||
m_outputStream->flush(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
#pragma once | ||
|
||
// Work-around for compilation error caused by spdlog using Windows headers | ||
#include <Windows.h> | ||
|
||
#include <spdlog/sinks/base_sink.h> | ||
|
||
#include <mutex> | ||
|
||
namespace miniant::Spdlog { | ||
|
||
class OStreamSink : public spdlog::sinks::base_sink<std::mutex> { | ||
public: | ||
explicit OStreamSink(std::shared_ptr<std::ostream> outputStream, bool forceFlush=false); | ||
|
||
std::mutex& GetMutex(); | ||
|
||
protected: | ||
void sink_it_(const spdlog::details::log_msg& message) override; | ||
void flush_() override; | ||
|
||
private: | ||
std::shared_ptr<std::ostream> m_outputStream; | ||
bool m_forceFlush; | ||
}; | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
#include "Console.h" | ||
|
||
#include <Windows.h> | ||
|
||
#include <iostream> | ||
|
||
using namespace miniant::Windows; | ||
|
||
Console::Console(std::function<void()> onShow): | ||
m_onShow(std::move(onShow)) {} | ||
|
||
void Console::Open() { | ||
::AllocConsole(); | ||
|
||
FILE* dummy; | ||
freopen_s(&dummy, "conout$", "w", stdout); | ||
std::cout.clear(); | ||
|
||
if (m_onShow) | ||
m_onShow(); | ||
} | ||
|
||
void Console::Close() { | ||
::SendMessage(::GetConsoleWindow(), WM_CLOSE, 0, 0); | ||
::FreeConsole(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
#pragma once | ||
|
||
#include <functional> | ||
|
||
namespace miniant::Windows { | ||
|
||
class Console { | ||
public: | ||
Console(std::function<void()> onShow); | ||
|
||
void Open(); | ||
void Close(); | ||
|
||
private: | ||
std::function<void()> m_onShow; | ||
}; | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
#include "Exception.h" | ||
|
||
#include <Windows.h> | ||
|
||
#include <string> | ||
|
||
using namespace miniant::Windows; | ||
|
||
std::string GetErrorMessage() noexcept { | ||
DWORD lastError = ::GetLastError(); | ||
return "Last error: " + std::to_string(lastError); | ||
} | ||
|
||
Exception::Exception() noexcept: std::runtime_error(GetErrorMessage()) {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
#pragma once | ||
|
||
#include <stdexcept> | ||
|
||
namespace miniant::Windows { | ||
|
||
class Exception : std::runtime_error { | ||
public: | ||
Exception() noexcept; | ||
}; | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
#include "GlobalWindowProcedure.h" | ||
|
||
#include "Exception.h" | ||
|
||
using namespace miniant::Windows; | ||
|
||
std::unordered_map<HWND, GlobalWindowProcedure::WindowProcedure> GlobalWindowProcedure::s_windowProcedureMap; | ||
|
||
UINT GlobalWindowProcedure::GetFreeEventId() noexcept { | ||
static UINT nextFreeEventId = WM_USER; | ||
return nextFreeEventId++; | ||
} | ||
|
||
WNDCLASS GlobalWindowProcedure::RegisterWindowClass(LPCTSTR lpszClassName) { | ||
WNDCLASS wc = {}; | ||
wc.lpszClassName = lpszClassName; | ||
wc.lpfnWndProc = &WndProc; | ||
if (!::GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, reinterpret_cast<LPCWSTR>(&WndProc), &wc.hInstance)) | ||
throw Exception(); | ||
|
||
if (::RegisterClass(&wc) == 0) | ||
throw Exception(); | ||
|
||
return wc; | ||
} | ||
|
||
void GlobalWindowProcedure::SetWindowProcedure(HWND hWnd, WindowProcedure procedure) { | ||
s_windowProcedureMap[hWnd] = procedure; | ||
} | ||
|
||
LRESULT CALLBACK GlobalWindowProcedure::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { | ||
WindowProcedure* windowProcedure; | ||
try { | ||
windowProcedure = &s_windowProcedureMap.at(hWnd); | ||
} catch (std::out_of_range&) { | ||
return ::DefWindowProc(hWnd, uMsg, wParam, lParam); | ||
} | ||
|
||
if (*windowProcedure) { | ||
std::optional<LRESULT> lResult = (*windowProcedure)(hWnd, uMsg, wParam, lParam); | ||
if (lResult) | ||
return lResult.value(); | ||
} | ||
|
||
return ::DefWindowProc(hWnd, uMsg, wParam, lParam); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
#pragma once | ||
|
||
#include <Windows.h> | ||
|
||
#include <functional> | ||
#include <map> | ||
#include <optional> | ||
|
||
namespace miniant::Windows { | ||
|
||
class GlobalWindowProcedure { | ||
public: | ||
using WindowProcedure = std::function<std::optional<LRESULT>(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lparam)>; | ||
|
||
static UINT GetFreeEventId() noexcept; | ||
|
||
static WNDCLASS RegisterWindowClass(LPCTSTR lpszClassName); | ||
static void SetWindowProcedure(HWND hWnd, WindowProcedure procedure); | ||
|
||
private: | ||
static std::unordered_map<HWND, WindowProcedure> s_windowProcedureMap; | ||
|
||
static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); | ||
}; | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
#include "MessagingWindow.h" | ||
|
||
#include "Exception.h" | ||
#include "GlobalWindowProcedure.h" | ||
|
||
using namespace miniant::Windows; | ||
|
||
constexpr TCHAR CLASS_NAME[] = TEXT("MessagingWindow"); | ||
|
||
MessagingWindow::MessagingWindow() { | ||
m_hWnd = ::CreateWindowEx( | ||
0, | ||
CLASS_NAME, | ||
NULL, | ||
0, | ||
0, 0, 0, 0, | ||
HWND_MESSAGE, | ||
NULL, | ||
GlobalWindowProcedure::RegisterWindowClass(CLASS_NAME).hInstance, | ||
NULL); | ||
if (m_hWnd == NULL) | ||
throw Exception(); | ||
|
||
GlobalWindowProcedure::SetWindowProcedure(m_hWnd, [this](HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { | ||
auto eventHandler = m_eventHandlerMap.find(uMsg); | ||
if (eventHandler != m_eventHandlerMap.end()) { | ||
if (eventHandler->second) | ||
return eventHandler->second(*this, wParam, lParam); | ||
} | ||
|
||
return std::optional<LRESULT>(); | ||
}); | ||
} | ||
|
||
MessagingWindow::~MessagingWindow() noexcept { | ||
GlobalWindowProcedure::SetWindowProcedure(m_hWnd, nullptr); | ||
} | ||
|
||
HWND MessagingWindow::GetHWindow() noexcept { | ||
return m_hWnd; | ||
} | ||
|
||
void MessagingWindow::SetEventHandler(UINT event, EventHandler handler) { | ||
m_eventHandlerMap[event] = std::move(handler); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
#pragma once | ||
|
||
#include <Windows.h> | ||
|
||
#include <functional> | ||
#include <map> | ||
#include <optional> | ||
|
||
namespace miniant::Windows { | ||
|
||
class MessagingWindow { | ||
public: | ||
using EventHandler = std::function<std::optional<LRESULT>(MessagingWindow&, WPARAM, LPARAM)>; | ||
|
||
MessagingWindow(); | ||
~MessagingWindow() noexcept; | ||
|
||
HWND GetHWindow() noexcept; | ||
|
||
void SetEventHandler(UINT event, EventHandler handler); | ||
|
||
private: | ||
HWND m_hWnd; | ||
std::unordered_map<UINT, EventHandler> m_eventHandlerMap; | ||
}; | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
#include "TrayIcon.h" | ||
|
||
#include "Exception.h" | ||
#include "GlobalWindowProcedure.h" | ||
|
||
using namespace miniant::Windows; | ||
|
||
TrayIcon::TrayIcon(MessagingWindow& window, HICON hIcon): | ||
m_window(window) { | ||
m_data = {}; | ||
m_data.cbSize = sizeof(m_data); | ||
m_data.uVersion = NOTIFYICON_VERSION_4; | ||
m_data.uFlags = NIF_ICON | NIF_MESSAGE; | ||
m_data.hWnd = window.GetHWindow(); | ||
m_data.hIcon = hIcon; | ||
m_data.uID = 1; | ||
m_data.uCallbackMessage = GlobalWindowProcedure::GetFreeEventId(); | ||
|
||
window.SetEventHandler(m_data.uCallbackMessage, [this](const MessagingWindow& window, WPARAM wParam, LPARAM lParam) { | ||
switch (LOWORD(lParam)) { | ||
case WM_LBUTTONUP: | ||
if (m_lButtonUpHandler) | ||
m_lButtonUpHandler(*this); | ||
break; | ||
|
||
default: | ||
break; | ||
} | ||
|
||
return std::optional<LRESULT>(); | ||
}); | ||
} | ||
|
||
TrayIcon::~TrayIcon() noexcept { | ||
m_window.SetEventHandler(m_data.uCallbackMessage, nullptr); | ||
::Shell_NotifyIcon(NIM_DELETE, &m_data); | ||
} | ||
|
||
void TrayIcon::Show() { | ||
if (!::Shell_NotifyIcon(NIM_ADD, &m_data)) | ||
throw Exception(); | ||
|
||
if (!::Shell_NotifyIcon(NIM_SETVERSION, &m_data)) { | ||
::Shell_NotifyIcon(NIM_DELETE, &m_data); | ||
throw Exception(); | ||
} | ||
} | ||
|
||
void TrayIcon::Hide() { | ||
if (!::Shell_NotifyIcon(NIM_DELETE, &m_data)) | ||
throw Exception(); | ||
} | ||
|
||
void TrayIcon::SetLButtonUpHandler(TrayEventHandler handler) noexcept { | ||
m_lButtonUpHandler = std::move(handler); | ||
} |
Oops, something went wrong.