Compare commits
9 commits
main
...
users/sera
Author | SHA1 | Date | |
---|---|---|---|
|
7711a336db | ||
|
81018fc84b | ||
|
7704f153f4 | ||
|
0c60d64b09 | ||
|
4d888627e8 | ||
|
82cba89f7d | ||
|
2695fefaee | ||
|
0dd4540405 | ||
|
74614c476c |
5
.github/actions/spell-check/expect.txt
vendored
5
.github/actions/spell-check/expect.txt
vendored
|
@ -1309,6 +1309,7 @@ mlcfg
|
||||||
mmdeviceapi
|
mmdeviceapi
|
||||||
mmi
|
mmi
|
||||||
mmsys
|
mmsys
|
||||||
|
mmsystem
|
||||||
mockapi
|
mockapi
|
||||||
MODECHANGE
|
MODECHANGE
|
||||||
moderncop
|
moderncop
|
||||||
|
@ -1472,6 +1473,7 @@ NOTIFYICONDATAW
|
||||||
NOTIMPL
|
NOTIMPL
|
||||||
notmatch
|
notmatch
|
||||||
Noto
|
Noto
|
||||||
|
NOTOPMOST
|
||||||
NOTRACK
|
NOTRACK
|
||||||
NOUPDATE
|
NOUPDATE
|
||||||
NOZORDER
|
NOZORDER
|
||||||
|
@ -2078,6 +2080,7 @@ svgpreviewhandler
|
||||||
SWC
|
SWC
|
||||||
SWFO
|
SWFO
|
||||||
Switchbetweenvirtualdesktops
|
Switchbetweenvirtualdesktops
|
||||||
|
SWITCHEND
|
||||||
SWP
|
SWP
|
||||||
swprintf
|
swprintf
|
||||||
SWRESTORE
|
SWRESTORE
|
||||||
|
@ -2098,6 +2101,7 @@ SYSKEYUP
|
||||||
syslog
|
syslog
|
||||||
SYSMENU
|
SYSMENU
|
||||||
systemd
|
systemd
|
||||||
|
SYSTEMASTERISK
|
||||||
SYSTEMTIME
|
SYSTEMTIME
|
||||||
systray
|
systray
|
||||||
Tadele
|
Tadele
|
||||||
|
@ -2402,6 +2406,7 @@ Winhook
|
||||||
winkey
|
winkey
|
||||||
WINL
|
WINL
|
||||||
winmd
|
winmd
|
||||||
|
winmm
|
||||||
winnt
|
winnt
|
||||||
winres
|
winres
|
||||||
winrt
|
winrt
|
||||||
|
|
245
tools/AlwaysOnTop/AlwaysOnTop.cpp
Normal file
245
tools/AlwaysOnTop/AlwaysOnTop.cpp
Normal file
|
@ -0,0 +1,245 @@
|
||||||
|
#include "pch.h"
|
||||||
|
#include "AlwaysOnTop.h"
|
||||||
|
#include <mmsystem.h> // sound
|
||||||
|
#include <shellapi.h> // game mode
|
||||||
|
|
||||||
|
const static wchar_t* HOTKEY_WINDOW_CLASS_NAME = L"HotkeyHandleWindowClass";
|
||||||
|
|
||||||
|
// common
|
||||||
|
extern "C" IMAGE_DOS_HEADER __ImageBase;
|
||||||
|
|
||||||
|
// common
|
||||||
|
inline bool detect_game_mode()
|
||||||
|
{
|
||||||
|
QUERY_USER_NOTIFICATION_STATE notification_state;
|
||||||
|
if (SHQueryUserNotificationState(¬ification_state) != S_OK)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return (notification_state == QUNS_RUNNING_D3D_FULL_SCREEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
AlwaysOnTop::AlwaysOnTop()
|
||||||
|
{
|
||||||
|
s_instance = this;
|
||||||
|
Init();
|
||||||
|
StartTrackingTopmostWindows();
|
||||||
|
}
|
||||||
|
|
||||||
|
AlwaysOnTop::~AlwaysOnTop()
|
||||||
|
{
|
||||||
|
CleanUp();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AlwaysOnTop::Init()
|
||||||
|
{
|
||||||
|
HINSTANCE hinstance = reinterpret_cast<HINSTANCE>(&__ImageBase);
|
||||||
|
|
||||||
|
WNDCLASSEXW wcex{};
|
||||||
|
wcex.cbSize = sizeof(WNDCLASSEX);
|
||||||
|
wcex.lpfnWndProc = WndProc_Helper;
|
||||||
|
wcex.hInstance = hinstance;
|
||||||
|
wcex.lpszClassName = HOTKEY_WINDOW_CLASS_NAME;
|
||||||
|
RegisterClassExW(&wcex);
|
||||||
|
|
||||||
|
m_hotKeyHandleWindow = CreateWindowExW(WS_EX_TOOLWINDOW, HOTKEY_WINDOW_CLASS_NAME, L"", WS_POPUP, 0, 0, 0, 0, nullptr, nullptr, hinstance, this);
|
||||||
|
if (!m_hotKeyHandleWindow) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
RegisterHotKey(m_hotKeyHandleWindow, 1, MOD_CONTROL | MOD_NOREPEAT, 0x54 /* T */);
|
||||||
|
|
||||||
|
// subscribe to windows events
|
||||||
|
std::array<DWORD, 3> events_to_subscribe = {
|
||||||
|
EVENT_SYSTEM_MOVESIZEEND,
|
||||||
|
EVENT_SYSTEM_SWITCHEND,
|
||||||
|
EVENT_OBJECT_FOCUS
|
||||||
|
};
|
||||||
|
for (const auto event : events_to_subscribe)
|
||||||
|
{
|
||||||
|
auto hook = SetWinEventHook(event, event, nullptr, WinHookProc, 0, 0, WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNPROCESS);
|
||||||
|
if (hook)
|
||||||
|
{
|
||||||
|
m_staticWinEventHooks.emplace_back(hook);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MessageBoxW(NULL, L"Failed to set win event hook", L"AlwaysOnTop error", MB_OK | MB_ICONERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LRESULT AlwaysOnTop::WndProc(HWND window, UINT message, WPARAM wparam, LPARAM lparam) noexcept
|
||||||
|
{
|
||||||
|
if (message == WM_HOTKEY)
|
||||||
|
{
|
||||||
|
if (HWND fw{ GetForegroundWindow() })
|
||||||
|
{
|
||||||
|
ProcessCommand(fw);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AlwaysOnTop::ProcessCommand(HWND window)
|
||||||
|
{
|
||||||
|
bool gameMode = detect_game_mode();
|
||||||
|
if (!m_activateInGameMode && gameMode)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool topmost = IsTopmost(window);
|
||||||
|
if (topmost)
|
||||||
|
{
|
||||||
|
if (ResetTopmostWindow(window))
|
||||||
|
{
|
||||||
|
auto iter = std::find(m_topmostWindows.begin(), m_topmostWindows.end(), window);
|
||||||
|
if (iter != m_topmostWindows.end())
|
||||||
|
{
|
||||||
|
m_topmostWindows.erase(iter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (SetTopmostWindow(window))
|
||||||
|
{
|
||||||
|
m_topmostWindows.insert(m_topmostWindows.begin(), window);
|
||||||
|
OrderWindows();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto soundPlayed = PlaySound((LPCTSTR)SND_ALIAS_SYSTEMASTERISK, NULL, SND_ALIAS_ID);
|
||||||
|
if (!soundPlayed)
|
||||||
|
{
|
||||||
|
MessageBoxW(NULL, L"Sound playing error", L"AlwaysOnTop error", MB_OK | MB_ICONERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AlwaysOnTop::StartTrackingTopmostWindows()
|
||||||
|
{
|
||||||
|
using result_t = std::vector<HWND>;
|
||||||
|
result_t result;
|
||||||
|
|
||||||
|
auto enumWindows = [](HWND hwnd, LPARAM param) -> BOOL {
|
||||||
|
if (!IsWindowVisible(hwnd))
|
||||||
|
{
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto windowName = GetWindowTextLength(hwnd);
|
||||||
|
if (windowName > 0)
|
||||||
|
{
|
||||||
|
result_t& result = *reinterpret_cast<result_t*>(param);
|
||||||
|
result.push_back(hwnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
};
|
||||||
|
|
||||||
|
EnumWindows(enumWindows, reinterpret_cast<LPARAM>(&result));
|
||||||
|
|
||||||
|
for (HWND window : result)
|
||||||
|
{
|
||||||
|
if (IsTopmost(window))
|
||||||
|
{
|
||||||
|
m_topmostWindows.push_back(window);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
OrderWindows();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AlwaysOnTop::ResetAll()
|
||||||
|
{
|
||||||
|
for (HWND topWindow : m_topmostWindows)
|
||||||
|
{
|
||||||
|
if (!ResetTopmostWindow(topWindow))
|
||||||
|
{
|
||||||
|
//TODO: log error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_topmostWindows.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AlwaysOnTop::CleanUp()
|
||||||
|
{
|
||||||
|
ResetAll();
|
||||||
|
if (m_hotKeyHandleWindow)
|
||||||
|
{
|
||||||
|
DestroyWindow(m_hotKeyHandleWindow);
|
||||||
|
m_hotKeyHandleWindow = nullptr;
|
||||||
|
}
|
||||||
|
UnregisterClass(HOTKEY_WINDOW_CLASS_NAME, reinterpret_cast<HINSTANCE>(&__ImageBase));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AlwaysOnTop::OrderWindows() const noexcept
|
||||||
|
{
|
||||||
|
if (m_topmostWindows.empty())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL res = true;
|
||||||
|
for (int i = static_cast<int>(m_topmostWindows.size()) - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
res &= SetWindowPos(m_topmostWindows[i], nullptr, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOREDRAW);
|
||||||
|
|
||||||
|
if (!res)
|
||||||
|
{
|
||||||
|
MessageBoxW(NULL, L"Failed to order windows", L"AlwaysOnTop error", MB_OK | MB_ICONERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AlwaysOnTop::IsTopmost(HWND window) const noexcept
|
||||||
|
{
|
||||||
|
int exStyle = GetWindowLong(window, GWL_EXSTYLE);
|
||||||
|
return (exStyle & WS_EX_TOPMOST) == WS_EX_TOPMOST;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AlwaysOnTop::SetTopmostWindow(HWND window) const noexcept
|
||||||
|
{
|
||||||
|
return SetWindowPos(window, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AlwaysOnTop::ResetTopmostWindow(HWND window) const noexcept
|
||||||
|
{
|
||||||
|
return SetWindowPos(window, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AlwaysOnTop::IsTracked(HWND window) const noexcept
|
||||||
|
{
|
||||||
|
for (HWND topmostWindow : m_topmostWindows)
|
||||||
|
{
|
||||||
|
if (window == topmostWindow)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AlwaysOnTop::HandleWinHookEvent(WinHookEvent* data) noexcept
|
||||||
|
{
|
||||||
|
switch (data->event)
|
||||||
|
{
|
||||||
|
case EVENT_SYSTEM_MOVESIZEEND: // moved or resized
|
||||||
|
case EVENT_SYSTEM_SWITCHEND: // alt-tab
|
||||||
|
case EVENT_OBJECT_FOCUS: // focused
|
||||||
|
{
|
||||||
|
if (IsTracked(data->hwnd))
|
||||||
|
{
|
||||||
|
OrderWindows();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
78
tools/AlwaysOnTop/AlwaysOnTop.h
Normal file
78
tools/AlwaysOnTop/AlwaysOnTop.h
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// common
|
||||||
|
struct WinHookEvent
|
||||||
|
{
|
||||||
|
DWORD event;
|
||||||
|
HWND hwnd;
|
||||||
|
LONG idObject;
|
||||||
|
LONG idChild;
|
||||||
|
DWORD idEventThread;
|
||||||
|
DWORD dwmsEventTime;
|
||||||
|
};
|
||||||
|
|
||||||
|
class AlwaysOnTop
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
AlwaysOnTop();
|
||||||
|
~AlwaysOnTop();
|
||||||
|
|
||||||
|
void Init();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static LRESULT CALLBACK WndProc_Helper(HWND window, UINT message, WPARAM wparam, LPARAM lparam) noexcept
|
||||||
|
{
|
||||||
|
auto thisRef = reinterpret_cast<AlwaysOnTop*>(GetWindowLongPtr(window, GWLP_USERDATA));
|
||||||
|
|
||||||
|
if (!thisRef && (message == WM_CREATE))
|
||||||
|
{
|
||||||
|
const auto createStruct = reinterpret_cast<LPCREATESTRUCT>(lparam);
|
||||||
|
thisRef = reinterpret_cast<AlwaysOnTop*>(createStruct->lpCreateParams);
|
||||||
|
SetWindowLongPtr(window, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(thisRef));
|
||||||
|
}
|
||||||
|
|
||||||
|
return thisRef ? thisRef->WndProc(window, message, wparam, lparam) :
|
||||||
|
DefWindowProc(window, message, wparam, lparam);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static inline AlwaysOnTop* s_instance = nullptr;
|
||||||
|
std::vector<HWINEVENTHOOK> m_staticWinEventHooks;
|
||||||
|
|
||||||
|
HWND m_hotKeyHandleWindow{ nullptr };
|
||||||
|
std::vector<HWND> m_topmostWindows;
|
||||||
|
|
||||||
|
bool m_activateInGameMode = false;
|
||||||
|
|
||||||
|
LRESULT WndProc(HWND, UINT, WPARAM, LPARAM) noexcept;
|
||||||
|
|
||||||
|
void ProcessCommand(HWND window);
|
||||||
|
void StartTrackingTopmostWindows();
|
||||||
|
void ResetAll();
|
||||||
|
void CleanUp();
|
||||||
|
bool OrderWindows() const noexcept;
|
||||||
|
|
||||||
|
bool IsTopmost(HWND window) const noexcept;
|
||||||
|
bool SetTopmostWindow(HWND window) const noexcept;
|
||||||
|
bool ResetTopmostWindow(HWND window) const noexcept;
|
||||||
|
|
||||||
|
bool IsTracked(HWND window) const noexcept;
|
||||||
|
|
||||||
|
void HandleWinHookEvent(WinHookEvent* data) noexcept;
|
||||||
|
|
||||||
|
static void CALLBACK WinHookProc(HWINEVENTHOOK winEventHook,
|
||||||
|
DWORD event,
|
||||||
|
HWND window,
|
||||||
|
LONG object,
|
||||||
|
LONG child,
|
||||||
|
DWORD eventThread,
|
||||||
|
DWORD eventTime)
|
||||||
|
{
|
||||||
|
WinHookEvent data{ event, window, object, child, eventThread, eventTime };
|
||||||
|
if (s_instance)
|
||||||
|
{
|
||||||
|
s_instance->HandleWinHookEvent(&data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
31
tools/AlwaysOnTop/AlwaysOnTop.sln
Normal file
31
tools/AlwaysOnTop/AlwaysOnTop.sln
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio Version 16
|
||||||
|
VisualStudioVersion = 16.0.31424.327
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AlwaysOnTop", "AlwaysOnTop.vcxproj", "{24992310-6878-43B7-A01B-B8504A119B77}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|x64 = Debug|x64
|
||||||
|
Debug|x86 = Debug|x86
|
||||||
|
Release|x64 = Release|x64
|
||||||
|
Release|x86 = Release|x86
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{24992310-6878-43B7-A01B-B8504A119B77}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{24992310-6878-43B7-A01B-B8504A119B77}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{24992310-6878-43B7-A01B-B8504A119B77}.Debug|x86.ActiveCfg = Debug|Win32
|
||||||
|
{24992310-6878-43B7-A01B-B8504A119B77}.Debug|x86.Build.0 = Debug|Win32
|
||||||
|
{24992310-6878-43B7-A01B-B8504A119B77}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{24992310-6878-43B7-A01B-B8504A119B77}.Release|x64.Build.0 = Release|x64
|
||||||
|
{24992310-6878-43B7-A01B-B8504A119B77}.Release|x86.ActiveCfg = Release|Win32
|
||||||
|
{24992310-6878-43B7-A01B-B8504A119B77}.Release|x86.Build.0 = Release|Win32
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {5941BFF2-F97E-4BA8-A663-F5861673B0A4}
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
176
tools/AlwaysOnTop/AlwaysOnTop.vcxproj
Normal file
176
tools/AlwaysOnTop/AlwaysOnTop.vcxproj
Normal file
|
@ -0,0 +1,176 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<Import Project="packages\Microsoft.Windows.CppWinRT.2.0.211028.7\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('packages\Microsoft.Windows.CppWinRT.2.0.211028.7\build\native\Microsoft.Windows.CppWinRT.props')" />
|
||||||
|
<ItemGroup Label="ProjectConfigurations">
|
||||||
|
<ProjectConfiguration Include="Debug|Win32">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|Win32">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Debug|x64">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|x64">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
</ItemGroup>
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<VCProjectVersion>16.0</VCProjectVersion>
|
||||||
|
<Keyword>Win32Proj</Keyword>
|
||||||
|
<ProjectGuid>{24992310-6878-43b7-a01b-b8504a119b77}</ProjectGuid>
|
||||||
|
<RootNamespace>AlwaysOnTop</RootNamespace>
|
||||||
|
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v142</PlatformToolset>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v142</PlatformToolset>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v142</PlatformToolset>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v142</PlatformToolset>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
|
<ImportGroup Label="ExtensionSettings">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="Shared">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<PropertyGroup Label="UserMacros" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Windows</SubSystem>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<AdditionalDependencies>winmm.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Windows</SubSystem>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<AdditionalDependencies>winmm.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Windows</SubSystem>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<AdditionalDependencies>winmm.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Windows</SubSystem>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<AdditionalDependencies>winmm.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="AlwaysOnTop.cpp" />
|
||||||
|
<ClCompile Include="main.cpp" />
|
||||||
|
<ClCompile Include="pch.cpp">
|
||||||
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
|
||||||
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
|
||||||
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
|
||||||
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="AlwaysOnTop.h" />
|
||||||
|
<ClInclude Include="pch.h" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="packages.config" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
<Import Project="packages\Microsoft.Windows.CppWinRT.2.0.211028.7\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('packages\Microsoft.Windows.CppWinRT.2.0.211028.7\build\native\Microsoft.Windows.CppWinRT.targets')" />
|
||||||
|
<Import Project="packages\Microsoft.Windows.ImplementationLibrary.1.0.211019.2\build\native\Microsoft.Windows.ImplementationLibrary.targets" Condition="Exists('packages\Microsoft.Windows.ImplementationLibrary.1.0.211019.2\build\native\Microsoft.Windows.ImplementationLibrary.targets')" />
|
||||||
|
</ImportGroup>
|
||||||
|
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||||
|
<PropertyGroup>
|
||||||
|
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Error Condition="!Exists('packages\Microsoft.Windows.CppWinRT.2.0.211028.7\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', 'packages\Microsoft.Windows.CppWinRT.2.0.211028.7\build\native\Microsoft.Windows.CppWinRT.props'))" />
|
||||||
|
<Error Condition="!Exists('packages\Microsoft.Windows.CppWinRT.2.0.211028.7\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\Microsoft.Windows.CppWinRT.2.0.211028.7\build\native\Microsoft.Windows.CppWinRT.targets'))" />
|
||||||
|
<Error Condition="!Exists('packages\Microsoft.Windows.ImplementationLibrary.1.0.211019.2\build\native\Microsoft.Windows.ImplementationLibrary.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\Microsoft.Windows.ImplementationLibrary.1.0.211019.2\build\native\Microsoft.Windows.ImplementationLibrary.targets'))" />
|
||||||
|
</Target>
|
||||||
|
</Project>
|
39
tools/AlwaysOnTop/AlwaysOnTop.vcxproj.filters
Normal file
39
tools/AlwaysOnTop/AlwaysOnTop.vcxproj.filters
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup>
|
||||||
|
<Filter Include="Source Files">
|
||||||
|
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||||
|
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Header Files">
|
||||||
|
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||||
|
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Resource Files">
|
||||||
|
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||||
|
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||||
|
</Filter>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="AlwaysOnTop.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="pch.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="main.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="pch.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="AlwaysOnTop.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="packages.config" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
38
tools/AlwaysOnTop/main.cpp
Normal file
38
tools/AlwaysOnTop/main.cpp
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
#include "pch.h"
|
||||||
|
|
||||||
|
#include "AlwaysOnTop.h"
|
||||||
|
|
||||||
|
inline int run_message_loop(const bool until_idle = false, const std::optional<uint32_t> timeout_seconds = {})
|
||||||
|
{
|
||||||
|
MSG msg{};
|
||||||
|
bool stop = false;
|
||||||
|
UINT_PTR timerId = 0;
|
||||||
|
if (timeout_seconds.has_value())
|
||||||
|
{
|
||||||
|
timerId = SetTimer(nullptr, 0, *timeout_seconds * 1000, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!stop && GetMessageW(&msg, nullptr, 0, 0))
|
||||||
|
{
|
||||||
|
TranslateMessage(&msg);
|
||||||
|
DispatchMessageW(&msg);
|
||||||
|
stop = until_idle && !PeekMessageW(&msg, nullptr, 0, 0, PM_NOREMOVE);
|
||||||
|
stop = stop || (msg.message == WM_TIMER && msg.wParam == timerId);
|
||||||
|
}
|
||||||
|
if (timeout_seconds.has_value())
|
||||||
|
{
|
||||||
|
KillTimer(nullptr, timerId);
|
||||||
|
}
|
||||||
|
return static_cast<int>(msg.wParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ PWSTR lpCmdLine, _In_ int nCmdShow)
|
||||||
|
{
|
||||||
|
winrt::init_apartment();
|
||||||
|
|
||||||
|
AlwaysOnTop app;
|
||||||
|
|
||||||
|
run_message_loop();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
5
tools/AlwaysOnTop/packages.config
Normal file
5
tools/AlwaysOnTop/packages.config
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<packages>
|
||||||
|
<package id="Microsoft.Windows.CppWinRT" version="2.0.211028.7" targetFramework="native" />
|
||||||
|
<package id="Microsoft.Windows.ImplementationLibrary" version="1.0.211019.2" targetFramework="native" />
|
||||||
|
</packages>
|
1
tools/AlwaysOnTop/pch.cpp
Normal file
1
tools/AlwaysOnTop/pch.cpp
Normal file
|
@ -0,0 +1 @@
|
||||||
|
#include "pch.h"
|
4
tools/AlwaysOnTop/pch.h
Normal file
4
tools/AlwaysOnTop/pch.h
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
#pragma once
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#include <windows.h>
|
||||||
|
#include <winrt/base.h>
|
Loading…
Reference in a new issue