поведение окон - а'ля Winamp
ваши предложения. :-))
и я подумал, неужели никто еще не сталкивался с такой же проблемой. вряд ли. может кто поделится исходниками:-))
дело в том, что я уже это все делаю - WM_WINDOWPOSCHANGING, WM_WINDOWPOSCHANGED, WM_MOVING, WM_SIZING - за всем слежу, однако, остались еще глюки, которые не смог еще выловить.
и я подумал, неужели никто еще не сталкивался с такой же проблемой. вряд ли. может кто поделится исходниками:-))
// Win32
#include <windows.h>
char szAppName[] = "About1" ;
char szChild[] = "Child";
HINSTANCE hInstance ;
HWND hwndList[5], hwndMain;
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
LRESULT CALLBACK ChildWndProc (HWND, UINT, WPARAM, LPARAM) ;
bool IsCloseToWindow (HWND, LPWINDOWPOS, int, int);
void IsCloseToDeskTop (LPWINDOWPOS, int, int);
void DockedOnSizing (WPARAM, int &);
void DockedOnMoving (WPARAM, int &);
int WINAPI WinMain (HINSTANCE hInst, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
MSG msg ;
WNDCLASSEX wndclass ;
hInstance =hInst;
wndclass.cbSize = sizeof (wndclass) ;
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (hInstance, szAppName) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = szAppName ;
wndclass.lpszClassName = szAppName ;
wndclass.hIconSm = LoadIcon (hInstance, szAppName) ;
RegisterClassEx (&wndclass) ;
wndclass.lpfnWndProc = ChildWndProc ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szChild ;
RegisterClassEx (&wndclass) ;
hwndMain = CreateWindow (szAppName, "About Box Demo Program",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
100, 50,
NULL, NULL, hInstance, NULL) ;
ShowWindow (hwndMain, iCmdShow) ;
UpdateWindow (hwndMain) ;
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
UINT wDeviceID;
LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
static int fSave;
switch (iMsg)
{
case WM_CREATE :
hInstance = ((LPCREATESTRUCT) lParam)->hInstance ;
hwndList[0] = CreateWindow(szChild, "Child 1",
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
CW_USEDEFAULT, CW_USEDEFAULT,
100, 50,
hwnd, NULL, hInstance, NULL) ;
return 0 ;
case WM_MOVING :
DockedOnMoving(wParam, fSave);
return true;
case WM_SIZING :
DockedOnSizing(wParam, fSave);
return true;
case WM_WINDOWPOSCHANGING :
IsCloseToDeskTop((LPWINDOWPOS)lParam, fSave, 15);
IsCloseToWindow(hwndList[0], (LPWINDOWPOS)lParam, fSave, 15) ;
return 0;
case WM_DESTROY :
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, iMsg, wParam, lParam) ;
}
LRESULT CALLBACK ChildWndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
static int fSave;
switch (iMsg)
{
case WM_CREATE :
return 0 ;
case WM_MOVING :
DockedOnMoving(wParam, fSave);
return true;
case WM_SIZING :
DockedOnSizing(wParam, fSave);
return true;
case WM_WINDOWPOSCHANGING :
IsCloseToDeskTop((LPWINDOWPOS)lParam, fSave, 15);
IsCloseToWindow(hwndMain, (LPWINDOWPOS)lParam, fSave, 15) ;
return 0;
}
return DefWindowProc (hwnd, iMsg, wParam, lParam) ;
}
bool IsCloseToWindow(HWND hwndDockedTo, LPWINDOWPOS lpwp, int fMoving, int StickAt)
{
bool DockedByX=false;
bool DockedByY=false;
RECT WorkArea;
if(hwndDockedTo)
{
GetWindowRect(hwndDockedTo, &WorkArea);
if( lpwp->y + lpwp->cy > WorkArea.top - StickAt && lpwp->y < WorkArea.bottom + StickAt)
{
if( fMoving&2 && abs(WorkArea.left - lpwp->cx - lpwp->x) <= StickAt)
{
if( !(fMoving&1) ) lpwp->cx = WorkArea.left-lpwp->x;
else lpwp->x = WorkArea.left-lpwp->cx;
DockedByY=true;
}
if( fMoving&1 && abs(WorkArea.right - lpwp->x) <= StickAt)
{
if( !(fMoving&2) ) lpwp->cx = lpwp->x - WorkArea.right + lpwp->cx;
lpwp->x = WorkArea.right;
DockedByY=true;
}
if(DockedByY)
{
if( WorkArea.bottom > lpwp->y + lpwp->cy/2)
if( fMoving&4 && abs(WorkArea.bottom - lpwp->cy - lpwp->y) <= StickAt) lpwp->y = WorkArea.bottom - lpwp->cy;else;
else
if( fMoving&4 && abs(WorkArea.bottom - lpwp->y) <= StickAt) lpwp->y = WorkArea.bottom;
if(WorkArea.top < lpwp->y + lpwp->cy/2)
if( fMoving&8 && abs(WorkArea.top - lpwp->y) <= StickAt) lpwp->y = WorkArea.top;else;
else
if( fMoving&8 && abs(WorkArea.top - lpwp->y - lpwp->cy) <= StickAt) lpwp->y = WorkArea.top-lpwp->cy;
}
}
if( lpwp->x + lpwp->cx > WorkArea.left && lpwp->x < WorkArea.right)
{
if( fMoving&8 && abs(WorkArea.top - lpwp->y - lpwp->cy) <= StickAt)
{
if( !(fMoving&4) ) lpwp->cy = WorkArea.top - lpwp->y;
else lpwp->y = WorkArea.top - lpwp->cy;
DockedByX=true;
}
if( fMoving&4 && abs(WorkArea.bottom - lpwp->y ) <= StickAt)
{
if(!(fMoving&8)) lpwp->cy = lpwp->y - WorkArea.bottom + lpwp->cy;
lpwp->y = WorkArea.bottom;
DockedByX=true;
}
if(DockedByX)
{
if( fMoving&1 && abs(WorkArea.left - lpwp->x) <= StickAt) lpwp->x = WorkArea.left;
if( fMoving&2 && abs(WorkArea.right - lpwp->x-lpwp->cx) <= StickAt) lpwp->x = WorkArea.right-lpwp->cx;
}
}
}
return (DockedByX || DockedByY);
}
void IsCloseToDeskTop(LPWINDOWPOS lpwp, int fMoving, int StickAt)
{
RECT WorkArea;
SystemParametersInfo(SPI_GETWORKAREA, 0, &WorkArea, 0);
WorkArea.right -= lpwp->cx;
WorkArea.bottom -= lpwp->cy;
if( abs(WorkArea.left - lpwp->x) <= StickAt && fMoving&1)
{
if( !(fMoving&2) ) lpwp->cx +=lpwp->x - WorkArea.left;
lpwp->x = WorkArea.left;
}
if( abs(WorkArea.right - lpwp->x) <= StickAt && fMoving&2)
{
if( !(fMoving&1) ) lpwp->cx +=WorkArea.right - lpwp->x ;
else lpwp->x = WorkArea.right;
}
if( abs(WorkArea.top - lpwp->y) <= StickAt && fMoving&4)
{
if( !(fMoving&8) ) lpwp->cy += lpwp->y - WorkArea.top;
lpwp->y = WorkArea.top;
}
if( abs(WorkArea.bottom - lpwp->y) <= StickAt && fMoving&8)
{
if( !(fMoving&4) ) lpwp->cy += WorkArea.bottom - lpwp->y ;
else lpwp->y = WorkArea.bottom;
}
}
void DockedOnSizing(WPARAM wParam, int &fMoving)
{
fMoving&=~15;
if(wParam==9) fMoving|=15;
else
{
if(wParam==1 || wParam==4 || wParam==7) fMoving|=1;
if(wParam==2 || wParam==5 || wParam==8) fMoving|=2;
if(wParam==3 || wParam==4 || wParam==5) fMoving|=4;
if(wParam==6 || wParam==7 || wParam==8) fMoving|=8;
}
}
void DockedOnMoving(WPARAM wParam, int &fMoving)
{
fMoving|=15;
}