m.634226.c.html,a00614.html

Win32k: caption.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('a00614.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">

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

浏览源代码.

宏定义

#define MIN   0x01
 
#define MAX   0x02
 
#define NOMIN   0x04
 
#define NOMAX   0x08
 
#define NOCLOSE   0x10
 
#define SMCAP   0x20
 
#define NOSIZE   (NOMIN | NOMAX)
 

函数

WORD xxxTrackCaptionButton (PWND pwnd, UINT hit)
 
PCURSOR xxxGetWindowSmIcon (PWND pwnd, BOOL fDontSendMsg)
 
VOID BltMe4Times (POEMBITMAPINFO pOem, int cxySlot, int cxyIcon, HDC hdcSrc, PCURSOR pcursor, UINT flags)
 
VOID DrawCaptionIcon (HDC hdc, LPRECT lprc, PCURSOR pcursor, HBRUSH hbrFill, UINT flags)
 
BOOL xxxDrawCaptionTemp (PWND pwnd, HDC hdc, LPRECT lprc, HFONT hFont, PCURSOR pcursor, PUNICODE_STRING pstrText, UINT flags)
 
VOID xxxDrawCaptionBar (PWND pwnd, HDC hdc, UINT wFlags)
 

宏定义说明

◆ MAX

#define MAX   0x02

在文件 caption.c17 行定义.

◆ MIN

#define MIN   0x01

在文件 caption.c16 行定义.

◆ NOCLOSE

#define NOCLOSE   0x10

在文件 caption.c20 行定义.

◆ NOMAX

#define NOMAX   0x08

在文件 caption.c19 行定义.

◆ NOMIN

#define NOMIN   0x04

在文件 caption.c18 行定义.

◆ NOSIZE

#define NOSIZE   (NOMIN | NOMAX)

在文件 caption.c22 行定义.

◆ SMCAP

#define SMCAP   0x20

在文件 caption.c21 行定义.

函数说明

◆ BltMe4Times()

VOID BltMe4Times (POEMBITMAPINFO pOem,
int cxySlot,
int cxyIcon,
HDC hdcSrc,
PCURSOR pcursor,
UINT flags 
)

在文件 caption.c310 行定义.

317 {
318  RECT rc;
319  int i;
320  int j;
321  BOOL fMask = TRUE;
322  LONG rop;
323  HBRUSH hBrush = (flags & DC_INBUTTON) ? SYSHBR(3DHILIGHT) : SYSHBR(ACTIVECAPTION);
324 
325  for (i = 0; i < 2; i++) {
326 
327  rop = SRCAND;
328 
329  rc.left = pOem-> x;
330  rc.top = pOem-> y;
331  rc.right = rc.left + pOem-> cx;
332  rc.bottom = rc.top + pOem-> cy;
333 
334  FillRect( gpDispInfo-> hdcBits, &rc, hBrush);
335 
336  rc.top += (cxySlot - cxyIcon) / 2;
337  rc.left += SYSMET(CXBORDER) + (cxySlot - cxyIcon) / 2;
338 
339  for (j = 0; j < 2; j++) {
340 
342  rc.left,
343  rc.top,
344  cxyIcon,
345  cxyIcon,
346  hdcSrc,
347  pcursor,
348  fMask,
349  rop);
350 
351  fMask = !fMask;
352  rop = SRCINVERT;
353  }
354 
355  pOem += DOBI_CAPOFF;
356  hBrush = (flags & DC_INBUTTON) ? SYSHBR(3DFACE) : SYSHBR(INACTIVECAPTION);
357  }
358 }

引用了 BltIcon(), tagOEMBITMAPINFO::cx, tagOEMBITMAPINFO::cy, FillRect(), gpDispInfo, tagDISPLAYINFO::hdcBits, tagOEMBITMAPINFO::x , 以及 tagOEMBITMAPINFO::y.

被这些函数引用 DrawCaptionIcon().

◆ DrawCaptionIcon()

VOID DrawCaptionIcon (HDC hdc,
LPRECT lprc,
PCURSOR pcursor,
HBRUSH hbrFill,
UINT flags 
)

在文件 caption.c370 行定义.

376 {
377  int i;
378  int xStart = 0;
379  int cxySlot;
380  POEMBITMAPINFO pOem;
381  RECT rc;
382  CAPTIONCACHE ccTemp;
383 
384  /*
385  * Check the size of the icon to see if it matches the size of the
386  * cache we created. Most of the time this will match. Also, if
387  * we are drawing with DC_INBUTTON in 16 colors, don't cache.
388  */
389  cxySlot = lprc->bottom - lprc->top;
390 
391  if ((cxySlot != oemInfo.bm[OBI_CAPCACHE1].cy) || (hbrFill == ghbrGray)) {
392 
393  rc.left = lprc->left;
394  rc.top = lprc->top;
395  rc.right = lprc->left + cxySlot;
396  rc.bottom = lprc->top + cxySlot;
397 
398  FillRect(hdc, &rc, hbrFill);
399 
400  rc.left += SYSMET(CXBORDER) + (cxySlot - SYSMET(CXSMICON)) / 2;
401  rc.top += (cxySlot - SYSMET(CYSMICON)) / 2;
402 
403  _DrawIconEx(hdc,
404  rc.left,
405  rc.top,
406  pcursor,
407  SYSMET(CXSMICON),
408  SYSMET(CYSMICON),
409  0,
410  NULL,
411  DI_NORMAL);
412 
413  goto Done;
414  }
415 
416  if (flags & DC_INBUTTON) {
417 
418  /*
419  * The DC_INBUTTON icons is always slot 0.
420  */
421  i = (( cachedCaptions[0]. spcursor == pcursor) ? 0 : CCACHEDCAPTIONS);
422 
423  } else {
424 
425  /*
426  * Search the cache to see if this cursor is currently cached.
427  */
428  for (i = 1; i < CCACHEDCAPTIONS; i++) {
429  if ( cachedCaptions[i].spcursor == pcursor)
430  break;
431  }
432  }
433 
434  if (i >= CCACHEDCAPTIONS) {
435 
436  /*
437  * Icon wasn't cached, so try and add it to the cache
438  */
439  if (flags & DC_INBUTTON) {
440 
441  /*
442  * The tray's special DC_INBUTTON style always goes in slot 0.
443  */
444  i = 0;
445 
446  } else {
447 
448  /*
449  * Look for an empty slot in the cache. If we can't find one,
450  * stuff the new icon at the end of the cache. The result will
451  * be that the last item will be deleted.
452  */
453  for (i = 1; i < CCACHEDCAPTIONS - 1; i++) {
454  if ( cachedCaptions[i].spcursor == NULL)
455  break;
456  }
457  }
458 
459  /*
460  * Add an item to the cache by blting an active and inactive copy of
461  * the icon.
462  */
463  BltMe4Times( cachedCaptions[i].pOem,
464  cxySlot,
465  SYSMET(CXSMICON),
466  ghdcMem,
467  pcursor,
468  flags);
469 
470  Lock(&( cachedCaptions[i].spcursor), pcursor);
471  #ifdef DEBUG
472  cachedCaptions[i]. hico = (HICON)PtoH(pcursor);
473  #endif
474  }
475 
476  /*
477  * We have a hit, so move that cached icon to the front of the cache.
478  * This means that the least recently used icon will be the last
479  * icon in the cache. Remember, we never update index 0 because it
480  * is reserved for the DC_INBUTTON icon.
481  */
482  for ( ; i > 1; i-- ) {
483 
484  /*
485  * Move the entry toward the front
486  */
487  ccTemp = cachedCaptions[i];
488  cachedCaptions[i] = cachedCaptions[i - 1];
489  cachedCaptions[i - 1] = ccTemp;
490 
491  #ifdef DEBUG
492  /*
493  * In checked builds we need to adjust the lock records for
494  * the cursor so it has the correct address.
495  */
496  if ( gfTrackLocks) {
497  if ( cachedCaptions[i].spcursor)
498  HMRelocateLockRecord(&( cachedCaptions[i].spcursor), ( int) sizeof( CAPTIONCACHE));
499  if ( cachedCaptions[i - 1].spcursor)
500  HMRelocateLockRecord(&( cachedCaptions[i - 1].spcursor), -( int) sizeof( CAPTIONCACHE));
501  }
502  #endif
503  }
504 
505 
506  #ifdef DEBUG
507  /*
508  * Make sure the icon we want to draw is the one
509  * that we hit in the cache.
510  */
511  UserAssert( cachedCaptions[i].hico == PtoH(pcursor) );
512  #endif
513 
514  /*
515  * Determine what cached bitmap to blt.
516  */
517  pOem = cachedCaptions[i]. pOem;
518  if (!(flags & DC_ACTIVE))
519  pOem += DOBI_CAPOFF;
520 
521  GreBitBlt(hdc,
522  lprc->left,
523  lprc->top,
524  cxySlot,
525  cxySlot,
526  gpDispInfo-> hdcBits,
527  pOem->x,
528  pOem->y,
529  SRCCOPY,
530  0);
531 
532 Done:
533  /*
534  * Adjust the given rectangle for the icon we just drew
535  */
536  lprc->left += cxySlot;
537 }

引用了 _DrawIconEx(), BltMe4Times(), cachedCaptions, CCACHEDCAPTIONS, FillRect(), gfTrackLocks, ghbrGray, ghdcMem, gpDispInfo, tagDISPLAYINFO::hdcBits, tagCAPTIONCACHE::hico, HMRelocateLockRecord(), tagCAPTIONCACHE::pOem, tagCAPTIONCACHE::spcursor, UserAssert, tagOEMBITMAPINFO::x , 以及 tagOEMBITMAPINFO::y.

被这些函数引用 xxxDrawCaptionTemp().

◆ xxxDrawCaptionBar()

VOID xxxDrawCaptionBar (PWND pwnd,
HDC hdc,
UINT wFlags 
)

在文件 caption.c768 行定义.

772 {
773  UINT bm = OBI_CLOSE;
774  RECT rcWindow;
775  HBRUSH hBrush = NULL;
776  HBRUSH hCapBrush;
777  int colorBorder;
778  UINT wBtns;
779  UINT wCode;
780 
781  /*
782  * If we're not currently showing on the screen, return.
783  * NOTE
784  * If you remove the IsVisible() check from DrawWindowFrame(), then
785  * be careful to remove the NC_NOVISIBLE flag too. This is a smallish
786  * speed thing, so that we don't have to call IsVisible() twice on a
787  * window. DrawWindowFrame() already checks.
788  */
789  if (!(wFlags & DC_NOVISIBLE) && ! IsVisible(pwnd))
790  return;
791 
792  /*
793  * Clear this flag so we know the frame has been drawn.
794  */
795  ClearHungFlag(pwnd, WFREDRAWFRAMEIFHUNG);
796 
797  CopyOffsetRect(&rcWindow,
798  &pwnd-> rcWindow,
799  -pwnd-> rcWindow.left,
800  -pwnd-> rcWindow.top);
801 
802  hCapBrush = (wFlags & DC_ACTIVE) ? SYSHBR(ACTIVECAPTION) : SYSHBR(INACTIVECAPTION);
803 
804  wCode = 0;
805 
806  if (! _MNCanClose(pwnd))
807  wCode |= NOCLOSE;
808 
809  if (!TestWF(pwnd, WFMAXBOX))
810  wCode |= NOMAX;
811  else if (TestWF(pwnd, WFMAXIMIZED))
812  wCode |= MAX;
813 
814  if (!TestWF(pwnd, WFMINBOX))
815  wCode |= NOMIN;
816  else if(TestWF(pwnd, WFMINIMIZED))
817  wCode |= MIN;
818 
819  if (TestWF(pwnd, WFMINIMIZED)) {
820 
821  if (wFlags & DC_FRAME) {
822 
823  /*
824  * Raised outer edge + border
825  */
826  DrawEdge(hdc, &rcWindow, EDGE_RAISED, (BF_RECT | BF_ADJUST));
827  DrawFrame(hdc, &rcWindow, 1, DF_3DFACE);
828  InflateRect(&rcWindow, -SYSMET(CXBORDER), -SYSMET(CYBORDER));
829 
830  } else {
831  InflateRect(&rcWindow, -SYSMET(CXFIXEDFRAME), -SYSMET(CYFIXEDFRAME));
832  }
833 
834  rcWindow.bottom = rcWindow.top + SYSMET(CYSIZE);
835 
836  hBrush = GreSelectBrush(hdc, hCapBrush);
837 
838  } else {
839 
840  /*
841  * BOGUS
842  * What color should we draw borders in? The check is NOT simple.
843  * At create time, we set the 3D bits. NCCREATE will also
844  * set them for listboxes, edit fields,e tc.
845  */
846  colorBorder = (TestWF(pwnd, WEFEDGEMASK) && !TestWF(pwnd, WFOLDUI)) ? COLOR_3DFACE : COLOR_WINDOWFRAME;
847 
848  /*
849  * Draw the window frame.
850  */
851  if (wFlags & DC_FRAME) {
852 
853  /*
854  * Window edge
855  */
856  if (TestWF(pwnd, WEFWINDOWEDGE))
857  DrawEdge(hdc, &rcWindow, EDGE_RAISED, BF_RECT | BF_ADJUST);
858  else if (TestWF(pwnd, WEFSTATICEDGE))
859  DrawEdge(hdc, &rcWindow, BDR_SUNKENOUTER, BF_RECT | BF_ADJUST);
860 
861 
862  /*
863  * Size border
864  */
865  if (TestWF(pwnd, WFSIZEBOX)) {
866 
867  DrawFrame(hdc,
868  &rcWindow,
869  gpsi-> gclBorder,
870  ((wFlags & DC_ACTIVE) ? DF_ACTIVEBORDER : DF_INACTIVEBORDER));
871 
872  InflateRect(&rcWindow,
873  - gpsi-> gclBorder * SYSMET(CXBORDER),
874  - gpsi-> gclBorder * SYSMET(CYBORDER));
875  }
876 
877  /*
878  * Normal border
879  */
880  if (TestWF(pwnd, WFBORDERMASK) || TestWF(pwnd, WEFDLGMODALFRAME)) {
881  DrawFrame(hdc, &rcWindow, 1, (colorBorder << 3));
882  InflateRect(&rcWindow, -SYSMET(CXBORDER), -SYSMET(CYBORDER));
883  }
884 
885  } else {
886 
887  int cBorders;
888 
889  cBorders = GetWindowBorders(pwnd->style, pwnd->ExStyle, TRUE, FALSE);
890 
891  InflateRect(&rcWindow,
892  -cBorders * SYSMET(CXBORDER),
893  -cBorders * SYSMET(CYBORDER));
894  }
895 
896  /*
897  * Punt if the window doesn't have a caption currently showing on screen.
898  */
899  if (!TestWF(pwnd, WFCPRESENT))
900  return;
901 
902  if (TestWF(pwnd, WEFTOOLWINDOW)) {
903  wCode |= SMCAP;
904  rcWindow.bottom = rcWindow.top + SYSMET(CYSMSIZE);
905  bm = OBI_CLOSE_PAL;
906  } else
907  rcWindow.bottom = rcWindow.top + SYSMET(CYSIZE);
908 
909  #if 0
910  /* Draw the border beneath the caption.
911  *
912  *
913  * hBrush = GreSelectBrush(hdc, ahbrSystem[colorBorder]);
914  *GrePatBlt(hdc, rcWindow.left, rcWindow.bottom,
915  * rcWindow.right - rcWindow.left,
916  * SYSMET(CYBORDER), PATCOPY);
917  */
918  #endif
919 
920  {
921  POLYPATBLT PolyData;
922 
923  PolyData.x = rcWindow.left;
924  PolyData.y = rcWindow.bottom;
925  PolyData.cx = rcWindow.right - rcWindow.left;
926  PolyData.cy = SYSMET(CYBORDER);
927  PolyData.BrClr.hbr = ahbrSystem[colorBorder];
928 
929  GrePolyPatBlt(hdc,PATCOPY,&PolyData,1,PPB_BRUSH);
930  }
931 
932  GreSelectBrush(hdc, hCapBrush);
933 
934  }
935 
936  if (!TestWF(pwnd, WFSYSMENU) && TestWF(pwnd, WFWIN40COMPAT))
937  goto JustDrawIt;
938 
939  /*
940  * New Rules:
941  * (1) The caption has a horz border beneath it separating it from the
942  * menu or client.
943  * (2) The caption text area has an edge of space on the left and right
944  * before the characters.
945  * (3) We account for the descent below the baseline of the caption char
946  */
947  wBtns = 1;
948 
949  if (!(wFlags & DC_BUTTONS)) {
950 
951  if ((!wCode) || (!(wCode & SMCAP) && ((wCode & NOSIZE) != NOSIZE))) {
952 
953  wBtns += 2;
954 
955  } else {
956 
957  rcWindow.right -= SYSMET(CXEDGE);
958 
959  if ((wCode == NOSIZE) && (wCode && TestWF(pwnd, WEFCONTEXTHELP)))
960  wBtns++;
961  }
962 
963  rcWindow.right -= wBtns * ((wCode & SMCAP) ? SYSMET(CXSMSIZE) : SYSMET(CXSIZE));
964 
965  goto JustDrawIt;
966  }
967 
968  if (!wCode || (wCode == NOSIZE)) {
969 
970  POEMBITMAPINFO pOem = oemInfo.bm + OBI_CAPBTNS;
971  int cx;
972 
973  cx = (wCode ? SYSMET(CXSIZE) + SYSMET(CXEDGE) : SYSMET(CXSIZE) * 3);
974 
975  if (!(wFlags & DC_ACTIVE))
976  pOem += DOBI_CAPOFF;
977 
978  rcWindow.right -= cx;
979 
980  GreBitBlt(hdc,
981  rcWindow.right,
982  rcWindow.top,
983  cx,
984  pOem-> cy,
985  gpDispInfo-> hdcBits,
986  pOem-> x + pOem-> cx - SYSMET(CXSIZE) - cx,
987  pOem-> y,
988  SRCCOPY,
989  0);
990 
991  if (wCode && TestWF(pwnd, WEFCONTEXTHELP)) {
992 
993  rcWindow.right -= SYSMET(CXSIZE) - SYSMET(CXEDGE);
994 
995  GreBitBlt(hdc,
996  rcWindow.right,
997  rcWindow.top,
998  SYSMET(CXSIZE),
999  pOem-> cy,
1000  gpDispInfo-> hdcBits,
1001  pOem-> x + pOem-> cx - SYSMET(CXSIZE),
1002  pOem-> y,
1003  SRCCOPY,
1004  0);
1005  }
1006 
1007  goto JustDrawIt;
1008  }
1009 
1010  /*
1011  * Draw the caption buttons
1012  */
1013  rcWindow.top += SYSMET(CYEDGE);
1014  rcWindow.bottom -= SYSMET(CYEDGE);
1015 
1016  rcWindow.right -= SYSMET(CXEDGE);
1017 
1018  GrePatBlt(hdc,
1019  rcWindow.right,
1020  rcWindow.top,
1021  SYSMET(CXEDGE),
1022  rcWindow.bottom - rcWindow.top,
1023  PATCOPY);
1024 
1025  if (wCode & NOCLOSE)
1026  bm += DOBI_INACTIVE;
1027 
1028  rcWindow.right -= oemInfo.bm[bm].cx;
1029  BitBltSysBmp(hdc, rcWindow.right, rcWindow.top, bm);
1030 
1031  if (!(wCode & SMCAP) && ((wCode & NOSIZE) != NOSIZE)) {
1032 
1033  rcWindow.right -= SYSMET(CXEDGE);
1034 
1035  GrePatBlt(hdc,
1036  rcWindow.right,
1037  rcWindow.top,
1038  SYSMET(CXEDGE),
1039  rcWindow.bottom - rcWindow.top,
1040  PATCOPY);
1041 
1042  /*
1043  * Max Box
1044  * If window is maximized use the restore bitmap;
1045  * otherwise use the regular zoom bitmap
1046  */
1047  bm = (wCode & MAX) ? OBI_RESTORE : ((wCode & NOMAX) ? OBI_ZOOM_I : OBI_ZOOM);
1048 
1049  rcWindow.right -= oemInfo.bm[bm].cx;
1050  BitBltSysBmp(hdc, rcWindow.right, rcWindow.top, bm);
1051 
1052  /*
1053  * Min Box
1054  */
1055  bm = (wCode & MIN) ? OBI_RESTORE : ((wCode & NOMIN) ? OBI_REDUCE_I : OBI_REDUCE);
1056 
1057  rcWindow.right -= oemInfo.bm[bm].cx;
1058  BitBltSysBmp(hdc, rcWindow.right, rcWindow.top, bm);
1059 
1060  rcWindow.right -= SYSMET(CXEDGE);
1061 
1062  GrePatBlt(hdc,
1063  rcWindow.right,
1064  rcWindow.top,
1065  SYSMET(CXEDGE),
1066  rcWindow.bottom - rcWindow.top,
1067  PATCOPY);
1068 
1069  wBtns += 2;
1070  }
1071 
1072  if ((wCode & ( NOCLOSE | NOSIZE)) &&
1073  (!(wCode & SMCAP)) && TestWF(pwnd, WEFCONTEXTHELP)) {
1074 
1075  rcWindow.right -= SYSMET(CXEDGE);
1076 
1077  GrePatBlt(hdc,
1078  rcWindow.right,
1079  rcWindow.top,
1080  SYSMET(CXEDGE),
1081  rcWindow.bottom - rcWindow.top,
1082  PATCOPY);
1083 
1084 
1085  bm = OBI_HELP;
1086 
1087  rcWindow.right -= oemInfo.bm[bm].cx;
1088  BitBltSysBmp(hdc, rcWindow.right, rcWindow.top, bm);
1089 
1090  wBtns++;
1091  }
1092 
1093  rcWindow.top -= SYSMET(CYEDGE);
1094  rcWindow.bottom += SYSMET(CYEDGE);
1095 
1096  wBtns *= (wCode & SMCAP) ? SYSMET(CXSMSIZE) : SYSMET(CXSIZE);
1097 
1098  {
1099  POLYPATBLT PolyData[2];
1100 
1101  PolyData[0].x = rcWindow.right;
1102  PolyData[0].y = rcWindow.top;
1103  PolyData[0].cx = wBtns;
1104  PolyData[0].cy = SYSMET(CYEDGE);
1105  PolyData[0].BrClr.hbr = NULL;
1106 
1107  PolyData[1].x = rcWindow.right;
1108  PolyData[1].y = rcWindow.bottom - SYSMET(CYEDGE);
1109  PolyData[1].cx = wBtns;
1110  PolyData[1].cy = SYSMET(CYEDGE);
1111  PolyData[1].BrClr.hbr = NULL;
1112 
1113  GrePolyPatBlt(hdc,PATCOPY,&PolyData[0],2,PPB_BRUSH);
1114  }
1115 
1116  #if 0
1117  GrePatBlt(hdc, rcWindow.right, rcWindow.top, wBtns, SYSMET(CYEDGE), PATCOPY);
1118  GrePatBlt(hdc, rcWindow.right, rcWindow.bottom - SYSMET(CYEDGE), wBtns, SYSMET(CYEDGE), PATCOPY);
1119  #endif
1120 
1121  /*
1122  * We're going to release this DC--we don't need to bother reselecting
1123  * in the old brush
1124  */
1125  if (hBrush)
1126  GreSelectBrush(hdc, hBrush);
1127 
1128 JustDrawIt:
1129 
1130  /*
1131  * Call DrawCaption only if we need to draw the icon and text
1132  */
1133  if (wFlags & (DC_TEXT | DC_ICON)) {
1134  xxxDrawCaptionTemp(pwnd,
1135  hdc,
1136  &rcWindow,
1137  NULL,
1138  NULL,
1139  NULL,
1140  wFlags | ((wCode & SMCAP) ? DC_SMALLCAP : 0));
1141  }
1142 }

引用了 _MNCanClose(), ahbrSystem, BitBltSysBmp(), ClearHungFlag(), CopyOffsetRect(), tagOEMBITMAPINFO::cx, tagOEMBITMAPINFO::cy, DrawEdge(), DrawFrame(), tagSERVERINFO::gclBorder, GetWindowBorders(), gpDispInfo, gpsi, tagDISPLAYINFO::hdcBits, InflateRect(), IsVisible(), MAX, MIN, NOCLOSE, NOMAX, NOMIN, NOSIZE, tagWND::rcWindow, SMCAP, UINT(), tagOEMBITMAPINFO::x, xxxDrawCaptionTemp() , 以及 tagOEMBITMAPINFO::y.

被这些函数引用 RedrawHungWindowFrame(), xxxDrawWindowFrame(), xxxDWP_DoNCActivate() , 以及 xxxRedrawTitle().

◆ xxxDrawCaptionTemp()

BOOL xxxDrawCaptionTemp (PWND pwnd,
HDC hdc,
LPRECT lprc,
HFONT hFont,
PCURSOR pcursor,
PUNICODE_STRING pstrText,
UINT flags 
)

在文件 caption.c544 行定义.

552 {
553  int iOldMode;
554  HBRUSH hbrFill;
555  LONG clrOldText;
556  LONG clrOldBk;
557  BOOL fItFit = TRUE;
558  SIZE size;
559 
560  CheckLock(pwnd);
561 
562  if (lprc->right <= lprc->left)
563  return FALSE;
564 
565  if (pwnd != NULL) {
566 
567  if (!pcursor &&
568  _HasCaptionIcon(pwnd) &&
569  !(flags & DC_SMALLCAP) &&
570  TestWF(pwnd, WFSYSMENU)) {
571 
572  /*
573  * Only get the icon if we can send messages AND the window has
574  * a system menu.
575  */
576  pcursor = xxxGetWindowSmIcon(pwnd, (flags & DC_NOSENDMSG));
577  }
578  }
579 
580  /*
581  * Set up the colors
582  */
583  if (flags & DC_ACTIVE) {
584 
585  if (flags & DC_INBUTTON) {
586 
587  if ((oemInfo.BitCount < 8) ||
588  (SYSRGB(3DHILIGHT) != SYSRGB(SCROLLBAR)) ||
589  (SYSRGB(3DHILIGHT) == SYSRGB(WINDOW))) {
590  clrOldText = SYSRGB(3DFACE);
591  clrOldBk = SYSRGB(3DHILIGHT);
592  hbrFill = ghbrGray;
593  iOldMode = GreSetBkMode(hdc, TRANSPARENT);
594  } else {
595  clrOldText = SYSRGB(BTNTEXT);
596  clrOldBk = SYSRGB(3DHILIGHT);
597  hbrFill = SYSHBR(3DHILIGHT);
598  }
599 
600  } else {
601  clrOldText = SYSRGB(CAPTIONTEXT);
602  clrOldBk = SYSRGB(ACTIVECAPTION);
603  hbrFill = SYSHBR(ACTIVECAPTION);
604  }
605 
606  } else {
607 
608  if (flags & DC_INBUTTON) {
609  clrOldText = SYSRGB(BTNTEXT);
610  clrOldBk = SYSRGB(3DFACE);
611  hbrFill = SYSHBR(3DFACE);
612  } else {
613  clrOldText = SYSRGB(INACTIVECAPTIONTEXT);
614  clrOldBk = SYSRGB(INACTIVECAPTION);
615  hbrFill = SYSHBR(INACTIVECAPTION);
616  }
617  }
618 
619 
620  /*
621  * Set up drawing colors.
622  */
623  clrOldText = GreSetTextColor(hdc, clrOldText);
624  clrOldBk = GreSetBkColor(hdc, clrOldBk);
625 
626  if (pcursor && !(flags & DC_SMALLCAP)) {
627 
628  if (flags & DC_ICON)
629  DrawCaptionIcon(hdc, lprc, pcursor, hbrFill, flags);
630  else
631  lprc->left += lprc->bottom - lprc->top;
632  }
633 
634  if (flags & DC_TEXT) {
635  int cch;
636  HFONT hfnOld;
637  int yCentered;
638  WCHAR szText[CCHTITLEMAX];
639  UNICODE_STRING strTmp;
640 
641  /*
642  * Note -- the DC_NOSENDMSG check is not in Chicago. It needs to be,
643  * since GetWindowText calls back to the window. FritzS
644  */
645 
646  /*
647  * Get the text for the caption.
648  */
649  if (pstrText == NULL) {
650 
651  if ((pwnd == NULL) || (flags & DC_NOSENDMSG)) {
652 
653  if (pwnd && pwnd-> strName. Length) {
654  cch = TextCopy(&pwnd-> strName, szText, CCHTITLEMAX - 1);
655  strTmp.Length = (USHORT)(cch * sizeof(WCHAR));
656  } else {
657  szText[0] = TEXT( '\0');
658  cch = strTmp.Length = 0;
659  }
660 
661  } else {
662  cch = xxxGetWindowText(pwnd, szText, CCHTITLEMAX - 1);
663  strTmp.Length = (USHORT)(cch * sizeof(WCHAR));
664  }
665 
666  /*
667  * We don't use RtlInitUnicodeString() to initialize the string
668  * because it does a wstrlen() on the string, which is a waste
669  * since we already know its length.
670  */
671  strTmp.Buffer = szText;
672  strTmp.MaximumLength = strTmp.Length + sizeof(UNICODE_NULL);
673  pstrText = &strTmp;
674 
675  } else {
676  cch = pstrText->Length / sizeof(WCHAR);
677  }
678 
679  /*
680  * We need to set up font first, in case we're centering caption.
681  * Fortunately, no text at all is uncommon...
682  */
683  if (hFont == NULL) {
684 
685  if (flags & DC_SMALLCAP) {
686  hFont = ghSmCaptionFont;
687  yCentered = cySmCaptionFontChar;
688  } else {
689  hFont = gpsi-> hCaptionFont;
690  yCentered = cyCaptionFontChar;
691  }
692 
693  yCentered = (lprc->top + lprc->bottom - yCentered) / 2;
694 
695  hfnOld = GreSelectFont(hdc, hFont);
696 
697  } else {
698 
699  TEXTMETRICW tm;
700 
701  /*
702  * UNCOMMON case: only for control panel
703  */
704  hfnOld = GreSelectFont(hdc, hFont);
705 
706  if (! _GetTextMetricsW(hdc, &tm)) {
707  RIPMSG0( RIP_WARNING, "xxxDrawCaptionTemp: _GetTextMetricsW Failed");
708  tm.tmHeight = gpsi-> tmSysFont.tmHeight;
709  }
710  yCentered = (lprc->top + lprc->bottom - tm.tmHeight) / 2;
711  }
712 
713  /*
714  * Draw text
715  */
716  FillRect(hdc, lprc, hbrFill);
717 
718  if (hbrFill == ghbrGray) {
719  GreSetTextColor(hdc, SYSRGB(BTNTEXT));
720  GreSetBkColor(hdc, SYSRGB(GRAYTEXT));
721  }
722 
723  GreGetTextExtentW(hdc, pstrText->Buffer, cch, &size, GGTE_WIN3_EXTENT);
724 
725  if (!(flags & DC_CENTER) && (!cch || (size.cx <= (lprc->right - lprc->left - SYSMET(CXEDGE))))) {
726  GreExtTextOutW(hdc, lprc->left + SYSMET(CXEDGE), yCentered,
727  ETO_CLIPPED, lprc, pstrText->Buffer, cch, NULL);
728  } else {
729 
730  DRAWTEXTPARAMS dtp;
731 
732  dtp.cbSize = sizeof(DRAWTEXTPARAMS);
733  dtp.iLeftMargin = SYSMET(CXEDGE);
734  dtp.iRightMargin = 0;
735 
736  DrawTextEx(hdc,
737  pstrText->Buffer,
738  cch,
739  lprc,
740  DT_NOPREFIX | DT_END_ELLIPSIS | DT_SINGLELINE | DT_VCENTER |
741  ((flags & DC_CENTER) ? DT_CENTER : 0), &dtp);
742 
743  fItFit = FALSE;
744  }
745 
746  if (hfnOld)
747  GreSelectFont(hdc, hfnOld);
748  }
749 
750  /*
751  * Restore colors
752  */
753  GreSetTextColor(hdc, clrOldText);
754  GreSetBkColor(hdc, clrOldBk);
755 
756  if (hbrFill == ghbrGray)
757  GreSetBkMode(hdc, iOldMode);
758 
759  return fItFit;
760 }

引用了 _GetTextMetricsW(), _HasCaptionIcon(), CheckLock(), cyCaptionFontChar, cySmCaptionFontChar, DrawCaptionIcon(), FillRect(), ghbrGray, ghSmCaptionFont, gpsi, tagSERVERINFO::hCaptionFont, _LARGE_UNICODE_STRING::Length, RIP_WARNING, RIPMSG0, tagWND::strName, TextCopy(), tagSERVERINFO::tmSysFont, xxxGetWindowSmIcon() , 以及 xxxGetWindowText().

被这些函数引用 NtUserDrawCaption(), NtUserDrawCaptionTemp(), xxxAnimateCaption() , 以及 xxxDrawCaptionBar().

◆ xxxGetWindowSmIcon()

PCURSOR xxxGetWindowSmIcon (PWND pwnd,
BOOL fDontSendMsg 
)

在文件 caption.c216 行定义.

219 {
220  PCURSOR pcursor = NULL;
221  HICON hico = NULL;
222  PCLS pcls = pwnd-> pcls;
223  DWORD dwResult = 0;
224 
225  CheckLock(pwnd);
226 
227  /*
228  * We check per-window stuff first then per-class stuff, preferring a
229  * real small icon over a stretched big one.
230  *
231  * Per-window small icon
232  * Per-window big icon stretched small
233  * Per-class small icon
234  * Per-class big icon stretched small
235  * WM_QUERYDRAGICON big icon stretched small (for 3.x dudes)
236  *
237  * Try window small icon first
238  * NOTE: The WM_SETICON and WM_GETICON messags are for ISVs only.
239  */
240  if ((hico = (HICON) _GetProp(pwnd, MAKEINTATOM( gpsi-> atomIconSmProp), PROPF_INTERNAL)) != NULL) {
241 
242  if (pcursor = ( PCURSOR) HMValidateHandleNoRip(hico, TYPE_CURSOR)) {
243  return pcursor;
244  } else {
245  RIPMSG1( RIP_WARNING, "GetWindowSmIcon: Invalid small icon handle (0x%08X)", hico);
246  }
247  }
248 
249  /*
250  * Try class small icon next
251  */
252  pcursor = pcls->spicnSm;
253  if (pcursor != NULL)
254  return pcursor;
255 
256  if (!TestWF(pwnd, WFWIN40COMPAT) &&
257  (!TestWF(pwnd, WFOLDUI) ||
258  !TestWF(pwnd, WEFMDICHILD)) &&
259  !fDontSendMsg) {
260 
261  DWORD dwResult;
262 
263  /*
264  * A few old apps like Corel don't set their class icon and other
265  * data until long after we need it. If we send them WM_QUERYDRAGICON,
266  * they will fault because they don't check the return from GWL to
267  * get their data. WFOLDUI apps won't ever get a WM_QUERYDRAGICON,
268  * sorry. Currently the apps with this hack (not for this reason
269  * necessarily)
270  * Corel Photo-Paint 5.0
271  * Myst 2.0
272  * Visual Baler 3.0
273  * Quicken
274  */
275  if ( xxxSendMessageTimeout(pwnd,
276  WM_QUERYDRAGICON,
277  0,
278  0,
279  SMTO_NORMAL,
280  100,
281  &dwResult)) {
282 
283  hico = (HICON)dwResult;
284  }
285 
286  if (hico) {
287 
288  hico = xxxCreateWindowSmIcon(pwnd, hico, FALSE);
289  pcursor = ( PCURSOR) HMValidateHandleNoRip(hico, TYPE_CURSOR);
290 
291  if (pcursor == NULL)
292  hico = NULL;
293  }
294  }
295 
296  if (pcursor == NULL)
297  pcursor = SYSICO(WINLOGO);
298 
299  return pcursor;
300 }

引用了 _GetProp(), tagSERVERINFO::atomIconSmProp, CheckLock(), DWORD, gpsi, HMValidateHandleNoRip(), tagWND::pcls, RIP_WARNING, RIPMSG1, xxxCreateWindowSmIcon() , 以及 xxxSendMessageTimeout().

被这些函数引用 RealDrawMenuItem() , 以及 xxxDrawCaptionTemp().

◆ xxxTrackCaptionButton()

WORD xxxTrackCaptionButton (PWND pwnd,
UINT hit 
)

在文件 caption.c39 行定义.

42 {
43  WORD cmd = 0;
44  MSG msg;
45  HDC hdc;
46  WORD bm;
47  int x;
48  int y;
49  WORD wState;
50  WORD wNewState;
51  BOOL fMouseUp = FALSE;
52  int cBorders;
53  int cxS;
54  int cyS;
55  RECT rcBtn;
56 
57  if (TestWF(pwnd, WFMINIMIZED)) {
58 
59  x = -SYSMET(CXFIXEDFRAME);
60  y = -SYSMET(CYFIXEDFRAME);
61 
62  } else {
63 
64  cBorders = GetWindowBorders(pwnd->style, pwnd->ExStyle, TRUE, FALSE);
65  x = -cBorders * SYSMET(CXBORDER);
66  y = -cBorders * SYSMET(CYBORDER);
67  }
68 
69  CopyInflateRect(&rcBtn, &pwnd-> rcWindow, x, y);
70 
71  x = -pwnd-> rcWindow.left;
72  y = -pwnd-> rcWindow.top;
73 
74  /*
75  * Get real caption area: subtract final border underneath caption
76  * that separates it from everything else.
77  */
78  if (TestWF(pwnd, WEFTOOLWINDOW)) {
79  cxS = SYSMET(CXSMSIZE);
80  cyS = SYSMET(CYSMSIZE);
81  } else {
82  cxS = SYSMET(CXSIZE);
83  cyS = SYSMET(CYSIZE);
84  }
85 
86  if (hit == HTCLOSE) {
87 
88  if ( _MNCanClose(pwnd)) {
89  bm = TestWF(pwnd, WEFTOOLWINDOW) ? OBI_CLOSE_PAL : OBI_CLOSE;
90  cmd = SC_CLOSE;
91  }
92 
93  } else if (hit == HTREDUCE) {
94 
95  /*
96  * Reduce button isn't last button, so shift left by one button
97  */
98  if (TestWF(pwnd, WFMINBOX)) {
99 
100  rcBtn.right -= cxS * 2;
101  x += SYSMET(CXEDGE);
102 
103  if (TestWF(pwnd, WFMINIMIZED)) {
104  bm = OBI_RESTORE;
105  cmd = SC_RESTORE;
106  } else {
107  bm = OBI_REDUCE;
108  cmd = SC_MINIMIZE;
109  }
110  }
111 
112  } else if (hit == HTZOOM) {
113 
114  if (TestWF(pwnd, WFMAXBOX)) {
115 
116  rcBtn.right -= cxS;
117 
118  if (TestWF(pwnd, WFMAXIMIZED)) {
119  bm = OBI_RESTORE;
120  cmd = SC_RESTORE;
121  } else {
122  bm = OBI_ZOOM;
123  cmd = SC_MAXIMIZE;
124  }
125  }
126 
127  } else {
128 
129  /*
130  * hit == HTHELP
131  */
132  if (TestWF(pwnd, WEFCONTEXTHELP)) {
133  rcBtn.right -= cxS;
134 
135  bm = OBI_HELP;
136  cmd = SC_CONTEXTHELP;
137  }
138  }
139 
140  if (cmd) {
141 
142  rcBtn.bottom = rcBtn.top + cyS;
143  rcBtn.left = rcBtn.right - cxS;
144 
145  /*
146  * Adjust 'x' and 'y' to window coordinates
147  */
148  x += rcBtn.left;
149  y += rcBtn.top + SYSMET(CYEDGE);
150 
151  /*
152  * rcBtn (screen coords hit rect) has a one-border tolerance all
153  * around
154  */
155  InflateRect(&rcBtn, SYSMET(CXBORDER), SYSMET(CYBORDER));
156 
157  hdc = _GetDCEx(pwnd, NULL, DCX_WINDOW | DCX_USESTYLE);
158 
159  /*
160  * Draw the image in its depressed state.
161  */
162  BitBltSysBmp(hdc, x, y, bm + DOBI_PUSHED);
163 
164  wState = DOBI_PUSHED;
165  }
166 
167  xxxSetCapture(pwnd);
168 
169  while (!fMouseUp) {
170 
171  if (xxxGetMessage(&msg, NULL, WM_MOUSEFIRST, WM_MOUSELAST)) {
172 
173  if (msg.message == WM_LBUTTONUP) {
174 
176  fMouseUp = TRUE;
177 
178  } else if ((msg.message == WM_MOUSEMOVE) && cmd) {
179 
180  wNewState = PtInRect(&rcBtn, msg.pt) ? DOBI_PUSHED : DOBI_NORMAL;
181 
182  if (wState != wNewState) {
183  wState = wNewState;
184  BitBltSysBmp(hdc, x, y, bm + wState);
185  }
186  }
187  #if 0
188  /*
189  * LATER mikeke my guess is we don't need this crap
190  * } else if (pwnd != PtiCurrent()->pq->spwndCapture) {
191  * // Someone else grabbed the capture. Bail out.
192  * break;
193  */
194  #endif
195  }
196  }
197 
198  if (!cmd)
199  return(0);
200 
201  if (wState && (cmd != SC_CONTEXTHELP))
202  BitBltSysBmp(hdc, x, y, bm);
203 
204  _ReleaseDC(hdc);
205 
206  return (fMouseUp && PtInRect(&rcBtn, msg.pt)) ? cmd : 0;
207 }

引用了 _GetDCEx(), _MNCanClose(), _ReleaseDC(), BitBltSysBmp(), CopyInflateRect(), GetWindowBorders(), InflateRect(), PtInRect(), tagWND::rcWindow, xxxReleaseCapture() , 以及 xxxSetCapture().

被这些函数引用 xxxDWP_NCMouse().

#define RIPMSG0(flags, szFmt)
Definition: winerrp.h:131
POEMBITMAPINFO pOem
Definition: userk.h:1797
#define SMCAP
Definition: caption.c:21
MIN
#define MIN
Definition: caption.c:16
Definition: userk.h:1803
PCLS pcls
Definition: user.h:1403
int xxxGetWindowText(PWND pwnd, LPWSTR psz, int cchMax)
#define NOSIZE
Definition: caption.c:22
BOOL FAR BitBltSysBmp(HDC hdc, int x, int y, UINT i)
Definition: mngrayc.c:28
HBRUSH ahbrSystem[COLOR_MAX]
Definition: client/random.c:27
VOID DrawCaptionIcon(HDC hdc, LPRECT lprc, PCURSOR pcursor, HBRUSH hbrFill, UINT flags)
Definition: caption.c:370
HFONT hCaptionFont
Definition: user.h:1039
#define UserAssert(exp)
Definition: usersrv.h:117
LONG xxxSendMessageTimeout(PWND pwnd, UINT message, DWORD wParam, LONG lParam, UINT fuFlags, UINT uTimeout, LPLONG lpdwResult)
Definition: sendmsg.c:644
#define RIPMSG1(flags, szFmt, p1)
Definition: winerrp.h:132
#define NOMAX
Definition: caption.c:19
LARGE_UNICODE_STRING strName
Definition: user.h:1414
BOOL _HasCaptionIcon(PWND pwnd)
Definition: rtl/winmgr.c:649
HFONT ghSmCaptionFont
Definition: kernel/globals.c:417
VOID ClearHungFlag(PWND pwnd, WORD wFlag)
Definition: hungapp.c:93
#define NOCLOSE
Definition: caption.c:20
HICON hico
Definition: userk.h:1799
#define CCACHEDCAPTIONS
Definition: kernel/globals.h:33
struct tagCURSOR * PCURSOR
Definition: user.h:56
int cyCaptionFontChar
Definition: kernel/globals.c:415
HDC ghdcMem
Definition: kernel/globals.c:399
BOOL _ReleaseDC(HDC hdc)
Definition: dc.c:102
int cy
Definition: user.h:807
PDISPLAYINFO gpDispInfo
Definition: kernel/globals.c:125
BOOL APIENTRY PtInRect(CONST RECT *prc, POINT pt)
Definition: rect.c:111
MAX
#define MAX
Definition: caption.c:17
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
int APIENTRY FillRect(HDC hdc, LPCRECT prc, HBRUSH hBrush)
Definition: rtl/draw.c:29
BOOL DrawEdge(HDC hdc, LPRECT lprc, UINT edge, UINT flags)
Definition: rtl/draw.c:776
RECT rcWindow
Definition: user.h:1398
BOOL APIENTRY InflateRect(LPRECT prc, int cx, int cy)
Definition: rect.c:158
int cySmCaptionFontChar
Definition: kernel/globals.c:418
int GetWindowBorders(LONG lStyle, DWORD dwExStyle, BOOL fWindow, BOOL fClient)
Definition: rtl/winmgr.c:501
int cx
Definition: user.h:806
#define RIP_WARNING
Definition: winerrp.h:29
HICON xxxCreateWindowSmIcon(PWND pwnd, HICON hIconBig, BOOL fNotQueryDrag)
Definition: dwp.c:1105
CAPTIONCACHE cachedCaptions[CCACHEDCAPTIONS]
Definition: kernel/globals.c:17
BOOL DrawFrame(HDC hdc, LPRECT prect, int clFrame, int cmd)
BOOL xxxReleaseCapture(VOID)
Definition: capture.c:69
ULONG Length
Definition: user.h:281
TEXTMETRIC tmSysFont
Definition: user.h:1017
PVOID FASTCALL HMValidateHandleNoRip(HANDLE h, BYTE btype)
Definition: rtl/wow.c:303
BOOL _MNCanClose(PWND pwnd)
Definition: rtl/menu.c:78
#define NOMIN
Definition: caption.c:18
BOOL APIENTRY CopyInflateRect(LPRECT prcDst, CONST RECT *prcSrc, int cx, int cy)
Definition: rect.c:46
int x
Definition: user.h:804
BOOL xxxDrawCaptionTemp(PWND pwnd, HDC hdc, LPRECT lprc, HFONT hFont, PCURSOR pcursor, PUNICODE_STRING pstrText, UINT flags)
Definition: caption.c:544
BOOL HMRelocateLockRecord(PVOID ppobjNew, int cbDelta)
PWND xxxSetCapture(PWND pwnd)
Definition: capture.c:23
typedef UINT(FAR WINAPI *MSGSOUNDPROC)()
HANDLE _GetProp(PWND pwnd, LPWSTR pszKey, BOOL fInternal)
Definition: rtl/winprop.c:69
HDC hdcBits
Definition: user.h:1568
UINT TextCopy(PLARGE_UNICODE_STRING pstr, LPWSTR lpstr, UINT size)
Definition: rtl/random.c:108
BOOL gfTrackLocks
Definition: handtabl.c:21
VOID CheckLock(PVOID pobj)
HDC _GetDCEx(HWND hwnd, HRGN hrgnClip, DWORD flags)
int y
Definition: user.h:805
BOOL _GetTextMetricsW(HDC hdc, LPTEXTMETRICW ptm)
Definition: kernel/server.c:1223
VOID BltMe4Times(POEMBITMAPINFO pOem, int cxySlot, int cxyIcon, HDC hdcSrc, PCURSOR pcursor, UINT flags)
Definition: caption.c:310
BOOL _DrawIconEx(HDC hdc, int x, int y, PCURSOR pcur, int cx, int cy, UINT istepIfAniCur, HBRUSH hbrush, UINT diFlags)
Definition: wmicon.c:93
PSERVERINFO gpsi
Definition: clglobal.c:39
PCURSOR xxxGetWindowSmIcon(PWND pwnd, BOOL fDontSendMsg)
Definition: caption.c:216
Definition: user.h:1323
ATOM atomIconSmProp
Definition: user.h:1035
BOOL IsVisible(PWND pwnd)
Definition: rtl/winmgr.c:456
PCURSOR spcursor
Definition: userk.h:1796
BOOL BltIcon(HDC hdc, int x, int y, int cx, int cy, HDC hdcSrc, PCURSOR pcursor, BOOL fMask, LONG rop)
Definition: wmicon.c:32
int gclBorder
Definition: user.h:982
HBRUSH ghbrGray
Definition: client/random.c:25

一键复制

编辑

Web IDE

原始数据

按行查看

历史

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
``` <!DOCTYPE html> <html> <head> <title></title> </head> <style> * { padding: 0; margin: 0; } html, body { height: 100%; padding: 0; margin: 0; background: #000; } canvas { position: absolute; width: 100%; height: 100%; } .aa { position: fixed; left: 50%; bottom: 10px; color: #ccc; } </style> <body> <canvas id="pinkboard"></canvas> <script> /* * Settings */ var settings = { particles: { length: 500, // maximum amount of particles duration: 2, // particle duration in sec velocity: 100, // particle velocity in pixels/sec effect: -0.75, // play with this for a nice effect size: 30 // particle size in pixels } }; /* * RequestAnimationFrame polyfill by Erik M?ller */ (function () { var b = 0; var c = ["ms", "moz", "webkit", "o"]; for (var a = 0; a < c.length && !window.requestAnimationFrame; ++a) { window.requestAnimationFrame = window[c[a] + "RequestAnimationFrame"]; window.cancelAnimationFrame = window[c[a] + "CancelAnimationFrame"] || window[c[a] + "CancelRequestAnimationFrame"]; } if (!window.requestAnimationFrame) { window.requestAnimationFrame = function (h, e) { var d = new Date().getTime(); var f = Math.max(0, 16 - (d - b)); var g = window.setTimeout(function () { h(d + f); }, f); b = d + f; return g; }; } if (!window.cancelAnimationFrame) { window.cancelAnimationFrame = function (d) { clearTimeout(d); }; } })(); /* * Point class */ var Point = (function () { function Point(x, y) { this.x = typeof x !== "undefined" ? x : 0; this.y = typeof y !== "undefined" ? y : 0; } Point.prototype.clone = function () { return new Point(this.x, this.y); }; Point.prototype.length = function (length) { if (typeof length == "undefined") return Math.sqrt(this.x * this.x + this.y * this.y); this.normalize(); this.x *= length; this.y *= length; return this; }; Point.prototype.normalize = function () { var length = this.length(); this.x /= length; this.y /= length; return this; }; return Point; })(); /* * Particle class */ var Particle = (function () { function Particle() { this.position = new Point(); this.velocity = new Point(); this.acceleration = new Point(); this.age = 0; } Particle.prototype.initialize = function (x, y, dx, dy) { this.position.x = x; this.position.y = y; this.velocity.x = dx; this.velocity.y = dy; this.acceleration.x = dx * settings.particles.effect; this.acceleration.y = dy * settings.particles.effect; this.age = 0; }; Particle.prototype.update = function (deltaTime) { this.position.x += this.velocity.x * deltaTime; this.position.y += this.velocity.y * deltaTime; this.velocity.x += this.acceleration.x * deltaTime; this.velocity.y += this.acceleration.y * deltaTime; this.age += deltaTime; }; Particle.prototype.draw = function (context, image) { function ease(t) { return --t * t * t + 1; } var size = image.width * ease(this.age / settings.particles.duration); context.globalAlpha = 1 - this.age / settings.particles.duration; context.drawImage( image, this.position.x - size / 2, this.position.y - size / 2, size, size ); }; return Particle; })(); /* * ParticlePool class */ var ParticlePool = (function () { var particles, firstActive = 0, firstFree = 0, duration = settings.particles.duration; function ParticlePool(length) { // create and populate particle pool particles = new Array(length); for (var i = 0; i < particles.length; i++) particles[i] = new Particle(); } ParticlePool.prototype.add = function (x, y, dx, dy) { particles[firstFree].initialize(x, y, dx, dy); // handle circular queue firstFree++; if (firstFree == particles.length) firstFree = 0; if (firstActive == firstFree) firstActive++; if (firstActive == particles.length) firstActive = 0; }; ParticlePool.prototype.update = function (deltaTime) { var i; // update active particles if (firstActive < firstFree) { for (i = firstActive; i < firstFree; i++) particles[i].update(deltaTime); } if (firstFree < firstActive) { for (i = firstActive; i < particles.length; i++) particles[i].update(deltaTime); for (i = 0; i < firstFree; i++) particles[i].update(deltaTime); } // remove inactive particles while ( particles[firstActive].age >= duration && firstActive != firstFree ) { firstActive++; if (firstActive == particles.length) firstActive = 0; } }; ParticlePool.prototype.draw = function (context, image) { // draw active particles if (firstActive < firstFree) { for (i = firstActive; i < firstFree; i++) particles[i].draw(context, image); } if (firstFree < firstActive) { for (i = firstActive; i < particles.length; i++) particles[i].draw(context, image); for (i = 0; i < firstFree; i++) particles[i].draw(context, image); } }; return ParticlePool; })(); /* * Putting it all together */ (function (canvas) { var context = canvas.getContext("2d"), particles = new ParticlePool(settings.particles.length), particleRate = settings.particles.length / settings.particles.duration, // particles/sec time; // get point on heart with -PI <= t <= PI function pointOnHeart(t) { return new Point( 160 * Math.pow(Math.sin(t), 3), 130 * Math.cos(t) - 50 * Math.cos(2 * t) - 20 * Math.cos(3 * t) - 10 * Math.cos(4 * t) + 25 ); } // creating the particle image using a dummy canvas var image = (function () { var canvas = document.createElement("canvas"), context = canvas.getContext("2d"); canvas.width = settings.particles.size; canvas.height = settings.particles.size; // helper function to create the path function to(t) { var point = pointOnHeart(t); point.x = settings.particles.size / 2 + (point.x * settings.particles.size) / 350; point.y = settings.particles.size / 2 - (point.y * settings.particles.size) / 350; return point; } // create the path context.beginPath(); var t = -Math.PI; var point = to(t); context.moveTo(point.x, point.y); while (t < Math.PI) { t += 0.01; // baby steps! point = to(t); context.lineTo(point.x, point.y); } context.closePath(); // create the fill context.fillStyle = "#ea80b0"; context.fill(); // create the image var image = new Image(); image.src = canvas.toDataURL(); return image; })(); // render that thing! function render() { // next animation frame requestAnimationFrame(render); // update time var newTime = new Date().getTime() / 1000, deltaTime = newTime - (time || newTime); time = newTime; // clear canvas context.clearRect(0, 0, canvas.width, canvas.height); // create new particles var amount = particleRate * deltaTime; for (var i = 0; i < amount; i++) { var pos = pointOnHeart(Math.PI - 2 * Math.PI * Math.random()); var dir = pos.clone().length(settings.particles.velocity); particles.add( canvas.width / 2 + pos.x, canvas.height / 2 - pos.y, dir.x, -dir.y ); } // update and draw particles particles.update(deltaTime); particles.draw(context, image); } // handle (re-)sizing of the canvas function onResize() { canvas.width = canvas.clientWidth; canvas.height = canvas.clientHeight; } window.onresize = onResize; // delay rendering bootstrap setTimeout(function () { onResize(); render(); }, 10); })(document.getElementById("pinkboard")); </script> </body> </html> ``` ![示例图片](https://devbit-static.oss-cn-beijing.aliyuncs.com/devbit-static/img/heart.png)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值