Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- 2018 Window Cast
- http://discord.futuregadgetlab.net
- full multi-monitor support
- HOTKEYS:
- [winkey + numpad 1~9] to move and resize selected window
- [winkey + numpad 5] to toggle maximizing window
- [winkey + numpad 0] bring window to middle resized 800x600
- [winkey + period] to print some window debug info
- set "verbose" to false to avoid spam and disable period debug
- */
- #define WINVER _WIN32_WINNT_WIN7 // windows vista can fuck off
- #define WIN32_LEAN_AND_MEAN // windows junk can fuck off
- #define NO_STRICT // windows types can fuck off
- #include <iostream>
- #include <stdexcept>
- //#include <string>
- #include <windows.h>
- static constexpr const bool verbose{ true };
- class ForegroundWindow
- {
- const void* fgw;
- public:
- [[nodiscard]] operator const void*() const { return fgw; }
- [[nodiscard]] operator void*(){ return const_cast< void* >(fgw); }
- ForegroundWindow()
- : fgw(GetForegroundWindow())
- {
- if (fgw == nullptr) throw std::runtime_error(
- "Couldn't obtain foreground window");
- if constexpr (verbose) std::cout
- << "\tForeground window obtained" << std::endl;
- }
- };
- typedef std::pair<long, long> Coordinate;
- typedef Coordinate Dimensions;
- class MonitorInfoFromWindow
- {
- typedef MONITORINFOEXA MonitorInfo_t;
- [[nodiscard]] auto check(const void* hwnd)
- {
- if (hwnd == nullptr) throw std::invalid_argument("hwnd was null!");
- else return const_cast< void* >(hwnd);
- }
- [[nodiscard]] MonitorInfo_t getMonitorInfo()
- {
- MonitorInfo_t monitorInfo{};
- monitorInfo.cbSize = sizeof(MonitorInfo_t);
- if (monitor == nullptr) throw std::runtime_error(
- "MonitorFromWindow returned null");
- GetMonitorInfoA(const_cast< void* >(monitor), &monitorInfo);
- return monitorInfo;
- }
- public:
- const void* monitor;
- const MonitorInfo_t info;
- const decltype(MonitorInfo_t::szDevice)& name;
- Coordinate origin;
- Dimensions workspaceDimensions;
- MonitorInfoFromWindow(const void* hwnd) :
- monitor(MonitorFromWindow(check(hwnd), MONITOR_DEFAULTTONEAREST)),
- info(getMonitorInfo()),
- name(info.szDevice),
- origin(info.rcMonitor.left, info.rcMonitor.top),
- workspaceDimensions(
- info.rcWork.right - info.rcWork.left,
- info.rcWork.bottom - info.rcWork.top)
- {
- if constexpr (verbose) std::cout
- << "\ton \" " << name << " \""
- << " with dimensions "
- << workspaceDimensions.first << "x" << workspaceDimensions.second
- << " at origin "
- << '(' << origin.first << ',' << origin.second << ')'
- << std::endl;
- }
- };
- void moveWindow(const void* fgw, const Coordinate& orig, const Dimensions& dim)
- {
- const auto& [dimension_x, dimension_y]{ dim };
- const auto& [origin_x, origin_y]{ orig };
- if (!SetWindowPos(
- const_cast< void* >(fgw),
- HWND_TOP, // it seems HWND_TOPMOST is "always ontop"
- origin_x, origin_y,
- dimension_x, dimension_y,
- SWP_SHOWWINDOW)) throw std::runtime_error(
- "Couldn't set window position");
- if constexpr (verbose) std::cout
- << "\tmoved to origin "
- << '(' << origin_x << ',' << origin_y << ')'
- << " with dimensions "
- << dimension_x << "x" << dimension_y
- << std::endl;
- }
- enum Pos
- {
- Top = (1 << 0),
- Bottom = (1 << 1),
- Left = (1 << 2),
- Right = (1 << 3)
- };
- [[nodiscard]] Pos operator|(Pos a, Pos b)
- { return Pos( int( a ) | int( b ) ); }
- class Position
- {
- const bool top:1;
- const bool bottom:1;
- const bool left:1;
- const bool right:1;
- bool reserved:4; // padding
- public:
- [[nodiscard]] bool isBottom() const { return bottom; }
- [[nodiscard]] bool isRight() const { return right; }
- [[nodiscard]] bool isVertical() const { return top || bottom; }
- [[nodiscard]] bool isHorizontal() const { return left || right; }
- Position(Pos p) :
- top((p & Pos::Top)),
- bottom((p & Pos::Bottom)),
- left((p & Pos::Left)),
- right((p & Pos::Right))
- {
- if ((top && bottom) || (left && right)) throw std::invalid_argument(
- "Conflicting position arguments");
- ForegroundWindow fgw;
- MonitorInfoFromWindow info(fgw);
- auto& origin{ info.origin };
- auto& [origin_x, origin_y]{ origin };
- auto& dimensions{ info.workspaceDimensions };
- auto& [dimension_x, dimension_y]{ dimensions };
- if (isBottom()) origin_y += dimension_y / 2;
- if (isRight()) origin_x += dimension_x / 2;
- if (isVertical()) dimension_y /= 2;
- if (isHorizontal()) dimension_x /= 2;
- moveWindow(fgw, origin, dimensions);
- }
- };
- void toggleMaximize()
- {
- ForegroundWindow fgw;
- WINDOWPLACEMENT wp{};
- wp.length = sizeof(wp);
- if (!GetWindowPlacement(fgw, &wp)) throw std::runtime_error(
- "Couldn't get window placement");
- wp.showCmd == SW_MAXIMIZE || wp.showCmd == SW_SHOWMAXIMIZED ?
- ShowWindow(fgw, SW_RESTORE) : ShowWindow(fgw, SW_SHOWMAXIMIZED);
- if constexpr (verbose) std::cout << '\t' <<
- (wp.showCmd == SW_MAXIMIZE || wp.showCmd == SW_SHOWMAXIMIZED ?
- "restored" : "maximized") << " window" << std::endl;
- }
- void center()
- {
- ForegroundWindow fgw;
- MonitorInfoFromWindow info(fgw);
- auto& origin{ info.origin };
- auto& [origin_x, origin_y]{ origin };
- auto& dimensions{ info.workspaceDimensions };
- auto& [dimension_x, dimension_y]{ dimensions };
- origin_x += dimension_x / 3;
- origin_y += dimension_y / 3;
- dimension_x = 800;
- dimension_y = 600;
- moveWindow(fgw, origin, dimensions);
- }
- void test()
- {
- if constexpr (verbose)
- {
- ForegroundWindow fgw;
- char t[MAX_PATH]{ '\0' };
- GetWindowText(fgw, t, sizeof(t));
- std::cout << "\tnamed \" " << t << " \"" << std::endl;
- MonitorInfoFromWindow info(fgw);
- }
- }
- // TODO "always on top" toggle via (win + numpad asterisk)?
- int main([[maybe_unused]] int argc, [[maybe_unused]] char* argv[])
- {
- // set up hotkeys
- for (unsigned int k = VK_NUMPAD0; k <= VK_NUMPAD9; ++k)
- {
- if (!RegisterHotKey(nullptr, 0, MOD_NOREPEAT | MOD_WIN, k))
- throw std::runtime_error("Failed to bind hotkey");
- }
- // set up test() function hotkey if we're verbose
- if constexpr (verbose)
- {
- if (!RegisterHotKey(nullptr, 0, MOD_NOREPEAT | MOD_WIN, VK_DECIMAL))
- throw std::runtime_error("Failed to bind testing hotkey");
- }
- // get response when a hotkey is pressed
- MSG msg{};
- while (GetMessage(&msg, nullptr, 0, 0) > 0)
- {
- if (msg.message == WM_HOTKEY)
- {
- const auto vKey{ msg.lParam >> 16 }; // high order bits is vkey
- if constexpr (verbose) std::cout
- << "\n\tkey " << vKey << " pressed" << std::endl;
- try
- {
- switch (vKey)
- {
- case VK_NUMPAD0: center(); break;
- case VK_NUMPAD1: Position(Pos::Bottom | Pos::Left); break;
- case VK_NUMPAD2: Position(Pos::Bottom); break;
- case VK_NUMPAD3: Position(Pos::Bottom | Pos::Right); break;
- case VK_NUMPAD4: Position(Pos::Left); break;
- case VK_NUMPAD5: toggleMaximize(); break;
- case VK_NUMPAD6: Position(Pos::Right); break;
- case VK_NUMPAD7: Position(Pos::Top | Pos::Left); break;
- case VK_NUMPAD8: Position(Pos::Top); break;
- case VK_NUMPAD9: Position(Pos::Top | Pos::Right); break;
- case VK_DECIMAL: test(); break;
- default: throw std::runtime_error("got unexpected hotkey!");
- };
- }
- catch (...) // all the things
- {
- // TODO this part. I'm lazy. just swallow errors
- std::cerr << "[ERROR] caught exception" << std::endl;
- }
- }
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement