Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Coordinate changes #7

Open
cryptoxx opened this issue Dec 27, 2016 · 10 comments
Open

Coordinate changes #7

cryptoxx opened this issue Dec 27, 2016 · 10 comments

Comments

@cryptoxx
Copy link

What are left-bottom coordinates ? Tried everything and nothing work so far.
These are default left-top:
static const RECT kHotCorner = {
.top = -20,
.left = 20,
.right = +20,
.bottom = +20,
};

@taviso
Copy link
Owner

taviso commented Dec 27, 2016

Probably something like this, if you don't mind hardcoding the resolution:

static const RECT kHotCorner = {
    .top = YourVerticalResolution - 20,
    .left = -20,
    .right = +20,
    .bottom = YourVerticalResolution + 20,
};

If you don't want to hardcode it (perhaps you change resolution sometimes), you can get your resolution dynamically with GetWindowRect(), e.g. remove const from kHotCorner add then something like this to the top of WinMain():

    GetWindowRect(GetDesktopWindow(), &kHotCorner);

    kHotCorner.top = kHotCorner.bottom - 20;
    kHotCorner.bottom += 20;
    kHotCorner.left = -20;
    kHotCorner.right = +20;

Hope that helps!

@cryptoxx
Copy link
Author

cryptoxx commented Dec 27, 2016

thanks. Switching corners with hardcoded res. is working well. Eg. bottom-left@1080p:

.top = +1070,
.left = -20,
.right = +20,
.bottom = +1100,

however I'm using notebook with 4K build-in display in work (native resolution) and I'm connecting external FHD monitor at home. I need to test GetWindowRect out because hardcoded resolution is not working in this case - obviously.

EDIT: Unfortunately, i can't make dynamic resolution works when corner is changed from default to any other. This may be an issue for notebook users with external displays if they decide to use other corner.

@taviso
Copy link
Owner

taviso commented Dec 27, 2016

You want the corner to be moved when you change resolution automatically?

I understand now. Hmm, to do this I think you will need to handle WM_DISPLAYCHANGE, this isn't difficult, try this. First add a WindowProc above WinMain(), e.g.:

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
        if (uMsg == WM_DISPLAYCHANGE) {
            GetWindowRect(GetDesktopWindow(), &kHotCorner);
            kHotCorner.top = kHotCorner.bottom - 20;
            kHotCorner.bottom += 20;
            kHotCorner.left = -20;
            kHotCorner.right = +20;
            return 0;
        }

        return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

Now you need to create an invisible message-only window to get windows messages, just add this to the top of WinMain()

    HWND Window;

    Window = CreateWindowEx(0, "Message", NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL);

    SetWindowLong(Window, GWL_WNDPROC, WindowProc);

Now when you change resolution, the corner will move. Does that work?

@taviso
Copy link
Owner

taviso commented Dec 27, 2016

I should add these to a wiki page in case someone else wants the same thing as you.

@Joaoha
Copy link

Joaoha commented May 20, 2020

Hi

How can I change this to be the upper right corner of the screen?
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
if (uMsg == WM_DISPLAYCHANGE) {
GetWindowRect(GetDesktopWindow(), &kHotCorner);
kHotCorner.top = kHotCorner.bottom - 20;
kHotCorner.bottom += 20;
kHotCorner.left = -20;
kHotCorner.right = +20;
return 0;
}

    return DefWindowProc(hwnd, uMsg, wParam, lParam);

}

@taviso
Copy link
Owner

taviso commented May 20, 2020

I think you just want something like this:

    GetWindowRect(GetDesktopWindow(), &kHotCorner);
    kHotCorner.bottom   = 20;
    kHotCorner.left     = kHotCorner.right - 20;

@Joaoha
Copy link

Joaoha commented May 20, 2020

Doesn't seem to work...
cl /nologo /O2 /c hotcorner.c
hotcorner.c
hotcorner.c(26): error C2099: initializer is not a constant
hotcorner.c(152): warning C4047: 'function': 'LONG' differs in levels of indirection from 'LRESULT (__stdcall *)(HWND,UINT,WPARAM,LPARAM)'
hotcorner.c(152): warning C4024: 'SetWindowLongA': different types for formal and actual parameter 3
NMAKE : fatal error U1077: '"C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.26.28801\bin\HostX86\x86\cl.EXE"' : return code '0x2'
Stop.

Thanks

@taviso
Copy link
Owner

taviso commented May 21, 2020

It's just saying you need to remove the const before you change it (at the top).

@Joaoha
Copy link

Joaoha commented May 21, 2020

ok, I've changed it but it still activates on top LEFT corner, not Top Right corner.


#include <stdlib.h>
#include <windows.h>

#pragma comment(lib, "USER32")
#pragma comment(linker, "/SUBSYSTEM:WINDOWS")

#define KEYDOWN(k) ((k) & 0x80)

// This is a **very** minimal hotcorner app, written in C. Maybe its not the
// optimal way to do this, but it works for me.
//
// Zero state is stored anywhere, no registry keys or configuration files.
//
// - If you want to configure something, edit the code.
// - If you want to uninstall it, just delete it.
//
// Tavis Ormandy <taviso@cmpxchg8b.com> December, 2016
//
// https://github.com/taviso/hotcorner
//

// If the mouse enters this rectangle, activate the hot corner function.
// There are some hints about changing corners here
//      https://github.com/taviso/hotcorner/issues/7#issuecomment-269367351
static RECT kHotCorner = {
  .top    = -20,
  .left   = -20,
  .right  = +20,
  .bottom = +20,
};

// Input to inject when corner activated (Win+Tab by default).
static const INPUT kCornerInput[] = {
    { INPUT_KEYBOARD, .ki = { VK_LWIN, .dwFlags = 0 }},
    { INPUT_KEYBOARD, .ki = { VK_TAB,  .dwFlags = 0 }},
    { INPUT_KEYBOARD, .ki = { VK_TAB,  .dwFlags = KEYEVENTF_KEYUP }},
    { INPUT_KEYBOARD, .ki = { VK_LWIN, .dwFlags = KEYEVENTF_KEYUP }},
};

// How long cursor has to linger in the kHotCorner RECT to trigger input.
static const DWORD kHotDelay = 100;

// You can exit the application using the hot key CTRL+ALT+C by default, if it
// interferes with some application you're using (e.g. a full screen game).
static const DWORD kHotKeyModifiers = MOD_CONTROL | MOD_ALT;
static const DWORD kHotKey = 'C';

static HANDLE CornerThread = INVALID_HANDLE_VALUE;

// This thread runs when the cursor enters the hot corner, and waits to see if the cursor stays in the corner.
// If the mouse leaves while we're waiting, the thread is just terminated.
static DWORD WINAPI CornerHotFunc(LPVOID lpParameter)
{
    BYTE KeyState[256];
    POINT Point;

    Sleep(kHotDelay);

    // Check if a mouse putton is pressed, maybe a drag operation?
    if (GetKeyState(VK_LBUTTON) < 0 || GetKeyState(VK_RBUTTON) < 0) {
        return 0;
    }

    // Check if any modifier keys are pressed.
    if (GetKeyboardState(KeyState)) {
        if (KEYDOWN(KeyState[VK_SHIFT]) || KEYDOWN(KeyState[VK_CONTROL])
          || KEYDOWN(KeyState[VK_MENU]) || KEYDOWN(KeyState[VK_LWIN])
          || KEYDOWN(KeyState[VK_RWIN])) {
            return 0;
        }
    }

    // Verify the corner is still hot
    if (GetCursorPos(&Point) == FALSE) {
        return 1;
    }

    // Check co-ordinates.
    if (PtInRect(&kHotCorner, Point)) {
        #pragma warning(suppress : 4090)
        if (SendInput(_countof(kCornerInput), kCornerInput, sizeof(INPUT)) != _countof(kCornerInput)) {
            return 1;
        }
    }

    return 0;
}

static LRESULT CALLBACK MouseHookCallback(int nCode, WPARAM wParam, LPARAM lParam)
{
    MSLLHOOKSTRUCT *evt = (MSLLHOOKSTRUCT *) lParam;

    // If the mouse hasn't moved, we're done.
    if (wParam != WM_MOUSEMOVE)
        goto finish;

    // Check if the cursor is hot or cold.
    if (!PtInRect(&kHotCorner, evt->pt)) {

        // The corner is cold, and was cold before.
        if (CornerThread == INVALID_HANDLE_VALUE)
            goto finish;

        // The corner is cold, but was previously hot.
        TerminateThread(CornerThread, 0);

        CloseHandle(CornerThread);

        // Reset state.
        CornerThread = INVALID_HANDLE_VALUE;

        goto finish;
    }

    // The corner is hot, check if it was already hot.
    if (CornerThread != INVALID_HANDLE_VALUE) {
        goto finish;
    }

    // Check if a mouse putton is pressed, maybe a drag operation?
    if (GetKeyState(VK_LBUTTON) < 0 || GetKeyState(VK_RBUTTON) < 0) {
        goto finish;
    }

    // The corner is hot, and was previously cold. Here we start a thread to
    // monitor if the mouse lingers.
    CornerThread = CreateThread(NULL, 0, CornerHotFunc, NULL, 0, NULL);

finish:
    return CallNextHookEx(NULL, nCode, wParam, lParam);
}

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
  if (uMsg == WM_DISPLAYCHANGE) {
    GetWindowRect(GetDesktopWindow(), &kHotCorner);
    kHotCorner.top = kHotCorner.bottom - 20;
    kHotCorner.bottom = 20;
    kHotCorner.left = kHotCorner.right - 20;
    kHotCorner.right = +20;
    return 0;
  }

  return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
  HWND Window;
  Window = CreateWindowEx(0, "Message", NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL);
  SetWindowLong(Window, GWL_WNDPROC, WindowProc);

	MSG Msg;
    HHOOK MouseHook;

    if (!(MouseHook = SetWindowsHookEx(WH_MOUSE_LL, MouseHookCallback, NULL, 0)))
        return 1;

    RegisterHotKey(NULL, 1, kHotKeyModifiers, kHotKey);

    while (GetMessage(&Msg, NULL, 0, 0)) {
        if (Msg.message == WM_HOTKEY) {
            break;
        }
        DispatchMessage(&Msg);
    }

    UnhookWindowsHookEx(MouseHook);

    return Msg.wParam;
}```

@taviso
Copy link
Owner

taviso commented May 21, 2020

You didn't call the code to change the corner unless there's WM_DISPLAYCHANGE event, just copy that code into the top of WinMain() and it will work.

i.e., copy these lines:

GetWindowRect(GetDesktopWindow(), &kHotCorner);
kHotCorner.top = kHotCorner.bottom - 20;
kHotCorner.bottom = 20;
kHotCorner.left = kHotCorner.right - 20;
kHotCorner.right = +20;

And put them after this line:

HHOOK MouseHook;

(Note: please put three backticks (```) around code on github or it's really hard to read!)

Like this:
```
Code goes here
```

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants