Browse Source

Fixed #3 and #10

* Instead of the overthinked and overcomplicated way the Win+X
  key combination was handled before, it now just sends a
  WM_CONTEXTMENU message to the Start button and Explorer takes
  care of the rest (I still haven't managed to figure out why the
  COM interface call did not work though)
* Added more info to IImmersiveMonitorService
pull/20/head 22000.168.0.11
Valentin Radu 4 years ago
parent
commit
74966c518a
  1. 242
      ExplorerPatcher/dllmain.c

242
ExplorerPatcher/dllmain.c

@ -165,7 +165,6 @@ HWND archivehWnd;
funchook_t* funchook = NULL; funchook_t* funchook = NULL;
HMODULE hModule = NULL; HMODULE hModule = NULL;
HANDLE hIsWinXShown = NULL; HANDLE hIsWinXShown = NULL;
INT64 lockEnsureWinXHotkeyOnlyOnce;
typedef LONG NTSTATUS, * PNTSTATUS; typedef LONG NTSTATUS, * PNTSTATUS;
#define STATUS_SUCCESS (0x00000000) #define STATUS_SUCCESS (0x00000000)
@ -411,6 +410,31 @@ typedef struct IImmersiveMonitorServiceVtbl
/* [in] */ HMONITOR hMonitor, /* [in] */ HMONITOR hMonitor,
_COM_Outptr_ IUnknown** ppvObject); _COM_Outptr_ IUnknown** ppvObject);
HRESULT(STDMETHODCALLTYPE* method6)(
IImmersiveMonitorService* This);
HRESULT(STDMETHODCALLTYPE* method7)(
IImmersiveMonitorService* This);
HRESULT(STDMETHODCALLTYPE* QueryService)(
IImmersiveMonitorService* This,
HMONITOR hMonitor,
GUID*,
GUID*,
void** ppvObject
);
HRESULT(STDMETHODCALLTYPE* method9)(
IImmersiveMonitorService* This);
HRESULT(STDMETHODCALLTYPE* QueryServiceFromWindow)(
IImmersiveMonitorService* This,
HWND hWnd,
GUID* a3,
GUID* a4,
void** ppvObject
);
END_INTERFACE END_INTERFACE
} IImmersiveMonitorServiceVtbl; } IImmersiveMonitorServiceVtbl;
@ -783,6 +807,8 @@ typedef struct
IUnknown* iunk; IUnknown* iunk;
} ShowLauncherTipContextMenuParameters; } ShowLauncherTipContextMenuParameters;
HWND hWinXWnd;
DWORD ShowLauncherTipContextMenu( DWORD ShowLauncherTipContextMenu(
ShowLauncherTipContextMenuParameters* params ShowLauncherTipContextMenuParameters* params
) )
@ -796,7 +822,7 @@ DWORD ShowLauncherTipContextMenu(
wc.hCursor = LoadCursorW(NULL, IDC_ARROW); wc.hCursor = LoadCursorW(NULL, IDC_ARROW);
RegisterClass(&wc); RegisterClass(&wc);
HWND hWnd = CreateWindowInBand( hWinXWnd = CreateWindowInBand(
0, 0,
CLASS_NAME, CLASS_NAME,
0, 0,
@ -811,8 +837,8 @@ DWORD ShowLauncherTipContextMenu(
(char*)params->_this - 0x58, (char*)params->_this - 0x58,
7 7
); );
ShowWindow(hWnd, SW_SHOW); ShowWindow(hWinXWnd, SW_SHOW);
SetForegroundWindow(hWnd); SetForegroundWindow(hWinXWnd);
while (!(*((HMENU*)((char*)params->_this + 0xe8)))) while (!(*((HMENU*)((char*)params->_this + 0xe8))))
{ {
@ -826,7 +852,7 @@ DWORD ShowLauncherTipContextMenu(
INT64* unknown_array = calloc(4, sizeof(INT64)); INT64* unknown_array = calloc(4, sizeof(INT64));
ImmersiveContextMenuHelper_ApplyOwnerDrawToMenuFunc( ImmersiveContextMenuHelper_ApplyOwnerDrawToMenuFunc(
*((HMENU*)((char*)params->_this + 0xe8)), *((HMENU*)((char*)params->_this + 0xe8)),
hWnd, hWinXWnd,
&(params->point), &(params->point),
0xc, 0xc,
unknown_array unknown_array
@ -838,13 +864,13 @@ DWORD ShowLauncherTipContextMenu(
params->point.x, params->point.x,
params->point.y, params->point.y,
0, 0,
hWnd, hWinXWnd,
0 0
); );
ImmersiveContextMenuHelper_RemoveOwnerDrawFromMenuFunc( ImmersiveContextMenuHelper_RemoveOwnerDrawFromMenuFunc(
*((HMENU*)((char*)params->_this + 0xe8)), *((HMENU*)((char*)params->_this + 0xe8)),
hWnd, hWinXWnd,
&(params->point) &(params->point)
); );
free(unknown_array); free(unknown_array);
@ -872,7 +898,7 @@ DWORD ShowLauncherTipContextMenu(
finalize: finalize:
params->iunk->lpVtbl->Release(params->iunk); params->iunk->lpVtbl->Release(params->iunk);
SendMessage( SendMessage(
hWnd, hWinXWnd,
WM_CLOSE, WM_CLOSE,
0, 0,
0 0
@ -882,6 +908,50 @@ DWORD ShowLauncherTipContextMenu(
return 0; return 0;
} }
POINT GetDefaultWinXPosition()
{
POINT point, ptCursor;
GetCursorPos(&ptCursor);
MONITORINFO mi;
mi.cbSize = sizeof(MONITORINFO);
GetMonitorInfo(
MonitorFromPoint(
ptCursor,
MONITOR_DEFAULTTONEAREST
),
&mi
);
// https://stackoverflow.com/questions/44746234/programatically-get-windows-taskbar-info-autohidden-state-taskbar-coordinates
APPBARDATA abd;
abd.cbSize = sizeof(APPBARDATA);
SHAppBarMessage(ABM_GETTASKBARPOS, &abd);
if (abd.rc.left < 5 && abd.rc.top > 5)
{
// TB_POS_BOTTOM
point.x = mi.rcMonitor.left;
point.y = mi.rcMonitor.bottom;
}
else if (abd.rc.left < 5 && abd.rc.top < 5 && abd.rc.right > abd.rc.bottom)
{
// TB_POS_TOP
point.x = mi.rcMonitor.left;
point.y = mi.rcMonitor.top;
}
else if (abd.rc.left < 5 && abd.rc.top < 5 && abd.rc.right < abd.rc.bottom)
{
// TB_POS_LEFT
point.x = mi.rcMonitor.left;
point.y = mi.rcMonitor.top;
}
else if (abd.rc.left > 5 && abd.rc.top < 5)
{
// TB_POS_RIGHT
point.x = mi.rcMonitor.right;
point.y = mi.rcMonitor.top;
}
return point;
}
INT64 CLauncherTipContextMenu_ShowLauncherTipContextMenuHook( INT64 CLauncherTipContextMenu_ShowLauncherTipContextMenuHook(
void* _this, void* _this,
POINT* pt POINT* pt
@ -899,45 +969,7 @@ INT64 CLauncherTipContextMenu_ShowLauncherTipContextMenuHook(
} }
else else
{ {
POINT ptCursor; point = GetDefaultWinXPosition();
GetCursorPos(&ptCursor);
MONITORINFO mi;
mi.cbSize = sizeof(MONITORINFO);
GetMonitorInfo(
MonitorFromPoint(
ptCursor,
MONITOR_DEFAULTTONEAREST
),
&mi
);
// https://stackoverflow.com/questions/44746234/programatically-get-windows-taskbar-info-autohidden-state-taskbar-coordinates
APPBARDATA abd;
abd.cbSize = sizeof(APPBARDATA);
SHAppBarMessage(ABM_GETTASKBARPOS, &abd);
if (abd.rc.left < 5 && abd.rc.top > 5)
{
// TB_POS_BOTTOM
point.x = mi.rcMonitor.left;
point.y = mi.rcMonitor.bottom;
}
else if (abd.rc.left < 5 && abd.rc.top < 5 && abd.rc.right > abd.rc.bottom)
{
// TB_POS_TOP
point.x = mi.rcMonitor.left;
point.y = mi.rcMonitor.top;
}
else if (abd.rc.left < 5 && abd.rc.top < 5 && abd.rc.right < abd.rc.bottom)
{
// TB_POS_LEFT
point.x = mi.rcMonitor.left;
point.y = mi.rcMonitor.top;
}
else if (abd.rc.left > 5 && abd.rc.top < 5)
{
// TB_POS_RIGHT
point.x = mi.rcMonitor.right;
point.y = mi.rcMonitor.top;
}
} }
IUnknown* iunk; IUnknown* iunk;
@ -980,62 +1012,36 @@ INT64 CTray_HandleGlobalHotkeyHook(
// see https://github.com/valinet/ExplorerPatcher/issues/3 // see https://github.com/valinet/ExplorerPatcher/issues/3
if (hIsWinXShown) if (hIsWinXShown)
{ {
INPUT ip[2]; SendMessage(hWinXWnd, WM_CLOSE, 0, 0);
ip[0].type = INPUT_KEYBOARD; }
ip[0].ki.wScan = 0; else
ip[0].ki.time = 0; {
ip[0].ki.dwExtraInfo = 0; HWND hWnd = FindWindowEx(
ip[0].ki.wVk = VK_ESCAPE; NULL,
ip[0].ki.dwFlags = 0; NULL,
ip[1].type = INPUT_KEYBOARD; L"Shell_TrayWnd",
ip[1].ki.wScan = 0; NULL
ip[1].ki.time = 0; );
ip[1].ki.dwExtraInfo = 0; if (hWnd)
ip[1].ki.wVk = VK_ESCAPE; {
ip[1].ki.dwFlags = KEYEVENTF_KEYUP; hWnd = FindWindowEx(
SendInput(2, ip, sizeof(INPUT)); hWnd,
return 0; NULL,
L"Start",
NULL
);
if (hWnd)
{
POINT pt = GetDefaultWinXPosition();
PostMessage(
hWnd,
WM_CONTEXTMENU,
hWnd,
MAKELPARAM(pt.x, pt.y)
);
}
}
} }
HWND hWnd = GetForegroundWindow();
HWND g_ProgWin = FindWindowEx(
NULL,
NULL,
L"Progman",
NULL
);
SetForegroundWindow(g_ProgWin);
INPUT ip[4];
ip[0].type = INPUT_KEYBOARD;
ip[0].ki.wScan = 0;
ip[0].ki.time = 0;
ip[0].ki.dwExtraInfo = 0;
ip[0].ki.wVk = VK_LWIN;
ip[0].ki.dwFlags = 0;
ip[1].type = INPUT_KEYBOARD;
ip[1].ki.wScan = 0;
ip[1].ki.time = 0;
ip[1].ki.dwExtraInfo = 0;
ip[1].ki.wVk = 0x51; // 0x46;
ip[1].ki.dwFlags = 0;
ip[2].type = INPUT_KEYBOARD;
ip[2].ki.wScan = 0;
ip[2].ki.time = 0;
ip[2].ki.dwExtraInfo = 0;
ip[2].ki.wVk = 0x51; // 0x46;
ip[2].ki.dwFlags = KEYEVENTF_KEYUP;
ip[3].type = INPUT_KEYBOARD;
ip[3].ki.wScan = 0;
ip[3].ki.time = 0;
ip[3].ki.dwExtraInfo = 0;
ip[3].ki.wVk = VK_LWIN;
ip[3].ki.dwFlags = KEYEVENTF_KEYUP;
InterlockedExchange64(&lockEnsureWinXHotkeyOnlyOnce, 1);
SendInput(4, ip, sizeof(INPUT));
SetForegroundWindow(hWnd);
return 0; return 0;
} }
return CTray_HandleGlobalHotkeyFunc( return CTray_HandleGlobalHotkeyFunc(
@ -1075,38 +1081,6 @@ HRESULT CImmersiveHotkeyNotification_OnMessageHook(
INT64 lParam INT64 lParam
) )
{ {
if (InterlockedExchange64(&lockEnsureWinXHotkeyOnlyOnce, 0) &&
wParam == 30 && // 28, 15
IsDesktopInputContextFunc(_this, msg)
)
{
IUnknown* pMonitor = NULL;
HRESULT hr = CImmersiveHotkeyNotification_GetMonitorForHotkeyNotificationFunc(
(char*)_this - 0x68,
&pMonitor,
0
);
if (SUCCEEDED(hr))
{
IUnknown* pMenu = NULL;
IUnknown_QueryService(
pMonitor,
&IID_ILauncherTipContextMenu,
&IID_ILauncherTipContextMenu,
&pMenu
);
if (pMenu)
{
CLauncherTipContextMenu_ShowLauncherTipContextMenuHook(
pMenu,
0
);
pMenu->lpVtbl->Release(pMenu);
}
}
return 0;
}
return CImmersiveHotkeyNotification_OnMessageFunc( return CImmersiveHotkeyNotification_OnMessageFunc(
_this, _this,
msg, msg,

Loading…
Cancel
Save