signature=af972d07a7b1e8cd17a3d011d31aa690,a00836.html

Win32k: scrollw.c 文件参考
Win32k

/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&dn=gpl-2.0.txt GPL-v2 */

var searchBox = new SearchBox("searchBox", "search",false,'搜索');

/* @license-end */

/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&dn=gpl-2.0.txt GPL-v2 */

$(function() {

initMenu('',true,false,'search.php','搜索');

$(document).ready(function() { init_search(); });

});

/* @license-end */

class="ui-resizable-handle">

/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&dn=gpl-2.0.txt GPL-v2 */

$(document).ready(function(){initNavTree('a00836.html',''); initResizable(); });

/* @license-end */

οnmοuseοver="return searchBox.OnSearchSelectShow()"

οnmοuseοut="return searchBox.OnSearchSelectHide()"

οnkeydοwn="return searchBox.OnSearchSelectKey(event)">

name="MSearchResults" id="MSearchResults">

scrollw.c 文件参考
#include "precomp.h"

浏览源代码.

函数

int GetTrueClipRgn (HDC hdc, HRGN hrgnClip)
 
int InternalScrollDC (HDC hdc, int dx, int dy, RECT *prcSrc, RECT *prcClip, HRGN hrgnInvalid, HRGN hrgnUpdate, LPRECT prcUpdate, BOOL fLogUnits)
 
BOOL _ScrollDC (HDC hdc, int dx, int dy, LPRECT prcSrc, LPRECT prcClip, HRGN hrgnUpdate, LPRECT prcUpdate)
 
int xxxScrollWindowEx (PWND pwnd, int dx, int dy, RECT *prcScroll, RECT *prcClip, HRGN hrgnUpdate, LPRECT prcUpdate, DWORD flags)
 

函数说明

◆ _ScrollDC()

BOOL _ScrollDC (HDC hdc,
int dx,
int dy,
LPRECT prcSrc,
LPRECT prcClip,
HRGN hrgnUpdate,
LPRECT prcUpdate 
)

在文件 scrollw.c642 行定义.

650 {
651  RECT rcSrc;
652  RECT rcSpb;
653  PWND pwnd;
654  HRGN hrgnInvalid;
655  BOOL fRet;
656 
657  /*
658  * ScrollDC does not scroll update region. Under WinNT, an app calling
659  * GetUpdateRgn() then ScrollDC() then InvalidateRgn() will not get
660  * any new update region that happened between the Get and Scroll. Under
661  * Win3.1, that was not a problem because no other app ran during this
662  * time. So pass hrgnInvalid - this will affect the hrgnUpdate and
663  * prcUpdate values being returned from ScrollDC with the update region.
664  */
665  hrgnInvalid = NULL;
666  if ((pwnd = FastWindowFromDC(hdc)) != NULL) {
667 
668  hrgnInvalid = pwnd-> hrgnUpdate;
669 
670  if ( hrgnInvalid == MAXREGION) {
671 
672  /*
673  * This is a fix for winhell, a performance testing app
674  * written by some guy working for a windows magazine.
675  * this app scrolls it's window while it is completely
676  * invalid. We normaly won't scroll invalid bits but
677  * but we make the exception here
678  */
679  hrgnInvalid = NULL;
680  }
681  }
682 
683  fRet = InternalScrollDC(hdc,
684  dx,
685  dy,
686  prcSrc,
687  prcClip,
688  hrgnInvalid,
689  hrgnUpdate,
690  prcUpdate,
691  TRUE) != ERROR;
692 
693  /*
694  * InternalScrollDC() only scrolls those areas inside the visible region.
695  * This means it does no operations on parts of the window if the window
696  * isn't visible. This means SPBs don't get properly invalidated. This
697  * could be seen by starting a dir, then moving another window with the
698  * mouse (and keeping the mouse down until the dir finished). The
699  * screen is remembered with an SPB, and the dir window doesn't get
700  * properly invalidated because of this.
701  */
702  if (pwnd != NULL && AnySpbs()) {
703 
704  if (HIWORD(prcSrc) != 0) {
705 
706  rcSrc = *prcSrc;
707  OffsetRect(&rcSrc, pwnd-> rcClient.left, pwnd-> rcClient.top);
708 
709  rcSpb = rcSrc;
710  OffsetRect(&rcSpb, dx, dy);
711  UnionRect(&rcSpb, &rcSpb, &rcSrc);
712 
713  } else {
714  rcSpb = pwnd-> rcClient;
715  }
716 
717  SpbCheckRect(pwnd, &rcSpb, 0);
718  }
719 
720  return fRet;
721 }

引用了 FastWindowFromDC(), hrgnInvalid, tagWND::hrgnUpdate, InternalScrollDC(), OffsetRect(), tagWND::rcClient, SpbCheckRect() , 以及 UnionRect().

被这些函数引用 NtUserScrollDC() , 以及 xxxPaintIconsInSwitchWindow().

◆ GetTrueClipRgn()

int GetTrueClipRgn (HDC hdc,
HRGN hrgnClip 
)

在文件 scrollw.c30 行定义.

33 {
34  POINT pt;
35  int code;
36 
37  code = GreCopyVisRgn(hdc, hrgnClip);
38 
39  /*
40  * NOTE!!! The global hrgnScrl2 is used in this routine!
41  */
42  GreGetDCOrg(hdc, &pt);
43 
44  if (GreGetRandomRgn(hdc, hrgnScrl2, 1)) {
45  GreOffsetRgn( hrgnScrl2, pt.x, pt.y);
46  code = IntersectRgn(hrgnClip, hrgnClip, hrgnScrl2);
47  }
48 
49  /*
50  * Finally convert the result to DC coordinates
51  */
52  GreOffsetRgn(hrgnClip, -pt.x, -pt.y);
53 
54  return code;
55 }

引用了 hrgnScrl2.

被这些函数引用 InternalScrollDC().

◆ InternalScrollDC()

int InternalScrollDC (HDC hdc,
int dx,
int dy,
RECT * prcSrc,
RECT * prcClip,
HRGN hrgnInvalid,
HRGN hrgnUpdate,
LPRECT prcUpdate,
BOOL fLogUnits 
)

在文件 scrollw.c67 行定义.

77 {
78  RECT rcVis;
79  RECT rcSrc;
80  RECT rcClip;
81  RECT rcUnclippedSrc;
82  RECT rcDst;
83  RECT rcUpdate;
84  RECT rcValid;
85  BOOL fSrcNotEmpty;
86  BOOL fHaveVisRgn;
87  POINT rgpt[2];
88  POINT pt;
89  int dxLog;
90  int dyLog;
91  int wClip;
92  int wClipValid;
93 
94  fHaveVisRgn = FALSE;
95 
96  /*
97  * Enter a critical region to ensure that no one changes visrgns
98  * or update regions while we scroll bits around.
99  */
100  GreLockDisplay( gpDispInfo-> pDevLock);
101 
102  if ((wClip = GreGetClipBox(hdc, &rcVis, TRUE)) == ERROR) {
103 
104 ErrorExit:
105 
106  GreUnlockDisplay( gpDispInfo-> pDevLock);
107  return ERROR;
108  }
109 
110  CopyRect(&rcSrc, (HIWORD(prcSrc) ? prcSrc : &rcVis));
111 
112  if (HIWORD(prcClip))
113  CopyRect(&rcClip, prcClip);
114 
115  dxLog = dx;
116  dyLog = dy;
117 
118  if (fLogUnits) {
119 
120  /*
121  * Convert input parameters to device coordinates
122  */
123  GreLPtoDP(hdc, (LPPOINT)&rcVis, 2);
124  GreLPtoDP(hdc, (LPPOINT)&rcSrc, 2);
125 
126  if (HIWORD(prcClip))
127  GreLPtoDP(hdc, (LPPOINT)&rcClip, 2);
128 
129  /*
130  * The delta values must be treated as a vector from
131  * the point (0, 0) to (dx, dy). Scale it as such, then
132  * compute the difference. This handles flipped coordinate systems.
133  */
134  rgpt[0].x = rgpt[0].y = 0;
135  rgpt[1].x = dx;
136  rgpt[1].y = dy;
137 
138  GreLPtoDP(hdc, rgpt, 2);
139 
140  dx = rgpt[1].x - rgpt[0].x;
141  dy = rgpt[1].y - rgpt[0].y;
142  }
143 
144  switch (wClip) {
145  case NULLREGION:
146 
147 NullExit:
148 
149  if (hrgnUpdate && !GreSetRectRgn(hrgnUpdate, 0, 0, 0, 0))
150  goto ErrorExit;
151 
152  if (HIWORD(prcUpdate))
153  SetRectEmpty(prcUpdate);
154 
155  GreUnlockDisplay( gpDispInfo-> pDevLock);
156  return NULLREGION;
157 
158  case COMPLEXREGION:
160  fHaveVisRgn = TRUE;
161  break;
162  }
163 
164  /*
165  * First compute the source and destination rectangles.
166  *
167  * rcDst = Offset(rcSrc, dx, dy)
168  */
169  rcDst.left = rcSrc.left + dx;
170  rcDst.right = rcSrc.right + dx;
171  rcDst.top = rcSrc.top + dy;
172  rcDst.bottom = rcSrc.bottom + dy;
173 
174  /*
175  * If necessary, intersect with caller-supplied clip rect.
176  */
177  if (HIWORD(prcClip)) {
178 
179  if ((wClip == SIMPLEREGION) &&
180  (( hrgnInvalid == NULL) || ( hrgnInvalid == MAXREGION))) {
181 
182  /*
183  * Simple clip region: just a rect intersection
184  */
185  if (! IntersectRect(&rcVis, &rcVis, &rcClip))
186  goto NullExit;
187 
188  } else {
189 
190  if (!fHaveVisRgn) {
191 
192  if ( GetTrueClipRgn(hdc, hrgnScrlVis) == ERROR)
193  goto ErrorExit;
194 
195  fHaveVisRgn = TRUE;
196  }
197 
198  GreSetRectRgn( hrgnScrl1,
199  rcClip.left,
200  rcClip.top,
201  rcClip.right,
202  rcClip.bottom);
203 
204  wClip = IntersectRgn( hrgnScrlVis, hrgnScrl1, hrgnScrlVis);
205  switch (wClip) {
206  case ERROR:
207  goto ErrorExit;
208 
209  case NULLREGION:
210  goto NullExit;
211 
212  case SIMPLEREGION:
213 
214  /*
215  * If the clipped region is simple, we're back in fat
216  * rect city.
217  */
218  GreGetRgnBox( hrgnScrlVis, &rcVis);
219  break;
220 
221  case COMPLEXREGION:
222  break;
223  }
224  }
225  }
226 
227  /*
228  * Time for basic scrolling area calculations:
229  *
230  * Dst = Offset(Src, dx, dy) & Vis
231  * Src = Src & Vis
232  * Valid = Offset(Src, dx, dy) & Dst
233  * Valid = Valid & Invalid & Offset(Invalid, dx, dy)
234  * Update = (Src | Dst) - Valid
235  *
236  * If the vis region is simple, then we know that the valid region
237  * will be rectangular.
238  *
239  * The rectangular calculation case can only deal with
240  * hrgnInvalid == NULL or (HRGN)1: the region case is handled the hard way.
241  */
242  if ((wClip == SIMPLEREGION) &&
243  (( hrgnInvalid == NULL) || ( hrgnInvalid == MAXREGION))) {
244 
245  /*
246  * Save a copy of this for update rect calc optimization.
247  */
248  CopyRect(&rcUnclippedSrc, &rcSrc);
249 
250  /*
251  * Dst = Offset(Src, dx, dy) & Vis.
252  */
253  IntersectRect(&rcDst, &rcDst, &rcVis);
254 
255  /*
256  * Src = Src & Vis.
257  */
258  fSrcNotEmpty = IntersectRect(&rcSrc, &rcSrc, &rcVis);
259 
260  /*
261  * Valid = Offset(Src, dx, dy) & Dst.
262  */
263  if ( hrgnInvalid == MAXREGION) {
264  SetRectEmpty(&rcValid);
265  } else {
266 
267  rcValid.left = rcSrc.left + dx;
268  rcValid.right = rcSrc.right + dx;
269  rcValid.top = rcSrc.top + dy;
270  rcValid.bottom = rcSrc.bottom + dy;
271 
272  IntersectRect(&rcValid, &rcValid, &rcDst);
273  }
274 
275  /*
276  * Now calculate the update area.
277  *
278  * There are two cases where the result will be a rectangle:
279  *
280  * 1) The source rectangle lies completely within the visrgn,
281  * and the source and destination don't overlap. In this
282  * case the update region is equal to the source rect.
283  *
284  * 2) The clipped source rectangle is empty, in which case
285  * the update region is equal to the clipped dest rect.
286  *
287  * 3) We're scrolling in one dimension only, and the source
288  * and destination DO overlap. In this case we can use
289  * UnionRect() and SubtractRect() to do the area arithmetic.
290  */
291  if (!fSrcNotEmpty) {
292 
293  /*
294  * Clipped source is empty. Update area is the clipped dest.
295  */
296  CopyRect(&rcUpdate, &rcDst);
297  goto RectUpdate;
298 
299  } else if ( IntersectRect(&rcUpdate, &rcSrc, &rcDst)) {
300 
301  /*
302  * They overlap. If we're scrolling in one dimension only
303  * then we can use rect arithmetic...
304  */
305  if (dx == 0 || dy == 0) {
306 
307  UnionRect(&rcUpdate, &rcSrc, &rcDst);
308  SubtractRect(&rcUpdate, &rcUpdate, &rcValid);
309  goto RectUpdate;
310  }
311 
312  } else if ( EqualRect(&rcSrc, &rcUnclippedSrc)) {
313 
314  /*
315  * They don't overlap, and the source lies completely
316  * within the visible region. Update region is the source.
317  */
318  CopyRect(&rcUpdate, &rcSrc);
319 RectUpdate:
320  if (HIWORD(prcUpdate))
321  CopyRect(prcUpdate, &rcUpdate);
322 
323  if (hrgnUpdate &&
324  !GreSetRectRgn(hrgnUpdate,
325  rcUpdate.left,
326  rcUpdate.top,
327  rcUpdate.right,
328  rcUpdate.bottom)) {
329 
330  goto ErrorExit;
331  }
332 
333  wClip = SIMPLEREGION;
334  if (rcUpdate.left >= rcUpdate.right ||
335  rcUpdate.top >= rcUpdate.bottom)
336 
337  wClip = NULLREGION;
338 
339  goto DoRectBlt;
340  }
341 
342  /*
343  * The update region isn't rectangular. Need to do our
344  * area calculations with region calls. Skip all this
345  * if the caller doesn't care about the update region.
346  *
347  * If he wants a rectangle but no region, use hrgnScrl2 as a temp.
348  */
349  if (hrgnUpdate == NULL && HIWORD(prcUpdate))
350  hrgnUpdate = hrgnScrl2;
351 
352  if (hrgnUpdate != NULL) {
353 
354  /*
355  * hrgnUpdateCalc = (rcSrc | rcDst) - rcBltDst
356  */
357  GreSetRectRgn( hrgnScrl1,
358  rcSrc.left,
359  rcSrc.top,
360  rcSrc.right,
361  rcSrc.bottom);
362 
363  GreSetRectRgn(hrgnUpdate,
364  rcDst.left,
365  rcDst.top,
366  rcDst.right,
367  rcDst.bottom);
368 
369  if (UnionRgn(hrgnUpdate, hrgnUpdate, hrgnScrl1) == ERROR)
370  goto ErrorExit;
371 
372  GreSetRectRgn( hrgnScrl1,
373  rcValid.left,
374  rcValid.top,
375  rcValid.right,
376  rcValid.bottom);
377 
378  wClip = SubtractRgn(hrgnUpdate, hrgnUpdate, hrgnScrl1);
379 
380  if (wClip == ERROR)
381  goto ErrorExit;
382 
383  if (HIWORD(prcUpdate))
384  GreGetRgnBox(hrgnUpdate, prcUpdate);
385  }
386 
387 DoRectBlt:
388 
389  /*
390  * If the valid rectangle's not empty, then copy those bits...
391  */
392  if (rcValid.left < rcValid.right && rcValid.top < rcValid.bottom) {
393 
394  /*
395  * If the DC is in a funny map mode, then be sure to map from
396  * device to logical coordinates for BLT call...
397  */
398  if (fLogUnits)
399  GreDPtoLP(hdc, (LPPOINT)&rcValid, 2);
400 
401  GreBitBlt(hdc,
402  rcValid.left,
403  rcValid.top,
404  rcValid.right - rcValid.left,
405  rcValid.bottom - rcValid.top,
406  hdc,
407  rcValid.left - dxLog,
408  rcValid.top - dyLog,
409  SRCCOPY,
410  0);
411  }
412 
413  } else {
414 
415  GreGetDCOrg(hdc, &pt);
416 
417  /*
418  * Get the true visrgn if we haven't already.
419  */
420  if (!fHaveVisRgn) {
421 
422  if ( GetTrueClipRgn(hdc, hrgnScrlVis) == ERROR)
423  goto ErrorExit;
424 
425  fHaveVisRgn = TRUE;
426  }
427 
428  /*
429  * The visrgn is not empty. Need to do all our calculations
430  * with regions.
431  *
432  * hrgnSrc = hrgnSrc & hrgnScrlVis
433  */
434  GreSetRectRgn( hrgnScrlSrc,
435  rcSrc.left,
436  rcSrc.top,
437  rcSrc.right,
438  rcSrc.bottom);
439 
440  if (IntersectRgn( hrgnScrlSrc, hrgnScrlSrc, hrgnScrlVis) == ERROR)
441  goto ErrorExit;
442 
443  /*
444  * hrgnDst = hrgnDst & hrgnScrlVis
445  */
446  GreSetRectRgn( hrgnScrlDst,
447  rcDst.left,
448  rcDst.top,
449  rcDst.right,
450  rcDst.bottom);
451 
452  if (IntersectRgn( hrgnScrlDst, hrgnScrlDst, hrgnScrlVis) == ERROR)
453  goto ErrorExit;
454 
455  /*
456  * Now compute the valid region:
457  *
458  * Valid = Offset(Src, dx, dy) & Dst.
459  * Valid = Valid & Invalid & Offset(Invalid, dx, dy)
460  *
461  * If hrgnInvalid is (HRGN)1, then the valid area is empty.
462  */
463  wClipValid = NULLREGION;
464  if ( hrgnInvalid != MAXREGION) {
465 
466  /*
467  * Valid = Offset(Src, dx, dy) & Dst
468  */
469  if (CopyRgn( hrgnScrlValid, hrgnScrlSrc) == ERROR)
470  goto ErrorExit;
471 
472  GreOffsetRgn( hrgnScrlValid, dx, dy);
473  wClipValid = IntersectRgn( hrgnScrlValid,
474  hrgnScrlValid,
475  hrgnScrlDst);
476 
477  /*
478  * Valid = Valid - Invalid - Offset(Invalid, dx, dy)
479  * We need bother only if hrgnInvalid is a real region.
480  */
481  if ( hrgnInvalid > MAXREGION) {
482 
483  if (wClipValid != ERROR && wClipValid != NULLREGION) {
484 
485  /*
486  * hrgnInvalid is in screen coordinates: map to dc coords
487  */
488  CopyRgn( hrgnScrl2, hrgnInvalid);
489  GreOffsetRgn( hrgnScrl2, -pt.x, -pt.y);
490 
491  wClipValid = SubtractRgn( hrgnScrlValid,
492  hrgnScrlValid,
493  hrgnScrl2);
494  }
495 
496  if (wClipValid != ERROR && wClipValid != NULLREGION) {
497  GreOffsetRgn( hrgnScrl2, dx, dy);
498 
499  wClipValid = SubtractRgn( hrgnScrlValid,
500  hrgnScrlValid,
501  hrgnScrl2);
502  }
503  }
504 
505  if (wClipValid == ERROR)
506  goto ErrorExit;
507  }
508 
509  /*
510  * If he wants a rectangle but no region, use hrgnScrl2 as a temp.
511  */
512  if (hrgnUpdate == NULL && HIWORD(prcUpdate))
513  hrgnUpdate = hrgnScrl2;
514 
515  if (hrgnUpdate != NULL) {
516 
517  /*
518  * Update = (Src | Dst) - Valid.
519  */
520  wClip = UnionRgn(hrgnUpdate, hrgnScrlDst, hrgnScrlSrc);
521  if (wClip == ERROR)
522  goto ErrorExit;
523 
524  if (wClipValid != NULLREGION)
525  wClip = SubtractRgn(hrgnUpdate, hrgnUpdate, hrgnScrlValid);
526 
527  if (HIWORD(prcUpdate))
528  GreGetRgnBox(hrgnUpdate, prcUpdate);
529  }
530 
531  if (wClipValid != NULLREGION) {
532 
533  #ifdef LATER
534 
535  /*
536  * don't use the visrgn here
537  */
538  HRGN hrgnSaveVis = GreCreateRectRgn(0, 0, 0, 0);
539 
540  if (hrgnSaveVis != NULL) {
541 
542  BOOL fClipped;
543 
544  fClipped = (GreGetRandomRgn(hdc, hrgnSaveVis, 1) == 1);
545  GreExtSelectClipRgn(hdc, hrgnScrlValid, RGN_COPY);
546 
547  /*
548  * If the DC is in a funny map mode, then be sure to
549  * map from device to logical coordinates for BLT call...
550  */
551  if (fLogUnits)
552  GreDPtoLP(hdc, (LPPOINT)&rcDst, 2);
553 
554  /*
555  * Gdi can take along time to process this call if
556  * it's a printer DC
557  */
558  GreBitBlt(hdc,
559  rcDst.left,
560  rcDst.top,
561  rcDst.right - rcDst.left,
562  rcDst.bottom - rcDst.top,
563  hdc,
564  rcDst.left - dxLog,
565  rcDst.top - dyLog,
566  SRCCOPY,
567  0);
568 
569  GreExtSelectClipRgn(hdc,
570  (fClipped ? hrgnSaveVis : NULL),
571  RGN_COPY);
572 
573  GreDeleteObject(hrgnSaveVis);
574  }
575 
576  #else
577 
578  /*
579  * Visrgn is expected in screen coordinates: offset
580  * as appropriate.
581  */
582  GreOffsetRgn( hrgnScrlValid, pt.x, pt.y);
583 
584  /*
585  * Select in the temporary vis rgn, saving the old
586  */
587 
588  GreSelectVisRgn(hdc, hrgnScrlValid, NULL, SVR_SWAP);
589 
590  /*
591  * If the DC is in a funny map mode, then be sure to map from
592  * device to logical coordinates for BLT call...
593  */
594  if (fLogUnits)
595  GreDPtoLP(hdc, (LPPOINT)&rcDst, 2);
596 
597  /*
598  * Gdi can take along time to process this call if it's
599  * a printer DC.
600  */
601  GreBitBlt(hdc,
602  rcDst.left,
603  rcDst.top,
604  rcDst.right - rcDst.left,
605  rcDst.bottom - rcDst.top,
606  hdc,
607  rcDst.left - dxLog,
608  rcDst.top - dyLog,
609  SRCCOPY,
610  0);
611 
612  /*
613  * Restore the old vis rgn, leaving hrgnScrlValid with
614  * a valid rgn
615  */
616  GreSelectVisRgn(hdc, hrgnScrlValid, NULL, SVR_SWAP);
617 
618  #endif
619  }
620  }
621 
622  /*
623  * If necessary, convert the resultant update rect back
624  * to logical coordinates.
625  */
626  if (fLogUnits && HIWORD(prcUpdate))
627  GreDPtoLP(hdc, (LPPOINT)prcUpdate, 2);
628 
629  GreUnlockDisplay( gpDispInfo-> pDevLock);
630 
631  return wClip;
632 }

引用了 CopyRect(), EqualRect(), GetTrueClipRgn(), gpDispInfo, hrgnInvalid, hrgnScrl1, hrgnScrl2, hrgnScrlDst, hrgnScrlSrc, hrgnScrlValid, hrgnScrlVis, IntersectRect(), tagDISPLAYINFO::pDevLock, SetRectEmpty(), SubtractRect() , 以及 UnionRect().

被这些函数引用 _ScrollDC() , 以及 xxxScrollWindowEx().

◆ xxxScrollWindowEx()

int xxxScrollWindowEx (PWND pwnd,
int dx,
int dy,
RECT * prcScroll,
RECT * prcClip,
HRGN hrgnUpdate,
LPRECT prcUpdate,
DWORD flags 
)

在文件 scrollw.c731 行定义.

740 {
741  INT code;
742  HDC hdc;
743  int dxDev;
744  int dyDev;
745  RECT rcSrcDev;
746  RECT rcSpb, rcSrc;
747  DWORD flagsDCX;
748  BOOL fHideCaret;
749  BOOL fRcScroll = (BOOL)HIWORD(prcScroll);
750  BOOL fInvisible = FALSE;
751  PCARET pcaret;
752  POINT pt;
753  TL tlpwndChild;
754  HRGN hrgnInvalid;
755 
756  CheckLock(pwnd);
757 
758  if (pwnd == NULL)
759  pwnd = PtiCurrent()-> rpdesk-> pDeskInfo-> spwnd; // pwndDesktop
760 
761  /*
762  * If nothing's moving, nothing to do.
763  */
764  if ((dx | dy) == 0 ) {
765 
766  goto DoNothing;
767 
768  } else if (! IsVisible(pwnd)) {
769 
770  /* We want to offset our children if we're not minimized. IsVisible()
771  * will return FALSE if we're minimized, invisible, or the child of
772  * a minimized/invisible ancestore.
773  */
774  if (!TestWF(pwnd, WFMINIMIZED) &&
775  (flags & SW_SCROLLCHILDREN) &&
776  !fRcScroll) {
777 
778  fInvisible = TRUE;
779  flags &= ~SW_INVALIDATE;
780  }
781 
782 DoNothing:
783 
784  if (hrgnUpdate != NULL)
785  GreSetRectRgn(hrgnUpdate, 0, 0, 0, 0);
786 
787  if (HIWORD(prcUpdate) != 0)
788  SetRectEmpty(prcUpdate);
789 
790  if (!fInvisible)
791  return NULLREGION;
792  }
793 
794  /*
795  * Hide the caret.
796  */
797  fHideCaret = FALSE;
798 
799  if (!fInvisible) {
800  pcaret = & PtiCurrent()-> pq-> caret;
801  if (pcaret-> spwnd != NULL && _IsDescendant(pcaret-> spwnd, pwnd)) {
802  fHideCaret = TRUE;
804  }
805  }
806 
807  /*
808  * If scrollwindow, and window is clipchildren, use a cache entry.
809  * Otherwise, always use a
810  *
811  * Determine what kind of DC we'll be needing. If the DCX_CACHE bit
812  * isn't set, it means that we'll be operating in logical coordinates.
813  */
814  if (flags & SW_SCROLLWINDOW) {
815 
816  /*
817  * ScrollWindow() call: use the cache if not OWNDC or CLASSDC.
818  */
819  flagsDCX = DCX_USESTYLE;
820  if (!TestCF(pwnd, CFOWNDC) && !TestCF(pwnd, CFCLASSDC))
821  flagsDCX |= DCX_CACHE;
822 
823  /*
824  * If SW_SCROLLCHILDREN (i.e., lprcScroll == NULL) and CLIPCHILDREN,
825  * then use the cache and don't clip children.
826  * This is screwy, but 3.0 backward compatible.
827  */
828  if ((flags & SW_SCROLLCHILDREN) && TestWF(pwnd, WFCLIPCHILDREN))
829  flagsDCX |= DCX_NOCLIPCHILDREN | DCX_CACHE;
830 
831  } else {
832 
833  /*
834  * ScrollWindowEx() call: always use the cache
835  */
836  flagsDCX = DCX_USESTYLE | DCX_CACHE;
837 
838  /*
839  * if SW_SCROLLCHILDREN, always use noclipchildren.
840  */
841  if (flags & SW_SCROLLCHILDREN)
842  flagsDCX |= DCX_NOCLIPCHILDREN;
843  }
844 
845  hdc = _GetDCEx(pwnd, NULL, flagsDCX);
846 
847  if (flags & SW_INVALIDATE) {
848 
849  /*
850  * Get device origin while DC is valid, for later offsetting
851  */
852  GreGetDCOrg(hdc, &pt);
853 
854  /*
855  * If the user didn't give us a region to use, use hrgnSW.
856  */
857  if (hrgnUpdate == NULL)
858  hrgnUpdate = hrgnSW;
859  }
860 
861  /*
862  * The DC will be in some logical coordinate system if OWNDC or CLASSDC.
863  */
864  if (!fRcScroll) {
865  prcScroll = &rcSrc;
866 
867  /*
868  * IMPORTANT:
869  * We have to use CopyOffsetRect() here because GetClientRect() gives
870  * unreliable results for minimized windows. 3.1 dudes get told that
871  * their client is non-empty, for compatibility reasons.
872  */
873  CopyOffsetRect(prcScroll,
874  &pwnd-> rcClient,
875  -pwnd-> rcClient.left,
876  -pwnd-> rcClient.top);
877 
878  /*
879  * If the DC might be a screwy one, then map the
880  * rect to logical units.
881  */
882  if (!(flagsDCX & DCX_CACHE))
883  GreDPtoLP(hdc, (LPPOINT)&rcSrc, 2);
884  }
885 
886  /*
887  * If the DC is in logical coordinates, map *prcScroll and dx, dy
888  * to device units for use later.
889  */
890  dxDev = dx;
891  dyDev = dy;
892  rcSrcDev = *prcScroll;
893 
894  if (!(flagsDCX & DCX_CACHE)) {
895 
896  POINT rgpt[2];
897 
898  GreLPtoDP(hdc, (POINT FAR*)&rcSrcDev, 2);
899 
900  /*
901  * The delta values must be treated as a vector from
902  * the point (0, 0) to (dx, dy). Scale it as such, then
903  * compute the difference. This handles flipped coordinate systems.
904  */
905  rgpt[0].x = rgpt[0].y = 0;
906  rgpt[1].x = dx;
907  rgpt[1].y = dy;
908 
909  GreLPtoDP(hdc, rgpt, 2);
910 
911  dxDev = rgpt[1].x - rgpt[0].x;
912  dyDev = rgpt[1].y - rgpt[0].y;
913  }
914 
915  if (fInvisible)
916  code = NULLREGION;
917  else {
918 
919  hrgnInvalid = pwnd-> hrgnUpdate;
920  if ((flags & SW_SCROLLWINDOW) && !TestWF(pwnd, WFWIN31COMPAT)) {
921  /*
922  * 3.0 Backward compatibility hack:
923  * The following incorrect code is what 3.0 used to do, and
924  * there are apps such as Finale and Scrapbook+ that have worked
925  * around this bug in ways that don't work with the "correct" code.
926  */
927  if (pwnd-> hrgnUpdate > MAXREGION) {
928  RECT rc;
929 
930  GreGetRgnBox(pwnd-> hrgnUpdate, &rc);
931  OffsetRect(&rc,
932  dxDev - pwnd-> rcClient.left,
933  dyDev - pwnd-> rcClient.top);
934 
935  xxxRedrawWindow(pwnd,
936  &rc, NULL,
937  RDW_INVALIDATE | RDW_ERASE | RDW_ALLCHILDREN);
938  }
939 
940  hrgnInvalid = NULL;
941  }
942 
943  code = InternalScrollDC(hdc,
944  dx,
945  dy,
946  prcScroll,
947  prcClip,
948  hrgnInvalid,
949  hrgnUpdate,
950  prcUpdate,
951  !(flagsDCX & DCX_CACHE));
952  }
953 
954  /*
955  * Release the hdc we used.
956  */
957  _ReleaseDC(hdc);
958 
959  /*
960  * Check the union of the src and dst rectangle against any SPBs.
961  * We do this because the window
962  * might be completely obscured by some window with an SPB, but
963  * since we're completely covered no BitBlt call will be made
964  * to accumulate bounds in that area.
965  */
966  if (!fInvisible && AnySpbs()) {
967 
968  if (fRcScroll) {
969  rcSrc = rcSrcDev;
970  OffsetRect(&rcSrc, pwnd-> rcClient.left, pwnd-> rcClient.top);
971 
972  rcSpb = rcSrc;
973  OffsetRect(&rcSpb, dxDev, dyDev);
974  UnionRect(&rcSpb, &rcSpb, &rcSrc);
975 
976  } else {
977 
978  /*
979  * Use the entire client area.
980  */
981  rcSpb = pwnd-> rcClient;
982  }
983 
984  SpbCheckRect(pwnd, &rcSpb, 0);
985  }
986 
987  /*
988  * If this guy wants to scroll his children, go at it. Only scroll those
989  * children intersecting prcScroll. Then invalidate any vis rgns
990  * calculated for these child windows.
991  */
992  if (flags & SW_SCROLLCHILDREN) {
993 
994  RECT rc;
995 
996  /*
997  * If this window has the caret then offset it if:
998  * a) The whole window is scrolling
999  * b) The rectangle scrolled contains the caret rectangle
1000  */
1001  if (!fInvisible && (pwnd == pcaret-> spwnd)) {
1002 
1003  if (fRcScroll)
1004  SetRect(&rc,
1005  pcaret-> x,
1006  pcaret-> y,
1007  pcaret-> x + pcaret-> cx,
1008  pcaret-> y + pcaret-> cy);
1009 
1010  if (!fRcScroll || IntersectRect(&rc, &rc, &rcSrcDev)) {
1011  pcaret-> x += dxDev;
1012  pcaret-> y += dyDev;
1013  }
1014  }
1015 
1016  if (fRcScroll) {
1017 
1018  /*
1019  * Create a copy of prcScroll and map to absolute coordinates...
1020  */
1021  rc = rcSrcDev;
1022  OffsetRect(&rc, pwnd-> rcClient.left, pwnd-> rcClient.top);
1023  }
1024 
1025  if (pwnd-> spwndChild) {
1026 
1027  OffsetChildren(pwnd,
1028  dxDev,
1029  dyDev,
1030  (fRcScroll ? (LPRECT)&rc : NULL));
1031 
1032  /*
1033  * If we're clipchildren, then shuffling our children
1034  * will affect our client visrgn (but not our window visrgn).
1035  * Otherwise, only our children's
1036  * visrgns were affected by the scroll.
1037  */
1038  InvalidateDCCache(pwnd,
1039  TestWF(pwnd, WFCLIPCHILDREN) ?
1040  IDC_CLIENTONLY : IDC_CHILDRENONLY);
1041 
1042  }
1043  }
1044 
1045  if (flags & SW_INVALIDATE) {
1046 
1047  /*
1048  * If the caller supplied a region, invalidate using a copy,
1049  * because InternalInvalidate may trash the passed-in region.
1050  */
1051  if (hrgnUpdate != hrgnSW)
1052  CopyRgn( hrgnSW, hrgnUpdate);
1053 
1054  /*
1055  * Make hrgnSW screen-relative before invalidation...
1056  */
1057  GreOffsetRgn( hrgnSW, pt.x, pt.y);
1058 
1060  pwnd,
1061  hrgnSW,
1062  (flags & SW_ERASE) ?
1063  (RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_ERASE) :
1064  (RDW_INVALIDATE | RDW_ALLCHILDREN));
1065  }
1066 
1067  /*
1068  * Send child move messages if needed.
1069  */
1070  if (flags & SW_SCROLLCHILDREN) {
1071 
1072  PWND pwndChild;
1073  RECT rc;
1074  RECT rcScrolledChildren;
1075 
1076  /*
1077  * NOTE: the following code will send MOVE messages
1078  * to windows that didn't move but were in the source rectangle.
1079  * This is not a big deal, and definitely not worth fixing.
1080  */
1081  if (fRcScroll) {
1082  rcScrolledChildren = rcSrcDev;
1083  OffsetRect(&rcScrolledChildren,
1084  dxDev + pwnd-> spwndParent-> rcClient.left,
1085  dyDev + pwnd-> spwndParent-> rcClient.top);
1086  }
1087 
1088  pwndChild = pwnd-> spwndChild;
1089  while (pwndChild != NULL) {
1090 
1091  ThreadLockAlways(pwndChild, &tlpwndChild);
1092 
1093  if (!fRcScroll ||
1094  IntersectRect(&rc, &rcScrolledChildren, &pwndChild-> rcWindow)) {
1095 
1096  /*
1097  * NOTE: Win 3.0 and below passed wParam == TRUE here.
1098  * This was not documented or used, so it was changed
1099  * to be consistent with the documentation.
1100  */
1101  xxxSendMessage(
1102  pwndChild,
1103  WM_MOVE,
1104  0,
1105  MAKELONG(pwndChild-> rcClient.left - pwnd-> rcClient.left,
1106  pwndChild-> rcClient.top - pwnd-> rcClient.top));
1107  }
1108 
1109  pwndChild = pwndChild-> spwndNext;
1110 
1111  ThreadUnlock(&tlpwndChild);
1112  }
1113  }
1114 
1115  if (fHideCaret) {
1116 
1117  /*
1118  * Show the caret again.
1119  */
1120  InternalShowCaret();
1121  }
1122 
1123  /*
1124  * Return the region code.
1125  */
1126  return code;
1127 }

引用了 _GetDCEx(), _IsDescendant(), _ReleaseDC(), tagQ::caret, CheckLock(), CopyOffsetRect(), tagCARET::cx, tagCARET::cy, DWORD, hrgnInvalid, hrgnSW, tagWND::hrgnUpdate, InternalHideCaret(), InternalScrollDC(), InternalShowCaret(), IntersectRect(), InvalidateDCCache(), IsVisible(), OffsetChildren(), OffsetRect(), tagDESKTOP::pDeskInfo, tagTHREADINFO::pq, PtiCurrent(), tagWND::rcClient, tagWND::rcWindow, tagTHREADINFO::rpdesk, SetRect(), SetRectEmpty(), SpbCheckRect(), tagDESKTOPINFO::spwnd, tagCARET::spwnd, tagWND::spwndChild, tagWND::spwndNext, tagWND::spwndParent, UnionRect(), tagCARET::x, xxxInternalInvalidate(), xxxRedrawWindow(), xxxSendMessage() , 以及 tagCARET::y.

被这些函数引用 NtUserScrollWindowEx().

HRGN hrgnScrl1
Definition: kernel/globals.c:461
BOOL InvalidateDCCache(PWND pwndInvalid, DWORD flags)
Definition: dc.c:1644
BOOL xxxRedrawWindow(PWND pwnd, LPRECT lprcUpdate, HRGN hrgnUpdate, DWORD flags)
Definition: update.c:302
HRGN hrgnScrlValid
Definition: kernel/globals.c:466
Definition: user.h:2238
BOOL APIENTRY UnionRect(LPRECT prcDst, CONST RECT *prcSrc1, CONST RECT *prcSrc2)
Definition: rect.c:233
PDESKTOPINFO pDeskInfo
Definition: userk.h:1706
BOOL APIENTRY SetRect(LPRECT prc, int left, int top, int right, int bottom)
Definition: rect.c:21
HRGN hrgnSW
Definition: kernel/globals.c:460
BOOL _IsDescendant(PWND pwndParent, PWND pwndChild)
Definition: rtl/winmgr.c:432
HRGN hrgnScrlVis
Definition: kernel/globals.c:463
INT
int INT
Definition: bench.c:6
LONG xxxSendMessage(PWND pwnd, UINT message, DWORD wParam, LONG lParam)
Definition: sendmsg.c:613
PTHREADINFO PtiCurrent(VOID)
Definition: winmgrc.c:526
void InternalHideCaret()
Definition: caret.c:334
struct tagWND * spwndNext
Definition: user.h:1391
HRGN hrgnUpdate
Definition: user.h:1406
BOOL APIENTRY OffsetRect(LPRECT prc, int cx, int cy)
Definition: rect.c:132
BOOL APIENTRY IntersectRect(LPRECT prcDst, CONST RECT *prcSrc1, CONST RECT *prcSrc2)
Definition: rect.c:184
BOOL _ReleaseDC(HDC hdc)
Definition: dc.c:102
PWND FastWindowFromDC(HDC hdc)
Definition: dc.c:1832
PDISPLAYINFO gpDispInfo
Definition: kernel/globals.c:125
BOOL APIENTRY CopyOffsetRect(LPRECT prcDst, CONST RECT *prcSrc, int cx, int cy)
Definition: rect.c:67
ddeml v[i< inst >][t< type >][hObj|pObj] Dump DDEML state information ddeml lists all ddeml instances for this process n ddeml t< type > lists all ddeml objects of the given type n n assumes link is first DWORD
Definition: exts.h:175
HRGN hrgnScrlSrc
Definition: kernel/globals.c:464
_TL
Definition: usercli.h:347
HRGN hrgnScrl2
Definition: kernel/globals.c:462
RECT rcWindow
Definition: user.h:1398
Definition: user.h:1388
struct tagWND * spwndParent
Definition: user.h:1392
HRGN hrgnInvalid
Definition: kernel/globals.c:439
CARET caret
Definition: userk.h:2182
BOOL APIENTRY EqualRect(CONST RECT *prc1, CONST RECT *prc2)
Definition: rect.c:285
int InternalScrollDC(HDC hdc, int dx, int dy, RECT *prcSrc, RECT *prcClip, HRGN hrgnInvalid, HRGN hrgnUpdate, LPRECT prcUpdate, BOOL fLogUnits)
Definition: scrollw.c:67
LPVOID pDevLock
Definition: user.h:1577
VOID SpbCheckRect(PWND pwnd, LPRECT lprc, DWORD flags)
Definition: spb.c:1031
VOID OffsetChildren(PWND pwnd, int dx, int dy, LPRECT prcHitTest)
Definition: swp.c:4607
VOID xxxInternalInvalidate(PWND pwnd, HRGN hrgnUpdate, DWORD flags)
Definition: update.c:1257
int y
Definition: user.h:2244
PDESKTOP rpdesk
Definition: userk.h:2288
struct tagQ * pq
Definition: userk.h:2273
BOOL APIENTRY SubtractRect(LPRECT prcDst, CONST RECT *prcSrc1, CONST RECT *prcSrc2)
Definition: rect.c:316
int GetTrueClipRgn(HDC hdc, HRGN hrgnClip)
Definition: scrollw.c:30
void InternalShowCaret()
Definition: caret.c:294
int cy
Definition: user.h:2245
VOID CheckLock(PVOID pobj)
int cx
Definition: user.h:2246
struct tagWND * spwnd
Definition: user.h:1603
struct tagWND * spwndChild
Definition: user.h:1393
BOOL APIENTRY SetRectEmpty(LPRECT prc)
Definition: rect.c:414
BOOL APIENTRY CopyRect(LPRECT prcDst, CONST RECT *prcSrc)
Definition: rect.c:391
HDC _GetDCEx(HWND hwnd, HRGN hrgnClip, DWORD flags)
struct tagWND * spwnd
Definition: user.h:2239
HRGN hrgnScrlDst
Definition: kernel/globals.c:465
RECT rcClient
Definition: user.h:1399
int x
Definition: user.h:2243
BOOL IsVisible(PWND pwnd)
Definition: rtl/winmgr.c:456

一键复制

编辑

Web IDE

原始数据

按行查看

历史

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值