This article contains functions and features that are not documented by the original manufacturer. By following advice in this article, you're doing so at your own risk. The methods presented in this article may rely on internal implementation and may not work in the future.
Intro
If you grab a window title on your Windows 11 (or Windows 10) system and shake it with the mouse, all other open windows on the screen will get minimized to the taskbar. Then if you shake the same window again, they will be brought back to the screen.
This feature is called "window shake" and it was available since Windows 10.
To enable (or disable) it on Windows 11, go to Start -> Settings -> System -> Multi-tasking. It will be available as a checkbox named, "Title bar window shake".On Windows 10, the same option is a part of the "Snap windows" feature in the same multi-tasking settings screen.
The question becomes, can we perform the result of the "window shake" feature programmatically in code?
Rbmm had done some reverse engineering to answer that question.
BTW, the answer is yes.And if you don't want to read how it works and just want to see the code, skip to the end.
"Window Shake" Feature Internals
It all starts in the ThemePreWndProc
function in the uxtheme.dll
module.
uxtheme.dll
is mapped into most GUI processes and provides familiar Windows OS visual styles.
When that window procedure receives the WM_MOVING
message, it calls the SHRegGetBoolUSValueW
function to obtain the System Registry setting:
SHRegGetBoolUSValueW(
L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced",
L"DisallowShaking",
FALSE,
TRUE
);
The result of that check is used to determine whether to continue or not.
IfDisallowShaking
value is set to a non-zero in any of the following registry keys, the "window shake" option is not performed:
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced
Otherwise it calls CShakeWnd::FromHwnd
and if it returns 0, it calls CShakeWnd::Attach
, which creates the CShakeWnd
class and attaches it to the window handle in HWND
using:
There's also an exported API from uxtheme.dll
(only by its ordinal number #86
). It has the following declaration:
The CShakeWnd
class has the following member functions:
CShakeWnd::AddReference
CShakeWnd::Attach
CShakeWnd::CShakeWnd
CShakeWnd::Detach
CShakeWnd::FromHwnd
CShakeWnd::FromHwndAddRef
CShakeWnd::GetMsgProc
CShakeWnd::HandleEscapeActions
CShakeWnd::IsGoodAngle
CShakeWnd::IsGoodLength
CShakeWnd::IsGoodRatio
CShakeWnd::MessageToShell
CShakeWnd::ReleaseReference
CShakeWnd::Shift
CShakeWnd::_cObj
CShakeWnd::_st
After some internal processing, the code will eventually call:
That function internally looks for the window with the "Shell_TrayWnd
" window class:
And then does:
ULONG dwProcessId;
if(GetWindowThreadProcessId(hwndTray, &dwProcessId))
{
AllowSetForegroundWindow(dwProcessId);
//...
}
And lastly:
That sends the hwndTray
a private message 0x4F2
.
The0x4F2
message is a private message for one of the Windows Explorer window classes in theWM_USER
range.
All further processing is then done inside the Explorer.exe
process.
The CShakeWnd::MessageToShell
itself is called from:
And from CShakeWnd::HandleEscapeAction
as such:
; void CShakeWnd::HandleEscapeAction(CShakeWnd::_ESC_ACTION)
;
; rcx = this
; rdx = _ESC_ACTION
mov qword ptr [rsp+8],rbx
push rdi
sub rsp,20h
mov rbx,rcx
mov edi,edx
mov rcx,qword ptr [rcx+58h]
test rcx,rcx
jne lbl_1
cmp edx,1
jne lbl_2
call qword ptr [GetCurrentThreadId]
nop dword ptr [rax+rax]
xor r8d,r8d
lea rdx,[CShakeWnd::GetMsgProc]
mov r9d,eax
lea ecx,[rdi+2]
call qword ptr [SetWindowsHookExW]
nop dword ptr [rax+rax]
mov qword ptr [rbx+58h],rax
jmp lbl_2
lbl_1:
call qword ptr [UnhookWindowsHookEx]
nop dword ptr [rax+rax]
and qword ptr [rbx+58h],0
cmp edi,2
jne lbl_2
mov rcx,qword ptr [rbx+18h]
call CShakeWnd::MessageToShell
lbl_2:
mov rbx,qword ptr [rsp+30h]
add rsp,20h
pop rdi
ret
The OnPreWindowMovingShakeHandler
invokes CShakeWnd::IsGoodLength
, CShakeWnd::IsGoodAngle
, CShakeWnd::IsGoodRatio
to determine what mouse moves to interpret as a shake.
"Window Shake" Implementation In Explorer.exe
Inside the Explorer.exe
, when it receives the 0x4F2
private message, it calls:
//'hWnd' = window handle for the window that was shaken
LRESULT CTray::_ShakeTriggered(enum SHOWDESKTOPTRIGGER, HWND hWnd)
That internally calls IsValidShakeWindow(hWnd)
and then IsShakeEnabled
, that is defined as such:
; int IsShakeEnabled(void)
push rbx
sub rsp,20h
lea rcx,[POLID_NoWindowMinimizingShortcuts] ; {4BF2C693-2A9A-48F8-89A6-0A778F7B1D7D}
call qword ptr [SHWindowsPolicy]
nop dword ptr [rax+rax]
test eax,eax
jne lbl_10
lea ebx,[rax+1]
mov dl,bl
lea rcx,['wil::Feature<__WilFeatureTraits_Feature_AeroShakeEnabled>::GetImpl'::'2'::impl]
call 'wil::details::FeatureImpl<__WilFeatureTraits_Feature_AeroShakeEnabled>::ReportUsage'
mov r9d,ebx
lea rdx,L"DisallowShaking"
xor r8d,r8d
lea rcx,L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced"
call qword ptr [SHRegGetBoolUSValueW]
nop dword ptr [rax+rax]
test eax,eax
jne lbl_10
call IsShakedAllowedInSku
test eax,eax
jne lbl_11
lbl_10:
xor ebx,ebx
lbl_11:
mov eax,ebx
add rsp,20h
pop rbx
ret
IsShakedAllowedInSku
is a gigantic function that determines if the "window shake" feature could be used, besides what is already specified by the "DisallowShaking" Registry setting.
If IsShakeEnabled
function returns success, the code invokes the private CTray::_MinimizeAll
function:
That in turn calls TrayUI::MinimizeAll
:
virtual BOOL TrayUI::MinimizeAll(BOOL b, HANDLE hEvent)
{
SendMessageW(hwnd, 0x435, (WPARAM)hEvent, b);
}
That function sends another private message 0x435
to the window with the "MSTaskSwWClass
" window class and the "Running applications
" title.
Then the following function gets called:
That creates a new worker thread:
That thread minimizes all windows and at the end signals the hEvent
that was passed earlier into CTaskBand::_MinimizeAll
.
Also depending on the boolean variable, that was passed into CTaskBand::_MinimizeAll
, it can send a private message into the Shell desktop window (that is returned by a call to the GetShellWindow
function.) As a result it will call the internal CDesktopBrowser::_Raise(BOOL)
function, with the following call-tree:
CDesktopBrowser::_WndProcBS
CDesktopBrowser::_OnRaise
CDesktopBrowser::_Raise
GetLastActivePopup
CDesktopBrowser::_EnsureRaisedDesktop
SHCreateWorkerWindowW
SetPropW
GlobalAddAtomW
SetPropW
GlobalDeleteAtom
SetPropW
SetPropW
DwmSetWindowAttribute
CZOrderManager::InsertWindowInZOrder
SHRestricted
RegisterDragDrop
CDesktopBrowser::_ShowOrHideDesktopIconsBasedOnDesktopVisibility
__security_check_cookie
ret
LockWindowUpdate
CDesktopBrowser::_SwapParents
GetWindowRect
SetWindowPos
SetForegroundWindow
LockWindowUpdate
SetFocus
__security_check_cookie
ret
PostMessageW
__security_check_cookie
ret
Proof Of Concept
If we eliminate all the System Registry checks, and most importantly, the IsShakedAllowedInSku
call, we can create the following POC function that will minimize all open windows, except for the one passed in as hwndMy
:
void MinimizeAll(_In_ BOOL bDialogsToo, _In_opt_ HWND hwndMy)
{
if (HWND hwnd = FindWindowW(L"Shell_TrayWnd", 0))
{
ULONG dwProcessId;
if (GetWindowThreadProcessId(hwnd, &dwProcessId))
{
AllowSetForegroundWindow(dwProcessId);
//WCHAR name[0x100];
//if (HMODULE hmod = LoadLibraryExW(L"taskbar.dll",
// 0,
// LOAD_LIBRARY_AS_IMAGE_RESOURCE))
//{
// LoadStringW(hmod, 0x252, name, _countof(name));
// FreeLibrary(hmod);
//}
HWND hWndChild = 0;
while (hWndChild = FindWindowExW(hwnd,
hWndChild,
REBARCLASSNAMEW,
0))
{
if (HWND hwndTask = FindWindowEx(hWndChild,
0,
L"MSTaskSwWClass",
0 /*name*/))
{
if (HANDLE hProcess = OpenProcess(PROCESS_DUP_HANDLE,
FALSE,
dwProcessId))
{
if (HANDLE hEvent = CreateEvent(0, 0, 0, 0))
{
HANDLE hRemoteEvent;
if (DuplicateHandle(GetCurrentProcess(),
hEvent,
hProcess,
&hRemoteEvent,
0,
0,
DUPLICATE_SAME_ACCESS))
{
if (PostMessageW(hwndTask,
0x435,
(WPARAM)hRemoteEvent,
bDialogsToo))
{
ULONG n;
while (1 == (n =
MsgWaitForMultipleObjectsEx(1,
&hEvent,
2000,
QS_ALLINPUT,
MWMO_INPUTAVAILABLE)))
{
MSG msg;
while (PeekMessageW(&msg, 0, 0, 0, PM_REMOVE))
{
DispatchMessageW(&msg);
}
}
if (WAIT_OBJECT_0 != n)
{
assert(false);
}
}
DuplicateHandle(hProcess,
hRemoteEvent,
0,
0,
0,
0,
DUPLICATE_CLOSE_SOURCE);
}
CloseHandle(hEvent);
}
CloseHandle(hProcess);
}
break;
}
}
}
}
}
You can get this code snippet at Rbmm's GitHub page.
Conclusion
"Window shake" is a convenience feature of the Windows Explorer that could come handy if you want to minimize all windows, except one.