test: caption.c Source File

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

# caption.c

Go to the documentation of this file.

    00001 /****************************** Module Header ******************************\
    00002 * Module Name: caption.c (aka wmcap.c)
    00003 *
    00004 * Copyright (c) 1985 - 1999, Microsoft Corporation
    00005 *
    00006 * History:
    00007 * 28-Oct-1990 MikeHar   Ported functions from Win 3.0 sources.
    00008 * 01-Feb-1991 MikeKe    Added Revalidation code (None)
    00009 * 03-Jan-1992 IanJa     Neutralized (ANSI/wide-character)
    00010 \***************************************************************************/
    00011
    00012 #include "precomp.h"
    00013 #pragma hdrstop
    00014
    00015
    00016 #define MIN     0x01
    00017 #define MAX     0x02
    00018 #define NOMIN   0x04
    00019 #define NOMAX   0x08
    00020 #define NOCLOSE 0x10
    00021 #define SMCAP   0x20
    00022 #define NOSIZE  (NOMIN | NOMAX)
    00023
    00024 /***************************************************************************\
    00025 * CalcCaptionButton
    00026 *
    00027 * This calculates the location of the caption button.
    00028 \***************************************************************************/
    00029
    00030 DWORD xxxCalcCaptionButton(PWND pwnd, int iButton, LPWORD pcmd, LPRECT prcBtn, LPWORD pbm)
    00031 {
    00032     int x, y, cBorders, cxS, cyS;
    00033
    00034     CheckLock(pwnd);
    00035
    00036     *pcmd = 0;
    00037
    00038     if (TestWF(pwnd, WFMINIMIZED)) {
    00039
    00040         x = -SYSMET(CXFIXEDFRAME);
    00041         y = -SYSMET(CYFIXEDFRAME);
    00042
    00043     } else {
    00044
    00045         cBorders = GetWindowBorders(pwnd->style, pwnd->ExStyle, TRUE, FALSE);
    00046         x = -cBorders * SYSMET(CXBORDER);
    00047         y = -cBorders * SYSMET(CYBORDER);
    00048     }
    00049
    00050     CopyInflateRect(prcBtn, &pwnd->rcWindow, x, y);
    00051
    00052     x = -pwnd->rcWindow.left;
    00053     y = -pwnd->rcWindow.top;
    00054
    00055     /*
    00056      * Get real caption area:  subtract final border underneath caption
    00057      * that separates it from everything else.
    00058      */
    00059     if (TestWF(pwnd, WEFTOOLWINDOW)) {
    00060         cxS = SYSMET(CXSMSIZE);
    00061         cyS = SYSMET(CYSMSIZE);
    00062     } else {
    00063         cxS = SYSMET(CXSIZE);
    00064         cyS = SYSMET(CYSIZE);
    00065     }
    00066
    00067     if (iButton == INDEX_TITLEBAR_CLOSEBUTTON) {
    00068
    00069         if (xxxMNCanClose(pwnd)) {
    00070             *pbm  = TestWF(pwnd, WEFTOOLWINDOW) ? OBI_CLOSE_PAL : OBI_CLOSE;
    00071             *pcmd = SC_CLOSE;
    00072         }
    00073
    00074     } else if (iButton == INDEX_TITLEBAR_MINBUTTON) {
    00075
    00076         /*
    00077          * Reduce button isn't last button, so shift left by one button
    00078          */
    00079         if (TestWF(pwnd, WFMINBOX)) {
    00080
    00081             prcBtn->right -= cxS * 2;
    00082             x += SYSMET(CXEDGE);
    00083
    00084             if (TestWF(pwnd, WFMINIMIZED)) {
    00085                 *pbm  = OBI_RESTORE;
    00086                 *pcmd = SC_RESTORE;
    00087             } else {
    00088                 *pbm  = OBI_REDUCE;
    00089                 *pcmd = SC_MINIMIZE;
    00090             }
    00091         }
    00092
    00093     } else if (iButton == INDEX_TITLEBAR_MAXBUTTON) {
    00094
    00095         if (TestWF(pwnd, WFMAXBOX)) {
    00096
    00097             prcBtn->right -= cxS;
    00098
    00099             if (TestWF(pwnd, WFMAXIMIZED)) {
    00100                 *pbm  = OBI_RESTORE;
    00101                 *pcmd = SC_RESTORE;
    00102             } else {
    00103                 *pbm  = OBI_ZOOM;
    00104                 *pcmd = SC_MAXIMIZE;
    00105             }
    00106         }
    00107
    00108     } else { // iButton == INDEX_TITLEBAR_HELPBUTTON
    00109
    00110         if (TestWF(pwnd, WEFCONTEXTHELP)) {
    00111             prcBtn->right -= cxS;
    00112
    00113             *pbm = OBI_HELP;
    00114             *pcmd = SC_CONTEXTHELP;
    00115         }
    00116     }
    00117
    00118     if (*pcmd) {
    00119
    00120         prcBtn->bottom = prcBtn->top + cyS;
    00121         prcBtn->left   = prcBtn->right - cxS;
    00122
    00123         /*
    00124          * Adjust 'x' and 'y' to window coordinates
    00125          */
    00126         x += prcBtn->left;
    00127         y += prcBtn->top + SYSMET(CYEDGE);
    00128
    00129         /*
    00130          * rcBtn (screen coords hit rect) has a one-border tolerance all
    00131          * around
    00132          */
    00133         InflateRect(prcBtn, SYSMET(CXBORDER), SYSMET(CYBORDER));
    00134 #ifdef USE_MIRRORING
    00135             //Mirror the rect because the buttons in the left hand side of the window if it mirrored
    00136             if (TestWF(pwnd, WEFLAYOUTRTL)) {
    00137                 cxS           = prcBtn->right - prcBtn->left;
    00138                 prcBtn->right = pwnd->rcWindow.right - (prcBtn->left - pwnd->rcWindow.left);
    00139                 prcBtn->left  = prcBtn->right - cxS;
    00140             }
    00141 #endif
    00142     }
    00143
    00144     return (DWORD)MAKELONG(x, y);
    00145 }
    00146
    00147 /***************************************************************************\
    00148 * xxxTrackCaptionButton
    00149 *
    00150 * Handles clicking and dragging on caption buttons.
    00151 * We draw the button depressed then track the mouse.  If the user moves
    00152 * outside of the button, undepress it.  When the mouse button is finally
    00153 * released, we return whether the mouse was inside the button or not.  I.E.,
    00154 * whether the button was clicked.
    00155 *
    00156 \***************************************************************************/
    00157
    00158 WORD xxxTrackCaptionButton(
    00159     PWND pwnd,
    00160     UINT hit)
    00161 {
    00162     WORD  cmd;
    00163     MSG   msg;
    00164     HDC   hdc;
    00165     WORD  bm;
    00166     int   x;
    00167     int   y;
    00168     WORD  wState;
    00169     WORD  wNewState;
    00170     BOOL  fMouseUp = FALSE;
    00171     RECT  rcBtn;
    00172     DWORD dwWhere;
    00173     int   iButton;
    00174     WORD  wf;
    00175     UserAssert(IsWinEventNotifyDeferredOK());
    00176
    00177     CheckLock(pwnd);
    00178
    00179     /*
    00180      * Set up iButton for this and future STATECHANGE events
    00181      */
    00182     switch (hit) {
    00183     case HTCLOSE:
    00184         iButton = INDEX_TITLEBAR_CLOSEBUTTON;
    00185         wf = WFCLOSEBUTTONDOWN;
    00186         break;
    00187
    00188     case HTREDUCE:
    00189         iButton = INDEX_TITLEBAR_MINBUTTON;
    00190         wf = WFREDUCEBUTTONDOWN;
    00191         break;
    00192
    00193     case HTZOOM:
    00194         iButton = INDEX_TITLEBAR_MAXBUTTON;
    00195         wf = WFZOOMBUTTONDOWN;
    00196         break;
    00197
    00198     case HTHELP:
    00199         iButton = INDEX_TITLEBAR_HELPBUTTON;
    00200         wf = WFHELPBUTTONDOWN;
    00201         break;
    00202
    00203     default:
    00204         UserAssert(FALSE);
    00205     }
    00206     dwWhere = xxxCalcCaptionButton(pwnd, iButton, &cmd, &rcBtn, &bm);
    00207     x = GET_X_LPARAM(dwWhere);
    00208     y = GET_Y_LPARAM(dwWhere);
    00209
    00210     if (cmd) {
    00211         /*
    00212          * Draw the image in its depressed state.
    00213          */
    00214         hdc = _GetDCEx(pwnd, NULL, DCX_WINDOW | DCX_USESTYLE);
    00215         BitBltSysBmp(hdc, x, y, bm + DOBI_PUSHED);
    00216         _ReleaseDC(hdc);
    00217
    00218         wState = DOBI_PUSHED;
    00219
    00220         /*
    00221          * Notification of button press.
    00222          */
    00223
    00224         SetWF(pwnd, wf);
    00225
    00226         if (FWINABLE()) {
    00227             xxxWindowEvent(EVENT_OBJECT_STATECHANGE, pwnd, OBJID_TITLEBAR,
    00228                     iButton, 0);
    00229         }
    00230     } else {
    00231         iButton = 0;
    00232     }
    00233
    00234     xxxSetCapture(pwnd);
    00235
    00236     while (!fMouseUp) {
    00237
    00238         if (xxxPeekMessage(&msg, NULL, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE)) {
    00239             if (msg.message == WM_LBUTTONUP) {
    00240
    00241                 xxxReleaseCapture();
    00242                 fMouseUp = TRUE;
    00243
    00244             } else if ((msg.message == WM_MOUSEMOVE) && cmd) {
    00245
    00246                 wNewState = PtInRect(&rcBtn, msg.pt) ? DOBI_PUSHED : DOBI_NORMAL;
    00247
    00248                 if (wState != wNewState) {
    00249                     wState = wNewState;
    00250
    00251                     hdc = _GetDCEx(pwnd, NULL, DCX_WINDOW | DCX_USESTYLE);
    00252                     BitBltSysBmp(hdc, x, y, bm + wState);
    00253                     _ReleaseDC(hdc);
    00254
    00255                     if (wState == DOBI_PUSHED) {
    00256                         SetWF(pwnd, wf);
    00257                     } else {
    00258                         ClrWF(pwnd, wf);
    00259                     }
    00260
    00261                     if (FWINABLE()) {
    00262                         xxxWindowEvent(EVENT_OBJECT_STATECHANGE, pwnd, OBJID_TITLEBAR,
    00263                                 iButton, 0);
    00264                     }
    00265                 }
    00266             }
    00267         } else if (!xxxSleepThread(QS_MOUSE, 0, TRUE)) {
    00268             break;
    00269         }
    00270         if (pwnd != PtiCurrent()->pq->spwndCapture) {
    00271             /*
    00272              * We lost capture. This could have happened during
    00273              *  the WM_CAPTURECHANGED callback or later if we
    00274              *  are/were not in the foreground queue.
    00275              */
    00276             break;
    00277         }
    00278     }
    00279
    00280     if (!cmd)
    00281         return 0;
    00282
    00283     if (wState && (cmd != SC_CONTEXTHELP)) {
    00284         hdc = _GetDCEx(pwnd, NULL, DCX_WINDOW | DCX_USESTYLE);
    00285         BitBltSysBmp(hdc, x, y, bm);
    00286         _ReleaseDC(hdc);
    00287
    00288         ClrWF(pwnd, wf);
    00289
    00290         if (FWINABLE()) {
    00291             xxxWindowEvent(EVENT_OBJECT_STATECHANGE, pwnd, OBJID_TITLEBAR,
    00292                     iButton, 0);
    00293         }
    00294     }
    00295
    00296     return (fMouseUp && PtInRect(&rcBtn, msg.pt)) ? cmd : 0;
    00297 }
    00298
    00299 /***************************************************************************\
    00300 * GetWindowSmIcon
    00301 *
    00302 * Gets icon to draw in caption of window
    00303 *
    00304 \***************************************************************************/
    00305
    00306 PCURSOR xxxGetWindowSmIcon(
    00307     PWND pwnd,
    00308     BOOL fDontSendMsg)
    00309 {
    00310     PCURSOR pcursor = NULL;
    00311     HICON   hico = NULL;
    00312     PCLS    pcls = pwnd->pcls;
    00313     DWORD   dwResult = 0;
    00314
    00315     CheckLock(pwnd);
    00316
    00317     /*
    00318      * We check per-window stuff first then per-class stuff, preferring a
    00319      * real small icon over a stretched big one.
    00320      *
    00321      * Per-window small icon
    00322      * Per-window big icon stretched small
    00323      * Per-class small icon
    00324      * Per-class big icon stretched small
    00325      * WM_QUERYDRAGICON big icon stretched small (for 3.x dudes)
    00326      *
    00327      * Try window small icon first
    00328      * NOTE:  The WM_SETICON and WM_GETICON messags are for ISVs only.
    00329      */
    00330     if ((hico = (HICON)_GetProp(pwnd, MAKEINTATOM(gpsi->atomIconSmProp), PROPF_INTERNAL)) != NULL) {
    00331
    00332         if (pcursor = (PCURSOR)HMValidateHandleNoSecure(hico, TYPE_CURSOR)) {
    00333             return pcursor;
    00334         } else {
    00335             RIPMSG1(RIP_WARNING,"GetWindowSmIcon: Invalid small icon handle (0x%p)", hico);
    00336         }
    00337     }
    00338
    00339     /*
    00340      * Try class small icon next
    00341      */
    00342     pcursor = pcls->spicnSm;
    00343     if (pcursor != NULL)
    00344         return pcursor;
    00345
    00346     if (!TestWF(pwnd, WFWIN40COMPAT) &&
    00347         (!TestWF(pwnd, WFOLDUI)      ||
    00348         !TestWF(pwnd, WEFMDICHILD))  &&
    00349         !fDontSendMsg) {
    00350
    00351         ULONG_PTR dwResult;
    00352
    00353         /*
    00354          * A few old apps like Corel don't set their class icon and other
    00355          * data until long after we need it.  If we send them WM_QUERYDRAGICON,
    00356          * they will fault because they don't check the return from GWL to
    00357          * get their data.  WFOLDUI apps won't ever get a WM_QUERYDRAGICON,
    00358          * sorry.  Currently the apps with this hack (not for this reason
    00359          * necessarily)
    00360          *      Corel Photo-Paint 5.0
    00361          *      Myst 2.0
    00362          *      Visual Baler 3.0
    00363          *      Quicken
    00364          */
    00365         if (xxxSendMessageTimeout(pwnd,
    00366                                   WM_QUERYDRAGICON,
    00367                                   0,
    00368                                   0,
    00369                                   SMTO_NORMAL,
    00370                                   100,
    00371                                   &dwResult)) {
    00372
    00373             hico = (HICON)dwResult;
    00374         }
    00375
    00376         if (hico) {
    00377
    00378             hico = xxxCreateWindowSmIcon(pwnd, hico, FALSE);
    00379             pcursor = (PCURSOR)HMValidateHandleNoSecure(hico, TYPE_CURSOR);
    00380
    00381             if (pcursor == NULL)
    00382                 hico = NULL;
    00383         }
    00384     }
    00385
    00386     if (pcursor == NULL) {
    00387         pcursor = SYSICO(WINLOGO);
    00388     }
    00389
    00390     return pcursor;
    00391 }
    00392
    00393 /***************************************************************************\
    00394 * BltMe4Times
    00395 *
    00396 * This routine blts out two copies of the specified caption icon.  One
    00397 * with for an active window and one for an inactive window.
    00398 *
    00399 \***************************************************************************/
    00400
    00401 VOID BltMe4Times(
    00402     POEMBITMAPINFO pOem,
    00403     int            cxySlot,
    00404     int            cxyIcon,
    00405     HDC            hdcSrc,
    00406     PCURSOR        pcursor,
    00407     UINT           flags)
    00408 {
    00409     RECT            rc;
    00410     int             i;
    00411     int             j;
    00412     BOOL            fMask = TRUE;
    00413     LONG            rop;
    00414     HBRUSH          hBrush;
    00415
    00416     hBrush = (flags & DC_INBUTTON) ? SYSHBR(3DHILIGHT) : SYSHBR(ACTIVECAPTION);
    00417
    00418     for (i = 0; i < 2; i++) {
    00419
    00420         rop = SRCAND;
    00421
    00422         rc.left   = pOem->x;
    00423         rc.top    = pOem->y;
    00424         rc.right  = rc.left + pOem->cx;
    00425         rc.bottom = rc.top + pOem->cy;
    00426         FillRect(HDCBITS(), &rc, hBrush);
    00427
    00428         rc.top  += (cxySlot - cxyIcon) / 2;
    00429         rc.left += SYSMET(CXBORDER) + (cxySlot - cxyIcon) / 2;
    00430
    00431         for (j = 0; j < 2; j++) {
    00432                     BltIcon(
    00433                     HDCBITS(),
    00434                     rc.left,
    00435                     rc.top,
    00436                     cxyIcon,
    00437                     cxyIcon,
    00438                     hdcSrc,
    00439                     pcursor,
    00440                     fMask,
    00441                     rop);
    00442
    00443             fMask = !fMask;
    00444             rop = SRCINVERT;
    00445         }
    00446
    00447         pOem += DOBI_CAPOFF;
    00448         hBrush = (flags & DC_INBUTTON) ? SYSHBR(3DFACE) : SYSHBR(INACTIVECAPTION);
    00449     }
    00450 }
    00451
    00452 /***************************************************************************\
    00453 *
    00454 *  DrawCaptionIcon
    00455 *
    00456 *  In order to speed up the drawing of caption icons a cache is maintained.
    00457 *  Within the cache, the first entry, 0, is for the tray's depressed caption
    00458 *  look.  Items 1..CCACHEDCAPTIONS are for the actual caption's icons.
    00459 *
    00460 \***************************************************************************/
    00461
    00462 VOID DrawCaptionIcon(
    00463     HDC     hdc,
    00464     LPRECT  lprc,
    00465     PCURSOR pcursor,
    00466     HBRUSH  hbrFill,
    00467     UINT    flags)
    00468 {
    00469     int            i;
    00470     int            xStart = 0;
    00471     int            cxySlot;
    00472     POEMBITMAPINFO pOem;
    00473     RECT           rc;
    00474     CAPTIONCACHE   ccTemp;
    00475
    00476     /*
    00477      * Check the size of the icon to see if it matches the size of the
    00478      * cache we created.  Most of the time this will match.  Also, if
    00479      * we are drawing with DC_INBUTTON in 16 colors, don't cache.
    00480      */
    00481     cxySlot = lprc->bottom - lprc->top;
    00482
    00483     if ((cxySlot != gpsi->oembmi[OBI_CAPCACHE1].cy) || (hbrFill == gpsi->hbrGray)) {
    00484
    00485         rc.left   = lprc->left;
    00486         rc.top    = lprc->top;
    00487         rc.right  = lprc->left + cxySlot;
    00488         rc.bottom = lprc->top + cxySlot;
    00489
    00490         FillRect(hdc, &rc, hbrFill);
    00491
    00492         rc.left += SYSMET(CXBORDER) + (cxySlot - SYSMET(CXSMICON)) / 2;
    00493         rc.top  += (cxySlot - SYSMET(CYSMICON)) / 2;
    00494
    00495         _DrawIconEx(hdc,
    00496                     rc.left,
    00497                     rc.top,
    00498                     pcursor,
    00499                     SYSMET(CXSMICON),
    00500                     SYSMET(CYSMICON),
    00501                     0,
    00502                     NULL,
    00503                     DI_NORMAL);
    00504
    00505         goto Done;
    00506     }
    00507
    00508     if (flags & DC_INBUTTON) {
    00509
    00510         /*
    00511          * The DC_INBUTTON icons is always slot 0.
    00512          */
    00513         i = ((gcachedCaptions[0].spcursor == pcursor) ? 0 : CCACHEDCAPTIONS);
    00514
    00515     } else {
    00516
    00517         /*
    00518          * Search the cache to see if this cursor is currently cached.
    00519          */
    00520         for (i = 1; i < CCACHEDCAPTIONS; i++) {
    00521             if (gcachedCaptions[i].spcursor == pcursor)
    00522                 break;
    00523         }
    00524     }
    00525
    00526     if (i >= CCACHEDCAPTIONS) {
    00527
    00528         /*
    00529          * Icon wasn't cached, so try and add it to the cache
    00530          */
    00531         if (flags & DC_INBUTTON) {
    00532
    00533             /*
    00534              * The tray's special DC_INBUTTON style always goes in slot 0.
    00535              */
    00536             i = 0;
    00537
    00538         } else {
    00539
    00540             /*
    00541              * Look for an empty slot in the cache.  If we can't find one,
    00542              * stuff the new icon at the end of the cache.  The result will
    00543              * be that the last item will be deleted.
    00544              */
    00545             for (i = 1; i < CCACHEDCAPTIONS - 1; i++) {
    00546                 if (gcachedCaptions[i].spcursor == NULL)
    00547                     break;
    00548             }
    00549         }
    00550
    00551         /*
    00552          * Add an item to the cache by blting an active and inactive copy of
    00553          * the icon.
    00554          */
    00555         BltMe4Times(gcachedCaptions[i].pOem,
    00556                     cxySlot,
    00557                     SYSMET(CXSMICON),
    00558                     ghdcMem,
    00559                     pcursor,
    00560                     flags);
    00561
    00562         Lock(&(gcachedCaptions[i].spcursor), pcursor);
    00563 #if DBG
    00564         gcachedCaptions[i].hico = (HICON)PtoH(pcursor);
    00565 #endif
    00566     }
    00567
    00568     /*
    00569      * We have a hit, so move that cached icon to the front of the cache.
    00570      * This means that the least recently used icon will be the last
    00571      * icon in the cache.  Remember, we never update index 0 because it
    00572      * is reserved for the DC_INBUTTON icon.
    00573      */
    00574     for ( ; i > 1; i-- ) {
    00575
    00576         /*
    00577          * Move the entry toward the front
    00578          */
    00579         ccTemp = gcachedCaptions[i];
    00580         gcachedCaptions[i]     = gcachedCaptions[i - 1];
    00581         gcachedCaptions[i - 1] = ccTemp;
    00582
    00583 #if DEBUGTAGS
    00584         /*
    00585          * In checked builds we need to adjust the lock records for
    00586          * the cursor so it has the correct address.
    00587          */
    00588         if (IsDbgTagEnabled(DBGTAG_TrackLocks)) {
    00589             if (gcachedCaptions[i].spcursor)
    00590                 HMRelocateLockRecord(&(gcachedCaptions[i].spcursor), (int)sizeof(CAPTIONCACHE));
    00591             if (gcachedCaptions[i - 1].spcursor)
    00592                 HMRelocateLockRecord(&(gcachedCaptions[i - 1].spcursor), -(int)sizeof(CAPTIONCACHE));
    00593         }
    00594 #endif
    00595     }
    00596
    00597
    00598 #if DBG
    00599     /*
    00600      *  Make sure the icon we want to draw is the one
    00601      *  that we hit in the cache.
    00602      */
    00603     UserAssert( gcachedCaptions[i].hico == PtoH(pcursor) );
    00604 #endif
    00605
    00606     /*
    00607      * Determine what cached bitmap to blt.
    00608      */
    00609     pOem = gcachedCaptions[i].pOem;
    00610     if (!(flags & DC_ACTIVE))
    00611         pOem += DOBI_CAPOFF;
    00612
    00613     GreBitBlt(hdc,
    00614               lprc->left,
    00615               lprc->top,
    00616               cxySlot,
    00617               cxySlot,
    00618               HDCBITS(),
    00619               pOem->x,
    00620               pOem->y,
    00621               SRCCOPY,
    00622               0);
    00623
    00624 Done:
    00625     /*
    00626      * Adjust the given rectangle for the icon we just drew
    00627      */
    00628     lprc->left += cxySlot;
    00629 }
    00630
    00631 /***************************************************************************\
    00632 * FillGradient
    00633 *
    00634 * The rectangle is broken into two triangles: {0, 1, 2} and {0, 2, 3}.
    00635 * Color on {0, 3} is black, and on {1, 2) is the active caption color.
    00636 *
    00637 * 0  1
    00638 * 3  2
    00639 *
    00640 * 12/06/96      vadimg      created
    00641 \***************************************************************************/
    00642
    00643 void FillGradient(HDC hdc, LPCRECT prc, COLORREF rgbLeft, COLORREF rgbRight)
    00644 {
    00645     TRIVERTEX avert[4];
    00646     static GRADIENT_RECT auRect[1] = {0,1};
    00647     #define GetCOLOR16(RGB, clr) ((COLOR16)(Get ## RGB ## Value(clr) << 8))
    00648
    00649     avert[0].Red = GetCOLOR16(R, rgbLeft);
    00650     avert[0].Green = GetCOLOR16(G, rgbLeft);
    00651     avert[0].Blue = GetCOLOR16(B, rgbLeft);
    00652
    00653     avert[1].Red = GetCOLOR16(R, rgbRight);
    00654     avert[1].Green = GetCOLOR16(G, rgbRight);
    00655     avert[1].Blue = GetCOLOR16(B, rgbRight);
    00656
    00657     avert[0].x = prc->left;
    00658     avert[0].y = prc->top;
    00659     avert[1].x = prc->right;
    00660     avert[1].y = prc->bottom;
    00661
    00662     GreGradientFill(hdc, avert, 2,(PVOID)auRect, 1, GRADIENT_FILL_RECT_H);
    00663 }
    00664
    00665 void FillCaptionGradient(HDC hdc, LPCRECT prc, BOOL fActive)
    00666 {
    00667     COLORREF rgbLeft, rgbRight;
    00668
    00669     if (fActive) {
    00670         rgbLeft = gpsi->argbSystem[COLOR_ACTIVECAPTION];
    00671         rgbRight = gpsi->argbSystem[COLOR_GRADIENTACTIVECAPTION];
    00672     } else {
    00673         rgbLeft = gpsi->argbSystem[COLOR_INACTIVECAPTION];
    00674         rgbRight = gpsi->argbSystem[COLOR_GRADIENTINACTIVECAPTION];
    00675     }
    00676     if (rgbLeft != rgbRight) {
    00677         FillGradient(hdc, prc, rgbLeft, rgbRight);
    00678     } else {
    00679         FillRect(hdc, prc, fActive ? SYSHBR(ACTIVECAPTION) : SYSHBR(INACTIVECAPTION));
    00680     }
    00681 }
    00682
    00683 /***************************************************************************\
    00684 * DrawCaptionTemp
    00685 *
    00686 \***************************************************************************/
    00687
    00688 BOOL xxxDrawCaptionTemp(
    00689     PWND            pwnd,  // pwnd may be NULL!
    00690     HDC             hdc,
    00691     LPRECT          lprc,
    00692     HFONT           hFont,
    00693     PCURSOR         pcursor,
    00694     PUNICODE_STRING pstrText,
    00695     UINT            flags)
    00696 {
    00697     int    iOldMode;
    00698     HBRUSH hbrFill;
    00699     LONG   clrOldText;
    00700     LONG   clrOldBk;
    00701     BOOL   fItFit = TRUE;
    00702     BOOL   fGradient = FALSE;
    00703     SIZE   size;
    00704     UINT   oldAlign;
    00705
    00706     CheckLock(pwnd);
    00707
    00708     if (lprc->right <= lprc->left)
    00709         return FALSE;
    00710
    00711     if (pwnd != NULL) {
    00712
    00713         if (!pcursor               &&
    00714             _HasCaptionIcon(pwnd)  &&
    00715             !(flags & DC_SMALLCAP) &&
    00716             TestWF(pwnd, WFSYSMENU)) {
    00717
    00718             /*
    00719              * Only get the icon if we can send messages AND the window has
    00720              * a system menu.
    00721              */
    00722             pcursor = xxxGetWindowSmIcon(pwnd, (flags & DC_NOSENDMSG));
    00723         }
    00724     }
    00725
    00726     /*
    00727      * Set up the colors
    00728      */
    00729     if (flags & DC_ACTIVE) {
    00730
    00731         if (flags & DC_INBUTTON) {
    00732             if (gpsi->BitCount < 8 ||
    00733                     SYSRGB(3DHILIGHT) != SYSRGB(SCROLLBAR) ||
    00734                     SYSRGB(3DHILIGHT) == SYSRGB(WINDOW)) {
    00735                 clrOldText = SYSRGB(3DFACE);
    00736                 clrOldBk   = SYSRGB(3DHILIGHT);
    00737                 hbrFill    = gpsi->hbrGray;
    00738                 iOldMode   = GreSetBkMode(hdc, TRANSPARENT);
    00739             } else {
    00740                 clrOldText = SYSRGB(BTNTEXT);
    00741                 clrOldBk   = SYSRGB(3DHILIGHT);
    00742                 hbrFill    = SYSHBR(3DHILIGHT);
    00743             }
    00744
    00745         } else {
    00746             clrOldText = SYSRGB(CAPTIONTEXT);
    00747             clrOldBk   = SYSRGB(ACTIVECAPTION);
    00748             hbrFill    = SYSHBR(ACTIVECAPTION);
    00749
    00750             if (flags & DC_GRADIENT) {
    00751                 fGradient = TRUE;
    00752                 iOldMode = GreSetBkMode(hdc, TRANSPARENT);
    00753             }
    00754         }
    00755
    00756     } else {
    00757
    00758         if (flags & DC_INBUTTON) {
    00759             clrOldText = SYSRGB(BTNTEXT);
    00760             clrOldBk   = SYSRGB(3DFACE);
    00761             hbrFill    = SYSHBR(3DFACE);
    00762         } else {
    00763             clrOldText = SYSRGB(INACTIVECAPTIONTEXT);
    00764             clrOldBk   = SYSRGB(INACTIVECAPTION);
    00765             hbrFill    = SYSHBR(INACTIVECAPTION);
    00766
    00767             if (flags & DC_GRADIENT) {
    00768                 fGradient = TRUE;
    00769                 iOldMode = GreSetBkMode(hdc, TRANSPARENT);
    00770             }
    00771         }
    00772     }
    00773
    00774
    00775     /*
    00776      * Set up drawing colors.
    00777      */
    00778     clrOldText = GreSetTextColor(hdc, clrOldText);
    00779     clrOldBk   = GreSetBkColor(hdc, clrOldBk);
    00780
    00781     if (pcursor && !(flags & DC_SMALLCAP)) {
    00782
    00783         if (flags & DC_ICON) {
    00784 #ifdef USE_MIRRORING
    00785             /*
    00786              * Preserve icon shape when BitBlitting it to a
    00787              * mirrored DC. This way we don't violate copyright
    00788              * issues on icons. [samera]
    00789              */
    00790             DWORD dwLayout=0L;
    00791             if ((dwLayout=GreGetLayout(hdc)) & LAYOUT_RTL)
    00792                 GreSetLayout(hdc, -1, dwLayout|LAYOUT_BITMAPORIENTATIONPRESERVED);
    00793 #endif
    00794             DrawCaptionIcon(hdc, lprc, pcursor, hbrFill, flags);
    00795
    00796 #ifdef USE_MIRRORING
    00797             /*
    00798              * Restore the DC to its previous layout state.
    00799              */
    00800             if (dwLayout & LAYOUT_RTL)
    00801                 GreSetLayout(hdc, -1, dwLayout);
    00802 #endif
    00803
    00804         } else {
    00805             lprc->left += lprc->bottom - lprc->top;
    00806         }
    00807     }
    00808
    00809     if (flags & DC_TEXT) {
    00810         int            cch;
    00811         HFONT          hfnOld;
    00812         int            yCentered;
    00813         WCHAR          szText[CCHTITLEMAX];
    00814         UNICODE_STRING strTmp;
    00815         PTHREADINFO ptiCurrent = PtiCurrentShared();
    00816
    00817         /*
    00818          * Note -- the DC_NOSENDMSG check is not in Chicago.  It needs to be,
    00819          * since GetWindowText calls back to the window.  FritzS
    00820          */
    00821
    00822         /*
    00823          *  Get the text for the caption.
    00824          */
    00825         if (pstrText == NULL) {
    00826
    00827             if ((pwnd == NULL) || (flags & DC_NOSENDMSG)) {
    00828
    00829                 if (pwnd && pwnd->strName.Length) {
    00830                     cch = TextCopy(&pwnd->strName, szText, CCHTITLEMAX - 1);
    00831                     strTmp.Length = (USHORT)(cch * sizeof(WCHAR));
    00832                 } else {
    00833                     szText[0] = TEXT('\0');
    00834                     cch = strTmp.Length = 0;
    00835                 }
    00836
    00837             } else {
    00838                 cch = xxxGetWindowText(pwnd, szText, CCHTITLEMAX - 1);
    00839                 strTmp.Length = (USHORT)(cch * sizeof(WCHAR));
    00840             }
    00841
    00842             /*
    00843              *  We don't use RtlInitUnicodeString() to initialize the string
    00844              *  because it does a wstrlen() on the string, which is a waste
    00845              *  since we already know its length.
    00846              */
    00847             strTmp.Buffer = szText;
    00848             strTmp.MaximumLength = strTmp.Length + sizeof(UNICODE_NULL);
    00849             pstrText = &strTmp;
    00850
    00851         } else {
    00852             cch = pstrText->Length / sizeof(WCHAR);
    00853             UserAssert(pstrText->Length < pstrText->MaximumLength);
    00854             UserAssert(pstrText->Buffer[cch] == 0);
    00855         }
    00856
    00857         /*
    00858          *  We need to set up font first, in case we're centering caption.
    00859          *  Fortunately, no text at all is uncommon...
    00860          */
    00861         if (hFont == NULL) {
    00862
    00863             if (flags & DC_SMALLCAP) {
    00864                 hFont = ghSmCaptionFont;
    00865                 yCentered = gcySmCaptionFontChar;
    00866             } else {
    00867                 hFont = gpsi->hCaptionFont;
    00868                 yCentered = gcyCaptionFontChar;
    00869             }
    00870
    00871             yCentered = (lprc->top + lprc->bottom - yCentered) / 2;
    00872
    00873             hfnOld = GreSelectFont(hdc, hFont);
    00874
    00875         } else {
    00876
    00877             TEXTMETRICW tm;
    00878
    00879             /*
    00880              * UNCOMMON case:  only for control panel
    00881              */
    00882             hfnOld = GreSelectFont(hdc, hFont);
    00883
    00884             if (!_GetTextMetricsW(hdc, &tm)) {
    00885                 RIPMSG0(RIP_WARNING, "xxxDrawCaptionTemp: _GetTextMetricsW Failed");
    00886                 tm.tmHeight = gpsi->tmSysFont.tmHeight;
    00887             }
    00888             yCentered = (lprc->top + lprc->bottom - tm.tmHeight) / 2;
    00889         }
    00890
    00891         /*
    00892          * Draw text
    00893          */
    00894         if (fGradient) {
    00895             FillCaptionGradient(hdc, lprc, flags & DC_ACTIVE);
    00896         } else {
    00897             FillRect(hdc, lprc, hbrFill);
    00898         }
    00899
    00900         if (hbrFill == gpsi->hbrGray) {
    00901             GreSetTextColor(hdc, SYSRGB(BTNTEXT));
    00902             GreSetBkColor(hdc, SYSRGB(GRAYTEXT));
    00903         }
    00904
    00905         /*
    00906          * GDI doesn't do callbacks to the LPK.  If an LPK is installed
    00907          * and we're not in thread cleanup mode, call the appropriate
    00908          * client side GDI routines.
    00909          */
    00910         if (CALL_LPK(ptiCurrent)) {
    00911             xxxClientGetTextExtentPointW(hdc, pstrText->Buffer, cch, &size);
    00912         } else {
    00913             GreGetTextExtentW(hdc, pstrText->Buffer, cch, &size, GGTE_WIN3_EXTENT);
    00914         }
    00915
    00916         if (pwnd && TestWF(pwnd, WEFRTLREADING)) {
    00917             oldAlign = GreSetTextAlign(hdc, TA_RTLREADING | GreGetTextAlign(hdc));
    00918         }
    00919         if (!(flags & DC_CENTER) && (!cch || (size.cx <= (lprc->right - lprc->left - SYSMET(CXEDGE))))) {
    00920             if (pwnd && TestWF(pwnd, WEFRIGHT)) {
    00921                 if (CALL_LPK(ptiCurrent)) {
    00922                     xxxClientExtTextOutW(hdc, lprc->right - (size.cx + SYSMET(CXEDGE)), yCentered,
    00923                         ETO_CLIPPED, lprc, pstrText->Buffer, cch, NULL);
    00924                 }
    00925                 else {
    00926                     GreExtTextOutW(hdc, lprc->right - (size.cx + SYSMET(CXEDGE)), yCentered,
    00927                        ETO_CLIPPED, lprc, pstrText->Buffer, cch, NULL);
    00928                 }
    00929             } else {
    00930                 if (CALL_LPK(ptiCurrent)) {
    00931                     xxxClientExtTextOutW(hdc, lprc->left + SYSMET(CXEDGE), yCentered,
    00932                         ETO_CLIPPED, lprc, pstrText->Buffer, cch, NULL);
    00933                 }
    00934                 else {
    00935                     GreExtTextOutW(hdc, lprc->left + SYSMET(CXEDGE), yCentered,
    00936                         ETO_CLIPPED, lprc, pstrText->Buffer, cch, NULL);
    00937                 }
    00938             }
    00939         } else {
    00940
    00941             DRAWTEXTPARAMS dtp;
    00942             UINT wSide;
    00943
    00944             dtp.cbSize       = sizeof(DRAWTEXTPARAMS);
    00945             dtp.iLeftMargin  = SYSMET(CXEDGE);
    00946             dtp.iRightMargin = 0;
    00947
    00948             wSide = (flags & DC_CENTER) ? DT_CENTER
    00949                                         : ((pwnd && TestWF(pwnd, WEFRIGHT)) ? DT_RIGHT : 0);
    00950
    00951             DrawTextEx(hdc,
    00952                        pstrText->Buffer,
    00953                        cch,
    00954                        lprc,
    00955                        DT_NOPREFIX | DT_END_ELLIPSIS | DT_SINGLELINE | DT_VCENTER |
    00956                        wSide, &dtp);
    00957
    00958             fItFit = FALSE;
    00959         }
    00960
    00961         if (pwnd && TestWF(pwnd, WEFRTLREADING))
    00962             GreSetTextAlign(hdc, oldAlign);
    00963
    00964         if (hfnOld)
    00965             GreSelectFont(hdc, hfnOld);
    00966     }
    00967
    00968     /*
    00969      * Restore colors
    00970      */
    00971     GreSetTextColor(hdc, clrOldText);
    00972     GreSetBkColor(hdc, clrOldBk);
    00973
    00974     if (hbrFill == gpsi->hbrGray)
    00975         GreSetBkMode(hdc, iOldMode);
    00976
    00977     return fItFit;
    00978 }
    00979
    00980 /***************************************************************************\
    00981 * xxxDrawCaptionBar
    00982 *
    00983 *
    00984 \***************************************************************************/
    00985
    00986 VOID xxxDrawCaptionBar(
    00987     PWND pwnd,
    00988     HDC  hdc,
    00989     UINT wFlags)
    00990 {
    00991     UINT   bm = OBI_CLOSE;
    00992     RECT   rcWindow;
    00993     HBRUSH hBrush = NULL;
    00994     HBRUSH hCapBrush;
    00995     int    colorBorder;
    00996     UINT   wBtns;
    00997     UINT   wCode;
    00998
    00999     CheckLock(pwnd);
    01000
    01001     /*
    01002      * If we're not currently showing on the screen, return.
    01003      * NOTE
    01004      * If you remove the IsVisible() check from DrawWindowFrame(), then
    01005      * be careful to remove the NC_NOVISIBLE flag too.  This is a smallish
    01006      * speed thing, so that we don't have to call IsVisible() twice on a
    01007      * window.  DrawWindowFrame() already checks.
    01008      */
    01009     if (!(wFlags & DC_NOVISIBLE) && !IsVisible(pwnd))
    01010         return;
    01011
    01012     /*
    01013      * Clear this flag so we know the frame has been drawn.
    01014      */
    01015     ClearHungFlag(pwnd, WFREDRAWFRAMEIFHUNG);
    01016
    01017     GetRect(pwnd, &rcWindow, GRECT_WINDOW | GRECT_WINDOWCOORDS);
    01018     if (TestALPHA(GRADIENTCAPTIONS)) {
    01019         hCapBrush = (wFlags & DC_ACTIVE) ? SYSHBR(GRADIENTACTIVECAPTION) : SYSHBR(GRADIENTINACTIVECAPTION);
    01020     } else {
    01021         hCapBrush = (wFlags & DC_ACTIVE) ? SYSHBR(ACTIVECAPTION) : SYSHBR(INACTIVECAPTION);
    01022     }
    01023
    01024     wCode = 0;
    01025
    01026     if (!xxxMNCanClose(pwnd))
    01027         wCode |= NOCLOSE;
    01028
    01029     if (!TestWF(pwnd, WFMAXBOX))
    01030         wCode |= NOMAX;
    01031     else if (TestWF(pwnd, WFMAXIMIZED))
    01032         wCode |= MAX;
    01033
    01034     if (!TestWF(pwnd, WFMINBOX))
    01035           wCode |= NOMIN;
    01036     else if(TestWF(pwnd, WFMINIMIZED))
    01037           wCode |= MIN;
    01038
    01039     if (TestWF(pwnd, WFMINIMIZED)) {
    01040
    01041         if (wFlags & DC_FRAME) {
    01042
    01043             /*
    01044              * Raised outer edge + border
    01045              */
    01046             DrawEdge(hdc, &rcWindow, EDGE_RAISED, (BF_RECT | BF_ADJUST));
    01047             DrawFrame(hdc, &rcWindow, 1, DF_3DFACE);
    01048             InflateRect(&rcWindow, -SYSMET(CXBORDER), -SYSMET(CYBORDER));
    01049
    01050         } else {
    01051             InflateRect(&rcWindow, -SYSMET(CXFIXEDFRAME), -SYSMET(CYFIXEDFRAME));
    01052         }
    01053
    01054         rcWindow.bottom = rcWindow.top + SYSMET(CYSIZE);
    01055
    01056         hBrush = GreSelectBrush(hdc, hCapBrush);
    01057
    01058     } else {
    01059         /*
    01060          * BOGUS
    01061          * What color should we draw borders in?  The check is NOT simple.
    01062          * At create time, we set the 3D bits.  NCCREATE will also
    01063          * set them for listboxes, edit fields,e tc.
    01064          */
    01065         colorBorder = (TestWF(pwnd, WEFEDGEMASK) && !TestWF(pwnd, WFOLDUI)) ? COLOR_3DFACE : COLOR_WINDOWFRAME;
    01066
    01067         /*
    01068          * Draw the window frame.
    01069          */
    01070         if (wFlags & DC_FRAME) {
    01071             /*
    01072              * Window edge
    01073              */
    01074             if (TestWF(pwnd, WEFWINDOWEDGE))
    01075                 DrawEdge(hdc, &rcWindow, EDGE_RAISED, BF_RECT | BF_ADJUST);
    01076             else if (TestWF(pwnd, WEFSTATICEDGE))
    01077                 DrawEdge(hdc, &rcWindow, BDR_SUNKENOUTER, BF_RECT | BF_ADJUST);
    01078
    01079             /*
    01080              * Size border
    01081              */
    01082             if (TestWF(pwnd, WFSIZEBOX)) {
    01083
    01084                 DrawFrame(hdc,
    01085                           &rcWindow,
    01086                           gpsi->gclBorder,
    01087                           ((wFlags & DC_ACTIVE) ? DF_ACTIVEBORDER : DF_INACTIVEBORDER));
    01088
    01089                 InflateRect(&rcWindow,
    01090                             -gpsi->gclBorder * SYSMET(CXBORDER),
    01091                             -gpsi->gclBorder * SYSMET(CYBORDER));
    01092             }
    01093
    01094             /*
    01095              * Normal border
    01096              */
    01097             if (TestWF(pwnd, WFBORDERMASK) || TestWF(pwnd, WEFDLGMODALFRAME)) {
    01098                 DrawFrame(hdc, &rcWindow, 1, (colorBorder << 3));
    01099                 InflateRect(&rcWindow, -SYSMET(CXBORDER), -SYSMET(CYBORDER));
    01100             }
    01101         } else {
    01102
    01103             int cBorders;
    01104
    01105             cBorders = GetWindowBorders(pwnd->style, pwnd->ExStyle, TRUE, FALSE);
    01106
    01107             InflateRect(&rcWindow,
    01108                         -cBorders * SYSMET(CXBORDER),
    01109                         -cBorders * SYSMET(CYBORDER));
    01110         }
    01111
    01112         /*
    01113          * Punt if the window doesn't have a caption currently showing on screen.
    01114          */
    01115         if (!TestWF(pwnd, WFCPRESENT))
    01116             return;
    01117
    01118         if (TestWF(pwnd, WEFTOOLWINDOW)) {
    01119             wCode |= SMCAP;
    01120             rcWindow.bottom = rcWindow.top + SYSMET(CYSMSIZE);
    01121             bm = OBI_CLOSE_PAL;
    01122         } else
    01123             rcWindow.bottom = rcWindow.top + SYSMET(CYSIZE);
    01124
    01125 #if 0
    01126         /* Draw the border beneath the caption.
    01127          *
    01128          *
    01129          * hBrush = GreSelectBrush(hdc, gpsi->ahbrSystem[colorBorder]);
    01130          *GrePatBlt(hdc, rcWindow.left, rcWindow.bottom,
    01131          *        rcWindow.right - rcWindow.left,
    01132          *        SYSMET(CYBORDER), PATCOPY);
    01133          */
    01134 #endif
    01135
    01136         {
    01137             POLYPATBLT PolyData;
    01138
    01139             PolyData.x         = rcWindow.left;
    01140             PolyData.y         = rcWindow.bottom;
    01141             PolyData.cx        = rcWindow.right - rcWindow.left;
    01142             PolyData.cy        = SYSMET(CYBORDER);
    01143             PolyData.BrClr.hbr = SYSHBRUSH(colorBorder);
    01144
    01145             GrePolyPatBlt(hdc,PATCOPY,&PolyData,1,PPB_BRUSH);
    01146         }
    01147
    01148         GreSelectBrush(hdc, hCapBrush);
    01149     }
    01150
    01151     if (!TestWF(pwnd, WFSYSMENU) && TestWF(pwnd, WFWIN40COMPAT))
    01152         goto JustDrawIt;
    01153
    01154     /*
    01155      * New Rules:
    01156      *  (1) The caption has a horz border beneath it separating it from the
    01157      *      menu or client.
    01158      *  (2) The caption text area has an edge of space on the left and right
    01159      *      before the characters.
    01160      *  (3) We account for the descent below the baseline of the caption char
    01161      */
    01162     wBtns = 1;
    01163
    01164     if (!(wFlags & DC_BUTTONS)) {
    01165
    01166         if ((!wCode) || (!(wCode & SMCAP) && ((wCode & NOSIZE) != NOSIZE))) {
    01167
    01168             wBtns += 2;
    01169
    01170         } else {
    01171
    01172             rcWindow.right -= SYSMET(CXEDGE);
    01173
    01174             if ((wCode == NOSIZE) && (wCode && TestWF(pwnd, WEFCONTEXTHELP)))
    01175                 wBtns++;
    01176         }
    01177
    01178         rcWindow.right -= wBtns * ((wCode & SMCAP) ? SYSMET(CXSMSIZE) : SYSMET(CXSIZE));
    01179
    01180         goto JustDrawIt;
    01181     }
    01182
    01183     if (!wCode || (wCode == NOSIZE)) {
    01184         POEMBITMAPINFO pOem = gpsi->oembmi + OBI_CAPBTNS;
    01185         int            cx;
    01186
    01187         cx = (wCode ? SYSMET(CXSIZE) + SYSMET(CXEDGE) : SYSMET(CXSIZE) * 3);
    01188
    01189         if (!(wFlags & DC_ACTIVE))
    01190             pOem += DOBI_CAPOFF;
    01191
    01192         rcWindow.right -= cx;
    01193
    01194         GreBitBlt(hdc,
    01195                   rcWindow.right,
    01196                   rcWindow.top,
    01197                   cx,
    01198                   pOem->cy,
    01199                   HDCBITS(),
    01200                   pOem->x + pOem->cx - SYSMET(CXSIZE) - cx,
    01201                   pOem->y,
    01202                   SRCCOPY,
    01203                   0);
    01204
    01205         if (wCode && TestWF(pwnd, WEFCONTEXTHELP)) {
    01206
    01207             rcWindow.right -= SYSMET(CXSIZE) - SYSMET(CXEDGE);
    01208
    01209             GreBitBlt(hdc,
    01210                       rcWindow.right,
    01211                       rcWindow.top,
    01212                       SYSMET(CXSIZE),
    01213                       pOem->cy,
    01214                       HDCBITS(),
    01215                       pOem->x + pOem->cx - SYSMET(CXSIZE),
    01216                       pOem->y,
    01217                       SRCCOPY,
    01218                       0);
    01219 #ifdef USE_MIRRORING
    01220             /*
    01221              * If the UI language is Hebrew we do not want to mirror the ? mark only
    01222              * Then redraw ? with out the button frame.
    01223              */
    01224             if (HEBREW_UI_LANGID() && TestWF(pwnd, WEFLAYOUTRTL)) {
    01225                 GreBitBlt(hdc,
    01226                           rcWindow.right-SYSMET(CXEDGE),
    01227                           rcWindow.top+2,
    01228                           SYSMET(CXSIZE)-SYSMET(CXEDGE)*2,
    01229                           pOem->cy-4,
    01230                           HDCBITS(),
    01231                           pOem->x + pOem->cx - SYSMET(CXSIZE) + SYSMET(CXEDGE),
    01232                           pOem->y + SYSMET(CXEDGE),
    01233                           SRCCOPY|NOMIRRORBITMAP,
    01234                           0);
    01235             }
    01236 #endif
    01237         }
    01238         goto JustDrawIt;
    01239     }
    01240
    01241     /*
    01242      * Draw the caption buttons
    01243      */
    01244     rcWindow.top    += SYSMET(CYEDGE);
    01245     rcWindow.bottom -= SYSMET(CYEDGE);
    01246
    01247     rcWindow.right -= SYSMET(CXEDGE);
    01248
    01249     GrePatBlt(hdc,
    01250               rcWindow.right,
    01251               rcWindow.top,
    01252               SYSMET(CXEDGE),
    01253               rcWindow.bottom - rcWindow.top,
    01254               PATCOPY);
    01255
    01256     if (wCode & NOCLOSE) {
    01257         bm += DOBI_INACTIVE;
    01258     }
    01259
    01260     rcWindow.right -= gpsi->oembmi[bm].cx;
    01261     BitBltSysBmp(hdc, rcWindow.right, rcWindow.top, bm);
    01262
    01263     if (!(wCode & SMCAP) && ((wCode & NOSIZE) != NOSIZE)) {
    01264
    01265         rcWindow.right -= SYSMET(CXEDGE);
    01266
    01267         GrePatBlt(hdc,
    01268                   rcWindow.right,
    01269                   rcWindow.top,
    01270                   SYSMET(CXEDGE),
    01271                   rcWindow.bottom - rcWindow.top,
    01272                   PATCOPY);
    01273
    01274         /*
    01275          * Max Box
    01276          * If window is maximized use the restore bitmap;
    01277          * otherwise use the regular zoom bitmap
    01278          */
    01279         bm = (wCode & MAX) ? OBI_RESTORE : ((wCode & NOMAX) ? OBI_ZOOM_I : OBI_ZOOM);
    01280         rcWindow.right -= gpsi->oembmi[bm].cx;
    01281         BitBltSysBmp(hdc, rcWindow.right, rcWindow.top, bm);
    01282
    01283         /*
    01284          * Min Box
    01285          */
    01286         bm = (wCode & MIN) ? OBI_RESTORE : ((wCode & NOMIN) ? OBI_REDUCE_I : OBI_REDUCE);
    01287         rcWindow.right -= gpsi->oembmi[bm].cx;
    01288         BitBltSysBmp(hdc, rcWindow.right, rcWindow.top, bm);
    01289         rcWindow.right -= SYSMET(CXEDGE);
    01290         GrePatBlt(hdc,
    01291                   rcWindow.right,
    01292                   rcWindow.top,
    01293                   SYSMET(CXEDGE),
    01294                   rcWindow.bottom - rcWindow.top,
    01295                   PATCOPY);
    01296
    01297         wBtns += 2;
    01298     }
    01299
    01300     if ((wCode & (NOCLOSE | NOSIZE)) &&
    01301         (!(wCode & SMCAP)) && TestWF(pwnd, WEFCONTEXTHELP)) {
    01302
    01303         rcWindow.right -= SYSMET(CXEDGE);
    01304
    01305         GrePatBlt(hdc,
    01306                   rcWindow.right,
    01307                   rcWindow.top,
    01308                   SYSMET(CXEDGE),
    01309                   rcWindow.bottom - rcWindow.top,
    01310                   PATCOPY);
    01311
    01312
    01313         bm = OBI_HELP;
    01314         rcWindow.right -= gpsi->oembmi[bm].cx;
    01315         BitBltSysBmp(hdc, rcWindow.right, rcWindow.top, bm);
    01316
    01317         wBtns++;
    01318     }
    01319
    01320     rcWindow.top    -= SYSMET(CYEDGE);
    01321     rcWindow.bottom += SYSMET(CYEDGE);
    01322
    01323     wBtns *= (wCode & SMCAP) ? SYSMET(CXSMSIZE) : SYSMET(CXSIZE);
    01324
    01325     {
    01326         POLYPATBLT PolyData[2];
    01327
    01328         PolyData[0].x         = rcWindow.right;
    01329         PolyData[0].y         = rcWindow.top;
    01330         PolyData[0].cx        = wBtns;
    01331         PolyData[0].cy        = SYSMET(CYEDGE);
    01332         PolyData[0].BrClr.hbr = NULL;
    01333
    01334         PolyData[1].x         = rcWindow.right;
    01335         PolyData[1].y         = rcWindow.bottom - SYSMET(CYEDGE);
    01336         PolyData[1].cx        = wBtns;
    01337         PolyData[1].cy        = SYSMET(CYEDGE);
    01338         PolyData[1].BrClr.hbr = NULL;
    01339
    01340         GrePolyPatBlt(hdc,PATCOPY,&PolyData[0],2,PPB_BRUSH);
    01341     }
    01342
    01343 #if 0
    01344     GrePatBlt(hdc, rcWindow.right, rcWindow.top, wBtns, SYSMET(CYEDGE), PATCOPY);
    01345     GrePatBlt(hdc, rcWindow.right, rcWindow.bottom - SYSMET(CYEDGE), wBtns, SYSMET(CYEDGE), PATCOPY);
    01346 #endif
    01347
    01348     /*
    01349      * We're going to release this DC--we don't need to bother reselecting
    01350      * in the old brush
    01351      */
    01352     if (hBrush)
    01353         GreSelectBrush(hdc, hBrush);
    01354
    01355 JustDrawIt:
    01356
    01357     /*
    01358      * Call DrawCaption only if we need to draw the icon or the text
    01359      * If the text gets truncated, set the window flag for
    01360      * the caption tooltip
    01361      */
    01362     if (wFlags & (DC_TEXT | DC_ICON)) {
    01363         if (!xxxDrawCaptionTemp(pwnd,
    01364                                hdc,
    01365                                &rcWindow,
    01366                                NULL,
    01367                                NULL,
    01368                                NULL,
    01369                                wFlags | ((wCode & SMCAP)  ? DC_SMALLCAP : 0) |
    01370                                (TestALPHA(GRADIENTCAPTIONS) ? DC_GRADIENT : 0))) {
    01371             SetWF(pwnd, WEFTRUNCATEDCAPTION);
    01372         } else {
    01373             ClrWF(pwnd, WEFTRUNCATEDCAPTION);
    01374         }
    01375     }
    01376 }