Listing 5: wnd_snap.c
Implementation of snappy subclassing
#include <windows.h> #include <windowsx.h> #include "wdjsub.h" #include "wnd_snap.h" #pragma warning( disable: 4100 ) // unref'd formal parameter static LRESULT CALLBACK snapWndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam ); #define HANDLE_WM_MOVING( hwnd, wParam, lParam, fn ) \ (fn)( hwnd, (RECT *) lParam ) #define HANDLE_WM_ENTERSIZEMOVE( hwnd, wParam, lParam, fn ) \ ((fn)(hwnd), 0L) #define shiftKeyPressed() (GetAsyncKeyState( VK_SHIFT ) < 0) static int cx, cy; // See Figure 3. static BOOL isClose( int a, int b ) { NONCLIENTMETRICS ncm = { 0 }; ncm.cbSize = sizeof ncm; SystemParametersInfo( SPI_GETNONCLIENTMETRICS, 0, &ncm, 0 ); return abs( a - b ) < ncm.iCaptionHeight; } static void onEnterSizeMove( HWND hwnd ) { POINT cur_pos = { 0 }; RECT rcWindow = { 0 }; GetWindowRect( hwnd, &rcWindow ); GetCursorPos( &cur_pos ); cx = cur_pos.x - rcWindow.left; cy = cur_pos.y - rcWindow.top; } static BOOL onMoving( HWND hwnd, RECT *prc ) { POINT cur_pos = { 0 }; RECT wa = { 0 }; if ( shiftKeyPressed() ) { return FALSE; } GetCursorPos( &cur_pos ); OffsetRect( prc, cur_pos.x - (prc->left + cx) , cur_pos.y - (prc->top + cy) ); SystemParametersInfo( SPI_GETWORKAREA, 0, &wa, 0 ); if ( isClose( prc->left, wa.left ) ) { OffsetRect( prc, wa.left - prc->left, 0 ); } else if ( isClose( wa.right, prc->right ) ) { OffsetRect( prc, wa.right - prc->right, 0 ); } if ( isClose( prc->top, wa.top ) ) { OffsetRect( prc, 0, wa.top - prc->top ); } else if ( isClose( wa.bottom, prc->bottom ) ) { OffsetRect( prc, 0, wa.bottom - prc->bottom ); } return TRUE; } static LRESULT CALLBACK snapWndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam ) { switch ( msg ) { HANDLE_MSG( hwnd, WM_ENTERSIZEMOVE, onEnterSizeMove ); HANDLE_MSG( hwnd, WM_MOVING , onMoving ); } return wdjCallOldProc( snapWndProc, hwnd, msg, wParam, lParam ); } BOOL WINAPI setSnap( HWND hwnd, BOOL enable ) { return enable ? wdjSubclass( snapWndProc, hwnd, 0 ) :wdjUnhook ( snapWndProc, hwnd ); }