Friday, October 9, 2015

Mouse wheel redirecting to proper window

Not so long time ago, Microsoft decided to change behavior of mouse wheel in their software and guidelines alike. At the beginning, when wheels weren't as popular as today, using mouse wheel caused to scroll currently focused control in the active window. It means that mouse position wasn't taken into consideration there. However, more intuitive solution seems to be affecting currently hovered control, no matter which window is focused. That is what Microsoft changed in their documentations — to be more precise under Mouse wheel guidelines:

Make the mouse wheel take effect without clicking or having input focus. Hovering is sufficient.

Unfortunately, I noticed that wxWidgets preserves the old behavior or simply doesn't change anything (I'm not sure — I've just started learning and using this library), so only focused control receives the WM_MOUSEWHEEL message. This can be a little annoying for example in FileZilla, which uses wxWidgets. It creates differences between Windows and other systems — which use the hovering way. I believe the library makers will move with the times and change it soon, so I will have to change tense of the this paragraph to past [; .

Anyway, to make your software even more awesome, you can redirect mouse wheel events to other applications under mouse, but without focus. Normally, such events (messages) are received only by an active window (without using hooks of course). Wouldn't it be great for example to scroll web browser on other monitor without activating it? I just can't stop myself from making an advertisement of Notepad++ here.

It's one out of few programs for Windows OS, which implement such behavior. I don't understand why it's so uncommon. Actually, you can write it in a few lines of code. In application message loop or window procedure simply check whether WM_MOUSEWHEEL belongs to your window using WindowFromPoint(POINT) with point included in lParam. The code is presented below:


if (message == WM_MOUSEWHEEL) {
    POINT mousePos = {
        GET_X_LPARAM(lParam),
        GET_Y_LPARAM(lParam)
    };
    HWND hWndPointed = WindowFromPoint(mousePos);
    if (hWndPointed != NULL && hWndPointed != hwnd){
        PostMessage(hWndPointed, WM_MOUSEWHEEL, wParam, lParam);
        return 0;
    }
}

It can also be simply implemented in your wxWidgets application by overriding MSWWindowProc method in custom frame class derived from wxFrame:

WXLRESULT YourFrame::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam) {
    // Redirect mouse wheel to other windows
    if (message == WM_MOUSEWHEEL) {
        POINT mousePos = {
            GET_X_LPARAM(lParam),
            GET_Y_LPARAM(lParam)
        };
        HWND hWndPointed = WindowFromPoint(mousePos);
        if (hWndPointed != nullptr && hWndPointed != this->GetHWND()){
            PostMessage(hWndPointed, WM_MOUSEWHEEL, wParam, lParam);
            return 0;
        }
    }
    return wxFrame::MSWWindowProc(message, wParam, lParam);
}

Just imagine every application properly redirecting mouse wheel to others..

EDIT: I've found a great piece of software for Windows you can install to achieve that behavior on all windows: KatMouse.

Friday, April 25, 2014

Fader - screensaver smoothly turning off display

When I was using Linux some time ago, I found out there is a really great thing about screensavers. Before starting, the display is fading out smoothly so you don't get shocked and you have ability to break starting screensaver. There is something similar in Windows (at least in 7) when turning off display, but it's hopelessly fast and you're not able to stop it. You have to wait for turning display off, then move mouse and wait for turning it on. In short, it sucks, doesn't it?

That feature in Linux is adorable, so I've written simple app for Windows which does better than default. Actually, it's a screensaver and after fadeout turns off display. It's not especially complex, but supports multi-screen displays, has some settings and can be stopped. I created this some years ago, and now I've decided to share it here with source code. If you would like to use the code, go ahead but it'd be nice if you place some info about the author:
https://github.com/piomar123/Fader

I should say something about settings. There is "alpha step" and "step interval". The first is amount of alpha (let's say brightness) changed every interval time. Alpha changes from 0 (transparent) to 255 (fully black), so greater values make fading faster and less smooth. Step interval is in milliseconds and the higher value, the slower fading is.
In conclusion, funny fact. Ironically, I'm not able to use this screensaver on my laptop due to wonderful mouse wireless receiver (actually the software) that prevents screensaver from starting.

Thursday, April 24, 2014

Let's write some dummy code

Portion of some amazing WinAPI kind of hack defines in headers:

#define UNREFERENCED_PARAMETER(P) {(P)=(P);}
#define UNREFERENCED_LOCAL_VARIABLE(L) {(L)=(L);}

It wouldn't be anything weird unless I found something here:
LRESULT APIENTRY EditBoxProc(
    HWND hwndDlg, 
    UINT uMsg, 
    WPARAM wParam, 
    LPARAM lParam) 
{ 
    HWND hwndEdit; 
 
    switch(uMsg) 
    { 
        // Typical switch case stuff (..)
    } 
    return FALSE; 
        UNREFERENCED_PARAMETER(lParam); 
} 
Although it does nothing, it does more nothing, because the statement is after end of function.. (Apparently it suppresses some warnings.)
Am I missing something or the only compiler which buys it can be made by Microsoft? I suppose this could be sufficient here (at least for GCC):
LRESULT APIENTRY EditBoxProc(
    HWND hwndDlg, 
    UINT uMsg, 
    WPARAM wParam, 
    LPARAM) { .. }

Saturday, April 12, 2014

RegisterBlogEx()

It may seem pointless to use pure Win32 API to create new software nowadays. There are many higher-level APIs that makes developing shorter, more effective and operating system slower.
However, you can find some great software written only in WinAPI (eg. Notepad++TPFanControl or some my applications). Why did they decide to create that way? Maybe due to:


Launching speed

Apps created in pure Windows API use mostly libraries that are probably already loaded into memory, because other software uses them (and so does OS). This is the lowest-level API in Windows (well, there can be also some kind of interrupts, I guess, but highly limited in user space), so it'll be difficult to start faster something that needs external libraries.


Running performance

Access to a whole window message queue allows you to check only these you really need. What's more, operations in WindowProcedure can be finished quickly (less than "several seconds") or sent to other threads, so messages are constantly processed. That would decrease probability of "not responding" programs which is really annoying state (a least for me) – the only things you can do are: forcing to close app, watching white window with this lovely circle: 
If it's not animating, your browser sux
or going for some more coffee. Writing code in non-managed technology (like standard C++) forces you to manage memory on your own (or not – there is a lot of memory.. who cares). But this eliminates the need for extra resources (eg. threads) for garbage collector and increases performance.

Portability

WinAPI is changing quite slowly and usually preserves good backward and forward compatibility. That means, what was created many years ago under older Windows should work in much newer version without major problems. Moreover, using standard system libraries (unlike in .NOT .NET which needs huge and fat framework to be installed additionally) makes it easier to port them into other OS. The brilliant example is Wine (Linux port of WinAPI libraries that allows you to run Windows apps natively). It's so good that some software works even faster and better than in Windows..




Smaller size

No extra libraries means smaller size, that's quite obvious. But not for GNU GCC, which puts some library garbage into console applications which makes simple "Hello world" about 500KB. That's good topic for another post. For the moment, you can read this article.

When I find some more time, I'll post more weird and not obvious stuff connected with WinAPI which I've found during Windows programming.