2 * Scroll windows and DCs
4 * Copyright David W. Metcalfe, 1993
15 #include "sysmetrics.h"
17 /* #define DEBUG_SCROLL */
22 extern HRGN DCE_GetVisRgn(HWND, WORD);
27 /* -----------------------------------------------------------------------
28 * SCROLL_TraceChildren
30 * Returns a region invalidated by children, siblings, and/or ansectors
31 * in the window rectangle or client rectangle
33 * dcx can have DCX_WINDOW, DCX_CLIPCHILDREN, DCX_CLIPSIBLINGS set
36 HRGN SCROLL_TraceChildren( HWND hScroll, short dx, short dy, WORD dcx)
38 WND *wndScroll = WIN_FindWndPtr( hScroll );
40 HRGN hUpdateRgn,hCombineRgn;
42 if( !wndScroll || ( !dx && !dy) ) return 0;
44 if( dcx & DCX_WINDOW )
45 hRgnWnd = CreateRectRgnIndirect(&wndScroll->rectWindow);
50 GetClientRect(hScroll,&rect);
51 hRgnWnd = CreateRectRgnIndirect(&rect);
54 hUpdateRgn = DCE_GetVisRgn( hScroll, dcx );
55 hCombineRgn = CreateRectRgn(0,0,0,0);
57 if( !hUpdateRgn || !hCombineRgn )
59 DeleteObject( hUpdateRgn? hUpdateRgn : hCombineRgn);
60 DeleteObject(hRgnWnd);
64 OffsetRgn( hUpdateRgn, dx, dy);
65 CombineRgn(hCombineRgn, hRgnWnd, hUpdateRgn, RGN_DIFF);
67 DeleteObject(hRgnWnd);
68 DeleteObject(hUpdateRgn);
74 /* ----------------------------------------------------------------------
75 * SCROLL_ScrollChildren
77 BOOL SCROLL_ScrollChildren( HWND hScroll, short dx, short dy)
79 WND *wndPtr = WIN_FindWndPtr(hScroll);
80 HWND hWnd = wndPtr->hwndChild;
84 if( !wndPtr || ( !dx && !dy )) return 0;
86 dprintf_scroll(stddeb,"SCROLL_ScrollChildren: hwnd "NPFMT" dx=%i dy=%i\n",hScroll,dx,dy);
88 /* get a region in client rect invalidated by siblings and ansectors */
89 hUpdateRgn = SCROLL_TraceChildren(hScroll, dx , dy, DCX_CLIPSIBLINGS);
91 /* update children coordinates */
94 wndPtr = WIN_FindWndPtr( hWnd );
96 /* we can check if window intersects with clipRect parameter
97 * and do not move it if not - just a thought. - AK
100 SetWindowPos(hWnd,0,wndPtr->rectWindow.left + dx,
101 wndPtr->rectWindow.top + dy, 0,0, SWP_NOZORDER |
102 SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOREDRAW |
105 hWnd = wndPtr->hwndNext;
108 /* invalidate uncovered region and paint frames */
109 b = RedrawWindow( hScroll, NULL, hUpdateRgn, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE |
110 RDW_ERASENOW | RDW_ALLCHILDREN );
112 DeleteObject( hUpdateRgn);
117 /*************************************************************************
118 * ScrollWindow (USER.61)
120 * FIXME: a bit broken
123 void ScrollWindow(HWND hwnd, short dx, short dy, LPRECT rect, LPRECT clipRect)
126 HRGN hrgnUpdate,hrgnClip;
129 dprintf_scroll(stddeb,"ScrollWindow: dx=%d, dy=%d, lpRect =%08lx clipRect=%i,%i,%i,%i\n",
130 dx, dy, (LONG)rect, (int)((clipRect)?clipRect->left:0),
131 (int)((clipRect)?clipRect->top:0),
132 (int)((clipRect)?clipRect->right:0),
133 (int)((clipRect)?clipRect->bottom:0));
135 /* if rect is NULL children have to be moved */
138 GetClientRect(hwnd, &rc);
139 hrgnClip = CreateRectRgnIndirect( &rc );
141 /* children will be Blt'ed too */
142 hdc = GetDCEx(hwnd, hrgnClip, DCX_CACHE | DCX_CLIPSIBLINGS);
143 DeleteObject(hrgnClip);
147 GetClientRect(hwnd,&rc);
148 dprintf_scroll(stddeb,"\trect=%i %i %i %i client=%i %i %i %i\n",
149 (int)rect->left,(int)rect->top,(int)rect->right,
150 (int)rect->bottom,(int)rc.left,(int)rc.top,
151 (int)rc.right,(int)rc.bottom);
157 if (clipRect == NULL)
158 GetClientRect(hwnd, &cliprc);
160 CopyRect(&cliprc, clipRect);
162 hrgnUpdate = CreateRectRgn(0, 0, 0, 0);
163 ScrollDC(hdc, dx, dy, &rc, &cliprc, hrgnUpdate, NULL);
164 ReleaseDC(hwnd, hdc);
168 /* FIXME: this doesn't take into account hrgnUpdate */
169 if( !SCROLL_ScrollChildren(hwnd,dx,dy) )
170 InvalidateRgn(hwnd, hrgnUpdate, TRUE);
174 HRGN hrgnInv = SCROLL_TraceChildren(hwnd,dx,dy,DCX_CLIPCHILDREN |
178 HRGN hrgnCombine = CreateRectRgn(0,0,0,0);
180 CombineRgn(hrgnCombine,hrgnInv,hrgnUpdate,RGN_OR);
181 dprintf_scroll(stddeb,"ScrollWindow: hrgnComb="NPFMT" hrgnInv="NPFMT" hrgnUpd="NPFMT"\n",
182 hrgnCombine,hrgnInv,hrgnUpdate);
184 DeleteObject(hrgnUpdate); DeleteObject(hrgnInv);
185 hrgnUpdate = hrgnCombine;
188 RedrawWindow( hwnd, NULL, hrgnUpdate, RDW_INVALIDATE | RDW_ERASE | RDW_ERASENOW);
191 DeleteObject(hrgnUpdate);
195 /*************************************************************************
196 * ScrollDC (USER.221)
201 BOOL ScrollDC(HDC hdc, short dx, short dy, LPRECT rc, LPRECT cliprc,
202 HRGN hrgnUpdate, LPRECT rcUpdate)
204 HRGN hrgnClip, hrgn1, hrgn2;
207 DC *dc = (DC *)GDI_GetObjPtr(hdc, DC_MAGIC);
209 dprintf_scroll(stddeb,"ScrollDC: dx=%d dy=%d, hrgnUpdate="NPFMT" rc=%i %i %i %i\n",
210 dx,dy,hrgnUpdate,(int)((rc)?rc->left:0),
211 (int)((rc)?rc->top:0),
212 (int)((rc)?rc->right:0),
213 (int)((rc)?rc->bottom:0));
220 hrgnClip = CreateRectRgnIndirect(cliprc);
221 SelectClipRgn(hdc, hrgnClip);
226 src.x = XDPTOLP(dc, rc->left);
227 dest.x = XDPTOLP(dc, rc->left + abs(dx));
231 src.x = XDPTOLP(dc, rc->left + abs(dx));
232 dest.x = XDPTOLP(dc, rc->left);
236 src.y = YDPTOLP(dc, rc->top);
237 dest.y = YDPTOLP(dc, rc->top + abs(dy));
241 src.y = YDPTOLP(dc, rc->top + abs(dy));
242 dest.y = YDPTOLP(dc, rc->top);
245 width = rc->right - rc->left - abs(dx);
246 height = rc->bottom - rc->top - abs(dy);
248 if (!BitBlt(hdc, dest.x, dest.y, width, height, hdc, src.x, src.y,
255 hrgn1 = CreateRectRgn(rc->left, rc->top, rc->left+dx, rc->bottom);
257 hrgn1 = CreateRectRgn(rc->right+dx, rc->top, rc->right,
260 hrgn1 = CreateRectRgn(0, 0, 0, 0);
263 hrgn2 = CreateRectRgn(rc->left, rc->top, rc->right, rc->top+dy);
265 hrgn2 = CreateRectRgn(rc->left, rc->bottom+dy, rc->right,
268 hrgn2 = CreateRectRgn(0, 0, 0, 0);
270 RgnType = CombineRgn(hrgnUpdate, hrgn1, hrgn2, RGN_OR);
275 if (rcUpdate) GetRgnBox( hrgnUpdate, rcUpdate );
280 /*************************************************************************
281 * ScrollWindowEx (USER.319)
285 * SCROLL_TraceChildren can help
288 int ScrollWindowEx(HWND hwnd, short dx, short dy, LPRECT rect, LPRECT clipRect,
289 HRGN hrgnUpdate, LPRECT rcUpdate, WORD flags)
294 dprintf_scroll(stddeb,"ScrollWindowEx: dx=%d, dy=%d, wFlags=%04x\n",dx, dy, flags);
299 GetClientRect(hwnd, &rc);
302 if (clipRect == NULL)
303 GetClientRect(hwnd, &cliprc);
305 CopyRect(&cliprc, clipRect);
307 ScrollDC(hdc, dx, dy, &rc, &cliprc, hrgnUpdate, rcUpdate);
309 if (flags | SW_INVALIDATE)
311 RedrawWindow( hwnd, NULL, hrgnUpdate, RDW_INVALIDATE | RDW_ERASE |
312 ((flags & SW_ERASE) ? RDW_ERASENOW : 0));
315 ReleaseDC(hwnd, hdc);