Source file: /~heha/hsn/maus32.zip/magnet/magnet32.cpp

#include <windows.h>
// Quelltext für Visual C++ 6.0, ausnahmsweise .CPP für Referenzparameter
// Funktion: "Magnetische Fenster" à la WinAmp oder KDE
// h#s 08/02
// In Einstellung "DEBUG" ist der Compiler-Schalter "/GZ" zu entfernen!
#pragma comment(linker,"/ALIGN:4096 /DLL /MERGE:.rsrc=.rdata /SECTION:.shared,RWS /RELEASE /NODEFAULTLIB")

#pragma data_seg(".shared")
HHOOK Hook=0;	// Initialisierung ist notwendig,
int SnapW=6;	// sonst ist's "bss_seg" und kein "data_seg"

//#pragma data_seg()
HHOOK HookProcess;	// Initialisierung für NT-Ladbarkeit? -> bss_seg

#define MAXINT 0x7FFFFFFF;
typedef enum {sleft=1, stop=2, sright=4, sbottom=8};	//Schnapp-Maske

int _fastcall Abs(int x) {
 if (x<0) x=-x;
 return x;
}

void _fastcall AbsMin(long &x2, long x) {
//Setzt x2 auf das Betragsminimum beider vzb. Zahlen
 if (Abs(x2)>Abs(x)) x2=x;
}

void _stdcall AdjustRect(HWND W, RECT &R, BYTE snap) {
//Modifiziert Zielrechteck <R> des Fensters <W> in Abhängigkeit
//der Nachbar- und des Elternfensters an den durch <snap> erlaubten Kanten
 RECT RP,R2;	//Eltern- und Geschwister-Rechteck
 POINT MP;	//Verschiebung
 HWND W2;	//Eltern- oder Geschwister-Fenster
 char s[8];	//für Klassenname (IconTitle sollte ausgeschlossen sein)

 MP.x=MP.y=MAXINT;
	//Ausrichtung an Eltern-Fenster: Client-Bereich, innen
 W2=GetParent(W);
 if (!W2) W2=GetDesktopWindow();
 GetClientRect(W2,&RP);
 MapWindowPoints(W2,0,(LPPOINT)&RP,2);	// wie ClientToScreen beider Ecken
 if (RP.top<R.bottom && R.top<RP.bottom) {
  if (sleft  &snap) AbsMin(MP.x,R.left  -RP.left);
  if (sright &snap) AbsMin(MP.x,R.right -RP.right);
 }
 if (RP.left<R.right && R.left<RP.right) {
  if (stop   &snap) AbsMin(MP.y,R.top   -RP.top);
  if (sbottom&snap) AbsMin(MP.y,R.bottom-RP.bottom);
 }
	//Ausrichtung an Geschwister: Ganze Fenster, außen
 for (W2=GetWindow(W2,GW_CHILD); W2; W2=GetWindow(W2,GW_HWNDNEXT)) {
  if (W2==W) continue;		//Nicht das eigene Fenster benutzen!
  if (!IsWindowVisible(W2)) continue;
  if (IsIconic(W2)) continue;
  GetClassName(W2,s,sizeof(s));
  if (!lstrcmp(s,"#32772")) continue;	//IconTitle
  GetWindowRect(W2,&R2);
  if (R2.top<R.bottom && R.top<R2.bottom) {
   if (sleft  &snap) AbsMin(MP.x,R.left  -R2.right);
   if (sright &snap) AbsMin(MP.x,R.right -R2.left);
  }
  if (R2.left<R.right && R.left<R2.right) {
   if (stop   &snap) AbsMin(MP.y,R.top   -R2.bottom);
   if (sbottom&snap) AbsMin(MP.y,R.bottom-R2.top);
  }
	//Ausrichtung an Geschwister: Eck-Kreuzungen bevorzugen
  if (Abs(R.bottom-R2.top)<=SnapW
    ||Abs(R.top-R2.bottom)<=SnapW) {
   if (sleft  &snap) AbsMin(MP.x,R.left  -R2.left);
   if (sright &snap) AbsMin(MP.x,R.right -R2.right);
  }
  if (Abs(R.left-R2.right)<=SnapW
    ||Abs(R.right-R2.left)<=SnapW) {
   if (stop   &snap) AbsMin(MP.y,R.top   -R2.top);
   if (sbottom&snap) AbsMin(MP.y,R.bottom-R2.bottom);
  }
 }
	//Schnappeffekt (Weite) prüfen
 if (Abs(MP.x)>SnapW) MP.x=0;
 if (Abs(MP.y)>SnapW) MP.y=0;
	//Rechteck verändern
 CopyRect(&R2,&R);
 if (sleft  &snap) R.left  -=MP.x;
 if (stop   &snap) R.top   -=MP.y;
 if (sright &snap) R.right -=MP.x;
 if (sbottom&snap) R.bottom-=MP.y;
	//Sicherung, dass Fenster nicht unerreichbar herausrutscht
 if (R.left >= RP.right) R.left =R2.left;
 if (R.right<= RP.left)  R.right=R2.right;
 if (R.top  <= RP.top-GetSystemMetrics(SM_CYCAPTION)) R.top=R2.top;
 if (R.top  >= RP.bottom) R.top=R2.top;
/* Zumindest Windows98 sorgt offenbar selbst dafür, dass aus MOVE
   kein SIZE wird, wenn das Rechteck einseitig modifiziert wurde. */
}

LRESULT CALLBACK CbtHook(int Code, WPARAM wParam, LPARAM lParam) {
 static BYTE snap=sleft|sright|stop|sbottom;	//rutscht nach .shared: OK
 LRESULT ret;
 HWND W;
 POINT P;
 int HitCode;

 ret=CallNextHookEx(Hook,Code,wParam,lParam);
 switch (Code) {
  case HCBT_SYSCOMMAND: switch (wParam&0xFFF0) {
   case SC_MOVE: {
    snap=sleft|sright|stop|sbottom;	//alle 4 Seiten ziehen lassen
   }break;
   case SC_SIZE: {
    snap=0;
    GetCursorPos(&P);			//funktioniert nur mit Maus!
    W=WindowFromPoint(P);
    if (!W) return ret;
    HitCode=SendMessage(W,WM_NCHITTEST,0,MAKELPARAM(P.x,P.y));
    switch (HitCode) {
     case HTLEFT:	snap=sleft;		break;
     case HTTOPLEFT:	snap=sleft|stop;	break;
     case HTTOP:	snap=stop;		break;
     case HTTOPRIGHT:	snap=stop|sright;	break;
     case HTRIGHT:	snap=sright;		break;
     case HTBOTTOMRIGHT:snap=sright|sbottom;	break;
     case HTBOTTOM:	snap=sbottom;		break;
     case HTBOTTOMLEFT:	snap=sleft|sbottom;	break;
     //default: MessageBeep(UINT(-1));
    }
   }break;
  }break;
  case HCBT_MOVESIZE: if (!(GetKeyState(VK_CONTROL)&0xFFFE)) {
   AdjustRect((HWND)wParam,*(LPRECT)lParam,snap);
  }
 }
 return ret;
}

extern "C" BOOL __stdcall _DllMainCRTStartup(
 HINSTANCE hinstDLL,	// DLL-Handle (=Basisadresse?)
 DWORD fdwReason,	// einer von 4 Gründen des Aufrufs
 LPVOID lpvReserved) {	// implizit-explizit-Flag
 switch (fdwReason) {
  case DLL_PROCESS_ATTACH: {
   DisableThreadLibraryCalls(hinstDLL);
   if (!Hook) {
    SnapW=GetProfileInt("Windows","Snap",SnapW);
    HookProcess=Hook=SetWindowsHookEx(WH_CBT,
      CbtHook,hinstDLL,0);
   }
  }break;
  case DLL_PROCESS_DETACH: {
   if (HookProcess) UnhookWindowsHookEx(HookProcess);
  }
 }
 return TRUE;
}
Detected encoding: ANSI (CP1252)4
Wrong umlauts? - Assume file is ANSI (CP1252) encoded