Skip to content

Instantly share code, notes, and snippets.

@meitinger
Last active November 25, 2018 23:58
Show Gist options
  • Save meitinger/fe45ff4618dca607a545525a8edad021 to your computer and use it in GitHub Desktop.
Save meitinger/fe45ff4618dca607a545525a8edad021 to your computer and use it in GitHub Desktop.
Utility that adds an always-on-top entry in the system menu.
/* Copyright (C) 2008-2018, Manuel Meitinger
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <Windows.h>
#pragma comment(linker, "/SUBSYSTEM:WINDOWS")
#pragma comment(lib, "Kernel32.lib")
#pragma comment(lib, "User32.lib")
#ifdef DLL
#pragma comment(linker, "/ENTRY:DllMain")
#ifdef _WIN64
#pragma comment(linker, "/EXPORT:CallWndProc")
#pragma comment(linker, "/EXPORT:GetMsgProc")
#else
#pragma comment(linker, "/EXPORT:CallWndProc=_CallWndProc@12")
#pragma comment(linker, "/EXPORT:GetMsgProc=_GetMsgProc@12")
#endif
#define COMMAND 0xEFF0
#define MAXLEN 100
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
// reduce the working set by disabling thread calls
if (fdwReason == DLL_PROCESS_ATTACH)
{
DisableThreadLibraryCalls(hinstDLL);
}
return TRUE;
}
static LPTSTR GetMenuItemString()
{
static LONG initialized = 0;
static TCHAR caption[MAXLEN] = TEXT("Always On &Top");
HMODULE taskmgr;
HMENU menu;
// only try to load the localized string once (thread safe)
if (!InterlockedBitTestAndSet(&initialized, 0))
{
// load the task manager as a resource (don't do this at home kids, erm I mean in a business app)
if ((taskmgr = LoadLibraryEx(TEXT("taskmgr.exe"), NULL, LOAD_LIBRARY_AS_IMAGE_RESOURCE)) != NULL)
{
// find the proper menu and get the "always on top" string
if ((menu = LoadMenu(taskmgr, MAKEINTRESOURCE(106))) != NULL)
{
GetMenuString(menu, 40006, caption, MAXLEN, MF_BYCOMMAND);
DestroyMenu(menu);
}
FreeLibrary(taskmgr);
}
}
// return the localized string
return caption;
}
static VOID InsertOrUpdateMenuItem(HWND window)
{
HMENU menu;
BOOL isNormal;
UINT state;
MENUITEMINFO item;
// get the system menu handle and the current topmost style
if ((menu = GetSystemMenu(window, FALSE)) == NULL)
{
return;
}
isNormal = (GetWindowLongPtr(window, GWL_EXSTYLE) & WS_EX_TOPMOST) == 0;
// get the state of the "always on top" entry and...
if ((state = GetMenuState(menu, COMMAND, MF_BYCOMMAND)) == -1)
{
// ...create it if it doesn't exist or...
item.cbSize = sizeof(item);
item.fMask = MIIM_CHECKMARKS | MIIM_STATE | MIIM_ID | MIIM_STRING;
item.hbmpChecked = NULL;
item.hbmpUnchecked = NULL;
item.fState = isNormal ? MFS_UNCHECKED : MFS_CHECKED;
item.wID = COMMAND;
item.dwTypeData = GetMenuItemString();
InsertMenuItem(menu, SC_CLOSE, FALSE, &item);
}
else
{
// ...update the check mark if necessary
if (((state & MF_CHECKED) == 0) != isNormal)
{
CheckMenuItem(menu, COMMAND, MF_BYCOMMAND | (isNormal ? MFS_UNCHECKED : MFS_CHECKED));
}
}
}
LRESULT CALLBACK CallWndProc(INT code, WPARAM wParam, LPARAM lParam)
{
#define msg ((PCWPSTRUCT)lParam)
if (code == HC_ACTION)
{
switch (msg->message)
{
case WM_ACTIVATE:
{
// create the custom system menu before WM_INITMENUPOPUP
GetSystemMenu(msg->hwnd, FALSE);
break;
}
case WM_INITMENUPOPUP:
{
// add or update the "always on top" entry
if ((BOOL)HIWORD(msg->lParam) == TRUE)
{
InsertOrUpdateMenuItem(msg->hwnd);
}
break;
}
case WM_UNINITMENUPOPUP:
{
// remove the "always on top" entry
if ((HIWORD(msg->lParam) & MF_SYSMENU) != 0)
{
DeleteMenu((HMENU)msg->wParam, COMMAND, MF_BYCOMMAND);
}
break;
}
}
}
return CallNextHookEx(NULL, code, wParam, lParam);
#undef msg
}
LRESULT CALLBACK GetMsgProc(INT code, WPARAM wParam, LPARAM lParam)
{
#define msg ((PMSG)lParam)
if (code == HC_ACTION)
{
// update the window's topmost style if the "always on top" entry was clicked
if (msg->message == WM_SYSCOMMAND && msg->wParam == COMMAND)
{
SetWindowPos(msg->hwnd, (GetWindowLongPtr(msg->hwnd, GWL_EXSTYLE) & WS_EX_TOPMOST) == 0 ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
}
}
return CallNextHookEx(NULL, code, wParam, lParam);
#undef msg
}
#else
#include <Psapi.h>
#pragma comment(linker, "/ENTRY:Run")
#pragma comment(lib, "Psapi.lib")
#ifdef _WIN64
#define MUTEX_NAME TEXT("{E88E4EFC-BEDA-463C-AC93-65154B1817FC}")
#else
#define MUTEX_NAME TEXT("{91383FDC-AF5D-4C17-9347-C3186177EAF6}")
#endif
void Run(void)
{
#define ApiCall(ret) \
{ \
if (!(ret)) \
{ \
exitCode = GetLastError(); \
goto CleanUp; \
} \
}
DWORD exitCode = ERROR_SUCCESS;
TCHAR baseName[MAX_PATH];
DWORD baseNameLen;
HANDLE mutex = NULL;
HMODULE library = NULL;
HOOKPROC callWndProc;
HHOOK callWndHook = NULL;
HOOKPROC getMsgProc;
HHOOK getMsgHook = NULL;
MSG msg;
BOOL ret;
// get the name of the DLL
ApiCall(baseNameLen = GetModuleBaseName(GetCurrentProcess(), NULL, baseName, MAX_PATH));
if (baseName[baseNameLen - 4] != TEXT('.'))
{
exitCode = ERROR_BAD_PATHNAME;
goto CleanUp;
}
baseName[baseNameLen - 3] = TEXT('d');
baseName[baseNameLen - 2] = TEXT('l');
baseName[baseNameLen - 1] = TEXT('l');
// ensure that only one instance is running (but don't fail if the test fails)
ApiCall(mutex = CreateMutex(NULL, FALSE, MUTEX_NAME));
if (GetLastError() == ERROR_ALREADY_EXISTS)
{
exitCode = ERROR_ALREADY_EXISTS;
goto CleanUp;
}
// load the hook library
ApiCall(library = LoadLibrary(baseName));
// for injecting the "always on top" entry into the system menu
ApiCall(callWndProc = (HOOKPROC)GetProcAddress(library, "CallWndProc"));
ApiCall(callWndHook = SetWindowsHookEx(WH_CALLWNDPROC, callWndProc, library, 0));
// initialize the hook for intercepting the entry's command messages
ApiCall(getMsgProc = (HOOKPROC)GetProcAddress(library, "GetMsgProc"));
ApiCall(getMsgHook = SetWindowsHookEx(WH_GETMESSAGE, getMsgProc, library, 0));
// pump the messages until the end of the session
while ((ret = GetMessage(&msg, NULL, 0, 0)) != 0)
{
if (ret == -1)
{
exitCode = GetLastError();
break;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
CleanUp:
if (mutex != NULL)
{
CloseHandle(mutex);
}
if (getMsgHook != NULL)
{
UnhookWindowsHookEx(getMsgHook);
}
if (callWndHook != NULL)
{
UnhookWindowsHookEx(callWndHook);
}
if (library != NULL)
{
FreeLibrary(library);
}
ExitProcess(exitCode);
}
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment