diff --git a/.gitignore b/.gitignore index 064db0e..aba634f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,10 @@ Release/ Debug/ x64/ +Utils/*.obj +Utils/*.exe *.opensdf *.sdf *.suo -*.dll \ No newline at end of file +*.dll +*.aps \ No newline at end of file diff --git a/Hook/Hook.vcxproj b/Hook/Hook.vcxproj index b32a68d..74c357e 100644 --- a/Hook/Hook.vcxproj +++ b/Hook/Hook.vcxproj @@ -169,6 +169,9 @@ + + + diff --git a/Hook/Hook.vcxproj.filters b/Hook/Hook.vcxproj.filters index c6375b3..de85191 100644 --- a/Hook/Hook.vcxproj.filters +++ b/Hook/Hook.vcxproj.filters @@ -25,4 +25,9 @@ + + + Header Files + + \ No newline at end of file diff --git a/Hook/VirtualDesktops.h b/Hook/VirtualDesktops.h index 66c83bf..e830012 100644 --- a/Hook/VirtualDesktops.h +++ b/Hook/VirtualDesktops.h @@ -1,7 +1,7 @@ /** * MoveToDesktop * -* Copyright (C) 2015 by Tobias Salzmann +* Copyright (C) 2015-2016 by Tobias Salzmann * * 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 diff --git a/Hook/dll.cpp b/Hook/dll.cpp deleted file mode 100644 index 17b74cc..0000000 --- a/Hook/dll.cpp +++ /dev/null @@ -1,25 +0,0 @@ -/** -* MoveToDesktop -* -* Copyright (C) 2015 by Tobias Salzmann -* -* 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 . -*/ - - -#include -#include "hook.h" - - - diff --git a/Hook/hook.cpp b/Hook/hook.cpp index 907ea4c..6e20dcf 100644 --- a/Hook/hook.cpp +++ b/Hook/hook.cpp @@ -1,7 +1,7 @@ /** * MoveToDesktop * -* Copyright (C) 2015 by Tobias Salzmann +* Copyright (C) 2015-2016 by Tobias Salzmann * Copyright (C) 2008-2011 by Manuel Meitinger * * This program is free software: you can redistribute it and/or modify @@ -22,48 +22,9 @@ #include #include - +#include #include "VirtualDesktops.h" - -#ifdef _DEBUG -#define LOGFILE "%temp%\\MoveToDesktop.log" -void Log(char *message) -{ - FILE *file; - - TCHAR logFile[MAX_PATH] = {0}; - ExpandEnvironmentStrings(LOGFILE, logFile, _countof(logFile)); - file = fopen(logFile, "a"); - - if (file == NULL) { - return; - } - else - { - char exepath[MAX_PATH]; - char msg[1024] = ""; - GetModuleFileName(0, exepath, MAX_PATH); - sprintf(msg, "%s: %s\n", exepath, message); - fputs(msg, file); - fclose(file); - } - - if (file) - fclose(file); -} -#else -#define Log -#endif - - - -#define MAXDESKTOPS 255 -#define MOVETOMENU_ID (0xDE100) -#define MOVETOMENU_NEW (MOVETOMENU_ID + 1) -#define MOVETOMENU_START (MOVETOMENU_NEW + 1) -#define MOVETOMENU_LAST (MOVETOMENU_START + MAXDESKTOPS) - - +#include "hook.h" IServiceProvider* pServiceProvider = nullptr; IVirtualDesktopManager *pDesktopManager = nullptr; @@ -79,21 +40,37 @@ enum EComStatus int ComStatus = COMSTATUS_UNINITIALIZED; bool bAddedMenu = false; +bool bReadIni = false; +bool bSwitchDesktopAfterMove = false; + +#define INIFILE "%APPDATA%\\MoveToDesktop.ini" BOOL InitCom() { + Log("Initalizing Com"); if (ComStatus == COMSTATUS_INITIALIZED) + { + Log("> Allready Initialized!"); return true; + } else if (ComStatus == COMSTATUS_ERROR) + { + Log("> Allready tried to initialize but it failed."); return false; + } ComStatus = COMSTATUS_ERROR; - ::CoInitialize(NULL); - - HRESULT hr = ::CoCreateInstance(CLSID_ImmersiveShell, NULL, CLSCTX_LOCAL_SERVER, __uuidof(IServiceProvider), (PVOID*)&pServiceProvider); + HRESULT hr = ::CoInitialize(NULL); + if (FAILED(hr)) + { + Log("> CoInitialize failed: %X", hr); + return FALSE; + } + hr = ::CoCreateInstance(CLSID_ImmersiveShell, NULL, CLSCTX_LOCAL_SERVER, __uuidof(IServiceProvider), (PVOID*)&pServiceProvider); if (FAILED(hr)) { + Log("> CoCreateInstance failed: %X", hr); return FALSE; } @@ -102,7 +79,7 @@ BOOL InitCom() hr = pServiceProvider->QueryService(__uuidof(IVirtualDesktopManager), &pDesktopManager); if (FAILED(hr)) { - + Log("> QueryService(DesktopManager) failed"); pServiceProvider->Release(); pServiceProvider = nullptr; return FALSE; @@ -113,7 +90,7 @@ BOOL InitCom() hr = pServiceProvider->QueryService(CLSID_VirtualDesktopAPI_Unknown, &pDesktopManagerInternal); if (FAILED(hr)) { - + Log("> QueryService(DesktopManagerInternal) failed"); pDesktopManager->Release(); pDesktopManager = nullptr; pServiceProvider->Release(); @@ -121,7 +98,6 @@ BOOL InitCom() return FALSE; } - ComStatus = COMSTATUS_INITIALIZED; return TRUE; } @@ -137,6 +113,17 @@ VOID FreeCom() } } +VOID ReadIni() +{ + if (bReadIni == true) + return; + bReadIni = true; + Log("Reading Ini"); + TCHAR iniFile[MAX_PATH] = { 0 }; + ExpandEnvironmentStrings(INIFILE, iniFile, _countof(iniFile)); + bSwitchDesktopAfterMove = (GetPrivateProfileInt("MoveToDesktop", "SwitchDesktopAfterMove", 0, iniFile) != 0); + Log("Ini: SwitchDesktopAfterMove = %d", (bSwitchDesktopAfterMove ? 1 : 0)); +} INT GetIndexOfItem(HMENU menu, UINT id) { @@ -151,8 +138,7 @@ INT GetIndexOfItem(HMENU menu, UINT id) return -1; } - -void AddMenu(HWND hwnd, HMENU menu) +VOID AddMenu(HWND hwnd, HMENU menu) { if (bAddedMenu == true) return; @@ -207,7 +193,7 @@ void AddMenu(HWND hwnd, HMENU menu) MoveToItem.fMask = MIIM_SUBMENU | MIIM_STATE | MIIM_ID | MIIM_STRING; Log("Add MoveToMenu"); MoveToItem.wID = MOVETOMENU_ID; - MoveToItem.dwTypeData = TEXT("Move To"); + MoveToItem.dwTypeData = TEXT("Move &To"); MoveToItem.hSubMenu = CreateMenu(); InsertMenuItem(systemMenu, SC_CLOSE, FALSE, &MoveToItem); @@ -221,7 +207,7 @@ void AddMenu(HWND hwnd, HMENU menu) char desktopName[64] = { 0 }; - sprintf_s(desktopName, sizeof(desktopName), "Desktop %d", i + 1); + sprintf_s(desktopName, sizeof(desktopName), "Desktop &%d", i + 1); MENUITEMINFO item = { 0 }; item.cbSize = sizeof(item); @@ -240,7 +226,7 @@ void AddMenu(HWND hwnd, HMENU menu) item.fMask = MIIM_ID | MIIM_STRING; item.fState = MFS_UNCHECKED; item.wID = MOVETOMENU_NEW; - item.dwTypeData = TEXT("New Desktop"); + item.dwTypeData = TEXT("&New Desktop"); InsertMenuItem(MoveToItem.hSubMenu, -1, FALSE, &item); } @@ -253,7 +239,7 @@ void AddMenu(HWND hwnd, HMENU menu) } } -void RemoveMenu(HWND hwnd, HMENU menu) +VOID RemoveMenu(HWND hwnd, HMENU menu) { if (bAddedMenu == false) return; @@ -279,16 +265,80 @@ void RemoveMenu(HWND hwnd, HMENU menu) } Log("Remove MoveToMenu"); DestroyMenu(MoveToItem.hSubMenu); - DeleteMenu(systemMenu, MoveToItem.wID, MF_BYCOMMAND); - - - + DeleteMenu(systemMenu, MoveToItem.wID, MF_BYCOMMAND); +} + +INT GetCurrentDesktopIndex(UINT *count) +{ + *count = 0; + IObjectArray *pObjectArray = nullptr; + IVirtualDesktop *pCurrentDesktop = nullptr; + + if (!InitCom()) + { + Log("InitCom failed"); + return -1; + } + + HRESULT hr = pDesktopManagerInternal->GetDesktops(&pObjectArray); + if (FAILED(hr)) + { + Log("pDesktopManagerInternal->GetDesktops failed %x", hr); + return -1; + } + + hr = pObjectArray->GetCount(count); + if (FAILED(hr)) + { + Log("pObjectArray->GetCount failed %x", hr); + pObjectArray->Release(); + return -1; + } + + + hr = pDesktopManagerInternal->GetCurrentDesktop(&pCurrentDesktop); + if (FAILED(hr)) + { + Log("pDesktopManagerInternal->GetCurrentDesktop failed %x", hr); + pObjectArray->Release(); + return -1; + } + + int index = -1; + for (UINT i = 0; i < *count && i < MAXDESKTOPS && index == -1; ++i) + { + IVirtualDesktop *pDesktop = nullptr; + + if (FAILED(pObjectArray->GetAt(i, __uuidof(IVirtualDesktop), (void**)&pDesktop))) + continue; + if (pDesktop == pCurrentDesktop) + { + index = MOVETOMENU_START + i; + } + pDesktop->Release(); + } + + pObjectArray->Release(); + + if (pCurrentDesktop != nullptr) + { + pCurrentDesktop->Release(); + } + return index; } void HandleSysCommand(WPARAM wParam, HWND hwnd) { if (wParam == MOVETOMENU_NEW) { + Log("Getting RootWindow of %X", hwnd); + HWND rootHwnd = GetAncestor(hwnd, GA_ROOTOWNER); + if (rootHwnd != NULL) + { + hwnd = rootHwnd; + } + + Log("Moving %X to new", hwnd); IVirtualDesktop *pNewDesktop = nullptr; HRESULT hr = pDesktopManagerInternal->CreateDesktopW(&pNewDesktop); if (FAILED(hr)) @@ -299,23 +349,37 @@ void HandleSysCommand(WPARAM wParam, HWND hwnd) hr = pNewDesktop->GetID(&id); if (SUCCEEDED(hr)) { - pDesktopManager->MoveWindowToDesktop(hwnd, id); + Log("pDesktopManager->MoveWindowToDesktop(%X, %X)", hwnd, id); + hr = pDesktopManager->MoveWindowToDesktop(hwnd, id); + if (SUCCEEDED(hr)) + { + if (bSwitchDesktopAfterMove) + { + pDesktopManagerInternal->SwitchDesktop(pNewDesktop); + } + } + else + { + Log("Error %d on moving %X to %X", hr, hwnd, id); + } } pNewDesktop->Release(); } else if (wParam >= MOVETOMENU_START && wParam <= MOVETOMENU_LAST) { - HMENU systemMenu; - if ((systemMenu = GetSystemMenu(hwnd, FALSE)) == NULL) + Log("Getting RootWindow of %X", hwnd); + HWND rootHwnd = GetAncestor(hwnd, GA_ROOTOWNER); + if (rootHwnd != NULL) { - return; + hwnd = rootHwnd; } - + Log("Moving %X to %X", hwnd, wParam); IObjectArray *pObjectArray = nullptr; HRESULT hr = pDesktopManagerInternal->GetDesktops(&pObjectArray); if (FAILED(hr)) { + Log("Failed to get desktops for %X", hwnd); return; } @@ -327,12 +391,59 @@ void HandleSysCommand(WPARAM wParam, HWND hwnd) if (SUCCEEDED(hr)) { - pDesktopManager->MoveWindowToDesktop(hwnd, id); + Log("pDesktopManager->MoveWindowToDesktop(%X, %X)", hwnd, id); + hr = pDesktopManager->MoveWindowToDesktop(hwnd, id); + if (SUCCEEDED(hr)) + { + if (bSwitchDesktopAfterMove) + { + pDesktopManagerInternal->SwitchDesktop(pDesktop); + } + } + else + { + Log("Error %X on moving %X to %X", hr, hwnd, id); + } } pDesktop->Release(); } pObjectArray->Release(); } + else if (wParam == MOVETOMENU_LEFT) + { + UINT count; + int index = GetCurrentDesktopIndex(&count); + Log("Current Index is %d", index); + Log("Current Count is %d", count); + if (index == -1) + return; + if (index == MOVETOMENU_START) + return; + Log("Switch to %d", index - 1); + HandleSysCommand(--index, hwnd); + } + else if (wParam == MOVETOMENU_RIGHT) + { + UINT count; + int index = GetCurrentDesktopIndex(&count); + Log("Current Index is %d", index); + Log("Current Count is %d", count); + if (index == -1) + return; + if (index == MOVETOMENU_LAST) + return; + if ((++index) <= (int)(count + MOVETOMENU_NEW)) + { + Log("Switch to %d", index); + HandleSysCommand(index, hwnd); + + } + else + { + Log("Create new desktop"); + HandleSysCommand(MOVETOMENU_NEW, hwnd); + } + } } LRESULT CALLBACK CallWndProc(INT code, WPARAM wParam, LPARAM lParam) @@ -392,7 +503,7 @@ LRESULT CALLBACK CallWndProc(INT code, WPARAM wParam, LPARAM lParam) // Do the command case WM_SYSCOMMAND: { - Log("WM_SYSCOMMAND"); + Log("WM_SYSCOMMAND %X %X", msg->wParam, msg->hwnd); HandleSysCommand(msg->wParam, msg->hwnd); break; } @@ -405,21 +516,27 @@ LRESULT CALLBACK CallWndProc(INT code, WPARAM wParam, LPARAM lParam) LRESULT CALLBACK GetMsgProc(INT code, WPARAM wParam, LPARAM lParam) { #define msg ((PMSG)lParam) - - if (code == HC_ACTION && msg->message == WM_SYSCOMMAND) + if (code == HC_ACTION) { - Log("WM_SYSCOMMAND"); - HandleSysCommand(msg->wParam, msg->hwnd); + switch (msg->message) + { + case WM_SYSCOMMAND: + { + Log("WM_SYSCOMMAND"); + HandleSysCommand(msg->wParam, msg->hwnd); + break; + } + } } - return CallNextHookEx(NULL, code, wParam, lParam); + return CallNextHookEx(NULL, code, wParam, lParam); #undef msg } - BOOL WINAPI DllMain(HINSTANCE handle, DWORD dwReason, LPVOID reserved) { if (dwReason == DLL_PROCESS_ATTACH) { + ReadIni(); } else if (dwReason == DLL_PROCESS_DETACH) { diff --git a/Hook/hook.h b/Hook/hook.h new file mode 100644 index 0000000..dbbdb85 --- /dev/null +++ b/Hook/hook.h @@ -0,0 +1,64 @@ +/** +* MoveToDesktop +* +* Copyright (C) 2015-2016 by Tobias Salzmann +* +* 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 . +*/ + +#define MAXDESKTOPS 255 +#define MOVETOMENU_ID (0xDE100) +#define MOVETOMENU_NEW (MOVETOMENU_ID + 1) +#define MOVETOMENU_START (MOVETOMENU_NEW + 1) +#define MOVETOMENU_LAST (MOVETOMENU_START + MAXDESKTOPS) +#define MOVETOMENU_LEFT (MOVETOMENU_LAST + 1) +#define MOVETOMENU_RIGHT (MOVETOMENU_LEFT + 1) + + +#ifdef _DEBUG +#define LOGFILE "%temp%\\MoveToDesktop.log" +#include +inline void Log(char *message, ...) +{ + FILE *file; + + TCHAR logFile[MAX_PATH] = { 0 }; + ExpandEnvironmentStrings(LOGFILE, logFile, _countof(logFile)); + fopen_s(&file, logFile, "a"); + + if (file == NULL) { + return; + } + else + { + char exepath[MAX_PATH]; + char inpmsg[1024] = ""; + char finalmsg[1024 + MAX_PATH] = ""; + va_list ptr; + va_start(ptr, message); + vsprintf_s(inpmsg, sizeof(inpmsg), message, ptr); + va_end(ptr); + GetModuleFileName(0, exepath, MAX_PATH); + + sprintf_s(finalmsg, sizeof(finalmsg), "%s: %s\n", exepath, inpmsg); + fputs(finalmsg, file); + fclose(file); + } + + if (file) + fclose(file); +} +#else +#define Log +#endif \ No newline at end of file diff --git a/LICENSE b/LICENSE index 8cb79ca..b136b75 100644 --- a/LICENSE +++ b/LICENSE @@ -1,7 +1,7 @@ /** * MoveToDesktop * -* Copyright (C) 2015 by Tobias Salzmann +* Copyright (C) 2015-2016 by Tobias Salzmann * * 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 diff --git a/MoveToDesktop.ini b/MoveToDesktop.ini new file mode 100644 index 0000000..c18e41a --- /dev/null +++ b/MoveToDesktop.ini @@ -0,0 +1,6 @@ +; +; Place this file in %AppData% +; +[MoveToDesktop] +; Switch Desktop after window was moved +SwitchDesktopAfterMove=1 \ No newline at end of file diff --git a/MoveToDesktop.sln b/MoveToDesktop.sln index 64fa05f..50a3157 100644 --- a/MoveToDesktop.sln +++ b/MoveToDesktop.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 14 -VisualStudioVersion = 14.0.23107.0 +VisualStudioVersion = 14.0.24720.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MoveToDesktop", "MoveToDesktop\MoveToDesktop.vcxproj", "{47BF4015-D8CF-4B07-B657-7E7ABDB72FDC}" ProjectSection(ProjectDependencies) = postProject @@ -12,30 +12,24 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hook", "Hook\Hook.vcxproj", EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU Debug|x64 = Debug|x64 Debug|x86 = Debug|x86 - Release|Any CPU = Release|Any CPU Release|x64 = Release|x64 Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {47BF4015-D8CF-4B07-B657-7E7ABDB72FDC}.Debug|Any CPU.ActiveCfg = Debug|Win32 {47BF4015-D8CF-4B07-B657-7E7ABDB72FDC}.Debug|x64.ActiveCfg = Debug|x64 {47BF4015-D8CF-4B07-B657-7E7ABDB72FDC}.Debug|x64.Build.0 = Debug|x64 {47BF4015-D8CF-4B07-B657-7E7ABDB72FDC}.Debug|x86.ActiveCfg = Debug|Win32 {47BF4015-D8CF-4B07-B657-7E7ABDB72FDC}.Debug|x86.Build.0 = Debug|Win32 - {47BF4015-D8CF-4B07-B657-7E7ABDB72FDC}.Release|Any CPU.ActiveCfg = Release|Win32 {47BF4015-D8CF-4B07-B657-7E7ABDB72FDC}.Release|x64.ActiveCfg = Release|x64 {47BF4015-D8CF-4B07-B657-7E7ABDB72FDC}.Release|x64.Build.0 = Release|x64 {47BF4015-D8CF-4B07-B657-7E7ABDB72FDC}.Release|x86.ActiveCfg = Release|Win32 {47BF4015-D8CF-4B07-B657-7E7ABDB72FDC}.Release|x86.Build.0 = Release|Win32 - {88D0BB04-305D-47DC-B4BD-9D3398FAFFE6}.Debug|Any CPU.ActiveCfg = Debug|Win32 {88D0BB04-305D-47DC-B4BD-9D3398FAFFE6}.Debug|x64.ActiveCfg = Debug|x64 {88D0BB04-305D-47DC-B4BD-9D3398FAFFE6}.Debug|x64.Build.0 = Debug|x64 {88D0BB04-305D-47DC-B4BD-9D3398FAFFE6}.Debug|x86.ActiveCfg = Debug|Win32 {88D0BB04-305D-47DC-B4BD-9D3398FAFFE6}.Debug|x86.Build.0 = Debug|Win32 - {88D0BB04-305D-47DC-B4BD-9D3398FAFFE6}.Release|Any CPU.ActiveCfg = Release|Win32 {88D0BB04-305D-47DC-B4BD-9D3398FAFFE6}.Release|x64.ActiveCfg = Release|x64 {88D0BB04-305D-47DC-B4BD-9D3398FAFFE6}.Release|x64.Build.0 = Release|x64 {88D0BB04-305D-47DC-B4BD-9D3398FAFFE6}.Release|x86.ActiveCfg = Release|Win32 diff --git a/MoveToDesktop/MoveToDesktop.vcxproj b/MoveToDesktop/MoveToDesktop.vcxproj index 985c3f9..0013945 100644 --- a/MoveToDesktop/MoveToDesktop.vcxproj +++ b/MoveToDesktop/MoveToDesktop.vcxproj @@ -86,6 +86,9 @@ + + taskkill /f /fi "IMAGENAME eq MoveToDesktop*" /im * + @@ -99,6 +102,9 @@ _DEBUG; _WIN64 + + taskkill /f /fi "IMAGENAME eq MoveToDesktop*" /im * + diff --git a/MoveToDesktop/hideim.h b/MoveToDesktop/hideim.h index 2fac7ab..2bbca00 100644 --- a/MoveToDesktop/hideim.h +++ b/MoveToDesktop/hideim.h @@ -1,7 +1,7 @@ /** * HideImports 1.0 * -* Copyright (C) 2015 by Tobias Salzmann +* Copyright (C) 2015-2016 by Tobias Salzmann * * 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 diff --git a/MoveToDesktop/main.cpp b/MoveToDesktop/main.cpp index 9d7cd97..d284ed2 100644 --- a/MoveToDesktop/main.cpp +++ b/MoveToDesktop/main.cpp @@ -1,7 +1,7 @@ /** * MoveToDesktop * -* Copyright (C) 2015 by Tobias Salzmann +* Copyright (C) 2015-2016 by Tobias Salzmann * Copyright (C) 2008-2011 by Manuel Meitinger * * This program is free software: you can redistribute it and/or modify @@ -23,6 +23,7 @@ #include "resource.h" #include "hideim.h" #include +#include "../Hook/hook.h" #ifdef _WIN64 @@ -33,6 +34,7 @@ #define TITLE "MoveToDesktop" #endif +bool bKeyDown = false; bool ExtractResource(const HINSTANCE hInstance, WORD resourceID, LPCTSTR szFilename) { @@ -60,7 +62,6 @@ bool ExtractResource(const HINSTANCE hInstance, WORD resourceID, LPCTSTR szFilen { return false; } - } BOOL IsWow64() @@ -88,6 +89,45 @@ BOOL IsWow64() } +LRESULT CALLBACK LowLevelKeyboardProc(int code, WPARAM wParam, LPARAM lParam) +{ +#define msg ((PKBDLLHOOKSTRUCT)lParam) + if (code == HC_ACTION) + { + if (wParam == WM_SYSKEYDOWN) + { + if (msg->vkCode == VK_RIGHT) + { + if (bKeyDown == false && ((GetKeyState(VK_LMENU) && GetKeyState(VK_LWIN)) || (GetKeyState(VK_RMENU) && GetKeyState(VK_RWIN)))) + { + bKeyDown = true; + Log("Sending to %X: MOVETOMENU_RIGHT", GetForegroundWindow()); + PostMessage(GetForegroundWindow(), WM_SYSCOMMAND, MOVETOMENU_RIGHT, 0); + return 1; + } + } + else if (msg->vkCode == VK_LEFT) + { + if (bKeyDown == false && ((GetKeyState(VK_LMENU) && GetKeyState(VK_LWIN)) || (GetKeyState(VK_RMENU) && GetKeyState(VK_RWIN)))) + { + bKeyDown = true; + Log("Sending to %X: MOVETOMENU_LEFT", GetForegroundWindow()); + PostMessage(GetForegroundWindow(), WM_SYSCOMMAND, MOVETOMENU_LEFT, 0); + return 1; + } + } + } + else if (wParam == WM_SYSKEYUP) + { + if (msg->vkCode == VK_RIGHT || msg->vkCode == VK_LEFT) + { + bKeyDown = false; + } + } + } + return CallNextHookEx(NULL, code, wParam, lParam); +#undef msg +} INT WINAPI WinMain(HINSTANCE instance, HINSTANCE prevInstance, LPSTR cmdLine, INT cmdShow) { @@ -130,7 +170,6 @@ INT WINAPI WinMain(HINSTANCE instance, HINSTANCE prevInstance, LPSTR cmdLine, IN return 1; } - // Extract 64bit version #ifdef _WIN32 #ifndef _DEBUG @@ -152,90 +191,106 @@ INT WINAPI WinMain(HINSTANCE instance, HINSTANCE prevInstance, LPSTR cmdLine, IN #endif #endif - - - + DWORD error; HMODULE library; // load the hook library if ((library = LoadLibrary(szTempFileName)) == NULL) { - DWORD error = GetLastError(); + error = GetLastError(); char buffer[128] = ""; sprintf_s(buffer, sizeof(buffer), "Could not load hook!\nErrorCode: %d", error); MessageBox(0, buffer, TITLE, MB_OK | MB_ICONERROR); return error; } - - __try + try { HOOKPROC callWndProc; HHOOK callWndHook; if ((callWndProc = (HOOKPROC)GetProcAddress(library, "CallWndProc")) == NULL) { - DWORD error = GetLastError(); - MessageBox(0, "Could not find CallWndProc in hook!", TITLE, MB_OK | MB_ICONERROR); - return error; + error = GetLastError(); + throw "Could not find CallWndProc in hook!"; } if ((callWndHook = SetWindowsHookExA(WH_CALLWNDPROC, callWndProc, library, 0)) == NULL) { - DWORD error = GetLastError(); + error = GetLastError(); char buffer[128] = ""; sprintf_s(buffer, sizeof(buffer), "Error on calling SetWindowsHookEx(WH_CALLWNDPROC)!\nErrorCode: %d", error); - MessageBox(0, buffer, TITLE, MB_OK | MB_ICONERROR); - return error; + throw buffer; } - __try + try { HOOKPROC getMsgProc; HHOOK getMsgHook; if ((getMsgProc = (HOOKPROC)GetProcAddress(library, "GetMsgProc")) == NULL) { - DWORD error = GetLastError(); - MessageBox(0, "Could not find GetMsgProc in hook.dll!", TITLE, MB_OK | MB_ICONERROR); - return error; + error = GetLastError(); + throw "Could not find GetMsgProc in hook.dll!"; } if ((getMsgHook = SetWindowsHookExA(WH_GETMESSAGE, getMsgProc, library, 0)) == NULL) { - DWORD error = GetLastError(); + error = GetLastError(); char buffer[128] = ""; sprintf_s(buffer, sizeof(buffer), "Error on calling SetWindowsHookEx(WH_GETMESSAGE)!\nErrorCode: %d", error); - MessageBox(0, buffer, TITLE, MB_OK | MB_ICONERROR); - return error; + throw buffer; } - __try + + try { - MSG msg; - BOOL ret; + HHOOK lowLevelKeyboardHook; - // pump the messages until the end of the session - while ((ret = GetMessage(&msg, NULL, 0, 0)) != 0) + if ((lowLevelKeyboardHook = SetWindowsHookExA(WH_KEYBOARD_LL, LowLevelKeyboardProc, library, 0)) == NULL) + { + error = GetLastError(); + char buffer[128] = ""; + sprintf_s(buffer, sizeof(buffer), "Error on calling SetWindowsHookEx(WH_KEYBOARD_LL)!\nErrorCode: %d", error); + throw buffer; + } + try { - if (ret == -1) + MSG msg; + BOOL ret; + + // pump the messages until the end of the session + while ((ret = GetMessage(&msg, NULL, 0, 0)) != 0) { - return GetLastError(); + if (ret == -1) + { + return GetLastError(); + } + TranslateMessage(&msg); + DispatchMessage(&msg); } - TranslateMessage(&msg); - DispatchMessage(&msg); } + catch(char *buffer) + { + MessageBox(0, buffer, TITLE, MB_OK | MB_ICONERROR); + } + UnhookWindowsHookEx(lowLevelKeyboardHook); } - __finally + catch (char *buffer) { - UnhookWindowsHookEx(getMsgHook); + MessageBox(0, buffer, TITLE, MB_OK | MB_ICONERROR); } + UnhookWindowsHookEx(getMsgHook); } - __finally + catch (char *buffer) { - UnhookWindowsHookEx(callWndHook); + MessageBox(0, buffer, TITLE, MB_OK | MB_ICONERROR); } + UnhookWindowsHookEx(callWndHook); } - __finally { - FreeLibrary(library); + catch (char *buffer) + { + MessageBox(0, buffer, TITLE, MB_OK | MB_ICONERROR); } + FreeLibrary(library); + ReleaseMutex(mutex); // return success return ERROR_SUCCESS; -} \ No newline at end of file +} diff --git a/MoveToDesktop/resource.aps b/MoveToDesktop/resource.aps deleted file mode 100644 index 5ad98a9..0000000 Binary files a/MoveToDesktop/resource.aps and /dev/null differ diff --git a/MoveToDesktop/resource.h b/MoveToDesktop/resource.h index 825f5e0..305dc07 100644 --- a/MoveToDesktop/resource.h +++ b/MoveToDesktop/resource.h @@ -1,7 +1,7 @@ /** * MoveToDesktop * -* Copyright (C) 2015 by Tobias Salzmann +* Copyright (C) 2015-2016 by Tobias Salzmann * * 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 diff --git a/MoveToDesktop/resource.rc b/MoveToDesktop/resource.rc index b2d3802..6152776 100644 Binary files a/MoveToDesktop/resource.rc and b/MoveToDesktop/resource.rc differ diff --git a/README.md b/README.md index b0f4959..9f5634c 100644 --- a/README.md +++ b/README.md @@ -5,15 +5,25 @@ Adds the Move to Desktop feature to the Windows 10 System menu: ![](https://raw.githubusercontent.com/Eun/MoveToDesktop/res/screenshot1.png) -[![Download](https://raw.githubusercontent.com/Eun/MoveToDesktop/res/download.png)](https://github.com/Eun/MoveToDesktop/releases/download/1.0/MoveToDesktop-1.0.zip) +[![Download](https://raw.githubusercontent.com/Eun/MoveToDesktop/res/download.png)](https://github.com/Eun/MoveToDesktop/releases/download/1.1/MoveToDesktop-1.1.zip) Installation Usage ====== Download and Run. +You can also move windows by using WIN+ALT+Left/Right You might need to install the x86 **and** x64 version of [Visual C++ Redistributable for Visual Studio 2015](https://www.microsoft.com/download/details.aspx?id=48145). +Settings +======== +You can place the [MoveToDesktop.ini](MoveToDesktop.ini) into `%AppData` and modify the settings in it. Changelog ========= +1.1: +* Hotkey +* Keyboard accelators +* Switch desktop after move +* Settings Ini File + 1.0: * Release diff --git a/Utils/close_all.cpp b/Utils/close_all.cpp new file mode 100644 index 0000000..f303d37 --- /dev/null +++ b/Utils/close_all.cpp @@ -0,0 +1,147 @@ +/** +* MoveToDesktop +* +* Copyright (C) 2015-2016 by Tobias Salzmann +* +* 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 . +*/ +// compile with cl.exe close_all.cpp +// description: Closes all virtual desktops +#include +#include +#include "../Hook/VirtualDesktops.h" + +#pragma comment (lib, "ole32.lib") + +IServiceProvider* pServiceProvider = nullptr; +IVirtualDesktopManager *pDesktopManager = nullptr; +IVirtualDesktopManagerInternal* pDesktopManagerInternal = nullptr; + +enum EComStatus +{ + COMSTATUS_UNINITIALIZED, + COMSTATUS_INITIALIZED, + COMSTATUS_ERROR, +}; + +int ComStatus = COMSTATUS_UNINITIALIZED; + + +BOOL InitCom() +{ + if (ComStatus == COMSTATUS_INITIALIZED) + return true; + else if (ComStatus == COMSTATUS_ERROR) + return false; + + ComStatus = COMSTATUS_ERROR; + ::CoInitialize(NULL); + + HRESULT hr = ::CoCreateInstance(CLSID_ImmersiveShell, NULL, CLSCTX_LOCAL_SERVER, __uuidof(IServiceProvider), (PVOID*)&pServiceProvider); + + if (FAILED(hr)) + { + return FALSE; + } + + + + hr = pServiceProvider->QueryService(__uuidof(IVirtualDesktopManager), &pDesktopManager); + if (FAILED(hr)) + { + + pServiceProvider->Release(); + pServiceProvider = nullptr; + return FALSE; + } + + + + hr = pServiceProvider->QueryService(CLSID_VirtualDesktopAPI_Unknown, &pDesktopManagerInternal); + if (FAILED(hr)) + { + + pDesktopManager->Release(); + pDesktopManager = nullptr; + pServiceProvider->Release(); + pServiceProvider = nullptr; + return FALSE; + } + + + ComStatus = COMSTATUS_INITIALIZED; + return TRUE; +} + +VOID FreeCom() +{ + if (ComStatus == COMSTATUS_INITIALIZED) + { + pDesktopManager->Release(); + pDesktopManagerInternal->Release(); + pServiceProvider->Release(); + ComStatus = COMSTATUS_UNINITIALIZED; + } +} + +void main() +{ + InitCom(); + + + IObjectArray *pObjectArray = nullptr; + IVirtualDesktop *pCurrentDesktop = nullptr; + + HRESULT hr = pDesktopManagerInternal->GetDesktops(&pObjectArray); + if (FAILED(hr)) + { + return; + } + + UINT count; + hr = pObjectArray->GetCount(&count); + if (FAILED(hr)) + { + pObjectArray->Release(); + return; + } + + + hr = pDesktopManagerInternal->GetCurrentDesktop(&pCurrentDesktop); + if (FAILED(hr)) + { + pCurrentDesktop = nullptr; + } + + + + for (UINT i = 0; i < count; ++i) + { + IVirtualDesktop *pDesktop = nullptr; + + if (FAILED(pObjectArray->GetAt(i, __uuidof(IVirtualDesktop), (void**)&pDesktop))) + continue; + + if (pDesktop != pCurrentDesktop) + { + printf("Closing %d\n",i); + pDesktopManagerInternal->RemoveDesktop(pDesktop, pCurrentDesktop); + } + pDesktop->Release(); + } + + pObjectArray->Release(); + + FreeCom(); +} \ No newline at end of file