| /* | |
| * User Interface Functions | |
| * | |
| * Copyright 1997 Dimitrie O. Paun | |
| * Copyright 1997 Bertho A. Stultiens | |
| */ | |
| #include "windef.h" | |
| #include "wingdi.h" | |
| #include "wine/winuser16.h" | |
| #include "winuser.h" | |
| #include "user.h" | |
| #include "debugtools.h" | |
| DEFAULT_DEBUG_CHANNEL(graphics); | |
| static const WORD wPattern_AA55[8] = { 0xaaaa, 0x5555, 0xaaaa, 0x5555, | |
| 0xaaaa, 0x5555, 0xaaaa, 0x5555 }; | |
| /* These tables are used in: | |
| * UITOOLS_DrawDiagEdge() | |
| * UITOOLS_DrawRectEdge() | |
| */ | |
| static const signed char LTInnerNormal[] = { | |
| -1, -1, -1, -1, | |
| -1, COLOR_BTNHIGHLIGHT, COLOR_BTNHIGHLIGHT, -1, | |
| -1, COLOR_3DDKSHADOW, COLOR_3DDKSHADOW, -1, | |
| -1, -1, -1, -1 | |
| }; | |
| static const signed char LTOuterNormal[] = { | |
| -1, COLOR_3DLIGHT, COLOR_BTNSHADOW, -1, | |
| COLOR_BTNHIGHLIGHT, COLOR_BTNHIGHLIGHT,COLOR_BTNSHADOW, -1, | |
| COLOR_3DDKSHADOW, COLOR_3DLIGHT, COLOR_BTNSHADOW, -1, | |
| -1, COLOR_3DLIGHT, COLOR_BTNSHADOW, -1 | |
| }; | |
| static const signed char RBInnerNormal[] = { | |
| -1, -1, -1, -1, | |
| -1, COLOR_BTNSHADOW, COLOR_BTNSHADOW, -1, | |
| -1, COLOR_3DLIGHT, COLOR_3DLIGHT, -1, | |
| -1, -1, -1, -1 | |
| }; | |
| static const signed char RBOuterNormal[] = { | |
| -1, COLOR_3DDKSHADOW, COLOR_BTNHIGHLIGHT, -1, | |
| COLOR_BTNSHADOW, COLOR_3DDKSHADOW, COLOR_BTNHIGHLIGHT, -1, | |
| COLOR_3DLIGHT, COLOR_3DDKSHADOW, COLOR_BTNHIGHLIGHT, -1, | |
| -1, COLOR_3DDKSHADOW, COLOR_BTNHIGHLIGHT, -1 | |
| }; | |
| static const signed char LTInnerSoft[] = { | |
| -1, -1, -1, -1, | |
| -1, COLOR_3DLIGHT, COLOR_3DLIGHT, -1, | |
| -1, COLOR_BTNSHADOW, COLOR_BTNSHADOW, -1, | |
| -1, -1, -1, -1 | |
| }; | |
| static const signed char LTOuterSoft[] = { | |
| -1, COLOR_BTNHIGHLIGHT, COLOR_3DDKSHADOW, -1, | |
| COLOR_3DLIGHT, COLOR_BTNHIGHLIGHT, COLOR_3DDKSHADOW, -1, | |
| COLOR_BTNSHADOW, COLOR_BTNHIGHLIGHT, COLOR_3DDKSHADOW, -1, | |
| -1, COLOR_BTNHIGHLIGHT, COLOR_3DDKSHADOW, -1 | |
| }; | |
| #define RBInnerSoft RBInnerNormal /* These are the same */ | |
| #define RBOuterSoft RBOuterNormal | |
| static const signed char LTRBOuterMono[] = { | |
| -1, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, | |
| COLOR_WINDOW, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, | |
| COLOR_WINDOW, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, | |
| COLOR_WINDOW, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, | |
| }; | |
| static const signed char LTRBInnerMono[] = { | |
| -1, -1, -1, -1, | |
| -1, COLOR_WINDOW, COLOR_WINDOW, COLOR_WINDOW, | |
| -1, COLOR_WINDOW, COLOR_WINDOW, COLOR_WINDOW, | |
| -1, COLOR_WINDOW, COLOR_WINDOW, COLOR_WINDOW, | |
| }; | |
| static const signed char LTRBOuterFlat[] = { | |
| -1, COLOR_BTNSHADOW, COLOR_BTNSHADOW, COLOR_BTNSHADOW, | |
| COLOR_WINDOWFRAME, COLOR_BTNSHADOW, COLOR_BTNSHADOW, COLOR_BTNSHADOW, | |
| COLOR_WINDOWFRAME, COLOR_BTNSHADOW, COLOR_BTNSHADOW, COLOR_BTNSHADOW, | |
| COLOR_WINDOWFRAME, COLOR_BTNSHADOW, COLOR_BTNSHADOW, COLOR_BTNSHADOW, | |
| }; | |
| static const signed char LTRBInnerFlat[] = { | |
| -1, -1, -1, -1, | |
| -1, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, | |
| -1, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, | |
| -1, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, | |
| }; | |
| /*********************************************************************** | |
| * UITOOLS_DrawDiagEdge | |
| * | |
| * Same as DrawEdge invoked with BF_DIAGONAL | |
| * | |
| * 03-Dec-1997: Changed by Bertho Stultiens | |
| * | |
| * See also comments with UITOOLS_DrawRectEdge() | |
| */ | |
| static BOOL UITOOLS95_DrawDiagEdge(HDC hdc, LPRECT rc, | |
| UINT uType, UINT uFlags) | |
| { | |
| POINT Points[4]; | |
| signed char InnerI, OuterI; | |
| HPEN InnerPen, OuterPen; | |
| POINT SavePoint; | |
| HPEN SavePen; | |
| int spx, spy; | |
| int epx, epy; | |
| int Width = rc->right - rc->left; | |
| int Height= rc->bottom - rc->top; | |
| int SmallDiam = Width > Height ? Height : Width; | |
| BOOL retval = !( ((uType & BDR_INNER) == BDR_INNER | |
| || (uType & BDR_OUTER) == BDR_OUTER) | |
| && !(uFlags & (BF_FLAT|BF_MONO)) ); | |
| int add = (LTRBInnerMono[uType & (BDR_INNER|BDR_OUTER)] != -1 ? 1 : 0) | |
| + (LTRBOuterMono[uType & (BDR_INNER|BDR_OUTER)] != -1 ? 1 : 0); | |
| /* Init some vars */ | |
| OuterPen = InnerPen = (HPEN)GetStockObject(NULL_PEN); | |
| SavePen = (HPEN)SelectObject(hdc, InnerPen); | |
| spx = spy = epx = epy = 0; /* Satisfy the compiler... */ | |
| /* Determine the colors of the edges */ | |
| if(uFlags & BF_MONO) | |
| { | |
| InnerI = LTRBInnerMono[uType & (BDR_INNER|BDR_OUTER)]; | |
| OuterI = LTRBOuterMono[uType & (BDR_INNER|BDR_OUTER)]; | |
| } | |
| else if(uFlags & BF_FLAT) | |
| { | |
| InnerI = LTRBInnerFlat[uType & (BDR_INNER|BDR_OUTER)]; | |
| OuterI = LTRBOuterFlat[uType & (BDR_INNER|BDR_OUTER)]; | |
| } | |
| else if(uFlags & BF_SOFT) | |
| { | |
| if(uFlags & BF_BOTTOM) | |
| { | |
| InnerI = RBInnerSoft[uType & (BDR_INNER|BDR_OUTER)]; | |
| OuterI = RBOuterSoft[uType & (BDR_INNER|BDR_OUTER)]; | |
| } | |
| else | |
| { | |
| InnerI = LTInnerSoft[uType & (BDR_INNER|BDR_OUTER)]; | |
| OuterI = LTOuterSoft[uType & (BDR_INNER|BDR_OUTER)]; | |
| } | |
| } | |
| else | |
| { | |
| if(uFlags & BF_BOTTOM) | |
| { | |
| InnerI = RBInnerNormal[uType & (BDR_INNER|BDR_OUTER)]; | |
| OuterI = RBOuterNormal[uType & (BDR_INNER|BDR_OUTER)]; | |
| } | |
| else | |
| { | |
| InnerI = LTInnerNormal[uType & (BDR_INNER|BDR_OUTER)]; | |
| OuterI = LTOuterNormal[uType & (BDR_INNER|BDR_OUTER)]; | |
| } | |
| } | |
| if(InnerI != -1) InnerPen = GetSysColorPen(InnerI); | |
| if(OuterI != -1) OuterPen = GetSysColorPen(OuterI); | |
| MoveToEx(hdc, 0, 0, &SavePoint); | |
| /* Don't ask me why, but this is what is visible... */ | |
| /* This must be possible to do much simpler, but I fail to */ | |
| /* see the logic in the MS implementation (sigh...). */ | |
| /* So, this might look a bit brute force here (and it is), but */ | |
| /* it gets the job done;) */ | |
| switch(uFlags & BF_RECT) | |
| { | |
| case 0: | |
| case BF_LEFT: | |
| case BF_BOTTOM: | |
| case BF_BOTTOMLEFT: | |
| /* Left bottom endpoint */ | |
| epx = rc->left-1; | |
| spx = epx + SmallDiam; | |
| epy = rc->bottom; | |
| spy = epy - SmallDiam; | |
| break; | |
| case BF_TOPLEFT: | |
| case BF_BOTTOMRIGHT: | |
| /* Left top endpoint */ | |
| epx = rc->left-1; | |
| spx = epx + SmallDiam; | |
| epy = rc->top-1; | |
| spy = epy + SmallDiam; | |
| break; | |
| case BF_TOP: | |
| case BF_RIGHT: | |
| case BF_TOPRIGHT: | |
| case BF_RIGHT|BF_LEFT: | |
| case BF_RIGHT|BF_LEFT|BF_TOP: | |
| case BF_BOTTOM|BF_TOP: | |
| case BF_BOTTOM|BF_TOP|BF_LEFT: | |
| case BF_BOTTOMRIGHT|BF_LEFT: | |
| case BF_BOTTOMRIGHT|BF_TOP: | |
| case BF_RECT: | |
| /* Right top endpoint */ | |
| spx = rc->left; | |
| epx = spx + SmallDiam; | |
| spy = rc->bottom-1; | |
| epy = spy - SmallDiam; | |
| break; | |
| } | |
| MoveToEx(hdc, spx, spy, NULL); | |
| SelectObject(hdc, OuterPen); | |
| LineTo(hdc, epx, epy); | |
| SelectObject(hdc, InnerPen); | |
| switch(uFlags & (BF_RECT|BF_DIAGONAL)) | |
| { | |
| case BF_DIAGONAL_ENDBOTTOMLEFT: | |
| case (BF_DIAGONAL|BF_BOTTOM): | |
| case BF_DIAGONAL: | |
| case (BF_DIAGONAL|BF_LEFT): | |
| MoveToEx(hdc, spx-1, spy, NULL); | |
| LineTo(hdc, epx, epy-1); | |
| Points[0].x = spx-add; | |
| Points[0].y = spy; | |
| Points[1].x = rc->left; | |
| Points[1].y = rc->top; | |
| Points[2].x = epx+1; | |
| Points[2].y = epy-1-add; | |
| Points[3] = Points[2]; | |
| break; | |
| case BF_DIAGONAL_ENDBOTTOMRIGHT: | |
| MoveToEx(hdc, spx-1, spy, NULL); | |
| LineTo(hdc, epx, epy+1); | |
| Points[0].x = spx-add; | |
| Points[0].y = spy; | |
| Points[1].x = rc->left; | |
| Points[1].y = rc->bottom-1; | |
| Points[2].x = epx+1; | |
| Points[2].y = epy+1+add; | |
| Points[3] = Points[2]; | |
| break; | |
| case (BF_DIAGONAL|BF_BOTTOM|BF_RIGHT|BF_TOP): | |
| case (BF_DIAGONAL|BF_BOTTOM|BF_RIGHT|BF_TOP|BF_LEFT): | |
| case BF_DIAGONAL_ENDTOPRIGHT: | |
| case (BF_DIAGONAL|BF_RIGHT|BF_TOP|BF_LEFT): | |
| MoveToEx(hdc, spx+1, spy, NULL); | |
| LineTo(hdc, epx, epy+1); | |
| Points[0].x = epx-1; | |
| Points[0].y = epy+1+add; | |
| Points[1].x = rc->right-1; | |
| Points[1].y = rc->top+add; | |
| Points[2].x = rc->right-1; | |
| Points[2].y = rc->bottom-1; | |
| Points[3].x = spx+add; | |
| Points[3].y = spy; | |
| break; | |
| case BF_DIAGONAL_ENDTOPLEFT: | |
| MoveToEx(hdc, spx, spy-1, NULL); | |
| LineTo(hdc, epx+1, epy); | |
| Points[0].x = epx+1+add; | |
| Points[0].y = epy+1; | |
| Points[1].x = rc->right-1; | |
| Points[1].y = rc->top; | |
| Points[2].x = rc->right-1; | |
| Points[2].y = rc->bottom-1-add; | |
| Points[3].x = spx; | |
| Points[3].y = spy-add; | |
| break; | |
| case (BF_DIAGONAL|BF_TOP): | |
| case (BF_DIAGONAL|BF_BOTTOM|BF_TOP): | |
| case (BF_DIAGONAL|BF_BOTTOM|BF_TOP|BF_LEFT): | |
| MoveToEx(hdc, spx+1, spy-1, NULL); | |
| LineTo(hdc, epx, epy); | |
| Points[0].x = epx-1; | |
| Points[0].y = epy+1; | |
| Points[1].x = rc->right-1; | |
| Points[1].y = rc->top; | |
| Points[2].x = rc->right-1; | |
| Points[2].y = rc->bottom-1-add; | |
| Points[3].x = spx+add; | |
| Points[3].y = spy-add; | |
| break; | |
| case (BF_DIAGONAL|BF_RIGHT): | |
| case (BF_DIAGONAL|BF_RIGHT|BF_LEFT): | |
| case (BF_DIAGONAL|BF_RIGHT|BF_LEFT|BF_BOTTOM): | |
| MoveToEx(hdc, spx, spy, NULL); | |
| LineTo(hdc, epx-1, epy+1); | |
| Points[0].x = spx; | |
| Points[0].y = spy; | |
| Points[1].x = rc->left; | |
| Points[1].y = rc->top+add; | |
| Points[2].x = epx-1-add; | |
| Points[2].y = epy+1+add; | |
| Points[3] = Points[2]; | |
| break; | |
| } | |
| /* Fill the interior if asked */ | |
| if((uFlags & BF_MIDDLE) && retval) | |
| { | |
| HBRUSH hbsave; | |
| HBRUSH hb = GetSysColorBrush(uFlags & BF_MONO ? COLOR_WINDOW | |
| :COLOR_BTNFACE); | |
| HPEN hpsave; | |
| HPEN hp = GetSysColorPen(uFlags & BF_MONO ? COLOR_WINDOW | |
| : COLOR_BTNFACE); | |
| hbsave = (HBRUSH)SelectObject(hdc, hb); | |
| hpsave = (HPEN)SelectObject(hdc, hp); | |
| Polygon(hdc, Points, 4); | |
| SelectObject(hdc, hbsave); | |
| SelectObject(hdc, hpsave); | |
| } | |
| /* Adjust rectangle if asked */ | |
| if(uFlags & BF_ADJUST) | |
| { | |
| if(uFlags & BF_LEFT) rc->left += add; | |
| if(uFlags & BF_RIGHT) rc->right -= add; | |
| if(uFlags & BF_TOP) rc->top += add; | |
| if(uFlags & BF_BOTTOM) rc->bottom -= add; | |
| } | |
| /* Cleanup */ | |
| SelectObject(hdc, SavePen); | |
| MoveToEx(hdc, SavePoint.x, SavePoint.y, NULL); | |
| return retval; | |
| } | |
| /*********************************************************************** | |
| * UITOOLS_DrawRectEdge | |
| * | |
| * Same as DrawEdge invoked without BF_DIAGONAL | |
| * | |
| * 23-Nov-1997: Changed by Bertho Stultiens | |
| * | |
| * Well, I started testing this and found out that there are a few things | |
| * that weren't quite as win95. The following rewrite should reproduce | |
| * win95 results completely. | |
| * The colorselection is table-driven to avoid awfull if-statements. | |
| * The table below show the color settings. | |
| * | |
| * Pen selection table for uFlags = 0 | |
| * | |
| * uType | LTI | LTO | RBI | RBO | |
| * ------+-------+-------+-------+------- | |
| * 0000 | x | x | x | x | |
| * 0001 | x | 22 | x | 21 | |
| * 0010 | x | 16 | x | 20 | |
| * 0011 | x | x | x | x | |
| * ------+-------+-------+-------+------- | |
| * 0100 | x | 20 | x | 16 | |
| * 0101 | 20 | 22 | 16 | 21 | |
| * 0110 | 20 | 16 | 16 | 20 | |
| * 0111 | x | x | x | x | |
| * ------+-------+-------+-------+------- | |
| * 1000 | x | 21 | x | 22 | |
| * 1001 | 21 | 22 | 22 | 21 | |
| * 1010 | 21 | 16 | 22 | 20 | |
| * 1011 | x | x | x | x | |
| * ------+-------+-------+-------+------- | |
| * 1100 | x | x | x | x | |
| * 1101 | x | x (22)| x | x (21) | |
| * 1110 | x | x (16)| x | x (20) | |
| * 1111 | x | x | x | x | |
| * | |
| * Pen selection table for uFlags = BF_SOFT | |
| * | |
| * uType | LTI | LTO | RBI | RBO | |
| * ------+-------+-------+-------+------- | |
| * 0000 | x | x | x | x | |
| * 0001 | x | 20 | x | 21 | |
| * 0010 | x | 21 | x | 20 | |
| * 0011 | x | x | x | x | |
| * ------+-------+-------+-------+------- | |
| * 0100 | x | 22 | x | 16 | |
| * 0101 | 22 | 20 | 16 | 21 | |
| * 0110 | 22 | 21 | 16 | 20 | |
| * 0111 | x | x | x | x | |
| * ------+-------+-------+-------+------- | |
| * 1000 | x | 16 | x | 22 | |
| * 1001 | 16 | 20 | 22 | 21 | |
| * 1010 | 16 | 21 | 22 | 20 | |
| * 1011 | x | x | x | x | |
| * ------+-------+-------+-------+------- | |
| * 1100 | x | x | x | x | |
| * 1101 | x | x (20)| x | x (21) | |
| * 1110 | x | x (21)| x | x (20) | |
| * 1111 | x | x | x | x | |
| * | |
| * x = don't care; (n) = is what win95 actually uses | |
| * LTI = left Top Inner line | |
| * LTO = left Top Outer line | |
| * RBI = Right Bottom Inner line | |
| * RBO = Right Bottom Outer line | |
| * 15 = COLOR_BTNFACE | |
| * 16 = COLOR_BTNSHADOW | |
| * 20 = COLOR_BTNHIGHLIGHT | |
| * 21 = COLOR_3DDKSHADOW | |
| * 22 = COLOR_3DLIGHT | |
| */ | |
| static BOOL UITOOLS95_DrawRectEdge(HDC hdc, LPRECT rc, | |
| UINT uType, UINT uFlags) | |
| { | |
| signed char LTInnerI, LTOuterI; | |
| signed char RBInnerI, RBOuterI; | |
| HPEN LTInnerPen, LTOuterPen; | |
| HPEN RBInnerPen, RBOuterPen; | |
| RECT InnerRect = *rc; | |
| POINT SavePoint; | |
| HPEN SavePen; | |
| int LBpenplus = 0; | |
| int LTpenplus = 0; | |
| int RTpenplus = 0; | |
| int RBpenplus = 0; | |
| BOOL retval = !( ((uType & BDR_INNER) == BDR_INNER | |
| || (uType & BDR_OUTER) == BDR_OUTER) | |
| && !(uFlags & (BF_FLAT|BF_MONO)) ); | |
| /* Init some vars */ | |
| LTInnerPen = LTOuterPen = RBInnerPen = RBOuterPen = (HPEN)GetStockObject(NULL_PEN); | |
| SavePen = (HPEN)SelectObject(hdc, LTInnerPen); | |
| /* Determine the colors of the edges */ | |
| if(uFlags & BF_MONO) | |
| { | |
| LTInnerI = RBInnerI = LTRBInnerMono[uType & (BDR_INNER|BDR_OUTER)]; | |
| LTOuterI = RBOuterI = LTRBOuterMono[uType & (BDR_INNER|BDR_OUTER)]; | |
| } | |
| else if(uFlags & BF_FLAT) | |
| { | |
| LTInnerI = RBInnerI = LTRBInnerFlat[uType & (BDR_INNER|BDR_OUTER)]; | |
| LTOuterI = RBOuterI = LTRBOuterFlat[uType & (BDR_INNER|BDR_OUTER)]; | |
| /* Bertho Stultiens states above that this function exactly matches win95 | |
| * In win98 BF_FLAT rectangles have an inner border same color as the | |
| * middle (COLOR_BTNFACE). I believe it's the same for win95 but since | |
| * I don't know I go with Bertho and just sets it for win98 until proven | |
| * otherwise. | |
| * Dennis Björklund, 10 June, 99 | |
| */ | |
| if( TWEAK_WineLook == WIN98_LOOK && LTInnerI != -1 ) | |
| LTInnerI = RBInnerI = COLOR_BTNFACE; | |
| } | |
| else if(uFlags & BF_SOFT) | |
| { | |
| LTInnerI = LTInnerSoft[uType & (BDR_INNER|BDR_OUTER)]; | |
| LTOuterI = LTOuterSoft[uType & (BDR_INNER|BDR_OUTER)]; | |
| RBInnerI = RBInnerSoft[uType & (BDR_INNER|BDR_OUTER)]; | |
| RBOuterI = RBOuterSoft[uType & (BDR_INNER|BDR_OUTER)]; | |
| } | |
| else | |
| { | |
| LTInnerI = LTInnerNormal[uType & (BDR_INNER|BDR_OUTER)]; | |
| LTOuterI = LTOuterNormal[uType & (BDR_INNER|BDR_OUTER)]; | |
| RBInnerI = RBInnerNormal[uType & (BDR_INNER|BDR_OUTER)]; | |
| RBOuterI = RBOuterNormal[uType & (BDR_INNER|BDR_OUTER)]; | |
| } | |
| if((uFlags & BF_BOTTOMLEFT) == BF_BOTTOMLEFT) LBpenplus = 1; | |
| if((uFlags & BF_TOPRIGHT) == BF_TOPRIGHT) RTpenplus = 1; | |
| if((uFlags & BF_BOTTOMRIGHT) == BF_BOTTOMRIGHT) RBpenplus = 1; | |
| if((uFlags & BF_TOPLEFT) == BF_TOPLEFT) LTpenplus = 1; | |
| if(LTInnerI != -1) LTInnerPen = GetSysColorPen(LTInnerI); | |
| if(LTOuterI != -1) LTOuterPen = GetSysColorPen(LTOuterI); | |
| if(RBInnerI != -1) RBInnerPen = GetSysColorPen(RBInnerI); | |
| if(RBOuterI != -1) RBOuterPen = GetSysColorPen(RBOuterI); | |
| MoveToEx(hdc, 0, 0, &SavePoint); | |
| /* Draw the outer edge */ | |
| SelectObject(hdc, LTOuterPen); | |
| if(uFlags & BF_TOP) | |
| { | |
| MoveToEx(hdc, InnerRect.left, InnerRect.top, NULL); | |
| LineTo(hdc, InnerRect.right, InnerRect.top); | |
| } | |
| if(uFlags & BF_LEFT) | |
| { | |
| MoveToEx(hdc, InnerRect.left, InnerRect.top, NULL); | |
| LineTo(hdc, InnerRect.left, InnerRect.bottom); | |
| } | |
| SelectObject(hdc, RBOuterPen); | |
| if(uFlags & BF_BOTTOM) | |
| { | |
| MoveToEx(hdc, InnerRect.right-1, InnerRect.bottom-1, NULL); | |
| LineTo(hdc, InnerRect.left-1, InnerRect.bottom-1); | |
| } | |
| if(uFlags & BF_RIGHT) | |
| { | |
| MoveToEx(hdc, InnerRect.right-1, InnerRect.bottom-1, NULL); | |
| LineTo(hdc, InnerRect.right-1, InnerRect.top-1); | |
| } | |
| /* Draw the inner edge */ | |
| SelectObject(hdc, LTInnerPen); | |
| if(uFlags & BF_TOP) | |
| { | |
| MoveToEx(hdc, InnerRect.left+LTpenplus, InnerRect.top+1, NULL); | |
| LineTo(hdc, InnerRect.right-RTpenplus, InnerRect.top+1); | |
| } | |
| if(uFlags & BF_LEFT) | |
| { | |
| MoveToEx(hdc, InnerRect.left+1, InnerRect.top+LTpenplus, NULL); | |
| LineTo(hdc, InnerRect.left+1, InnerRect.bottom-LBpenplus); | |
| } | |
| SelectObject(hdc, RBInnerPen); | |
| if(uFlags & BF_BOTTOM) | |
| { | |
| MoveToEx(hdc, InnerRect.right-1-RBpenplus, InnerRect.bottom-2, NULL); | |
| LineTo(hdc, InnerRect.left-1+LBpenplus, InnerRect.bottom-2); | |
| } | |
| if(uFlags & BF_RIGHT) | |
| { | |
| MoveToEx(hdc, InnerRect.right-2, InnerRect.bottom-1-RBpenplus, NULL); | |
| LineTo(hdc, InnerRect.right-2, InnerRect.top-1+RTpenplus); | |
| } | |
| if( ((uFlags & BF_MIDDLE) && retval) || (uFlags & BF_ADJUST) ) | |
| { | |
| int add = (LTRBInnerMono[uType & (BDR_INNER|BDR_OUTER)] != -1 ? 1 : 0) | |
| + (LTRBOuterMono[uType & (BDR_INNER|BDR_OUTER)] != -1 ? 1 : 0); | |
| if(uFlags & BF_LEFT) InnerRect.left += add; | |
| if(uFlags & BF_RIGHT) InnerRect.right -= add; | |
| if(uFlags & BF_TOP) InnerRect.top += add; | |
| if(uFlags & BF_BOTTOM) InnerRect.bottom -= add; | |
| if((uFlags & BF_MIDDLE) && retval) | |
| { | |
| FillRect(hdc, &InnerRect, GetSysColorBrush(uFlags & BF_MONO ? | |
| COLOR_WINDOW : COLOR_BTNFACE)); | |
| } | |
| if(uFlags & BF_ADJUST) | |
| *rc = InnerRect; | |
| } | |
| /* Cleanup */ | |
| SelectObject(hdc, SavePen); | |
| MoveToEx(hdc, SavePoint.x, SavePoint.y, NULL); | |
| return retval; | |
| } | |
| /********************************************************************** | |
| * DrawEdge (USER.659) | |
| */ | |
| BOOL16 WINAPI DrawEdge16( HDC16 hdc, LPRECT16 rc, UINT16 edge, UINT16 flags ) | |
| { | |
| RECT rect32; | |
| BOOL ret; | |
| CONV_RECT16TO32( rc, &rect32 ); | |
| ret = DrawEdge( hdc, &rect32, edge, flags ); | |
| CONV_RECT32TO16( &rect32, rc ); | |
| return ret; | |
| } | |
| /********************************************************************** | |
| * DrawEdge (USER32.@) | |
| */ | |
| BOOL WINAPI DrawEdge( HDC hdc, LPRECT rc, UINT edge, UINT flags ) | |
| { | |
| TRACE("%04x %d,%d-%d,%d %04x %04x\n", | |
| hdc, rc->left, rc->top, rc->right, rc->bottom, edge, flags ); | |
| if(flags & BF_DIAGONAL) | |
| return UITOOLS95_DrawDiagEdge(hdc, rc, edge, flags); | |
| else | |
| return UITOOLS95_DrawRectEdge(hdc, rc, edge, flags); | |
| } | |
| /************************************************************************ | |
| * UITOOLS_MakeSquareRect | |
| * | |
| * Utility to create a square rectangle and returning the width | |
| */ | |
| static int UITOOLS_MakeSquareRect(LPRECT src, LPRECT dst) | |
| { | |
| int Width = src->right - src->left; | |
| int Height = src->bottom - src->top; | |
| int SmallDiam = Width > Height ? Height : Width; | |
| *dst = *src; | |
| /* Make it a square box */ | |
| if(Width < Height) /* SmallDiam == Width */ | |
| { | |
| dst->top += (Height-Width)/2; | |
| dst->bottom = dst->top + SmallDiam; | |
| } | |
| else if(Width > Height) /* SmallDiam == Height */ | |
| { | |
| dst->left += (Width-Height)/2; | |
| dst->right = dst->left + SmallDiam; | |
| } | |
| return SmallDiam; | |
| } | |
| static void UITOOLS_DrawCheckedRect( HDC dc, LPRECT rect ) | |
| { | |
| if(GetSysColor(COLOR_BTNHIGHLIGHT) == RGB(255, 255, 255)) | |
| { | |
| HBITMAP hbm = CreateBitmap(8, 8, 1, 1, wPattern_AA55); | |
| HBRUSH hbsave; | |
| HBRUSH hb = CreatePatternBrush(hbm); | |
| COLORREF bg; | |
| FillRect(dc, rect, GetSysColorBrush(COLOR_BTNFACE)); | |
| bg = SetBkColor(dc, RGB(255, 255, 255)); | |
| hbsave = (HBRUSH)SelectObject(dc, hb); | |
| PatBlt(dc, rect->left, rect->top, rect->right-rect->left, rect->bottom-rect->top, 0x00FA0089); | |
| SelectObject(dc, hbsave); | |
| SetBkColor(dc, bg); | |
| DeleteObject(hb); | |
| DeleteObject(hbm); | |
| } | |
| else | |
| { | |
| FillRect(dc, rect, GetSysColorBrush(COLOR_BTNHIGHLIGHT)); | |
| } | |
| } | |
| /************************************************************************ | |
| * UITOOLS_DFC_ButtonPush | |
| * | |
| * Draw a push button coming from DrawFrameControl() | |
| * | |
| * Does a pretty good job in emulating MS behavior. Some quirks are | |
| * however there because MS uses a TrueType font (Marlett) to draw | |
| * the buttons. | |
| */ | |
| static BOOL UITOOLS95_DFC_ButtonPush(HDC dc, LPRECT r, UINT uFlags) | |
| { | |
| UINT edge; | |
| RECT myr = *r; | |
| if(uFlags & (DFCS_PUSHED | DFCS_CHECKED | DFCS_FLAT)) | |
| edge = EDGE_SUNKEN; | |
| else | |
| edge = EDGE_RAISED; | |
| if(uFlags & DFCS_CHECKED) | |
| { | |
| if(uFlags & DFCS_MONO) | |
| UITOOLS95_DrawRectEdge(dc, &myr, edge, BF_MONO|BF_RECT|BF_ADJUST); | |
| else | |
| UITOOLS95_DrawRectEdge(dc, &myr, edge, (uFlags&DFCS_FLAT)|BF_RECT|BF_SOFT|BF_ADJUST); | |
| UITOOLS_DrawCheckedRect( dc, &myr ); | |
| } | |
| else | |
| { | |
| if(uFlags & DFCS_MONO) | |
| { | |
| UITOOLS95_DrawRectEdge(dc, &myr, edge, BF_MONO|BF_RECT|BF_ADJUST); | |
| FillRect(dc, &myr, GetSysColorBrush(COLOR_BTNFACE)); | |
| } | |
| else | |
| { | |
| UITOOLS95_DrawRectEdge(dc, r, edge, (uFlags&DFCS_FLAT) | BF_MIDDLE | BF_RECT); | |
| } | |
| } | |
| /* Adjust rectangle if asked */ | |
| if(uFlags & DFCS_ADJUSTRECT) | |
| { | |
| r->left += 2; | |
| r->right -= 2; | |
| r->top += 2; | |
| r->bottom -= 2; | |
| } | |
| return TRUE; | |
| } | |
| /************************************************************************ | |
| * UITOOLS_DFC_ButtonChcek | |
| * | |
| * Draw a check/3state button coming from DrawFrameControl() | |
| * | |
| * Does a pretty good job in emulating MS behavior. Some quirks are | |
| * however there because MS uses a TrueType font (Marlett) to draw | |
| * the buttons. | |
| */ | |
| static BOOL UITOOLS95_DFC_ButtonCheck(HDC dc, LPRECT r, UINT uFlags) | |
| { | |
| RECT myr, bar; | |
| UINT flags = BF_RECT | BF_ADJUST; | |
| UITOOLS_MakeSquareRect(r, &myr); | |
| if(uFlags & DFCS_FLAT) flags |= BF_FLAT; | |
| else if(uFlags & DFCS_MONO) flags |= BF_MONO; | |
| UITOOLS95_DrawRectEdge( dc, &myr, EDGE_SUNKEN, flags ); | |
| if(uFlags & (DFCS_INACTIVE|DFCS_PUSHED)) | |
| FillRect(dc, &myr, GetSysColorBrush(COLOR_BTNFACE)); | |
| else if( (uFlags & DFCS_BUTTON3STATE) && (uFlags & DFCS_CHECKED) ) | |
| UITOOLS_DrawCheckedRect( dc, &myr ); | |
| else | |
| { | |
| FillRect(dc, &myr, GetSysColorBrush(COLOR_WINDOW)); | |
| } | |
| if(uFlags & DFCS_CHECKED) | |
| { | |
| int i, k; | |
| i = (uFlags & DFCS_INACTIVE) || (uFlags & 0xff) == DFCS_BUTTON3STATE ? | |
| COLOR_BTNSHADOW : COLOR_WINDOWTEXT; | |
| /* draw 7 bars, with h=3w to form the check */ | |
| bar.left = myr.left; | |
| bar.top = myr.top + 2; | |
| for (k = 0; k < 7; k++) { | |
| bar.left = bar.left + 1; | |
| bar.top = (k < 3) ? bar.top + 1 : bar.top - 1; | |
| bar.bottom = bar.top + 3; | |
| bar.right = bar.left + 1; | |
| FillRect(dc, &bar, GetSysColorBrush(i)); | |
| } | |
| } | |
| return TRUE; | |
| } | |
| /************************************************************************ | |
| * UITOOLS_DFC_ButtonRadio | |
| * | |
| * Draw a radio/radioimage/radiomask button coming from DrawFrameControl() | |
| * | |
| * Does a pretty good job in emulating MS behavior. Some quirks are | |
| * however there because MS uses a TrueType font (Marlett) to draw | |
| * the buttons. | |
| */ | |
| static BOOL UITOOLS95_DFC_ButtonRadio(HDC dc, LPRECT r, UINT uFlags) | |
| { | |
| RECT myr; | |
| int i; | |
| int SmallDiam = UITOOLS_MakeSquareRect(r, &myr); | |
| int BorderShrink = SmallDiam / 16; | |
| HPEN hpsave; | |
| HBRUSH hbsave; | |
| int xc, yc; | |
| if(BorderShrink < 1) BorderShrink = 1; | |
| if((uFlags & 0xff) == DFCS_BUTTONRADIOIMAGE) | |
| { | |
| FillRect(dc, r, (HBRUSH)GetStockObject(BLACK_BRUSH)); | |
| } | |
| xc = myr.left + SmallDiam - SmallDiam/2; | |
| yc = myr.top + SmallDiam - SmallDiam/2; | |
| /* Define bounding box */ | |
| i = 14*SmallDiam/16; | |
| myr.left = xc - i+i/2; | |
| myr.right = xc + i/2; | |
| myr.top = yc - i+i/2; | |
| myr.bottom = yc + i/2; | |
| if((uFlags & 0xff) == DFCS_BUTTONRADIOMASK) | |
| { | |
| hbsave = (HBRUSH)SelectObject(dc, GetStockObject(BLACK_BRUSH)); | |
| Ellipse(dc, myr.left, myr.top, myr.right, myr.bottom); | |
| SelectObject(dc, hbsave); | |
| } | |
| else | |
| { | |
| if(uFlags & (DFCS_FLAT|DFCS_MONO)) | |
| { | |
| hpsave = (HPEN)SelectObject(dc, GetSysColorPen(COLOR_WINDOWFRAME)); | |
| hbsave = (HBRUSH)SelectObject(dc, GetSysColorBrush(COLOR_WINDOWFRAME)); | |
| Ellipse(dc, myr.left, myr.top, myr.right, myr.bottom); | |
| SelectObject(dc, hbsave); | |
| SelectObject(dc, hpsave); | |
| } | |
| else | |
| { | |
| hpsave = (HPEN)SelectObject(dc, GetSysColorPen(COLOR_BTNHIGHLIGHT)); | |
| hbsave = (HBRUSH)SelectObject(dc, GetSysColorBrush(COLOR_BTNHIGHLIGHT)); | |
| Pie(dc, myr.left, myr.top, myr.right+1, myr.bottom+1, myr.left-1, myr.bottom, myr.right+1, myr.top); | |
| SelectObject(dc, GetSysColorPen(COLOR_BTNSHADOW)); | |
| SelectObject(dc, GetSysColorBrush(COLOR_BTNSHADOW)); | |
| Pie(dc, myr.left, myr.top, myr.right+1, myr.bottom+1, myr.right+1, myr.top, myr.left-1, myr.bottom); | |
| myr.left += BorderShrink; | |
| myr.right -= BorderShrink; | |
| myr.top += BorderShrink; | |
| myr.bottom -= BorderShrink; | |
| SelectObject(dc, GetSysColorPen(COLOR_3DLIGHT)); | |
| SelectObject(dc, GetSysColorBrush(COLOR_3DLIGHT)); | |
| Pie(dc, myr.left, myr.top, myr.right+1, myr.bottom+1, myr.left-1, myr.bottom, myr.right+1, myr.top); | |
| SelectObject(dc, GetSysColorPen(COLOR_3DDKSHADOW)); | |
| SelectObject(dc, GetSysColorBrush(COLOR_3DDKSHADOW)); | |
| Pie(dc, myr.left, myr.top, myr.right+1, myr.bottom+1, myr.right+1, myr.top, myr.left-1, myr.bottom); | |
| SelectObject(dc, hbsave); | |
| SelectObject(dc, hpsave); | |
| } | |
| i = 10*SmallDiam/16; | |
| myr.left = xc - i+i/2; | |
| myr.right = xc + i/2; | |
| myr.top = yc - i+i/2; | |
| myr.bottom = yc + i/2; | |
| i= !(uFlags & (DFCS_INACTIVE|DFCS_PUSHED)) ? COLOR_WINDOW : COLOR_BTNFACE; | |
| hpsave = (HPEN)SelectObject(dc, GetSysColorPen(i)); | |
| hbsave = (HBRUSH)SelectObject(dc, GetSysColorBrush(i)); | |
| Ellipse(dc, myr.left, myr.top, myr.right, myr.bottom); | |
| SelectObject(dc, hbsave); | |
| SelectObject(dc, hpsave); | |
| } | |
| if(uFlags & DFCS_CHECKED) | |
| { | |
| i = 6*SmallDiam/16; | |
| i = i < 1 ? 1 : i; | |
| myr.left = xc - i+i/2; | |
| myr.right = xc + i/2; | |
| myr.top = yc - i+i/2; | |
| myr.bottom = yc + i/2; | |
| i = uFlags & DFCS_INACTIVE ? COLOR_BTNSHADOW : COLOR_WINDOWTEXT; | |
| hbsave = (HBRUSH)SelectObject(dc, GetSysColorBrush(i)); | |
| hpsave = (HPEN)SelectObject(dc, GetSysColorPen(i)); | |
| Ellipse(dc, myr.left, myr.top, myr.right, myr.bottom); | |
| SelectObject(dc, hpsave); | |
| SelectObject(dc, hbsave); | |
| } | |
| /* FIXME: M$ has a polygon in the center at relative points: */ | |
| /* 0.476, 0.476 (times SmallDiam, SmallDiam) */ | |
| /* 0.476, 0.525 */ | |
| /* 0.500, 0.500 */ | |
| /* 0.500, 0.499 */ | |
| /* when the button is unchecked. The reason for it is unknown. The */ | |
| /* color is COLOR_BTNHIGHLIGHT, although the polygon gets painted at */ | |
| /* least 3 times (it looks like a clip-region when you see it happen). */ | |
| /* I do not really see a reason why this should be implemented. If you */ | |
| /* have a good reason, let me know. Maybe this is a quirk in the Marlett */ | |
| /* font. */ | |
| return TRUE; | |
| } | |
| /*********************************************************************** | |
| * UITOOLS_DrawFrameButton | |
| */ | |
| static BOOL UITOOLS95_DrawFrameButton(HDC hdc, LPRECT rc, UINT uState) | |
| { | |
| switch(uState & 0xff) | |
| { | |
| case DFCS_BUTTONPUSH: | |
| return UITOOLS95_DFC_ButtonPush(hdc, rc, uState); | |
| case DFCS_BUTTONCHECK: | |
| case DFCS_BUTTON3STATE: | |
| return UITOOLS95_DFC_ButtonCheck(hdc, rc, uState); | |
| case DFCS_BUTTONRADIOIMAGE: | |
| case DFCS_BUTTONRADIOMASK: | |
| case DFCS_BUTTONRADIO: | |
| return UITOOLS95_DFC_ButtonRadio(hdc, rc, uState); | |
| default: | |
| WARN("Invalid button state=0x%04x\n", uState); | |
| } | |
| return FALSE; | |
| } | |
| /*********************************************************************** | |
| * UITOOLS_DrawFrameCaption | |
| * | |
| * Draw caption buttons (win95), coming from DrawFrameControl() | |
| */ | |
| static BOOL UITOOLS95_DrawFrameCaption(HDC dc, LPRECT r, UINT uFlags) | |
| { | |
| POINT Line1[10]; | |
| POINT Line2[10]; | |
| int Line1N; | |
| int Line2N; | |
| RECT myr; | |
| int SmallDiam = UITOOLS_MakeSquareRect(r, &myr)-2; | |
| int i; | |
| HBRUSH hbsave; | |
| HPEN hpsave; | |
| HFONT hfsave, hf; | |
| int colorIdx = uFlags & DFCS_INACTIVE ? COLOR_BTNSHADOW : COLOR_BTNTEXT; | |
| int xc = (myr.left+myr.right)/2; | |
| int yc = (myr.top+myr.bottom)/2; | |
| int edge, move; | |
| char str[2] = "?"; | |
| UINT alignsave; | |
| int bksave; | |
| COLORREF clrsave; | |
| SIZE size; | |
| UITOOLS95_DFC_ButtonPush(dc, r, uFlags & 0xff00); | |
| switch(uFlags & 0xff) | |
| { | |
| case DFCS_CAPTIONCLOSE: | |
| { | |
| /* The "X" is made by drawing a series of lines. | |
| * The number of lines drawn depends on the size | |
| * of the bounding rect. e.g. For a 6x5 inside rect, | |
| * two lines are drawn from top-left to bottom-right, | |
| * and two lines from top-right to bottom-left. | |
| * | |
| * 0 1 2 3 4 5 0 1 2 3 4 5 | |
| * 1 * * * * | |
| * 2 * * * * | |
| * 3 * * * * | |
| * 4 * * * * | |
| * | |
| * Drawing one line for every 6 pixels in width | |
| * seems to provide the best proportions. | |
| */ | |
| POINT start, oldPos; | |
| INT width = myr.right - myr.left - 5; | |
| INT height = myr.bottom - myr.top - 6; | |
| INT numLines = (width / 6) + 1; | |
| hpsave = (HPEN)SelectObject(dc, GetSysColorPen(colorIdx)); | |
| start.x = myr.left + 2; | |
| start.y = myr.top + 2; | |
| if (width < 6) | |
| height = width; | |
| else | |
| start.y++; | |
| if (uFlags & DFCS_PUSHED) | |
| { | |
| start.x++; | |
| start.y++; | |
| } | |
| /* now use the width of each line */ | |
| width -= numLines - 1; | |
| for (i = 0; i < numLines; i++) | |
| { | |
| MoveToEx(dc, start.x + i, start.y, &oldPos); | |
| LineTo(dc, start.x + i + width, start.y + height); | |
| MoveToEx(dc, start.x + i, start.y + height - 1, &oldPos); | |
| LineTo(dc, start.x + i + width, start.y - 1); | |
| } | |
| SelectObject(dc, hpsave); | |
| return TRUE; | |
| } | |
| case DFCS_CAPTIONHELP: | |
| /* This one breaks the flow */ | |
| /* FIXME: We need the Marlett font in order to get this right. */ | |
| hf = CreateFontA(-SmallDiam, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, | |
| ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, | |
| DEFAULT_QUALITY, FIXED_PITCH|FF_DONTCARE, "System"); | |
| alignsave = SetTextAlign(dc, TA_TOP|TA_LEFT); | |
| bksave = SetBkMode(dc, TRANSPARENT); | |
| clrsave = GetTextColor(dc); | |
| hfsave = (HFONT)SelectObject(dc, hf); | |
| GetTextExtentPoint32A(dc, str, 1, &size); | |
| if(uFlags & DFCS_INACTIVE) | |
| { | |
| SetTextColor(dc, GetSysColor(COLOR_BTNHIGHLIGHT)); | |
| TextOutA(dc, xc-size.cx/2+1, yc-size.cy/2+1, str, 1); | |
| } | |
| SetTextColor(dc, GetSysColor(colorIdx)); | |
| TextOutA(dc, xc-size.cx/2, yc-size.cy/2, str, 1); | |
| SelectObject(dc, hfsave); | |
| SetTextColor(dc, clrsave); | |
| SetBkMode(dc, bksave); | |
| SetTextAlign(dc, alignsave); | |
| DeleteObject(hf); | |
| return TRUE; | |
| case DFCS_CAPTIONMIN: | |
| Line1[0].x = Line1[3].x = myr.left + 96*SmallDiam/750+2; | |
| Line1[1].x = Line1[2].x = Line1[0].x + 372*SmallDiam/750; | |
| Line1[0].y = Line1[1].y = myr.top + 563*SmallDiam/750+1; | |
| Line1[2].y = Line1[3].y = Line1[0].y + 92*SmallDiam/750; | |
| Line1N = 4; | |
| Line2N = 0; | |
| break; | |
| case DFCS_CAPTIONMAX: | |
| edge = 47*SmallDiam/750; | |
| Line1[0].x = Line1[5].x = myr.left + 57*SmallDiam/750+3; | |
| Line1[0].y = Line1[1].y = myr.top + 143*SmallDiam/750+1; | |
| Line1[1].x = Line1[2].x = Line1[0].x + 562*SmallDiam/750; | |
| Line1[5].y = Line1[4].y = Line1[0].y + 93*SmallDiam/750; | |
| Line1[2].y = Line1[3].y = Line1[0].y + 513*SmallDiam/750; | |
| Line1[3].x = Line1[4].x = Line1[1].x - edge; | |
| Line2[0].x = Line2[5].x = Line1[0].x; | |
| Line2[3].x = Line2[4].x = Line1[1].x; | |
| Line2[1].x = Line2[2].x = Line1[0].x + edge; | |
| Line2[0].y = Line2[1].y = Line1[0].y; | |
| Line2[4].y = Line2[5].y = Line1[2].y; | |
| Line2[2].y = Line2[3].y = Line1[2].y - edge; | |
| Line1N = 6; | |
| Line2N = 6; | |
| break; | |
| case DFCS_CAPTIONRESTORE: | |
| /* FIXME: this one looks bad at small sizes < 15x15 :( */ | |
| edge = 47*SmallDiam/750; | |
| move = 420*SmallDiam/750; | |
| Line1[0].x = Line1[9].x = myr.left + 198*SmallDiam/750+2; | |
| Line1[0].y = Line1[1].y = myr.top + 169*SmallDiam/750+1; | |
| Line1[6].y = Line1[7].y = Line1[0].y + 93*SmallDiam/750; | |
| Line1[7].x = Line1[8].x = Line1[0].x + edge; | |
| Line1[1].x = Line1[2].x = Line1[0].x + move; | |
| Line1[5].x = Line1[6].x = Line1[1].x - edge; | |
| Line1[9].y = Line1[8].y = Line1[0].y + 187*SmallDiam/750; | |
| Line1[2].y = Line1[3].y = Line1[0].y + 327*SmallDiam/750; | |
| Line1[4].y = Line1[5].y = Line1[2].y - edge; | |
| Line1[3].x = Line1[4].x = Line1[2].x - 140*SmallDiam/750; | |
| Line2[1].x = Line2[2].x = Line1[3].x; | |
| Line2[7].x = Line2[8].x = Line2[1].x - edge; | |
| Line2[0].x = Line2[9].x = Line2[3].x = Line2[4].x = Line2[1].x - move; | |
| Line2[5].x = Line2[6].x = Line2[0].x + edge; | |
| Line2[0].y = Line2[1].y = Line1[9].y; | |
| Line2[4].y = Line2[5].y = Line2[8].y = Line2[9].y = Line2[0].y + 93*SmallDiam/750; | |
| Line2[2].y = Line2[3].y = Line2[0].y + 327*SmallDiam/750; | |
| Line2[6].y = Line2[7].y = Line2[2].y - edge; | |
| Line1N = 10; | |
| Line2N = 10; | |
| break; | |
| default: | |
| WARN("Invalid caption; flags=0x%04x\n", uFlags); | |
| return FALSE; | |
| } | |
| /* Here the drawing takes place */ | |
| if(uFlags & DFCS_INACTIVE) | |
| { | |
| /* If we have an inactive button, then you see a shadow */ | |
| hbsave = (HBRUSH)SelectObject(dc, GetSysColorBrush(COLOR_BTNHIGHLIGHT)); | |
| hpsave = (HPEN)SelectObject(dc, GetSysColorPen(COLOR_BTNHIGHLIGHT)); | |
| Polygon(dc, Line1, Line1N); | |
| if(Line2N > 0) | |
| Polygon(dc, Line2, Line2N); | |
| SelectObject(dc, hpsave); | |
| SelectObject(dc, hbsave); | |
| } | |
| /* Correct for the shadow shift */ | |
| if (!(uFlags & DFCS_PUSHED)) | |
| { | |
| for(i = 0; i < Line1N; i++) | |
| { | |
| Line1[i].x--; | |
| Line1[i].y--; | |
| } | |
| for(i = 0; i < Line2N; i++) | |
| { | |
| Line2[i].x--; | |
| Line2[i].y--; | |
| } | |
| } | |
| /* Make the final picture */ | |
| hbsave = (HBRUSH)SelectObject(dc, GetSysColorBrush(colorIdx)); | |
| hpsave = (HPEN)SelectObject(dc, GetSysColorPen(colorIdx)); | |
| Polygon(dc, Line1, Line1N); | |
| if(Line2N > 0) | |
| Polygon(dc, Line2, Line2N); | |
| SelectObject(dc, hpsave); | |
| SelectObject(dc, hbsave); | |
| return TRUE; | |
| } | |
| /************************************************************************ | |
| * UITOOLS_DrawFrameScroll | |
| * | |
| * Draw a scroll-bar control coming from DrawFrameControl() | |
| */ | |
| static BOOL UITOOLS95_DrawFrameScroll(HDC dc, LPRECT r, UINT uFlags) | |
| { | |
| POINT Line[4]; | |
| RECT myr; | |
| int SmallDiam = UITOOLS_MakeSquareRect(r, &myr) - 2; | |
| int i; | |
| HBRUSH hbsave, hb, hb2; | |
| HPEN hpsave, hp, hp2; | |
| int tri = 290*SmallDiam/1000 - 1; | |
| int d46, d93; | |
| /* | |
| * This fixes a problem with really tiny "scroll" buttons. In particular | |
| * with the updown control. | |
| * Making sure that the arrow is as least 3 pixels wide (or high). | |
| */ | |
| if (tri == 0) | |
| tri = 1; | |
| switch(uFlags & 0xff) | |
| { | |
| case DFCS_SCROLLCOMBOBOX: | |
| case DFCS_SCROLLDOWN: | |
| Line[2].x = myr.left + 470*SmallDiam/1000 + 2; | |
| Line[2].y = myr.top + 687*SmallDiam/1000 + 1; | |
| Line[0].x = Line[2].x - tri; | |
| Line[1].x = Line[2].x + tri; | |
| Line[0].y = Line[1].y = Line[2].y - tri; | |
| break; | |
| case DFCS_SCROLLUP: | |
| Line[2].x = myr.left + 470*SmallDiam/1000 + 2; | |
| Line[2].y = myr.bottom - (687*SmallDiam/1000 + 1); | |
| Line[0].x = Line[2].x - tri; | |
| Line[1].x = Line[2].x + tri; | |
| Line[0].y = Line[1].y = Line[2].y + tri; | |
| break; | |
| case DFCS_SCROLLLEFT: | |
| Line[2].x = myr.right - (687*SmallDiam/1000 + 1); | |
| Line[2].y = myr.top + 470*SmallDiam/1000 + 2; | |
| Line[0].y = Line[2].y - tri; | |
| Line[1].y = Line[2].y + tri; | |
| Line[0].x = Line[1].x = Line[2].x + tri; | |
| break; | |
| case DFCS_SCROLLRIGHT: | |
| Line[2].x = myr.left + 687*SmallDiam/1000 + 1; | |
| Line[2].y = myr.top + 470*SmallDiam/1000 + 2; | |
| Line[0].y = Line[2].y - tri; | |
| Line[1].y = Line[2].y + tri; | |
| Line[0].x = Line[1].x = Line[2].x - tri; | |
| break; | |
| case DFCS_SCROLLSIZEGRIP: | |
| /* This one breaks the flow... */ | |
| UITOOLS95_DrawRectEdge(dc, r, EDGE_BUMP, BF_MIDDLE | ((uFlags&(DFCS_MONO|DFCS_FLAT)) ? BF_MONO : 0)); | |
| hpsave = (HPEN)SelectObject(dc, GetStockObject(NULL_PEN)); | |
| hbsave = (HBRUSH)SelectObject(dc, GetStockObject(NULL_BRUSH)); | |
| if(uFlags & (DFCS_MONO|DFCS_FLAT)) | |
| { | |
| hp = hp2 = GetSysColorPen(COLOR_WINDOWFRAME); | |
| hb = hb2 = GetSysColorBrush(COLOR_WINDOWFRAME); | |
| } | |
| else | |
| { | |
| hp = GetSysColorPen(COLOR_BTNHIGHLIGHT); | |
| hp2 = GetSysColorPen(COLOR_BTNSHADOW); | |
| hb = GetSysColorBrush(COLOR_BTNHIGHLIGHT); | |
| hb2 = GetSysColorBrush(COLOR_BTNSHADOW); | |
| } | |
| Line[0].x = Line[1].x = r->right-1; | |
| Line[2].y = Line[3].y = r->bottom-1; | |
| d46 = 46*SmallDiam/750; | |
| d93 = 93*SmallDiam/750; | |
| i = 586*SmallDiam/750; | |
| Line[0].y = r->bottom - i - 1; | |
| Line[3].x = r->right - i - 1; | |
| Line[1].y = Line[0].y + d46; | |
| Line[2].x = Line[3].x + d46; | |
| SelectObject(dc, hb); | |
| SelectObject(dc, hp); | |
| Polygon(dc, Line, 4); | |
| Line[1].y++; Line[2].x++; | |
| Line[0].y = Line[1].y + d93; | |
| Line[3].x = Line[2].x + d93; | |
| SelectObject(dc, hb2); | |
| SelectObject(dc, hp2); | |
| Polygon(dc, Line, 4); | |
| i = 398*SmallDiam/750; | |
| Line[0].y = r->bottom - i - 1; | |
| Line[3].x = r->right - i - 1; | |
| Line[1].y = Line[0].y + d46; | |
| Line[2].x = Line[3].x + d46; | |
| SelectObject(dc, hb); | |
| SelectObject(dc, hp); | |
| Polygon(dc, Line, 4); | |
| Line[1].y++; Line[2].x++; | |
| Line[0].y = Line[1].y + d93; | |
| Line[3].x = Line[2].x + d93; | |
| SelectObject(dc, hb2); | |
| SelectObject(dc, hp2); | |
| Polygon(dc, Line, 4); | |
| i = 210*SmallDiam/750; | |
| Line[0].y = r->bottom - i - 1; | |
| Line[3].x = r->right - i - 1; | |
| Line[1].y = Line[0].y + d46; | |
| Line[2].x = Line[3].x + d46; | |
| SelectObject(dc, hb); | |
| SelectObject(dc, hp); | |
| Polygon(dc, Line, 4); | |
| Line[1].y++; Line[2].x++; | |
| Line[0].y = Line[1].y + d93; | |
| Line[3].x = Line[2].x + d93; | |
| SelectObject(dc, hb2); | |
| SelectObject(dc, hp2); | |
| Polygon(dc, Line, 4); | |
| SelectObject(dc, hpsave); | |
| SelectObject(dc, hbsave); | |
| return TRUE; | |
| default: | |
| WARN("Invalid scroll; flags=0x%04x\n", uFlags); | |
| return FALSE; | |
| } | |
| /* Here do the real scroll-bar controls end up */ | |
| if( ! (uFlags & (0xff00 & ~DFCS_ADJUSTRECT)) ) | |
| /* UITOOLS95_DFC_ButtonPush always uses BF_SOFT which we don't */ | |
| /* want for the normal scroll-arrow button. */ | |
| UITOOLS95_DrawRectEdge( dc, r, EDGE_RAISED, (uFlags&DFCS_ADJUSTRECT) | BF_MIDDLE | BF_RECT); | |
| else | |
| UITOOLS95_DFC_ButtonPush(dc, r, (uFlags & 0xff00) ); | |
| if(uFlags & DFCS_INACTIVE) | |
| { | |
| hbsave = (HBRUSH)SelectObject(dc, GetSysColorBrush(COLOR_BTNHIGHLIGHT)); | |
| hpsave = (HPEN)SelectObject(dc, GetSysColorPen(COLOR_BTNHIGHLIGHT)); | |
| Polygon(dc, Line, 3); | |
| SelectObject(dc, hpsave); | |
| SelectObject(dc, hbsave); | |
| } | |
| if( (uFlags & DFCS_INACTIVE) || !(uFlags & DFCS_PUSHED) ) | |
| for(i = 0; i < 3; i++) | |
| { | |
| Line[i].x--; | |
| Line[i].y--; | |
| } | |
| i = uFlags & DFCS_INACTIVE ? COLOR_BTNSHADOW : COLOR_BTNTEXT; | |
| hbsave = (HBRUSH)SelectObject(dc, GetSysColorBrush(i)); | |
| hpsave = (HPEN)SelectObject(dc, GetSysColorPen(i)); | |
| Polygon(dc, Line, 3); | |
| SelectObject(dc, hpsave); | |
| SelectObject(dc, hbsave); | |
| return TRUE; | |
| } | |
| /************************************************************************ | |
| * UITOOLS_DrawFrameMenu | |
| * | |
| * Draw a menu control coming from DrawFrameControl() | |
| */ | |
| static BOOL UITOOLS95_DrawFrameMenu(HDC dc, LPRECT r, UINT uFlags) | |
| { | |
| POINT Points[6]; | |
| RECT myr; | |
| int SmallDiam = UITOOLS_MakeSquareRect(r, &myr); | |
| int i; | |
| HBRUSH hbsave; | |
| HPEN hpsave; | |
| int xe, ye; | |
| int xc, yc; | |
| BOOL retval = TRUE; | |
| /* Using black and white seems to be utterly wrong, but win95 doesn't */ | |
| /* use anything else. I think I tried all sys-colors to change things */ | |
| /* without luck. It seems as if this behavior is inherited from the */ | |
| /* win31 DFC() implementation... (you remember, B/W menus). */ | |
| FillRect(dc, r, (HBRUSH)GetStockObject(WHITE_BRUSH)); | |
| hbsave = (HBRUSH)SelectObject(dc, GetStockObject(BLACK_BRUSH)); | |
| hpsave = (HPEN)SelectObject(dc, GetStockObject(BLACK_PEN)); | |
| switch(uFlags & 0xff) | |
| { | |
| case DFCS_MENUARROW: | |
| i = 187*SmallDiam/750; | |
| Points[2].x = myr.left + 468*SmallDiam/750; | |
| Points[2].y = myr.top + 352*SmallDiam/750+1; | |
| Points[0].y = Points[2].y - i; | |
| Points[1].y = Points[2].y + i; | |
| Points[0].x = Points[1].x = Points[2].x - i; | |
| Polygon(dc, Points, 3); | |
| break; | |
| case DFCS_MENUBULLET: | |
| xe = myr.left; | |
| ye = myr.top + SmallDiam - SmallDiam/2; | |
| xc = myr.left + SmallDiam - SmallDiam/2; | |
| yc = myr.top + SmallDiam - SmallDiam/2; | |
| i = 234*SmallDiam/750; | |
| i = i < 1 ? 1 : i; | |
| myr.left = xc - i+i/2; | |
| myr.right = xc + i/2; | |
| myr.top = yc - i+i/2; | |
| myr.bottom = yc + i/2; | |
| Pie(dc, myr.left, myr.top, myr.right, myr.bottom, xe, ye, xe, ye); | |
| break; | |
| case DFCS_MENUCHECK: | |
| Points[0].x = myr.left + 253*SmallDiam/1000; | |
| Points[0].y = myr.top + 445*SmallDiam/1000; | |
| Points[1].x = myr.left + 409*SmallDiam/1000; | |
| Points[1].y = Points[0].y + (Points[1].x-Points[0].x); | |
| Points[2].x = myr.left + 690*SmallDiam/1000; | |
| Points[2].y = Points[1].y - (Points[2].x-Points[1].x); | |
| Points[3].x = Points[2].x; | |
| Points[3].y = Points[2].y + 3*SmallDiam/16; | |
| Points[4].x = Points[1].x; | |
| Points[4].y = Points[1].y + 3*SmallDiam/16; | |
| Points[5].x = Points[0].x; | |
| Points[5].y = Points[0].y + 3*SmallDiam/16; | |
| Polygon(dc, Points, 6); | |
| break; | |
| default: | |
| WARN("Invalid menu; flags=0x%04x\n", uFlags); | |
| retval = FALSE; | |
| break; | |
| } | |
| SelectObject(dc, hpsave); | |
| SelectObject(dc, hbsave); | |
| return retval; | |
| } | |
| /********************************************************************** | |
| * DrawFrameControl (USER.656) | |
| */ | |
| BOOL16 WINAPI DrawFrameControl16( HDC16 hdc, LPRECT16 rc, UINT16 uType, | |
| UINT16 uState ) | |
| { | |
| RECT rect32; | |
| BOOL ret; | |
| CONV_RECT16TO32( rc, &rect32 ); | |
| ret = DrawFrameControl( hdc, &rect32, uType, uState ); | |
| CONV_RECT32TO16( &rect32, rc ); | |
| return ret; | |
| } | |
| /********************************************************************** | |
| * DrawFrameControl (USER32.@) | |
| */ | |
| BOOL WINAPI DrawFrameControl( HDC hdc, LPRECT rc, UINT uType, | |
| UINT uState ) | |
| { | |
| /* Win95 doesn't support drawing in other mapping modes */ | |
| if(GetMapMode(hdc) != MM_TEXT) | |
| return FALSE; | |
| switch(uType) | |
| { | |
| case DFC_BUTTON: | |
| return UITOOLS95_DrawFrameButton(hdc, rc, uState); | |
| case DFC_CAPTION: | |
| return UITOOLS95_DrawFrameCaption(hdc, rc, uState); | |
| case DFC_MENU: | |
| return UITOOLS95_DrawFrameMenu(hdc, rc, uState); | |
| case DFC_SCROLL: | |
| return UITOOLS95_DrawFrameScroll(hdc, rc, uState); | |
| default: | |
| WARN("(%x,%p,%d,%x), bad type!\n", | |
| hdc,rc,uType,uState ); | |
| } | |
| return FALSE; | |
| } | |