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
);
23 extern HWND
CARET_GetHwnd();
28 /* -----------------------------------------------------------------------
29 * SCROLL_TraceChildren
31 * Returns a region invalidated by children, siblings, and/or ansectors
32 * in the window rectangle or client rectangle
34 * dcx can have DCX_WINDOW, DCX_CLIPCHILDREN, DCX_CLIPSIBLINGS set
37 HRGN
SCROLL_TraceChildren( HWND hScroll
, short dx
, short dy
, WORD dcx
)
39 WND
*wndScroll
= WIN_FindWndPtr( hScroll
);
41 HRGN hUpdateRgn
,hCombineRgn
;
43 if( !wndScroll
|| ( !dx
&& !dy
) ) return 0;
45 if( dcx
& DCX_WINDOW
)
46 hRgnWnd
= CreateRectRgnIndirect(&wndScroll
->rectWindow
);
51 GetClientRect(hScroll
,&rect
);
52 hRgnWnd
= CreateRectRgnIndirect(&rect
);
55 hUpdateRgn
= DCE_GetVisRgn( hScroll
, dcx
);
56 hCombineRgn
= CreateRectRgn(0,0,0,0);
58 if( !hUpdateRgn
|| !hCombineRgn
)
60 DeleteObject( hUpdateRgn
? hUpdateRgn
: hCombineRgn
);
61 DeleteObject(hRgnWnd
);
65 OffsetRgn( hUpdateRgn
, dx
, dy
);
66 CombineRgn(hCombineRgn
, hRgnWnd
, hUpdateRgn
, RGN_DIFF
);
68 DeleteObject(hRgnWnd
);
69 DeleteObject(hUpdateRgn
);
75 /* ----------------------------------------------------------------------
76 * SCROLL_ScrollChildren
78 BOOL
SCROLL_ScrollChildren( HWND hScroll
, short dx
, short dy
)
80 WND
*wndPtr
= WIN_FindWndPtr(hScroll
);
81 HWND hWnd
= wndPtr
->hwndChild
;
85 if( !wndPtr
|| ( !dx
&& !dy
)) return 0;
87 dprintf_scroll(stddeb
,"SCROLL_ScrollChildren: hwnd "NPFMT
" dx=%i dy=%i\n",hScroll
,dx
,dy
);
89 /* get a region in client rect invalidated by siblings and ansectors */
90 hUpdateRgn
= SCROLL_TraceChildren(hScroll
, dx
, dy
, DCX_CLIPSIBLINGS
);
92 /* update children coordinates */
95 wndPtr
= WIN_FindWndPtr( hWnd
);
97 /* we can check if window intersects with clipRect parameter
98 * and do not move it if not - just a thought. - AK
101 SetWindowPos(hWnd
,0,wndPtr
->rectWindow
.left
+ dx
,
102 wndPtr
->rectWindow
.top
+ dy
, 0,0, SWP_NOZORDER
|
103 SWP_NOSIZE
| SWP_NOACTIVATE
| SWP_NOREDRAW
|
106 hWnd
= wndPtr
->hwndNext
;
109 /* invalidate uncovered region and paint frames */
110 b
= RedrawWindow( hScroll
, NULL
, hUpdateRgn
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
|
111 RDW_ERASENOW
| RDW_ALLCHILDREN
);
113 DeleteObject( hUpdateRgn
);
118 /*************************************************************************
119 * ScrollWindow (USER.61)
121 * FIXME: a bit broken
124 void ScrollWindow(HWND hwnd
, short dx
, short dy
, LPRECT rect
, LPRECT clipRect
)
127 HRGN hrgnUpdate
,hrgnClip
;
129 HWND hCaretWnd
= CARET_GetHwnd();
131 dprintf_scroll(stddeb
,"ScrollWindow: dx=%d, dy=%d, lpRect =%08lx clipRect=%i,%i,%i,%i\n",
132 dx
, dy
, (LONG
)rect
, (int)((clipRect
)?clipRect
->left
:0),
133 (int)((clipRect
)?clipRect
->top
:0),
134 (int)((clipRect
)?clipRect
->right
:0),
135 (int)((clipRect
)?clipRect
->bottom
:0));
137 /* if rect is NULL children have to be moved */
140 GetClientRect(hwnd
, &rc
);
141 hrgnClip
= CreateRectRgnIndirect( &rc
);
143 if ((hCaretWnd
== hwnd
) || IsChild(hwnd
,hCaretWnd
))
144 HideCaret(hCaretWnd
);
147 /* children will be Blt'ed too */
148 hdc
= GetDCEx(hwnd
, hrgnClip
, DCX_CACHE
| DCX_CLIPSIBLINGS
);
149 DeleteObject(hrgnClip
);
153 GetClientRect(hwnd
,&rc
);
154 dprintf_scroll(stddeb
,"\trect=%i %i %i %i client=%i %i %i %i\n",
155 (int)rect
->left
,(int)rect
->top
,(int)rect
->right
,
156 (int)rect
->bottom
,(int)rc
.left
,(int)rc
.top
,
157 (int)rc
.right
,(int)rc
.bottom
);
159 if (hCaretWnd
== hwnd
) HideCaret(hCaretWnd
);
165 if (clipRect
== NULL
)
166 GetClientRect(hwnd
, &cliprc
);
168 CopyRect(&cliprc
, clipRect
);
170 hrgnUpdate
= CreateRectRgn(0, 0, 0, 0);
171 ScrollDC(hdc
, dx
, dy
, &rc
, &cliprc
, hrgnUpdate
, NULL
);
172 ReleaseDC(hwnd
, hdc
);
176 /* FIXME: this doesn't take into account hrgnUpdate */
177 if( !SCROLL_ScrollChildren(hwnd
,dx
,dy
) )
178 InvalidateRgn(hwnd
, hrgnUpdate
, TRUE
);
182 HRGN hrgnInv
= SCROLL_TraceChildren(hwnd
,dx
,dy
,DCX_CLIPCHILDREN
|
186 CombineRgn(hrgnUpdate
,hrgnInv
,hrgnUpdate
,RGN_OR
);
187 DeleteObject(hrgnInv
);
190 RedrawWindow( hwnd
, NULL
, hrgnUpdate
, RDW_INVALIDATE
| RDW_ERASE
| RDW_ERASENOW
);
193 DeleteObject(hrgnUpdate
);
194 if( hCaretWnd
) ShowCaret(hCaretWnd
);
198 /*************************************************************************
199 * ScrollDC (USER.221)
204 BOOL
ScrollDC(HDC hdc
, short dx
, short dy
, LPRECT rc
, LPRECT cliprc
,
205 HRGN hrgnUpdate
, LPRECT rcUpdate
)
207 HRGN hrgnClip
, hrgn1
, hrgn2
;
210 DC
*dc
= (DC
*)GDI_GetObjPtr(hdc
, DC_MAGIC
);
212 dprintf_scroll(stddeb
,"ScrollDC: dx=%d dy=%d, hrgnUpdate="NPFMT
" rc=%i %i %i %i\n",
213 dx
,dy
,hrgnUpdate
,(int)((rc
)?rc
->left
:0),
214 (int)((rc
)?rc
->top
:0),
215 (int)((rc
)?rc
->right
:0),
216 (int)((rc
)?rc
->bottom
:0));
223 hrgnClip
= CreateRectRgnIndirect(cliprc
);
224 SelectClipRgn(hdc
, hrgnClip
);
229 src
.x
= XDPTOLP(dc
, rc
->left
);
230 dest
.x
= XDPTOLP(dc
, rc
->left
+ abs(dx
));
234 src
.x
= XDPTOLP(dc
, rc
->left
+ abs(dx
));
235 dest
.x
= XDPTOLP(dc
, rc
->left
);
239 src
.y
= YDPTOLP(dc
, rc
->top
);
240 dest
.y
= YDPTOLP(dc
, rc
->top
+ abs(dy
));
244 src
.y
= YDPTOLP(dc
, rc
->top
+ abs(dy
));
245 dest
.y
= YDPTOLP(dc
, rc
->top
);
248 width
= rc
->right
- rc
->left
- abs(dx
);
249 height
= rc
->bottom
- rc
->top
- abs(dy
);
251 if (!BitBlt(hdc
, dest
.x
, dest
.y
, width
, height
, hdc
, src
.x
, src
.y
,
258 hrgn1
= CreateRectRgn(rc
->left
, rc
->top
, rc
->left
+dx
, rc
->bottom
);
260 hrgn1
= CreateRectRgn(rc
->right
+dx
, rc
->top
, rc
->right
,
263 hrgn1
= CreateRectRgn(0, 0, 0, 0);
266 hrgn2
= CreateRectRgn(rc
->left
, rc
->top
, rc
->right
, rc
->top
+dy
);
268 hrgn2
= CreateRectRgn(rc
->left
, rc
->bottom
+dy
, rc
->right
,
271 hrgn2
= CreateRectRgn(0, 0, 0, 0);
273 RgnType
= CombineRgn(hrgnUpdate
, hrgn1
, hrgn2
, RGN_OR
);
278 if (rcUpdate
) GetRgnBox( hrgnUpdate
, rcUpdate
);
283 /*************************************************************************
284 * ScrollWindowEx (USER.319)
288 * SCROLL_TraceChildren can help
291 int ScrollWindowEx(HWND hwnd
, short dx
, short dy
, LPRECT rect
, LPRECT clipRect
,
292 HRGN hrgnUpdate
, LPRECT rcUpdate
, WORD flags
)
297 dprintf_scroll(stddeb
,"ScrollWindowEx: dx=%d, dy=%d, wFlags=%04x\n",dx
, dy
, flags
);
302 GetClientRect(hwnd
, &rc
);
305 if (clipRect
== NULL
)
306 GetClientRect(hwnd
, &cliprc
);
308 CopyRect(&cliprc
, clipRect
);
310 ScrollDC(hdc
, dx
, dy
, &rc
, &cliprc
, hrgnUpdate
, rcUpdate
);
312 if (flags
| SW_INVALIDATE
)
314 RedrawWindow( hwnd
, NULL
, hrgnUpdate
, RDW_INVALIDATE
| RDW_ERASE
|
315 ((flags
& SW_ERASE
) ? RDW_ERASENOW
: 0));
318 ReleaseDC(hwnd
, hdc
);