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
= CreateRectRgnIndirect16(&wndScroll
->rectWindow
);
51 GetClientRect32(hScroll
,&rect
);
52 hRgnWnd
= CreateRectRgnIndirect32(&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
);
84 if( !wndPtr
|| ( !dx
&& !dy
)) return 0;
86 dprintf_scroll(stddeb
,"SCROLL_ScrollChildren: hwnd %04x 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 */
92 for (wndPtr
= wndPtr
->child
; wndPtr
; wndPtr
= wndPtr
->next
)
94 /* we can check if window intersects with clipRect parameter
95 * and do not move it if not - just a thought. - AK
97 SetWindowPos(wndPtr
->hwndSelf
, 0, wndPtr
->rectWindow
.left
+ dx
,
98 wndPtr
->rectWindow
.top
+ dy
, 0,0, SWP_NOZORDER
|
99 SWP_NOSIZE
| SWP_NOACTIVATE
| SWP_NOREDRAW
|
103 /* invalidate uncovered region and paint frames */
104 b
= RedrawWindow32( hScroll
, NULL
, hUpdateRgn
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
|
105 RDW_ERASENOW
| RDW_ALLCHILDREN
);
107 DeleteObject( hUpdateRgn
);
112 /*************************************************************************
113 * ScrollWindow (USER.61)
115 * FIXME: a bit broken
118 void ScrollWindow(HWND hwnd
, short dx
, short dy
, LPRECT16 rect
, LPRECT16 clipRect
)
121 HRGN hrgnUpdate
,hrgnClip
;
123 HWND hCaretWnd
= CARET_GetHwnd();
125 dprintf_scroll(stddeb
,"ScrollWindow: dx=%d, dy=%d, lpRect =%08lx clipRect=%i,%i,%i,%i\n",
126 dx
, dy
, (LONG
)rect
, (int)((clipRect
)?clipRect
->left
:0),
127 (int)((clipRect
)?clipRect
->top
:0),
128 (int)((clipRect
)?clipRect
->right
:0),
129 (int)((clipRect
)?clipRect
->bottom
:0));
131 /* if rect is NULL children have to be moved */
134 GetClientRect16(hwnd
, &rc
);
135 hrgnClip
= CreateRectRgnIndirect16( &rc
);
137 if ((hCaretWnd
== hwnd
) || IsChild(hwnd
,hCaretWnd
))
138 HideCaret(hCaretWnd
);
141 /* children will be Blt'ed too */
142 hdc
= GetDCEx(hwnd
, hrgnClip
, DCX_CACHE
| DCX_CLIPSIBLINGS
);
143 DeleteObject(hrgnClip
);
147 GetClientRect16(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
);
153 if (hCaretWnd
== hwnd
) HideCaret(hCaretWnd
);
155 CopyRect16(&rc
, rect
);
159 if (clipRect
== NULL
)
160 GetClientRect16(hwnd
, &cliprc
);
162 CopyRect16(&cliprc
, clipRect
);
164 hrgnUpdate
= CreateRectRgn(0, 0, 0, 0);
165 ScrollDC(hdc
, dx
, dy
, &rc
, &cliprc
, hrgnUpdate
, NULL
);
166 ReleaseDC(hwnd
, hdc
);
170 /* FIXME: this doesn't take into account hrgnUpdate */
171 if( !SCROLL_ScrollChildren(hwnd
,dx
,dy
) )
172 InvalidateRgn(hwnd
, hrgnUpdate
, TRUE
);
176 HRGN hrgnInv
= SCROLL_TraceChildren(hwnd
,dx
,dy
,DCX_CLIPCHILDREN
|
180 CombineRgn(hrgnUpdate
,hrgnInv
,hrgnUpdate
,RGN_OR
);
181 DeleteObject(hrgnInv
);
184 RedrawWindow32( hwnd
, NULL
, hrgnUpdate
, RDW_INVALIDATE
| RDW_ERASE
| RDW_ERASENOW
);
187 DeleteObject(hrgnUpdate
);
188 if( hCaretWnd
) ShowCaret(hCaretWnd
);
192 /*************************************************************************
193 * ScrollDC (USER.221)
198 BOOL
ScrollDC(HDC hdc
, short dx
, short dy
, LPRECT16 rc
, LPRECT16 cliprc
,
199 HRGN hrgnUpdate
, LPRECT16 rcUpdate
)
204 DC
*dc
= (DC
*)GDI_GetObjPtr(hdc
, DC_MAGIC
);
206 dprintf_scroll(stddeb
,"ScrollDC: dx=%d dy=%d, hrgnUpdate=%04x rcUpdate = %p cliprc = %p, rc=%d %d %d %d\n",
207 dx
, dy
, hrgnUpdate
, rcUpdate
, cliprc
, rc
? rc
->left
: 0,
208 rc
? rc
->top
: 0, rc
? rc
->right
: 0, rc
? rc
->bottom
: 0 );
215 fprintf(stdnimp
,"ScrollDC: Invalid HDC\n");
221 hrgnClip
= CreateRectRgnIndirect16(cliprc
);
222 SelectClipRgn(hdc
, hrgnClip
);
227 src
.x
= XDPTOLP(dc
, rc
->left
);
228 dest
.x
= XDPTOLP(dc
, rc
->left
+ abs(dx
));
232 src
.x
= XDPTOLP(dc
, rc
->left
+ abs(dx
));
233 dest
.x
= XDPTOLP(dc
, rc
->left
);
237 src
.y
= YDPTOLP(dc
, rc
->top
);
238 dest
.y
= YDPTOLP(dc
, rc
->top
+ abs(dy
));
242 src
.y
= YDPTOLP(dc
, rc
->top
+ abs(dy
));
243 dest
.y
= YDPTOLP(dc
, rc
->top
);
246 width
= rc
->right
- rc
->left
- abs(dx
);
247 height
= rc
->bottom
- rc
->top
- abs(dy
);
249 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
);
276 if (rcUpdate
) GetRgnBox16( hrgnUpdate
, rcUpdate
);
283 if( dx
> 0 ) rx
.right
= rc
->left
+dx
;
284 else if (dx
< 0) rx
.left
= rc
->right
+dx
;
285 else SetRectEmpty16( &rx
);
287 if( dy
> 0 ) ry
.bottom
= rc
->top
+dy
;
288 else if (dy
< 0) ry
.top
= rc
->bottom
+dy
;
289 else SetRectEmpty16( &ry
);
291 UnionRect16( rcUpdate
, &rx
, &ry
);
298 /*************************************************************************
299 * ScrollWindowEx (USER.319)
303 * SCROLL_TraceChildren can help
306 int ScrollWindowEx(HWND hwnd
, short dx
, short dy
, LPRECT16 rect
, LPRECT16 clipRect
,
307 HRGN hrgnUpdate
, LPRECT16 rcUpdate
, WORD flags
)
312 dprintf_scroll(stddeb
,"ScrollWindowEx: dx=%d, dy=%d, wFlags=%04x\n",dx
, dy
, flags
);
317 GetClientRect16(hwnd
, &rc
);
319 CopyRect16(&rc
, rect
);
320 if (clipRect
== NULL
)
321 GetClientRect16(hwnd
, &cliprc
);
323 CopyRect16(&cliprc
, clipRect
);
325 ScrollDC(hdc
, dx
, dy
, &rc
, &cliprc
, hrgnUpdate
, rcUpdate
);
327 if (flags
| SW_INVALIDATE
)
329 RedrawWindow32( hwnd
, NULL
, hrgnUpdate
, RDW_INVALIDATE
| RDW_ERASE
|
330 ((flags
& SW_ERASE
) ? RDW_ERASENOW
: 0));
333 ReleaseDC(hwnd
, hdc
);