Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

draw.c

Go to the documentation of this file.
00001 /****************************** Module Header ******************************\ 00002 * Module Name: draw.c 00003 * 00004 * Copyright (c) 1985 - 1999, Microsoft Corporation 00005 * 00006 * This module contains common drawing functions. 00007 * 00008 * History: 00009 * 12-Feb-1992 MikeKe Moved Drawtext to the client side 00010 \***************************************************************************/ 00011 00012 00013 CONST WCHAR szRadio[] = L"nmlkji"; 00014 CONST WCHAR szCheck[] = L"gfedcb"; 00015 00016 /***************************************************************************\ 00017 * FlipUserTextOutW 00018 * 00019 * Flip the check mark if the hdc is mirrored otherwise it just calls UserTextOutW 00020 * 00021 \***************************************************************************/ 00022 BOOL FlipUserTextOutW(HDC hdc, int x, int y, LPCWSTR ch, int nCount) 00023 { 00024 BOOL bRet; 00025 #ifdef USE_MIRRORING 00026 int iOldTextAlign, iGraphicsModeOld; 00027 00028 if ((UserGetLayout(hdc) & LAYOUT_RTL) && 00029 (nCount == 1) && 00030 ((ch[0] == TEXT('a')) ||(ch[0] == TEXT('b'))) 00031 ) 00032 { 00033 //Check mark then set the hdc in GM_COMPATIBLE to unmirror it. 00034 if (iGraphicsModeOld = UserSetGraphicsMode(hdc, GM_COMPATIBLE)) 00035 { 00036 iOldTextAlign = UserGetTextAlign(hdc); 00037 if ((iOldTextAlign & TA_CENTER) != TA_CENTER) 00038 { 00039 UserSetTextAlign(hdc, iOldTextAlign^TA_RIGHT); 00040 } 00041 bRet = UserTextOutW(hdc, x, y, ch, nCount); 00042 UserSetGraphicsMode(hdc, iGraphicsModeOld); 00043 UserSetTextAlign(hdc, iOldTextAlign); 00044 } 00045 } 00046 else 00047 #endif 00048 bRet = UserTextOutW(hdc, x, y, ch, nCount); 00049 00050 return bRet; 00051 } 00052 /***************************************************************************\ 00053 * FillRect 00054 * 00055 * Callable from either client or server contexts 00056 * 00057 * History: 00058 * 29-Oct-1990 MikeHar Ported from Windows. 00059 \***************************************************************************/ 00060 00061 int APIENTRY FillRect( 00062 HDC hdc, 00063 LPCRECT prc, 00064 HBRUSH hBrush) 00065 { 00066 ULONG_PTR iBrush; 00067 POLYPATBLT PolyData; 00068 00069 iBrush = (ULONG_PTR)hBrush - 1; 00070 if (iBrush <= COLOR_ENDCOLORS) { 00071 hBrush = SYSHBRUSH(iBrush); 00072 } 00073 00074 PolyData.x = prc->left; 00075 PolyData.y = prc->top; 00076 PolyData.cx = prc->right - prc->left; 00077 PolyData.cy = prc->bottom - prc->top; 00078 PolyData.BrClr.hbr = hBrush; 00079 00080 /* 00081 * Win95 incompatibility: they return either hBrush or the brush that 00082 * was previosuly selected in hdc. Not documented this way though. 00083 */ 00084 return UserPolyPatBlt(hdc, PATCOPY, &PolyData, 1, PPB_BRUSH); 00085 } 00086 00087 /***************************************************************************\ 00088 * InvertRect 00089 * 00090 * Can be called from either the client or server contexts. 00091 * 00092 * History: 00093 * 29-Oct-1990 MikeHar Ported from Windows. 00094 \***************************************************************************/ 00095 00096 BOOL APIENTRY InvertRect( 00097 HDC hdc, 00098 LPCRECT prc) 00099 { 00100 return UserPatBlt(hdc, 00101 prc->left, 00102 prc->top, 00103 prc->right - prc->left, 00104 prc->bottom - prc->top, 00105 DSTINVERT); 00106 } 00107 00108 /***************************************************************************\ 00109 * DrawDiagonalLine 00110 * 00111 * History: 00112 \***************************************************************************/ 00113 00114 DWORD DrawDiagonalLine( 00115 HDC hdc, 00116 LPRECT lprc, 00117 int iDirection, 00118 int iThickness, 00119 UINT flags) 00120 { 00121 RECT rc; 00122 LPINT py; 00123 int cx; 00124 int cy; 00125 int dx; 00126 int dy; 00127 LPINT pc; 00128 00129 POLYPATBLT ppbData[8]; 00130 int ppbCount = 0; 00131 00132 if (IsRectEmpty(lprc)) 00133 return 0L; 00134 00135 rc = *lprc; 00136 00137 /* 00138 * We draw slopes < 1 by varying y instead of x. 00139 */ 00140 --iThickness; 00141 00142 /* 00143 * HACK HACK HACK. REMOVE THIS ONCE MARLETT IS AROUND 00144 */ 00145 cy = rc.bottom - rc.top; 00146 cx = rc.right - rc.left; 00147 00148 if (!flags && (cy != cx)) 00149 cy -= iThickness * SYSMETRTL(CYBORDER); 00150 00151 if (cy >= cx) { 00152 00153 /* 00154 * "slope" is >= 1, so vary x by 1 00155 */ 00156 cy /= cx; 00157 pc = &cy; 00158 00159 cx = SYSMETRTL(CXBORDER); 00160 00161 } else { 00162 00163 /* 00164 * "slope" is < 1, so vary y by 1 00165 */ 00166 cx /= cy; 00167 pc = &cx; 00168 00169 cy = SYSMETRTL(CYBORDER); 00170 } 00171 00172 dx = cx; 00173 dy = iDirection * cy; 00174 00175 *pc = (*pc + iThickness) * SYSMETRTL(CYBORDER); 00176 00177 rc.right -= cx; 00178 rc.bottom -= cy; 00179 00180 /* 00181 * For negative slopes, start from opposite side. 00182 */ 00183 py = ((iDirection < 0) ? &rc.top : &rc.bottom); 00184 00185 while ((rc.left <= rc.right) && (rc.top <= rc.bottom)) { 00186 00187 if (!(flags & BF_MIDDLE)) { 00188 00189 /* 00190 * UserPatBlt(hdc, rc.left, *py, cx, cy, PATCOPY); 00191 */ 00192 00193 ppbData[ppbCount].x = rc.left; 00194 ppbData[ppbCount].y = *py; 00195 ppbData[ppbCount].cx = cx; 00196 ppbData[ppbCount].cy = cy; 00197 ppbData[ppbCount].BrClr.hbr = NULL; 00198 00199 ppbCount++; 00200 00201 } else { 00202 00203 /* 00204 * Fill interior. We can determine vertex in interior 00205 * by vector define. 00206 */ 00207 if (cy > SYSMETRTL(CYBORDER)) { 00208 00209 if (flags & BF_LEFT) { 00210 00211 /* 00212 * UserPatBlt(hdc, rc.left, lprc->top, cx, *py - lprc->top + cy, PATCOPY); 00213 */ 00214 00215 ppbData[ppbCount].x = rc.left; 00216 ppbData[ppbCount].y = lprc->top; 00217 ppbData[ppbCount].cx = cx; 00218 ppbData[ppbCount].cy = *py - lprc->top + cy; 00219 ppbData[ppbCount].BrClr.hbr = NULL; 00220 00221 ppbCount++; 00222 00223 } else { 00224 /* 00225 * UserPatBlt(hdc, rc.left, *py, cx, lprc->bottom - *py, PATCOPY); 00226 */ 00227 00228 ppbData[ppbCount].x = rc.left; 00229 ppbData[ppbCount].y = *py; 00230 ppbData[ppbCount].cx = cx; 00231 ppbData[ppbCount].cy = lprc->bottom - *py; 00232 ppbData[ppbCount].BrClr.hbr = NULL; 00233 00234 ppbCount++; 00235 } 00236 00237 } else { 00238 00239 if (flags & BF_TOP) { 00240 00241 /* 00242 * UserPatBlt(hdc, rc.left, *py, lprc->right - rc.left, cy, PATCOPY); 00243 */ 00244 00245 ppbData[ppbCount].x = rc.left; 00246 ppbData[ppbCount].y = *py; 00247 ppbData[ppbCount].cx = lprc->right - rc.left; 00248 ppbData[ppbCount].cy = cy; 00249 ppbData[ppbCount].BrClr.hbr = NULL; 00250 00251 ppbCount++; 00252 00253 } else { 00254 /* 00255 * UserPatBlt(hdc, lprc->left, *py, rc.left - lprc->left + cx, cy, PATCOPY); 00256 */ 00257 00258 ppbData[ppbCount].x = lprc->left; 00259 ppbData[ppbCount].y = *py; 00260 ppbData[ppbCount].cx = rc.left - lprc->left + cx; 00261 ppbData[ppbCount].cy = cy; 00262 ppbData[ppbCount].BrClr.hbr = NULL; 00263 00264 ppbCount++; 00265 00266 } 00267 } 00268 } 00269 00270 rc.left += dx; 00271 *py -= dy; 00272 00273 /* 00274 * do we need to flush PolyPatBlt ? 00275 */ 00276 if (ppbCount == 8) { 00277 UserPolyPatBlt(hdc, PATCOPY, &ppbData[0], 8, PPB_BRUSH); 00278 ppbCount = 0; 00279 } 00280 } 00281 00282 /* 00283 * any left-over PolyPatblt buffered operations? 00284 */ 00285 if (ppbCount != 0) { 00286 UserPolyPatBlt(hdc, PATCOPY, &ppbData[0], ppbCount, PPB_BRUSH); 00287 } 00288 00289 return MAKELONG(cx, cy); 00290 } 00291 00292 /***************************************************************************\ 00293 * FillTriangle 00294 * 00295 * Fills in the triangle whose sides are two rectangle edges and a 00296 * diagonal. The vertex in the interior can be determined from the 00297 * vector type. 00298 * 00299 * History: 00300 \***************************************************************************/ 00301 00302 BOOL FillTriangle( 00303 HDC hdc, 00304 LPRECT lprc, 00305 HBRUSH hbr, 00306 UINT flags) 00307 { 00308 HBRUSH hbrT; 00309 int nDirection; 00310 00311 switch (flags & (BF_RECT | BF_DIAGONAL)) { 00312 00313 case BF_DIAGONAL_ENDTOPLEFT: 00314 case BF_DIAGONAL_ENDBOTTOMRIGHT: 00315 nDirection = -1; 00316 break; 00317 00318 default: 00319 nDirection = 1; 00320 break; 00321 } 00322 hbrT = UserSelectBrush(hdc, hbr); 00323 DrawDiagonalLine(hdc, lprc, nDirection, 1, flags); 00324 /* 00325 * Don't care if the above functions failed for a bad hdc 00326 */ 00327 return (UserSelectBrush(hdc, hbrT) != NULL); 00328 } 00329 00330 /***************************************************************************\ 00331 * DrawDiagonal 00332 * 00333 * Called by DrawEdge() for BF_DIAGONAL edges. 00334 * 00335 * Draws line of slope 1, one of 4 different ones. The difference is 00336 * where the line starts and where the end point is. The BF_ flags for 00337 * BF_DIAGONAL specify where the end point is. For example, BF_DIAGONAL | 00338 * BF_TOP | BF_LEFT means to draw a line ending up at the top left corner. 00339 * So the origin must be bottom right, and the angle must be 3pi/4, or 00340 * 135 degrees. 00341 * 00342 * History: 00343 \***************************************************************************/ 00344 00345 BOOL DrawDiagonal( 00346 HDC hdc, 00347 LPRECT lprc, 00348 HBRUSH hbrTL, 00349 HBRUSH hbrBR, 00350 UINT flags) 00351 { 00352 HBRUSH hbrT; 00353 int nDirection; 00354 DWORD dAdjust; 00355 00356 /* 00357 * Away from light source 00358 */ 00359 hbrT = ((flags & BF_BOTTOM) ? hbrBR : hbrTL); 00360 00361 switch (flags & (BF_RECT | BF_DIAGONAL)){ 00362 00363 case BF_DIAGONAL_ENDTOPLEFT: 00364 case BF_DIAGONAL_ENDBOTTOMRIGHT: 00365 nDirection = -1; 00366 break; 00367 00368 default: 00369 nDirection = 1; 00370 break; 00371 } 00372 00373 hbrT = UserSelectBrush(hdc, hbrT); 00374 dAdjust = DrawDiagonalLine(hdc, lprc, nDirection, 1, (flags & ~BF_MIDDLE)); 00375 /* 00376 * Adjust rectangle for next border 00377 */ 00378 if (flags & BF_TOP) 00379 lprc->left += LOWORD(dAdjust); 00380 else 00381 lprc->right -= LOWORD(dAdjust); 00382 00383 if (flags & BF_RIGHT) 00384 lprc->top += HIWORD(dAdjust); 00385 else 00386 lprc->bottom -= HIWORD(dAdjust); 00387 00388 /* 00389 * Moved this to the end to save a check for return value 00390 */ 00391 return (UserSelectBrush(hdc, hbrT) != NULL); 00392 } 00393 00394 /***************************************************************************\ 00395 * DrawGrip 00396 * 00397 * History: 00398 \***************************************************************************/ 00399 00400 BOOL DrawGrip( 00401 HDC hdc, 00402 LPRECT lprc, 00403 UINT wState) 00404 { 00405 int x; 00406 int y; 00407 int c; 00408 HBRUSH hbrOld; 00409 DWORD rgbHilight; 00410 DWORD rgbShadow; 00411 DWORD rgbOld; 00412 POLYPATBLT PolyData; 00413 00414 c = min((lprc->right - lprc->left), (lprc->bottom - lprc->top)); 00415 x = lprc->right - c; // right justify 00416 y = lprc->bottom - c; // bottom justify 00417 00418 /* 00419 * Setup colors 00420 */ 00421 if (wState & (DFCS_FLAT | DFCS_MONO)) { 00422 hbrOld = SYSHBR(WINDOW); 00423 rgbHilight = SYSRGBRTL(WINDOWFRAME); 00424 rgbShadow = SYSRGBRTL(WINDOWFRAME); 00425 } else { 00426 hbrOld = SYSHBR(3DFACE); 00427 rgbHilight = SYSRGBRTL(3DHILIGHT); 00428 rgbShadow = SYSRGBRTL(3DSHADOW); 00429 } 00430 00431 PolyData.x = lprc->left; 00432 PolyData.y = lprc->top; 00433 PolyData.cx = lprc->right-lprc->left; 00434 PolyData.cy = lprc->bottom-lprc->top; 00435 PolyData.BrClr.hbr = hbrOld; 00436 UserPolyPatBlt(hdc, PATCOPY, &PolyData, 1, PPB_BRUSH); 00437 00438 rgbOld = UserSetTextColor(hdc, rgbHilight); 00439 00440 if (wState & DFCS_SCROLLSIZEGRIPRIGHT) { 00441 UserTextOutW(hdc, x, y, L"x", 1); 00442 UserSetTextColor(hdc, rgbShadow); 00443 UserTextOutW(hdc, x, y, L"y", 1); 00444 } else { 00445 UserTextOutW(hdc, x, y, L"o", 1); 00446 UserSetTextColor(hdc, rgbShadow); 00447 UserTextOutW(hdc, x, y, L"p", 1); 00448 } 00449 00450 UserSetTextColor(hdc, rgbOld); 00451 return TRUE; 00452 } 00453 00454 /***************************************************************************\ 00455 * DrawBox 00456 * 00457 * History: 00458 \***************************************************************************/ 00459 00460 BOOL DrawBox( 00461 HDC hdc, 00462 LPRECT lprc, 00463 UINT wControlState) 00464 { 00465 int cx; 00466 int cy; 00467 int c; 00468 int x; 00469 int y; 00470 LPCWSTR lp = szRadio; 00471 int i; 00472 BOOL fSkip0thItem; 00473 COLORREF clr[6]; 00474 COLORREF clrOld; 00475 00476 fSkip0thItem = ((wControlState & (DFCS_BUTTON3STATE | DFCS_PUSHED | 00477 DFCS_INACTIVE | DFCS_CHECKED)) == (DFCS_BUTTON3STATE | DFCS_CHECKED)); 00478 00479 /* 00480 * Don't need radio mask with marlett font! 00481 */ 00482 if (wControlState & DFCS_BUTTONRADIOMASK) { 00483 00484 clr[0] = clr[1] = clr[2] = clr[3] = clr[4] = 0L; 00485 FillRect(hdc, lprc, ghbrWhite); 00486 00487 } else { 00488 00489 /* 00490 * DFCS_BUTTONRADIOIMAGE 00491 */ 00492 if (wControlState & (DFCS_MONO | DFCS_FLAT)) { 00493 clr[1] = clr[2] = clr[3] = clr[4] = SYSRGBRTL(WINDOWFRAME); 00494 } else { 00495 clr[1] = SYSRGBRTL(3DLIGHT); 00496 clr[2] = SYSRGBRTL(3DDKSHADOW); 00497 clr[3] = SYSRGBRTL(3DHILIGHT); 00498 clr[4] = SYSRGBRTL(3DSHADOW); 00499 } 00500 00501 00502 if (wControlState & (DFCS_PUSHED | DFCS_INACTIVE)) 00503 clr[0] = SYSRGBRTL(3DFACE); 00504 else if (fSkip0thItem) 00505 clr[0] = SYSRGBRTL(3DHILIGHT); 00506 else 00507 clr[0] = SYSRGBRTL(WINDOW); 00508 00509 if (wControlState & DFCS_BUTTONRADIOIMAGE) 00510 FillRect(hdc, lprc, ghbrBlack); 00511 else if (!(wControlState & DFCS_BUTTONRADIO)) 00512 lp = szCheck; 00513 } 00514 00515 cx = lprc->right - lprc->left; 00516 cy = lprc->bottom - lprc->top; 00517 00518 c = min(cx,cy); 00519 x = lprc->left + ((cx - c) / 2); // - 1; 00520 y = lprc->top + ((cy - c) / 2); 00521 00522 if (fSkip0thItem && 00523 ((gpsi->BitCount < 8) || (SYSRGB(3DHILIGHT) == RGB(255,255,255)))) { 00524 00525 COLORREF clrBk; 00526 POLYPATBLT PolyData; 00527 00528 /* 00529 * Make the interior of a 3State checkbox which is just checked a 00530 * dither, just like an indeterminate push button which is pressed. 00531 */ 00532 clrBk = UserSetBkColor(hdc, SYSRGB(3DHILIGHT)); 00533 clrOld = UserSetTextColor(hdc, SYSRGB(3DFACE)); 00534 00535 PolyData.x = x; 00536 PolyData.y = y; 00537 PolyData.cx = cx; 00538 PolyData.cy = cy; 00539 PolyData.BrClr.hbr = gpsi->hbrGray; 00540 UserPolyPatBlt(hdc, PATCOPY, &PolyData, 1, PPB_BRUSH); 00541 00542 UserSetBkColor(hdc, clrBk); 00543 00544 } else { 00545 clrOld = UserSetTextColor(hdc, clr[0]); 00546 UserTextOutW(hdc, x, y, lp, 1); 00547 } 00548 00549 lp++; 00550 00551 for (i = 1; i < 5; i++) { 00552 UserSetTextColor(hdc, clr[i]); 00553 UserTextOutW(hdc, x, y, lp++, 1); 00554 } 00555 00556 if (wControlState & DFCS_CHECKED) { 00557 COLORREF clrCheck; 00558 00559 if (wControlState & (DFCS_BUTTON3STATE | DFCS_INACTIVE)) { 00560 clrCheck = SYSRGBRTL(3DSHADOW); 00561 } else if (wControlState & DFCS_HOT) { 00562 clrCheck = SYSRGBRTL(HOTLIGHT); 00563 } else { 00564 clrCheck = SYSRGBRTL(WINDOWTEXT); 00565 } 00566 00567 UserSetTextColor(hdc, clrCheck); 00568 FlipUserTextOutW(hdc, x, y, lp, 1); 00569 } 00570 00571 UserSetTextColor(hdc, clrOld); 00572 00573 return TRUE; 00574 } 00575 /***************************************************************************\ 00576 * GetCaptionChar 00577 * 00578 * History: 00579 * 04/02/97 GerardoB Created 00580 \***************************************************************************/ 00581 WCHAR GetCaptionChar (UINT wState) 00582 { 00583 wState &= DFCS_CAPTIONALL; 00584 switch (wState) { 00585 case DFCS_CAPTIONCLOSE: 00586 return TEXT('r'); 00587 case DFCS_CAPTIONMIN: 00588 return TEXT('0'); 00589 case DFCS_CAPTIONMAX: 00590 return TEXT('1'); 00591 case DFCS_CAPTIONRESTORE: 00592 return TEXT('2'); 00593 /* case DFCS_CAPTIONHELP: */ 00594 default: 00595 return TEXT('s'); 00596 } 00597 } 00598 /***************************************************************************\ 00599 * DrawMenuMark 00600 * 00601 * History: 00602 \***************************************************************************/ 00603 00604 BOOL DrawMenuMark( 00605 HDC hdc, 00606 LPRECT lprc, 00607 UINT wType, 00608 UINT wState) 00609 { 00610 COLORREF rgbOld; 00611 int x; 00612 int y; 00613 int c; 00614 int cx; 00615 int cy; 00616 WCHAR ch; 00617 00618 cx = lprc->right - lprc->left; 00619 cy = lprc->bottom - lprc->top; 00620 00621 c = min(cx,cy); 00622 x = lprc->left + ((cx - c) / 2) - ((cx > 0xb) ? 1 : 0); 00623 y = lprc->top + ((cy - c) / 2); 00624 00625 FillRect(hdc, lprc, ghbrWhite); 00626 00627 rgbOld = UserSetTextColor(hdc, 0L); 00628 00629 if (wType == DFC_MENU) { 00630 if (wState & DFCS_MENUCHECK) { 00631 ch = TEXT('a'); 00632 } else if (wState & DFCS_MENUBULLET) { 00633 ch = TEXT('h'); 00634 } else if (wState & DFCS_MENUARROWRIGHT) { 00635 ch = TEXT('w'); 00636 } else { 00637 ch = TEXT('8'); 00638 } 00639 } else { 00640 UserAssert(wType == DFC_POPUPMENU); 00641 ch = GetCaptionChar(wState); 00642 } 00643 00644 FlipUserTextOutW(hdc, x, y, &ch, 1); 00645 UserSetTextColor(hdc, rgbOld); 00646 00647 return TRUE; 00648 } 00649 00650 /***************************************************************************\ 00651 * DrawIt 00652 * 00653 * History: 00654 \***************************************************************************/ 00655 00656 BOOL DrawIt( 00657 HDC hdc, 00658 LPRECT lprc, 00659 UINT wState, 00660 WCHAR ch) 00661 { 00662 COLORREF rgb; 00663 int x; 00664 int y; 00665 int c; 00666 int cx; 00667 int cy; 00668 BOOL fDrawDisabled = wState & DFCS_INACTIVE; 00669 00670 cx = lprc->right - lprc->left; 00671 cy = lprc->bottom - lprc->top; 00672 00673 c = min(cx,cy); 00674 x = lprc->left + ((cx - c) / 2); 00675 y = lprc->top + ((cy - c) / 2); 00676 00677 if (fDrawDisabled) { 00678 rgb = SYSRGBRTL(3DHILIGHT); 00679 } else if (wState & DFCS_HOT) { 00680 rgb = SYSRGBRTL(HOTLIGHT); 00681 } else { 00682 rgb = SYSRGBRTL(BTNTEXT); 00683 } 00684 00685 rgb = UserSetTextColor(hdc, rgb); 00686 00687 if (wState & (DFCS_INACTIVE | DFCS_PUSHED)) { 00688 x++; 00689 y++; 00690 } 00691 00692 UserTextOutW(hdc, x, y, &ch, 1); 00693 00694 if (fDrawDisabled) { 00695 UserSetTextColor(hdc, SYSRGBRTL(3DSHADOW)); 00696 UserTextOutW(hdc, x - 1, y - 1, &ch, 1); 00697 } 00698 00699 UserSetTextColor(hdc, rgb); 00700 00701 return TRUE; 00702 } 00703 00704 /***************************************************************************\ 00705 * DrawScrollArrow 00706 * 00707 * History: 00708 \***************************************************************************/ 00709 00710 BOOL DrawScrollArrow( 00711 HDC hdc, 00712 LPRECT lprc, 00713 UINT wControlState) 00714 { 00715 WCHAR ch = (wControlState & DFCS_SCROLLHORZ) ? TEXT('3') : TEXT('5'); 00716 00717 if (wControlState & DFCS_SCROLLMAX) 00718 ch++; 00719 00720 return DrawIt(hdc, lprc, wControlState, ch); 00721 } 00722 00723 /***************************************************************************\ 00724 * DrawFrameControl 00725 * 00726 * History: 00727 \***************************************************************************/ 00728 00729 BOOL DrawFrameControl( 00730 HDC hdc, 00731 LPRECT lprc, 00732 UINT wType, 00733 UINT wState) 00734 { 00735 RECT rc; 00736 HFONT hFont; 00737 HFONT hOldFont; 00738 BOOL fRet = TRUE; 00739 int iOldBk; 00740 int c; 00741 BOOL fButton = FALSE; 00742 LOGFONTW lfw; 00743 #ifdef USE_MIRRORING 00744 int iGraphicsModeOld = 0; 00745 int iOldTextAlign; 00746 #endif 00747 00748 rc = *lprc; 00749 00750 #ifdef USE_MIRRORING 00751 /* 00752 * If the hdc is mirrored then set it in GM_ADVANCED mode 00753 * to enforce the text to be mirrored. 00754 */ 00755 if (UserGetLayout(hdc) & LAYOUT_RTL) { 00756 if (iGraphicsModeOld = UserSetGraphicsMode(hdc, GM_ADVANCED)) 00757 { 00758 iOldTextAlign = UserGetTextAlign(hdc); 00759 if ((iOldTextAlign & TA_CENTER) != TA_CENTER) 00760 { 00761 UserSetTextAlign(hdc, iOldTextAlign^TA_RIGHT); 00762 } 00763 } 00764 } 00765 #endif 00766 /* 00767 * Enforce monochrome/flat 00768 */ 00769 if (gpsi->BitCount == 1) 00770 wState |= DFCS_MONO; 00771 00772 if (wState & DFCS_MONO) 00773 wState |= DFCS_FLAT; 00774 00775 if ((wType != DFC_MENU) 00776 && (wType != DFC_POPUPMENU) 00777 && ((wType != DFC_BUTTON) || (wState & DFCS_BUTTONPUSH)) 00778 && ((wType != DFC_SCROLL) 00779 || !(wState & (DFCS_SCROLLSIZEGRIP | DFCS_SCROLLSIZEGRIPRIGHT)))) 00780 { 00781 UINT wBorder = BF_ADJUST; 00782 00783 if (wType != DFC_SCROLL) 00784 wBorder |= BF_SOFT; 00785 00786 UserAssert(DFCS_FLAT == BF_FLAT); 00787 UserAssert(DFCS_MONO == BF_MONO); 00788 00789 wBorder |= (wState & (DFCS_FLAT | DFCS_MONO)); 00790 00791 DrawPushButton(hdc, &rc, wState, wBorder); 00792 00793 if (wState & DFCS_ADJUSTRECT) 00794 *lprc = rc; 00795 00796 fButton = TRUE; 00797 } 00798 00799 iOldBk = UserSetBkMode(hdc, TRANSPARENT); 00800 if (!iOldBk) { 00801 /* 00802 * return FALSE if the hdc is bogus 00803 */ 00804 #ifdef USE_MIRRORING 00805 if (iGraphicsModeOld) { 00806 UserSetGraphicsMode(hdc, iGraphicsModeOld); 00807 UserSetTextAlign(hdc, iOldTextAlign); 00808 } 00809 #endif 00810 return FALSE; 00811 } 00812 00813 c = min(rc.right - rc.left, rc.bottom - rc.top); 00814 00815 if (c <= 0) { 00816 #ifdef USE_MIRRORING 00817 if (iGraphicsModeOld){ 00818 UserSetGraphicsMode(hdc, iGraphicsModeOld); 00819 UserSetTextAlign(hdc, iOldTextAlign); 00820 } 00821 #endif 00822 return FALSE; 00823 } 00824 00825 RtlZeroMemory(&lfw, sizeof(lfw)); 00826 lfw.lfHeight = c; 00827 lfw.lfWeight = FW_NORMAL; 00828 lfw.lfCharSet = SYMBOL_CHARSET; 00829 RtlCopyMemory(lfw.lfFaceName, L"Marlett", sizeof(L"Marlett")); 00830 hFont = UserCreateFontIndirectW(&lfw); 00831 00832 hOldFont = UserSelectFont(hdc, hFont); 00833 00834 if (!fButton) { 00835 00836 if ((wType == DFC_MENU) || (wType == DFC_POPUPMENU)) { 00837 if (wState & (DFCS_MENUARROWUP | DFCS_MENUARROWDOWN)) { 00838 if (!(wState & DFCS_TRANSPARENT)) { 00839 POLYPATBLT ppbData; 00840 00841 ppbData.x = lprc->left; 00842 ppbData.y = lprc->top; 00843 ppbData.cx = lprc->right - lprc->left; 00844 ppbData.cy = lprc->bottom - lprc->top; 00845 ppbData.BrClr.hbr = SYSHBR(MENU); 00846 UserPolyPatBlt(hdc, PATCOPY, &ppbData, 1, PPB_BRUSH); 00847 } 00848 DrawScrollArrow(hdc, &rc, 00849 (wState & (DFCS_HOT | DFCS_INACTIVE)) | ((wState & DFCS_MENUARROWUP) ? DFCS_SCROLLUP : DFCS_SCROLLDOWN)); 00850 } else { 00851 DrawMenuMark(hdc, &rc, wType, wState); 00852 } 00853 } else if (wType == DFC_BUTTON) { 00854 DrawBox(hdc, &rc, wState); 00855 } else { // wType == DFC_SCROLL 00856 DrawGrip(hdc, lprc, wState); 00857 } 00858 00859 } else if (wType == DFC_CAPTION) { 00860 DrawIt(hdc, &rc, wState, GetCaptionChar(wState)); 00861 } else if (wType == DFC_SCROLL) { 00862 00863 DrawScrollArrow(hdc, &rc, wState); 00864 00865 } else if (wType != DFC_BUTTON) { 00866 00867 fRet = FALSE; 00868 } 00869 00870 #ifdef USE_MIRRORING 00871 if (iGraphicsModeOld){ 00872 UserSetGraphicsMode(hdc, iGraphicsModeOld); 00873 UserSetTextAlign(hdc, iOldTextAlign); 00874 } 00875 #endif 00876 UserSetBkMode(hdc, iOldBk); 00877 UserSelectFont(hdc, hOldFont); 00878 UserDeleteObject(hFont); 00879 00880 return fRet; 00881 } 00882 00883 /***************************************************************************\ 00884 * DrawEdge 00885 * 00886 * Draws a 3D edge using 2 3D borders. Adjusts interior rectangle if desired 00887 * And fills it if requested. 00888 * 00889 * Returns: 00890 * FALSE if error 00891 * 00892 * History: 00893 * 30-Jan-1991 Laurabu Created. 00894 \***************************************************************************/ 00895 00896 BOOL DrawEdge( 00897 HDC hdc, 00898 LPRECT lprc, 00899 UINT edge, 00900 UINT flags) 00901 { 00902 HBRUSH hbrTL; 00903 HBRUSH hbrBR; 00904 RECT rc; 00905 UINT bdrType; 00906 POLYPATBLT ppbData[4]; 00907 UINT ppbCount; 00908 BOOL fResult = TRUE; 00909 00910 /* 00911 * Enforce monochromicity and flatness 00912 */ 00913 if (gpsi->BitCount == 1) 00914 flags |= BF_MONO; 00915 00916 if (flags & BF_MONO) 00917 flags |= BF_FLAT; 00918 00919 rc = *lprc; 00920 00921 /* 00922 * Draw the border segment(s), and calculate the remaining space as we 00923 * go. 00924 */ 00925 if (bdrType = (edge & BDR_OUTER)) { 00926 00927 DrawBorder: 00928 00929 /* 00930 * Get brushes. Note the symmetry between raised outer, 00931 * sunken inner and sunken outer, raised inner. 00932 */ 00933 if (flags & BF_FLAT) { 00934 00935 if (flags & BF_MONO) 00936 hbrBR = (bdrType & BDR_OUTER) ? SYSHBR(WINDOWFRAME) : SYSHBR(WINDOW); 00937 else 00938 hbrBR = (bdrType & BDR_OUTER) ? SYSHBR(3DSHADOW) : SYSHBR(3DFACE); 00939 00940 hbrTL = hbrBR; 00941 00942 } else { 00943 00944 /* 00945 * 5 == HILIGHT 00946 * 4 == LIGHT 00947 * 3 == FACE 00948 * 2 == SHADOW 00949 * 1 == DKSHADOW 00950 */ 00951 00952 switch (bdrType) { 00953 /* 00954 * +2 above surface 00955 */ 00956 case BDR_RAISEDOUTER: 00957 hbrTL = ((flags & BF_SOFT) ? SYSHBR(3DHILIGHT) : SYSHBR(3DLIGHT)); 00958 hbrBR = SYSHBR(3DDKSHADOW); // 1 00959 break; 00960 00961 /* 00962 * +1 above surface 00963 */ 00964 case BDR_RAISEDINNER: 00965 hbrTL = ((flags & BF_SOFT) ? SYSHBR(3DLIGHT) : SYSHBR(3DHILIGHT)); 00966 hbrBR = SYSHBR(3DSHADOW); // 2 00967 break; 00968 00969 /* 00970 * -1 below surface 00971 */ 00972 case BDR_SUNKENOUTER: 00973 hbrTL = ((flags & BF_SOFT) ? SYSHBR(3DDKSHADOW) : SYSHBR(3DSHADOW)); 00974 hbrBR = SYSHBR(3DHILIGHT); // 5 00975 break; 00976 00977 /* 00978 * -2 below surface 00979 */ 00980 case BDR_SUNKENINNER: 00981 hbrTL = ((flags & BF_SOFT) ? SYSHBR(3DSHADOW) : SYSHBR(3DDKSHADOW)); 00982 hbrBR = SYSHBR(3DLIGHT); // 4 00983 break; 00984 00985 default: 00986 return FALSE; 00987 } 00988 } 00989 00990 /* 00991 * Draw the sides of the border. NOTE THAT THE ALGORITHM FAVORS THE 00992 * BOTTOM AND RIGHT SIDES, since the light source is assumed to be top 00993 * left. If we ever decide to let the user set the light source to a 00994 * particular corner, then change this algorithm. 00995 */ 00996 if (flags & BF_DIAGONAL) { 00997 00998 fResult = DrawDiagonal(hdc, &rc, hbrTL, hbrBR, flags); 00999 01000 } else { 01001 01002 /* 01003 * reset ppbData index 01004 */ 01005 ppbCount = 0; 01006 01007 /* 01008 * Bottom Right edges 01009 */ 01010 /* 01011 * Right 01012 */ 01013 if (flags & BF_RIGHT) { 01014 01015 rc.right -= SYSMETRTL(CXBORDER); 01016 01017 ppbData[ppbCount].x = rc.right; 01018 ppbData[ppbCount].y = rc.top; 01019 ppbData[ppbCount].cx = SYSMETRTL(CXBORDER); 01020 ppbData[ppbCount].cy = rc.bottom - rc.top; 01021 ppbData[ppbCount].BrClr.hbr = hbrBR; 01022 ppbCount++; 01023 } 01024 01025 /* 01026 * Bottom 01027 */ 01028 if (flags & BF_BOTTOM) { 01029 rc.bottom -= SYSMETRTL(CYBORDER); 01030 01031 ppbData[ppbCount].x = rc.left; 01032 ppbData[ppbCount].y = rc.bottom; 01033 ppbData[ppbCount].cx = rc.right - rc.left; 01034 ppbData[ppbCount].cy = SYSMETRTL(CYBORDER); 01035 ppbData[ppbCount].BrClr.hbr = hbrBR; 01036 ppbCount++; 01037 } 01038 01039 /* 01040 * Top Left edges 01041 */ 01042 /* 01043 * Left 01044 */ 01045 if (flags & BF_LEFT) { 01046 ppbData[ppbCount].x = rc.left; 01047 ppbData[ppbCount].y = rc.top; 01048 ppbData[ppbCount].cx = SYSMETRTL(CXBORDER); 01049 ppbData[ppbCount].cy = rc.bottom - rc.top; 01050 ppbData[ppbCount].BrClr.hbr = hbrTL; 01051 ppbCount++; 01052 01053 rc.left += SYSMETRTL(CXBORDER); 01054 } 01055 01056 /* 01057 * Top 01058 */ 01059 if (flags & BF_TOP) { 01060 ppbData[ppbCount].x = rc.left; 01061 ppbData[ppbCount].y = rc.top; 01062 ppbData[ppbCount].cx = rc.right - rc.left; 01063 ppbData[ppbCount].cy = SYSMETRTL(CYBORDER); 01064 ppbData[ppbCount].BrClr.hbr = hbrTL; 01065 ppbCount++; 01066 01067 rc.top += SYSMETRTL(CYBORDER); 01068 } 01069 /* 01070 * Send all queued PatBlts to GDI in one go 01071 */ 01072 fResult = UserPolyPatBlt(hdc,PATCOPY,&ppbData[0],ppbCount,PPB_BRUSH); 01073 } 01074 } 01075 01076 if (bdrType = (edge & BDR_INNER)) { 01077 /* 01078 * Strip this so the next time through, bdrType will be 0. 01079 * Otherwise, we'll loop forever. 01080 */ 01081 edge &= ~BDR_INNER; 01082 goto DrawBorder; 01083 } 01084 01085 01086 /* 01087 * Select old brush back in, if we changed it. 01088 */ 01089 01090 /* 01091 * Fill the middle & clean up if asked 01092 */ 01093 if (flags & BF_MIDDLE) { 01094 if (flags & BF_DIAGONAL) 01095 fResult = FillTriangle(hdc, &rc, ((flags & BF_MONO) ? (HBRUSH)SYSHBR(WINDOW) : (HBRUSH)SYSHBR(3DFACE)), flags); 01096 else 01097 fResult = FillRect(hdc, &rc, ((flags & BF_MONO) ? (HBRUSH)SYSHBR(WINDOW) : (HBRUSH)SYSHBR(3DFACE))); 01098 } 01099 01100 if (flags & BF_ADJUST) 01101 *lprc = rc; 01102 01103 return fResult; 01104 } 01105 01106 /***************************************************************************\ 01107 * DrawPushButton 01108 * 01109 * Draws a push style button in the given state. Adjusts passed in rectangle 01110 * if desired. 01111 * 01112 * Algorithm: 01113 * Depending on the state we either draw 01114 * * raised edge (undepressed) 01115 * * sunken edge with extra shadow (depressed) 01116 * If it is an option push button (a push button that is 01117 * really a check button or a radio button like buttons 01118 * in tool bars), and it is checked, then we draw it 01119 * depressed with a different fill in the middle. 01120 * 01121 * History: 01122 * 05-Feb-19 Laurabu Created. 01123 \***************************************************************************/ 01124 01125 VOID DrawPushButton( 01126 HDC hdc, 01127 LPRECT lprc, 01128 UINT state, 01129 UINT flags) 01130 { 01131 RECT rc; 01132 HBRUSH hbrMiddle; 01133 DWORD rgbBack; 01134 DWORD rgbFore; 01135 BOOL fDither; 01136 01137 rc = *lprc; 01138 01139 DrawEdge(hdc, 01140 &rc, 01141 (state & (DFCS_PUSHED | DFCS_CHECKED)) ? EDGE_SUNKEN : EDGE_RAISED, 01142 (UINT)(BF_ADJUST | BF_RECT | (flags & (BF_SOFT | BF_FLAT | BF_MONO)))); 01143 01144 /* 01145 * BOGUS 01146 * On monochrome, need to do something to make pushed buttons look 01147 * better. 01148 */ 01149 01150 /* 01151 * Fill in middle. If checked, use dither brush (gray brush) with 01152 * black becoming normal color. 01153 */ 01154 fDither = FALSE; 01155 01156 if (state & DFCS_CHECKED) { 01157 01158 if ((gpsi->BitCount < 8) || (SYSRGBRTL(3DHILIGHT) == RGB(255,255,255))) { 01159 hbrMiddle = gpsi->hbrGray; 01160 rgbBack = UserSetBkColor(hdc, SYSRGBRTL(3DHILIGHT)); 01161 rgbFore = UserSetTextColor(hdc, SYSRGBRTL(3DFACE)); 01162 fDither = TRUE; 01163 } else { 01164 hbrMiddle = SYSHBR(3DHILIGHT); 01165 } 01166 01167 } else { 01168 hbrMiddle = SYSHBR(3DFACE); 01169 } 01170 01171 FillRect(hdc, &rc, hbrMiddle); 01172 01173 if (fDither) { 01174 UserSetBkColor(hdc, rgbBack); 01175 UserSetTextColor(hdc, rgbFore); 01176 } 01177 01178 if (flags & BF_ADJUST) 01179 *lprc = rc; 01180 } 01181 01182 /***************************************************************************\ 01183 * DrawFrame 01184 * 01185 * History: 01186 \***************************************************************************/ 01187 01188 BOOL DrawFrame( 01189 HDC hdc, 01190 PRECT prc, 01191 int clFrame, 01192 int cmd) 01193 { 01194 int x; 01195 int y; 01196 int cx; 01197 int cy; 01198 int cxWidth; 01199 int cyWidth; 01200 HANDLE hbrSave; 01201 LONG rop; 01202 POLYPATBLT PolyData[4]; 01203 01204 x = prc->left; 01205 y = prc->top; 01206 01207 cxWidth = SYSMETRTL(CXBORDER) * clFrame; 01208 cyWidth = SYSMETRTL(CYBORDER) * clFrame; 01209 01210 cx = prc->right - x - cxWidth; 01211 cy = prc->bottom - y - cyWidth; 01212 01213 rop = ((cmd & DF_ROPMASK) ? PATINVERT : PATCOPY); 01214 01215 if ((cmd & DF_HBRMASK) == DF_GRAY) { 01216 hbrSave = gpsi->hbrGray; 01217 } else { 01218 UserAssert(((cmd & DF_HBRMASK) >> 3) < COLOR_MAX); 01219 hbrSave = SYSHBRUSH((cmd & DF_HBRMASK) >> 3); 01220 } 01221 01222 PolyData[0].x = x; 01223 PolyData[0].y = y; 01224 PolyData[0].cx = cxWidth; 01225 PolyData[0].cy = cy; 01226 PolyData[0].BrClr.hbr = hbrSave; 01227 01228 PolyData[1].x = x + cxWidth; 01229 PolyData[1].y = y; 01230 PolyData[1].cx = cx; 01231 PolyData[1].cy = cyWidth; 01232 PolyData[1].BrClr.hbr = hbrSave; 01233 01234 PolyData[2].x = x; 01235 PolyData[2].y = y + cy; 01236 PolyData[2].cx = cx; 01237 PolyData[2].cy = cyWidth; 01238 PolyData[2].BrClr.hbr = hbrSave; 01239 01240 PolyData[3].x = x + cx; 01241 PolyData[3].y = y + cyWidth; 01242 PolyData[3].cx = cxWidth; 01243 PolyData[3].cy = cy; 01244 PolyData[3].BrClr.hbr = hbrSave; 01245 01246 UserPolyPatBlt(hdc, rop, &PolyData[0], 4, PPB_BRUSH); 01247 01248 return TRUE; 01249 } 01250 01251 /***************************************************************************\ 01252 * GetSignFromMappingMode 01253 * 01254 * For the current mapping mode, find out the sign of x from left to right, 01255 * and the sign of y from top to bottom. 01256 * 01257 * History: 01258 \***************************************************************************/ 01259 01260 BOOL GetSignFromMappingMode ( 01261 HDC hdc, 01262 PPOINT pptSign) 01263 { 01264 SIZE sizeViewPortExt; 01265 SIZE sizeWindowExt; 01266 01267 if (!UserGetViewportExtEx(hdc, &sizeViewPortExt) 01268 || !UserGetWindowExtEx(hdc, &sizeWindowExt)) { 01269 01270 return FALSE; 01271 } 01272 01273 pptSign->x = ((sizeViewPortExt.cx ^ sizeWindowExt.cx) < 0) ? -1 : 1; 01274 01275 pptSign->y = ((sizeViewPortExt.cy ^ sizeWindowExt.cy) < 0) ? -1 : 1; 01276 01277 return TRUE; 01278 } 01279 01280 /***************************************************************************\ 01281 * ClientFrame 01282 * 01283 * Draw a rectangle 01284 * 01285 * History: 01286 * 19-Jan-1993 MikeKe Created 01287 \***************************************************************************/ 01288 01289 BOOL ClientFrame( 01290 HDC hDC, 01291 LPCRECT pRect, 01292 HBRUSH hBrush, 01293 DWORD patOp) 01294 { 01295 int x; 01296 int y; 01297 POINT point; 01298 POINT ptSign; 01299 POLYPATBLT PolyData[4]; 01300 01301 if (!GetSignFromMappingMode (hDC, &ptSign)) 01302 return FALSE; 01303 01304 y = pRect->bottom - (point.y = pRect->top); 01305 if (y < 0) { 01306 return FALSE; 01307 } 01308 01309 x = pRect->right - (point.x = pRect->left); 01310 01311 /* 01312 * Check width and height signs 01313 */ 01314 if (((x ^ ptSign.x) < 0) || ((y ^ ptSign.y) < 0)) 01315 return FALSE; 01316 01317 // Top border 01318 PolyData[0].x = point.x; 01319 PolyData[0].y = point.y; 01320 PolyData[0].cx = x; 01321 PolyData[0].cy = ptSign.y; 01322 PolyData[0].BrClr.hbr = hBrush; 01323 01324 // Bottom border 01325 point.y = pRect->bottom - ptSign.y; 01326 PolyData[1].x = point.x; 01327 PolyData[1].y = point.y; 01328 PolyData[1].cx = x; 01329 PolyData[1].cy = ptSign.y; 01330 PolyData[1].BrClr.hbr = hBrush; 01331 01332 /* 01333 * Left Border 01334 * Don't xor the corners twice 01335 */ 01336 point.y = pRect->top + ptSign.y; 01337 y -= 2 * ptSign.y; 01338 PolyData[2].x = point.x; 01339 PolyData[2].y = point.y; 01340 PolyData[2].cx = ptSign.x; 01341 PolyData[2].cy = y; 01342 PolyData[2].BrClr.hbr = hBrush; 01343 01344 // Right Border 01345 point.x = pRect->right - ptSign.x; 01346 PolyData[3].x = point.x; 01347 PolyData[3].y = point.y; 01348 PolyData[3].cx = ptSign.x; 01349 PolyData[3].cy = y; 01350 PolyData[3].BrClr.hbr = hBrush; 01351 01352 return UserPolyPatBlt(hDC, patOp, PolyData, sizeof (PolyData) / sizeof (*PolyData), PPB_BRUSH); 01353 }

Generated on Sat May 15 19:39:46 2004 for test by doxygen 1.3.7