BOOL GradientRectangle(HDC hDC, int x0, int y0, int x1, int y1, COLORREF c0, COLORREF c1, int angle) { TRIVERTEX vert[4] = { { x0, y0, R16(c0), G16(c0), B16(c0), 0 }, // 0:c0 3:(c0+c1)/2 { x1, y1, R16(c1), G16(c1), B16(c1), 0 }, // { x0, y1, R16(c0, c1), G16(c0, c1), B16(c0, c1), 0 }, // { x1, y0, R16(c0, c1), G16(c0, c1), B16(c0, c1), 0 } // 2:(c0+c1)/2 1: c1 }; ULONG Index[] = { 0, 1, 2, 0, 1, 3}; switch ( angle % 180 ) { case 0: return GradientFill(hDC, vert, 2, Index, 1, GRADIENT_FILL_RECT_H); case 45: return GradientFill(hDC, vert, 4, Index, 2, GRADIENT_FILL_TRIANGLE); case 90: return GradientFill(hDC, vert, 2, Index, 1, GRADIENT_FILL_RECT_V); case 135: vert[0].x = x1; vert[3].x = x0; vert[1].x = x0; vert[2].x = x1; return GradientFill(hDC, vert, 4, Index, 2, GRADIENT_FILL_TRIANGLE); } return FALSE; }
// Gradient Filling Helper Routine void GradientFillRect( CDC *pDC, CRect &rect, COLORREF col_from, COLORREF col_to, bool vert_grad ) { TRIVERTEX vert[2]; GRADIENT_RECT mesh; vert[0].x = rect.left; vert[0].y = rect.top; vert[0].Alpha = 0x0000; vert[0].Blue = GetBValue(col_from) << 8; vert[0].Green = GetGValue(col_from) << 8; vert[0].Red = GetRValue(col_from) << 8; vert[1].x = rect.right; vert[1].y = rect.bottom; vert[1].Alpha = 0x0000; vert[1].Blue = GetBValue(col_to) << 8; vert[1].Green = GetGValue(col_to) << 8; vert[1].Red = GetRValue(col_to) << 8; mesh.UpperLeft = 0; mesh.LowerRight = 1; #if _MSC_VER >= 1300 // only VS7 and above has GradientFill as a pDC member pDC->GradientFill( vert, 2, &mesh, 1, vert_grad ? GRADIENT_FILL_RECT_V : GRADIENT_FILL_RECT_H ); #else GradientFill( pDC->m_hDC, vert, 2, &mesh, 1, vert_grad ? GRADIENT_FILL_RECT_V : GRADIENT_FILL_RECT_H ); #endif }
void COutlook2Ctrl::DrawGradientRect(CDC * pDC, CRect &rect, COLORREF cr1, COLORREF cr2, DWORD dwStyle) { #if(WINVER >= 0x0500) TRIVERTEX vert[2] ; GRADIENT_RECT gRect; vert [0] .x = rect.left; vert [0] .y = rect.top; vert [0] .Red = GetRValue(cr1)*0xFF00/255; vert [0] .Green = GetGValue(cr1)*0xFF00/255; vert [0] .Blue = GetBValue(cr1)*0xFF00/255; vert [0] .Alpha = 0; vert [1] .x = rect.right; vert [1] .y = rect.bottom; vert [1] .Red = GetRValue(cr2)*0xFF00/255; vert [1] .Green = GetGValue(cr2)*0xFF00/255; vert [1] .Blue = GetBValue(cr2)*0xFF00/255; vert [1] .Alpha = 0x0000; gRect.UpperLeft = 0; gRect.LowerRight = 1; GradientFill(pDC->GetSafeHdc(),vert,2,&gRect,1,dwStyle); #else pDC->FillSolidRect(rect, cr1); #endif }
void GraphicsMisc::DrawGradient(CDC* pDC, LPCRECT pRect, COLORREF crFrom, COLORREF crTo, BOOL bHorz, int nBorder) { TRIVERTEX vert[2]; GRADIENT_RECT gRect; vert[0] .x = pRect->left; vert[0] .y = pRect->top; vert[0] .Red = MAKEWORD(0, GetRValue(crFrom)); vert[0] .Green = MAKEWORD(0, GetGValue(crFrom)); vert[0] .Blue = MAKEWORD(0, GetBValue(crFrom)); vert[0] .Alpha = 0x0000; vert[1] .x = pRect->right; vert[1] .y = pRect->bottom; vert[1] .Red = MAKEWORD(0, GetRValue(crTo)); vert[1] .Green = MAKEWORD(0, GetGValue(crTo)); vert[1] .Blue = MAKEWORD(0, GetBValue(crTo)); vert[1] .Alpha = 0x0000; gRect.UpperLeft = 0; gRect.LowerRight = 1; GradientFill(pDC->GetSafeHdc(), vert, 2, &gRect, 1, bHorz ? GRADIENT_FILL_RECT_H : GRADIENT_FILL_RECT_V); if (nBorder >= 0) { // draw a border in from the edge CRect rBorder(pRect); rBorder.DeflateRect(nBorder, nBorder); DrawRect(pDC, rBorder, CLR_NONE, crFrom); } }
//----------------------------------------------------------------------------- // Purpose: // Input : rc - // clr1 - // clr2 - // vertical - //----------------------------------------------------------------------------- void CDrawHelper::DrawGradientFilledRect( RECT& rc, COLORREF clr1, COLORREF clr2, bool vertical ) { RECT rcDraw = rc; OffsetRect( &rcDraw, -m_x, -m_y ); TRIVERTEX vert[2] ; GRADIENT_RECT gradient_rect; vert[0].x = rcDraw.left; vert[0].y = rcDraw.top; vert[0].Red = GetRValue( clr1 ) << 8; vert[0].Green = GetGValue( clr1 ) << 8; vert[0].Blue = GetBValue( clr1 ) << 8; vert[0].Alpha = 0x0000; vert[1].x = rcDraw.right; vert[1].y = rcDraw.bottom; vert[1].Red = GetRValue( clr2 ) << 8; vert[1].Green = GetGValue( clr2 ) << 8; vert[1].Blue = GetBValue( clr2 ) << 8; vert[1].Alpha = 0x0000; gradient_rect.UpperLeft = 0; gradient_rect.LowerRight = 1; GradientFill( m_dcMemory, vert, 2, &gradient_rect, 1, vertical ? GRADIENT_FILL_RECT_V : GRADIENT_FILL_RECT_H ); }
void DrawGradient(HDC hdc, RECT const *pRect, char horz, COLORREF clrTopLeft, COLORREF clrBottomRight) { GRADIENT_RECT gRect = {0,1}; TRIVERTEX vert[2] = { {pRect->left,pRect->top,(COLOR16)(GetRValue(clrTopLeft)<<8),(COLOR16)(GetGValue(clrTopLeft)<<8),(COLOR16)(GetBValue(clrTopLeft)<<8),0}, {pRect->right,pRect->bottom,(COLOR16)(GetRValue(clrBottomRight)<<8),(COLOR16)(GetGValue(clrBottomRight)<<8),(COLOR16)(GetBValue(clrBottomRight)<<8),0} }; GradientFill(hdc,vert,2,&gRect,1,(horz==TRUE ? GRADIENT_FILL_RECT_H : GRADIENT_FILL_RECT_V)); }
void CTitleMenu::DrawItem(LPDRAWITEMSTRUCT di) { COLORREF crOldBk = ::SetBkColor(di->hDC, clLeft); if(m_bCanDoGradientFill&&(clLeft!=clRight)) { TRIVERTEX rcVertex[2]; di->rcItem.right--; // exclude this point, like FillRect does di->rcItem.bottom--; rcVertex[0].x=di->rcItem.left; rcVertex[0].y=di->rcItem.top; rcVertex[0].Red=GetRValue(clLeft)<<8; // color values from 0x0000 to 0xff00 !!!! rcVertex[0].Green=GetGValue(clLeft)<<8; rcVertex[0].Blue=GetBValue(clLeft)<<8; rcVertex[0].Alpha=0x0000; rcVertex[1].x=di->rcItem.right; rcVertex[1].y=di->rcItem.bottom; rcVertex[1].Red=GetRValue(clRight)<<8; rcVertex[1].Green=GetGValue(clRight)<<8; rcVertex[1].Blue=GetBValue(clRight)<<8; rcVertex[1].Alpha=0; GRADIENT_RECT rect; rect.UpperLeft=0; rect.LowerRight=1; // fill the area GradientFill( di->hDC,rcVertex,2,&rect,1,GRADIENT_FILL_RECT_H); } else { ::ExtTextOut(di->hDC, 0, 0, ETO_OPAQUE, &di->rcItem, NULL, 0, NULL); } if(bDrawEdge) ::DrawEdge(di->hDC, &di->rcItem, flag_edge, BF_RECT); int modeOld = ::SetBkMode(di->hDC, TRANSPARENT); COLORREF crOld = ::SetTextColor(di->hDC, clText); // select font into the dc HFONT hfontOld = (HFONT)SelectObject(di->hDC, (HFONT)m_Font); // add the menu margin offset di->rcItem.left += GetSystemMetrics(SM_CXMENUCHECK) + 8; // draw the text left aligned and vertically centered ::DrawText(di->hDC, m_strTitle, m_strTitle.GetLength(), &di->rcItem, DT_SINGLELINE|DT_VCENTER|DT_LEFT|DT_NOPREFIX|DT_NOCLIP); //Restore font and colors... ::SelectObject(di->hDC, hfontOld); ::SetBkMode(di->hDC, modeOld); ::SetBkColor(di->hDC, crOldBk); ::SetTextColor(di->hDC, crOld); }
void _ColorHorizGradientRectangle ( ChooseColorsStruct *ccs, HDC hDC, const RECT *const rect, const COLORREF color1, const COLORREF color2 ) { TRIVERTEX vertices[2]; GRADIENT_RECT gradient; HBRUSH hBrush; RECT rc; vertices[0].x = rect->left + COLOR_CHANNEL_SLIDER_OFFSET; vertices[0].y = rect->top; vertices[0].Red = ( ( ( unsigned short )GetRValue( color1 ) ) << 8 ); vertices[0].Green = ( ( ( unsigned short )GetGValue( color1 ) ) << 8 ); vertices[0].Blue = ( ( ( unsigned short )GetBValue( color1 ) ) << 8 ); vertices[0].Alpha = 0; vertices[1].x = rect->right - COLOR_CHANNEL_SLIDER_OFFSET; vertices[1].y = rect->bottom; vertices[1].Red = ( ( ( unsigned short )GetRValue( color2 ) ) << 8 ); vertices[1].Green = ( ( ( unsigned short )GetGValue( color2 ) ) << 8 ); vertices[1].Blue = ( ( ( unsigned short )GetBValue( color2 ) ) << 8 ); vertices[1].Alpha = 0; gradient.UpperLeft = 0; gradient.LowerRight = 1; GradientFill( hDC, vertices, 2, &gradient, 1, GRADIENT_FILL_RECT_H ); rc.top = 0; rc.bottom = rect->bottom; hBrush = CreateSolidBrush( color1 ); rc.left = 0; rc.right = COLOR_CHANNEL_SLIDER_OFFSET; FillRect( hDC, &rc, hBrush ); DeleteObject( hBrush ); hBrush = CreateSolidBrush( color2 ); rc.left = rect->right - COLOR_CHANNEL_SLIDER_OFFSET; rc.right = rect->right; FillRect( hDC, &rc, hBrush ); DeleteObject( hBrush ); }/* _ColorHorizGradientRectangle() */
static void FillGradientRect(HDC hDC, RECT& rect, COLORREF bk, COLORREF fore, ULONG dwMode) { TRIVERTEX v[2]; GRADIENT_RECT r[1]; v[0].x = (rect.left); v[0].y = (rect.top); v[0].Red = GetRValue(bk) << 8; v[0].Green = GetGValue(bk) << 8; v[0].Blue = GetBValue(bk) << 8; v[0].Alpha = 0x0000; v[1].x = (rect.right); v[1].y = (rect.bottom); v[1].Red = GetRValue(fore) << 8; v[1].Green = GetGValue(fore) << 8; v[1].Blue = GetBValue(fore) << 8; v[1].Alpha = 0x0000; r[0].UpperLeft = 0; r[0].LowerRight = 1; GradientFill(hDC, v, (ULONG)2, r, (ULONG)1, dwMode); }
void DrawGradientFill(HDC hdc, LPRECT rect, int clrfrom, int clrto) { TRIVERTEX vertex[2]; GRADIENT_RECT gRect = {0, 1}; vertex[0].x = 0; vertex[0].y = 0; vertex[0].Red = (clrfrom & 0x0000FF) << 8; vertex[0].Green = (clrfrom & 0x00FF00); vertex[0].Blue = (clrfrom & 0xFF0000) >> 8; vertex[0].Alpha = 0; vertex[1].x = rect->right; vertex[1].y = rect->bottom; vertex[1].Red = (clrto & 0x0000FF) << 8; vertex[1].Green = (clrto & 0x00FF00); vertex[1].Blue = (clrto & 0xFF0000) >> 8; vertex[1].Alpha = 0; GradientFill(hdc, vertex, 2, &gRect, 1, GRADIENT_FILL_RECT_H); }
void GradientFillRect(HDC hdc, const RECT *rcFill, COLORREF cr1, COLORREF cr2,BOOL bVert) { HDC hdc1=hdc; TRIVERTEX vert[2] ; vert [0] .x = rcFill->left; vert [0] .y = rcFill->top; vert [0] .Red = GetRValue(cr1)<<8; vert [0] .Green = GetGValue(cr1)<<8; vert [0] .Blue = GetBValue(cr1)<<8; vert [0] .Alpha = 0xff00; vert [1] .x = rcFill->right; vert [1] .y = rcFill->bottom; vert [1] .Red = GetRValue(cr2)<<8; vert [1] .Green = GetGValue(cr2)<<8; vert [1] .Blue = GetBValue(cr2)<<8; vert [1] .Alpha = 0xff00; GRADIENT_RECT gRect={0,1}; GradientFill(hdc1,vert,2,&gRect,1,bVert?GRADIENT_FILL_RECT_V:GRADIENT_FILL_RECT_H); }
void GradientFillH(HDC hdc, long x1, long y1, long x2, long y2, COLORREF c1, COLORREF c2) { TRIVERTEX vert[3] ; GRADIENT_RECT gRect; vert [0] .x = x1; vert [0] .y = y1; vert [0] .Red = RGB_RED(c1) << 8; vert [0] .Green = RGB_GREEN(c1) << 8; vert [0] .Blue = RGB_BLUE(c1) << 8; vert [0] .Alpha = 0x0000; vert [1] .x = x2; vert [1] .y = y2; vert [1] .Red = RGB_RED(c2) << 8; vert [1] .Green = RGB_GREEN(c2) << 8; vert [1] .Blue = RGB_BLUE(c2) << 8; vert [1] .Alpha = 0x0000; gRect.UpperLeft = 0; gRect.LowerRight = 1; GradientFill(hdc, vert, 2, &gRect, 1, GRADIENT_FILL_RECT_H); }
void CPropPageFrameEx::FillGDIGradientRectH(CDC *pDc, const RECT &rect, COLORREF clrLeft, COLORREF clrRight) { TRIVERTEX vert[2] ; GRADIENT_RECT gRect; vert [0] .x = rect.left; vert [0] .y = rect.top; vert [0] .Red = (short)(GetRValue( clrLeft ) << 8); vert [0] .Green = (short)(GetGValue( clrLeft ) << 8); vert [0] .Blue = (short)(GetBValue( clrLeft ) << 8); vert [0] .Alpha = 0x0000; vert [1] .x = rect.right; vert [1] .y = rect.bottom; vert [1] .Red = (short)(GetRValue( clrRight ) << 8); vert [1] .Green = (short)(GetGValue( clrRight ) << 8); vert [1] .Blue = (short)(GetBValue( clrRight ) << 8); vert [1] .Alpha = 0x0000; gRect.UpperLeft = 0; gRect.LowerRight = 1; GradientFill( pDc->m_hDC,vert,2,&gRect,1, GRADIENT_FILL_RECT_H ); }
static void FillGradient(HDC hdc, LPRECT lpRect, COLORREF col1, COLORREF col2) { TRIVERTEX vt[2]; GRADIENT_RECT rc; vt[0].x = lpRect->left; vt[0].y = lpRect->top; vt[0].Red = GetRValue(col1) << 8; vt[0].Green = GetGValue(col1) << 8; vt[0].Blue = GetBValue(col1) << 8; vt[0].Alpha = 0xFF00; vt[1].x = lpRect->right; vt[1].y = lpRect->bottom; vt[1].Red = GetRValue(col2) << 8; vt[1].Green = GetGValue(col2) << 8; vt[1].Blue = GetBValue(col2) << 8; vt[1].Alpha = 0xFF00; rc.UpperLeft = 0; rc.LowerRight = 1; GradientFill(hdc, vt, 2, &rc, 1, GRADIENT_FILL_RECT_H); }
static void DrawGradient(HDC hDC, RECT Region, COLORREF TopLeft, COLORREF TopRight, COLORREF BottomLeft, COLORREF BottomRight) { GRADIENT_TRIANGLE GradientTriangle[2] = { {0, 1, 2}, {2, 0, 3} }; TRIVERTEX Vertices[4] = { Region.left, Region.top, GetRValue(TopLeft) << 8, GetGValue(TopLeft) << 8, GetBValue(TopLeft) << 8, 0x0000, Region.left, Region.bottom, GetRValue(BottomLeft) << 8, GetGValue(BottomLeft) << 8, GetBValue(BottomLeft) << 8, 0x0000, Region.right, Region.bottom, GetRValue(BottomRight) << 8, GetGValue(BottomRight) << 8, GetBValue(BottomRight) << 8, 0x0000, Region.right, Region.top, GetRValue(TopRight) << 8, GetGValue(TopRight) << 8, GetBValue(TopRight) << 8, 0x0000 }; GradientFill(hDC, Vertices, 4, &GradientTriangle, 2, GRADIENT_FILL_TRIANGLE); }
/*-----------------------------------------------[ private ]-----------------*/ static BOOL paintColumn(HPS hps,WINDOWINFO *pwi,POBJECT pObj, RECTL rclCol,int iMode) { POINTL ptl1,ptl2; RECTL rcl; blocktext *pT = (blocktext *)pObj; ptl1.x = rclCol.xLeft; ptl1.y = rclCol.yBottom; ptl2.x = rclCol.xRight; ptl2.y = rclCol.yTop; rcl = rclCol; if (pT->bt.lPattern == PATSYM_DEFAULT && pT->bt.line.LineType == LINETYPE_INVISIBLE) return FALSE; if (iMode == MODE_PREPPRINTING) { /* ** During the print preparation we do not draw the column but ** we return true so the column painting can take this square ** into account. */ return TRUE; } GpiSetLineType(hps,pT->bt.line.LineType); GpiSetPattern(hps, PATSYM_SOLID); GpiSetColor(hps,pT->ulColColor); if (pT->bt.lPattern == PATSYM_DEFAULT) { /* ** No filling */ GpiSetColor(hps,pT->bt.line.LineColor); GpiMove(hps,&ptl1); GpiBox(hps,DRO_OUTLINE,&ptl2,0,0); } else if ( pT->bt.lPattern != PATSYM_GRADIENTFILL && pT->bt.lPattern != PATSYM_FOUNTAINFILL ) { /* ** we have a standard OS/2 patternfill. */ GpiMove(hps,&ptl1); if (pT->bt.line.LineColor == pT->ulColColor ) { GpiBox(hps,DRO_OUTLINEFILL, &ptl2,0,0); } else { GpiMove(hps,&ptl1); /* ** Draw the filling part */ GpiBox(hps,DRO_FILL, &ptl2,0,0); /* ** Draw the outline */ GpiMove(hps,&ptl1); GpiSetColor(hps,pT->bt.line.LineColor); GpiBox(hps,DRO_OUTLINE, &ptl2,0,0); } } else if (pT->bt.lPattern == PATSYM_GRADIENTFILL || pT->bt.lPattern == PATSYM_FOUNTAINFILL) { GpiBeginPath( hps, 1L); /* define a clip path */ GpiMove(hps,&ptl1); GpiBox(hps,DRO_OUTLINE, &ptl2,0,0); GpiEndPath(hps); GpiSetClipPath(hps,1L,SCP_AND); GpiSetPattern(hps,PATSYM_SOLID); if (pT->bt.lPattern == PATSYM_GRADIENTFILL) GradientFill(pwi,hps,&rcl,&pT->bt.gradient); else FountainFill(pwi,hps,&rcl,&pT->bt.fountain); GpiSetClipPath(hps, 0L, SCP_RESET); /* clear the clip path */ if (pT->bt.line.LineType != LINETYPE_INVISIBLE) { /* ** Draw the outline */ GpiMove(hps,&ptl1); GpiSetColor(hps,pT->bt.line.LineColor); GpiBox(hps,DRO_OUTLINE, &ptl2,0,0); } } return TRUE; }
void CSliderCtrlEx::OnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult) { int loopMax = colorList.GetSize(); // number of color ranges to process LPNMCUSTOMDRAW lpCustDraw = (LPNMCUSTOMDRAW)pNMHDR; //////////////////////////////////////////////////////////////////////////////// // OnCustomDraw() is called at many different stages during the painting process // of the control. We only care about the PREPAINT state or the ITEMPREPAINT // state and not always then. // // If we want to be notified about subcontrol painting, we have to say so when // we get the initial PREPAINT message. //////////////////////////////////////////////////////////////////////////////// if(lpCustDraw->dwDrawStage == CDDS_PREPAINT) { // should we report slider's position? int curVal = GetPos(); if((m_Callback != NULL) && (curVal != m_oldPosition)) { m_oldPosition = curVal; m_Callback(m_p2Object, m_data1, curVal, m_IsDragging); } // If we don't have any special coloring to do, skip all the silliness... if(loopMax <= 0) { *pResult = CDRF_DODEFAULT; } else { // We want to be informed when each part of the control is being // processed so we can intercept the channel drawing. *pResult = CDRF_NOTIFYITEMDRAW; // send messages for each piece-part } return; } /////////////////////////////////////////////////////////////////////////////// // A slider (track control) is drawn in several steps: // 1. Erase // 2. Tics // 3. Channel // 4. Thumb // // It would be nice to capture when the background has been painted and // before the other sub-pieces have been painted. Then we could just // substitute our own painting routine. But this doesn't seem to be // available. // // So this routine captures the tics by inserting operations before // painting the thumb. // // Look at the help on NMCUSTOMDRAW for complete details, but the pNMHDR // pointer looks at a structure like: // // typedef struct tagNMCUSTOMDRAWINFO { // NMHDR hdr; // DWORD dwDrawStage; // This indicates what stage of the drawing process is involved // HDC hdc; // graphics context of the control (or sub-component) // RECT rc; // DWORD dwItemSpec; // This is the particular piece-part of the slider involved // UINT uItemState; // LPARAM lItemlParam; // } NMCUSTOMDRAW // // The stages include CDDS_PREPAINT, which is just before painting of the entire // control. However, unless the *pResult parameter is set to CDRF_NOTIFYITEMDRAW, // we will get notification for the control as a whole, not for each piece-part. // So the first thing to do is set *pResult. Thereafter, we must intercept // the sub-parts. // // We don't care about painting the background (we will re-paint later on). We // don't care about PREPAINT on the CHANNEL or the TICS since we will overwrite // everything when we get to the THUMB. ///////////////////////////////////////////////////////////////////////////////// if((lpCustDraw->dwDrawStage == CDDS_ITEMPREPAINT) && (lpCustDraw->dwItemSpec != TBCD_THUMB)) { *pResult = CDRF_DODEFAULT; return; } // get channel orientation BOOL IsVertical = (TBS_VERT & GetStyle()) ? TRUE : FALSE; // Get the coordinates of the control's window CRect crect; GetClientRect(crect); // client coordinates (top = left = 0, bottom = height, right = width) // Much of this is "paraphrased" from Nic Wilson's work -- see the header file ////////////////////////////////////////////////////////////////////////////////// // This bit does the tics marks transparently. // Create a memory dc to hold a copy of the oldbitmap data that includes the tics, // because when we add the background in we will lose the tic marks. /////////////////////////////////////////////////////////////////////////////////// CDC *pDC = CDC::FromHandle(lpCustDraw->hdc); CDC SaveCDC; CBitmap SaveCBmp; //set the colours for the monochrome mask bitmap COLORREF crOldBack = pDC->SetBkColor(RGB(0,0,0)); // set to Black COLORREF crOldText = pDC->SetTextColor(RGB(255,255,255)); // set to White int iWidth = crect.Width(); // channel width int iHeight = crect.Height(); // channel height //////////////////////////////////////////////////////////////////////////// // Create an in-memory copy of displayed bitmap, including the tics. // This is a monochrome bitmap since it was created from a memory DC. // If it had been created from pDC (an actual device DC, not a memory // DC) then this would be something with 8, 16, 24, or 32 bits per pixel. // // This will have a black background, with the tic marks in white. // // For reasons I don't yet understand, this saves only the tic marks and // the channel's centerline (both originally in black), and not the other // colors (such as drawn AROUND the channel's centerline). I am not sure // what would have happened if the tic marks were not black... //////////////////////////////////////////////////////////////////////////// SaveCDC.CreateCompatibleDC(pDC); SaveCBmp.CreateCompatibleBitmap(&SaveCDC, iWidth, iHeight); CBitmap* SaveCBmpOld = (CBitmap *)SaveCDC.SelectObject(SaveCBmp); SaveCDC.BitBlt(0, 0, iWidth, iHeight, pDC, crect.left, crect.top, SRCCOPY); if(m_dumpBitmaps) // debugging stuff { SaveBitmap("MonoTicsMask.bmp",SaveCBmp); } // Do as much of this stuff in memory as possible, then blit it to the screen CDC memDC; memDC.CreateCompatibleDC(pDC); CBitmap memBM; memBM.CreateCompatibleBitmap(pDC,iWidth,iHeight); // create from pDC, not memDC CBitmap *oldbm = memDC.SelectObject(&memBM); //////////////////////////////////////////////////////////////////////////////// // copy screen bitmap to memory bitmap for manipulation. If this is the very // first time the control has been updated, the screen bitmap will show only // the tic marks (in black) and the default background color (RGB(214,207,189)). // If the control has been updated before, remnants of the previously drawn // background color ranges will also show up. //////////////////////////////////////////////////////////////////////////////// memDC.BitBlt(0,0,iWidth,iHeight,pDC,0,0,SRCCOPY); if(m_dumpBitmaps) // debugging { SaveBitmap("ScrnStart.bmp",memBM); } ///////////////////////////////////////////////////////////////////////////// // Color parts of the channel if necessary. It SHOULD be necessary since we // don't get notifications unless there are colors to print, but we may have // a race condition and it is best to check. ///////////////////////////////////////////////////////////////////////////// if(loopMax) { ///////////////////////////////////////////////////////////////////////////////// // We need to draw colors over the subrange of the channel that the center of the // thumb traverses, rather than the entire client window. Later on, extend these // colors outwards to the ends of the client window (for nicer appearance). This // allows for more precise correlation with color and thumb position. ///////////////////////////////////////////////////////////////////////////////// CRect chanRect; GetChannelRect(&chanRect); CRect thmbRect; GetThumbRect(&thmbRect); // For unknown reasons, GetChannelRect() returns a rectangle // as though it were a horizonally oriented slider, even if it isn't! if(IsVertical) { CRect n; // could probably just change chanRect directly n.left = chanRect.top; n.right = chanRect.bottom; n.top = chanRect.left; n.bottom = chanRect.right; n.NormalizeRect(); chanRect.CopyRect(&n); } // Offset into client rectangle for beginning of coloring range int Offset = chanRect.left + thmbRect.Width()/2; if(IsVertical) { Offset = chanRect.top + thmbRect.Height()/2; } // Range for center of thumb on the channel int ht = chanRect.Height() - thmbRect.Height(); int wd = chanRect.Width() - thmbRect.Width(); // scaling between control range and bitmap int min,max; GetRange(min,max); // range of values for the slider double scale = (double(max) - double(min))/double(IsVertical ? ht : wd); BOOL gotStartColor = FALSE; BOOL gotEndColor = FALSE; COLORREF startColor = 0, endColor = 0; int loop; // Loop through the array of color ranges for(loop = 0; loop < loopMax; loop++) { clrRange clr; clr = colorList[loop]; // Get the good values. If not set, then entire range is good int lval = clr.lval; int hval = clr.hval; if((lval < min) || (lval > max)) lval = min; if((hval > max) || (hval < min)) hval = max; if(lval == min) { gotStartColor = TRUE; startColor = clr.strColor; } if(hval == max) { gotEndColor = TRUE; endColor = clr.endColor; } int minVal = lval - min; // offset into bitmap for this color minVal = int(double(minVal)/scale); // width (or height for vertical slider) inside bitmap for this color int widthVal = hval - lval; widthVal = int((double(widthVal)/scale) + 1.0); // For drawing a gradient, we need to know the individual RGB values int sR,eR,sG,eG,sB,eB; // start and end R, G, and B values sR = GetRValue(clr.strColor); eR = GetRValue(clr.endColor); sG = GetGValue(clr.strColor); eG = GetGValue(clr.endColor); sB = GetBValue(clr.strColor); eB = GetBValue(clr.endColor); if(GradientFill != NULL) { TRIVERTEX vert[2]; // for specifying range to gradient fill GRADIENT_RECT gRect; // Warning C4244: conversion from 'int' to 'unsigned short', possible loss of data #pragma warning (push) #pragma warning (disable : 4244) vert[0].Red = sR<<8; // expects 16-bit color values! vert[0].Green = sG<<8; vert[0].Blue = sB<<8; vert[0].Alpha = 0; // no fading/transparency vert[1].Red = eR<<8; vert[1].Green = eG<<8; vert[1].Blue = eB<<8; vert[1].Alpha = 0; #pragma warning (pop) gRect.UpperLeft = 0; gRect.LowerRight = 1; BOOL retval; if(IsVertical) // vertically oriented? { vert[0].x = 0; vert[0].y = Offset + minVal; vert[1].x = iWidth; vert[1].y = Offset + minVal + widthVal; retval = GradientFill(memDC,vert,2,&gRect,1,GRADIENT_FILL_RECT_V); } else { vert[0].x = Offset + minVal; vert[0].y = 0; vert[1].x = Offset + minVal + widthVal; vert[1].y = iHeight; retval = GradientFill(memDC,vert,2,&gRect,1,GRADIENT_FILL_RECT_H); } } else { // Homebrew version of GradientFill for rectangles -- works pretty well, sort of. int i; for(i = 0; i < widthVal; i++) // for each pixel column in bitmap color range { int R = sR; int G = sG; int B = sB; if(widthVal) { R += ::MulDiv(eR - sR, i, widthVal); G += ::MulDiv(eG - sG, i, widthVal); B += ::MulDiv(eB - sB, i, widthVal); } if(IsVertical) { // widthVal really refers to height //memDC.FillSolidRect(0,minVal+i,iWidth,widthVal-i,GetNearestColor(memDC,RGB(R,G,B))); memDC.FillSolidRect( 0, // starting X value Offset + minVal + i, // starting Y value iWidth, // full width 1, // one pixel height GetNearestColor(memDC,RGB(R,G,B))); } else { //memDC.FillSolidRect(minVal+i,0,widthVal-i,iHeight,GetNearestColor(memDC,RGB(R,G,B))); memDC.FillSolidRect( Offset + minVal + i, // Starting X value 0, // Starting Y value 1, // 1 pixel wide iHeight, // full height GetNearestColor(memDC,RGB(R,G,B))); } } } } if(m_extendColors) { // If we have put in colors at the slider ends, then extend those same // colors to the rest of the background. We could try to determine the // colors by examining the bitmap, but this is awkward and it is just // as easy to grab them on-the-fly in the coloring loop above. // // If you want to see why this is done, just set m_extendColors to FALSE // and take a look at the control. Ugly. But there might be a legitimate // reason for it so leave the option to suppress. if(IsVertical) { if(gotStartColor) { memDC.FillSolidRect(0, 0, iWidth, Offset, startColor); } if(gotEndColor) { memDC.FillSolidRect(0, iHeight - Offset - 1, iWidth, Offset, endColor); } } else { if(gotStartColor) { memDC.FillSolidRect(0, 0, Offset, iHeight, startColor); } if(gotEndColor) { memDC.FillSolidRect(iWidth - Offset - 1, 0, Offset, iHeight, endColor); } } } } // The screen bitmap should now have only the color ranges filled in, no tic // marks should be visible. if(m_dumpBitmaps) // debugging { SaveBitmap("ScrnColors.bmp",memBM); } ////////////////////////////////////////////////////////////// // More "paraphrasing" from Nic Wilson's work... ////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// // At this point, memDC's bitmap contains just the color ranges drawn above. // No tic marks are visible. Doing SRCINVERT with the mask will draw in the // tic marks, but all the colors will be backwards. Also, the tics will be // whatever color was drawn in the color range stuff, rather than solid, // normal tic marks. SRCINVERT means the RGB values are changed by subtracting // from 255: // // RGB(255,0,0) --> RGB(0,255,255) // RGB(247,8,0) --> RGB(8,247,255) // RGB(214,40,255) --> RGB(41,215,0) // ///////////////////////////////////////////////////////////////////////////// memDC.SetBkColor(pDC->GetBkColor()); memDC.SetTextColor(pDC->GetTextColor()); memDC.BitBlt(0, 0, iWidth, iHeight, &SaveCDC, 0, 0, SRCINVERT); if(m_dumpBitmaps) // debugging { SaveBitmap("ScrnInvert.bmp",memBM); } // Change the tic marks from the color range to the background color. This // changes only the tic marks (and the channel centerline) and leaves the // rest alone. The tic marks wind up black. memDC.BitBlt(0, 0, iWidth, iHeight, &SaveCDC, 0, 0, SRCAND); if(m_dumpBitmaps) // debugging { SaveBitmap("ScrnAnd.bmp",memBM); } // Finally, invert the color ranges to their normal values. Since the tic // marks in the SaveCDC bitmap are white, they get inverted to black. memDC.BitBlt(0, 0, iWidth, iHeight, &SaveCDC, 0, 0, SRCINVERT); if(m_dumpBitmaps) // debugging { SaveBitmap("ScrnFinal.bmp",memBM); } // Now copy out to screen pDC->BitBlt(0,0,iWidth,iHeight,&memDC,0,0,SRCCOPY); // restore and clean up pDC->SetBkColor(crOldBack); pDC->SetTextColor(crOldText); DeleteObject(SelectObject(SaveCDC, SaveCBmpOld)); DeleteDC(SaveCDC); DeleteObject(SelectObject(memDC,oldbm)); DeleteDC(memDC); *pResult = CDRF_DODEFAULT; m_dumpBitmaps = FALSE; // only do this once! }
HBITMAP KGUISkin::CreateGradient(HDC hDC, COLORREF clrBase, COLORREF clrHigh, COLORREF clrLow, bool bVert) { HDC hMemDC = CreateCompatibleDC (hDC) ; HBITMAP hDDB = CreateCompatibleBitmap (hDC, m_nWidth, m_nWidth); if (hDDB == NULL) { ::DeleteDC (hMemDC) ; assert(false); return NULL; } HGDIOBJ hOldBmp = ::SelectObject (hMemDC, hDDB); TRIVERTEX vertex[4]; vertex[0].x = 0; vertex[0].y = 0; vertex[0].Red = GetRValue(clrHigh) * 256; vertex[0].Green = GetGValue(clrHigh) * 256; vertex[0].Blue = GetBValue(clrHigh) * 256; vertex[0].Alpha = 0x0000; vertex[1].Red = GetRValue(clrBase) * 256; vertex[1].Green = GetGValue(clrBase) * 256; vertex[1].Blue = GetBValue(clrBase) * 256; vertex[1].Alpha = 0x0000; if (bVert) { vertex[1].x = m_nWidth; vertex[1].y = m_nWidth / 2; vertex[3].x = 0; vertex[3].y = m_nWidth / 2; } else { vertex[3].y = 0; vertex[3].x = m_nWidth / 2; vertex[1].y = m_nWidth; vertex[1].x = m_nWidth / 2; } vertex[3].Red = GetRValue(clrBase) * 256; vertex[3].Green = GetGValue(clrBase) * 256; vertex[3].Blue = GetBValue(clrBase) * 256; vertex[3].Alpha = 0x0000; vertex[2].x = m_nWidth; vertex[2].y = m_nWidth; vertex[2].Red = GetRValue(clrLow) * 256; vertex[2].Green = GetGValue(clrLow) * 256; vertex[2].Blue = GetBValue(clrLow) * 256; vertex[2].Alpha = 0x0000; GRADIENT_RECT gRect; gRect.UpperLeft = 0; gRect.LowerRight= 1; GRADIENT_RECT gTriangle2; gTriangle2.UpperLeft = 0; gTriangle2.LowerRight = 1; if (bVert) { GradientFill(hMemDC, vertex, 2, &gRect, 1, GRADIENT_FILL_RECT_V); GradientFill(hMemDC, &vertex[2], 2, &gTriangle2, 1, GRADIENT_FILL_RECT_V); } else { GradientFill(hMemDC, vertex, 2, &gRect, 1, GRADIENT_FILL_RECT_H); GradientFill(hMemDC, &vertex[2], 2, &gTriangle2, 1, GRADIENT_FILL_RECT_H); } BITMAPINFO info; UInt32 nPitch = (m_nWidth * 24 + 31) / 32 * 4; UInt32 dibSize = sizeof(BITMAPINFOHEADER) + (nPitch * m_nWidth); BYTE * pBuf = new BYTE[dibSize]; BYTE *pData = (BYTE*)pBuf; memset(pBuf, 0, dibSize); memset(&info, 0, sizeof(BITMAPINFOHEADER)); info.bmiHeader.biBitCount = 24; info.bmiHeader.biCompression= BI_RGB; info.bmiHeader.biClrUsed = 0; info.bmiHeader.biHeight = m_nWidth; info.bmiHeader.biPlanes = 1; info.bmiHeader.biSizeImage = 0; info.bmiHeader.biSize = 40; info.bmiHeader.biWidth = m_nWidth; pData += sizeof(BITMAPINFOHEADER); // Copy the bitmap ::GetDIBits (hMemDC, hDDB, 0, m_nWidth, pData, &info, DIB_RGB_COLORS) ; HBITMAP hBitmap = ::CreateDIBitmap(hDC, &info.bmiHeader, CBM_INIT, pData, &info, DIB_RGB_COLORS); delete[] pBuf; ::SelectObject (hMemDC, hOldBmp); DeleteObject (hDDB) ; DeleteDC (hMemDC) ; return hBitmap; }
void ProgressWindow::draw(int count) { HDC hDC = GetDC(hWnd); int prgBase = getProgress(); int prg = min((prgBase * p_width)/1000, p_width-1); int center = int(prg*((cos(count*0.1)+1)*0.8) / 2); DWORD c=GetSysColor(COLOR_ACTIVECAPTION); double red=GetRValue(c); double green=GetGValue(c); double blue=GetBValue(c); double blue1=min(255., blue*1.4); double green1=min(255., green*1.4); double red1=min(255., red*1.4); int blueD=int(blue/2); int redD=int(red/2); int greenD=int(green/2); SelectObject(hDC, GetStockObject(DC_PEN)); SelectObject(hDC, GetStockObject(NULL_BRUSH)); SetDCPenColor(hDC, RGB(redD,greenD,blueD)); Rectangle(hDC, 0, 0, p_width, p_height-1); SelectObject(hDC, GetStockObject(DC_BRUSH)); SelectObject(hDC, GetStockObject(NULL_PEN)); SetDCBrushColor(hDC, GetSysColor(COLOR_3DHIGHLIGHT)); Rectangle(hDC, prg, 1, p_width-1, p_height-2); TRIVERTEX vert[4]; vert [0] .x = 1; vert [0] .y = 1; vert [0] .Red = 0xff00&DWORD(red*256); vert [0] .Green = 0xff00&DWORD(green*256); vert [0] .Blue = 0xff00&DWORD(blue*256); vert [0] .Alpha = 0x0000; vert [1] .x = center; vert [1] .y = p_height-2; vert [1] .Red = 0xff00&DWORD(red1*256); vert [1] .Green = 0xff00&DWORD(green1*256); vert [1] .Blue = 0xff00&DWORD(blue1*256); vert [1] .Alpha = 0x0000; vert [2] .x = center; vert [2] .y = 1; vert [2] .Red = 0xff00&DWORD(red1*256); vert [2] .Green = 0xff00&DWORD(green1*256); vert [2] .Blue = 0xff00&DWORD(blue1*256); vert [2] .Alpha = 0x0000; vert [3] .x = prg; vert [3] .y = p_height-2; vert [3] .Red = 0xff00&DWORD(red*256); vert [3] .Green = 0xff00&DWORD(green*256); vert [3] .Blue = 0xff00&DWORD(blue*256); vert [3] .Alpha = 0x0000; GRADIENT_RECT gr[2]; gr[0].UpperLeft=0; gr[0].LowerRight=1; gr[1].UpperLeft=2; gr[1].LowerRight=3; GradientFill(hDC,vert, 4, gr, 2, GRADIENT_FILL_RECT_H); ReleaseDC(hWnd, hDC); }
LRESULT VentanaDump::Evento_Pintar(HDC hDC, PAINTSTRUCT &PS) { RECT RC; GetClientRect(_hWnd, &RC); DWL::GDI::DWLhDC Buffer(hDC, RC.right, RC.bottom); // Creo la fuente para mostrar el error HFONT FuenteTahoma = CreateFont(15, 0, 0, 0, FW_BOLD, false, false, false, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, PROOF_QUALITY, FF_ROMAN, TEXT("Tahoma")); HFONT FuenteTahomaT = CreateFont(17, 0, 0, 0, FW_BOLD, false, false, false, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, PROOF_QUALITY, FF_ROMAN, TEXT("Tahoma")); HFONT FuenteVieja = static_cast<HFONT>(SelectObject(Buffer(), FuenteTahomaT)); // Pinto el fondo con un degradado TRIVERTEX GCVertex[2]; GRADIENT_RECT tGRect; COLORREF Col1 = DWL::SO::DWLEstilos::Colores.ControlEx_Fondo_DegradadoSuperior; COLORREF Col2 = DWL::SO::DWLEstilos::Colores.ControlEx_Fondo_DegradadoInferior; GCVertex[0].Red = DWL_RGB_OBTENER_R(Col1); GCVertex[0].Green = DWL_RGB_OBTENER_G(Col1); GCVertex[0].Blue = DWL_RGB_OBTENER_B(Col1); GCVertex[0].x = 0; GCVertex[0].y = 0; GCVertex[1].Red = DWL_RGB_OBTENER_R(Col2); GCVertex[1].Green = DWL_RGB_OBTENER_G(Col2); GCVertex[1].Blue = DWL_RGB_OBTENER_B(Col2); GCVertex[1].x = RC.right; GCVertex[1].y = RC.bottom; tGRect.UpperLeft = 0; tGRect.LowerRight = 1; GradientFill(Buffer(), GCVertex, 2, &tGRect, 1, DWLGRADIENT_FILL_RECT_V); UINT YT = 6; if (Sistema.App.Config.UtilizarBarraTituloWindows == false) { Buffer.PintarIcono(5, 5, 16, 16, IDI_DAP); _PintarTextoSombra(Buffer(), IDIOMA__ERROR_GRAVE, RGB(255,255,255), RGB(30, 30, 30), 25, 5); YT = 26; // Pinto el borde DWL::GDI::DWLBrocha Brocha(DWL::SO::DWLEstilos::Colores.ControlEx_Borde_Claro); DWL::GDI::DWLRegion Region(_hWnd); Buffer.EnmarcarRegion(&Region, &Brocha, VENTANAEX_BORDE, VENTANAEX_BORDE); Brocha.AsignarColor(DWL::SO::DWLEstilos::Colores.ControlEx_Borde_Normal); Buffer.EnmarcarRegion(&Region, &Brocha, VENTANAEX_BORDECLARO, VENTANAEX_BORDECLARO); } else { YT = 6; } Buffer.PintarIcono(5, YT + 5, 48, 48, IDI_ERRORFATAL); SelectObject(Buffer(), FuenteTahoma); _PintarTextoSombra(Buffer(), IDIOMA__HA_SUCEDIDO_UN_ERROR_GRAVE_EN_BUBATRONIK_Y_ESTE_DEBE_CERRARSE, RGB(255,255,255), RGB(30, 30, 30), 60, YT); _PintarTextoSombra(Buffer(), IDIOMA__SE_HA_CREADO_UN_INFORME_DE_ERRORES_DESEAS_ENVIARLO_A_WWW_DEVILDREY33_ES, RGB(255,255,255), RGB(30, 30, 30), 60, YT + 16); _PintarTextoSombra(Buffer(), IDIOMA__PULSA_EL_BOTON_ENVIAR_PARA_ENVIAR_EL_MENSAJE_Y_TERMINAR_O_PULSA_EL_BOTON, RGB(255,255,255), RGB(30, 30, 30), 60, YT + 32); _PintarTextoSombra(Buffer(), IDIOMA__TERMINAR_PARA_QUE_NO_SE_MANDE_EL_MENSAJE, RGB(255,255,255), RGB(30, 30, 30), 60, YT + 48); // Pinto el texto // DWL::DWLString Descripcion = TEXT("Ha ocurrido un error grave en la aplicación, y esta debe cerrarse.\nSi lo deseas puedes crear un archivo con información detallada sobre el error.\nEste archivo no contiene ningún dato confidencial, y puede ser de gran ayuda para encontrar y\nreparar errores infrecuentes en las aplicaciones.\nNOTA : en windows vista y superiores es recomendable guardar el archivo en la ruta inicial.\nPresiona Guardar para guardar el archivo de log y salir, o Terminar para salir."); // Elimino objetos de la memoria SelectObject(Buffer(), FuenteVieja); DeleteObject(FuenteTahoma); DeleteObject(FuenteTahomaT); BitBlt(hDC, 0, 0, RC.right, RC.bottom, Buffer(), 0, 0, SRCCOPY); return 0; };
HDC NT5_DrawBaseBackground(HDC hdcDesktop) { HBITMAP hBitmap = NULL; HDC hdcMem = NULL; BOOL bRet = FALSE; /* Create an an off screen DC to match the desktop DC */ hdcMem = CreateCompatibleDC(hdcDesktop); if (hdcMem) { /* Create a bitmap to draw the logoff screen onto */ hBitmap = CreateCompatibleBitmap(hdcDesktop, g_pInfo->cx, g_pInfo->cy); if (hBitmap) { /* Select it onto our off screen DC*/ SelectObject(hdcMem, hBitmap); /* Draw the centre block */ { HBITMAP hTempBitmap; HBRUSH hBrush; BITMAP bitmap; HDC hTempDC; /* Paint the blue centre block */ hBrush = CreateSolidBrush(RGB(90, 126, 220)); SelectObject(hdcMem, hBrush); PatBlt(hdcMem, 0, NT5_TOP_BORDER_HEIGHT, g_pInfo->cx, g_pInfo->cy - NT5_TOP_BORDER_HEIGHT - NT5_BOTTOM_BORDER_HEIGHT, PATCOPY); DeleteObject(hBrush); /* Load the shine effect */ hTempBitmap = (HBITMAP)LoadImageW(g_pInfo->hInstance, MAKEINTRESOURCEW(IDB_MAIN_PANEL_SHINE), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR); if (hTempBitmap) { /* Get the bitmap dimensions */ GetObjectW(hTempBitmap, sizeof(BITMAP), &bitmap); /* Create a temp DC for the bitmap */ hTempDC = CreateCompatibleDC(hdcDesktop); if (hTempDC) { /* Select the bitmap onto the temp DC */ SelectObject(hTempDC, hTempBitmap); /* Paint it onto the top left of the centre block */ BitBlt(hdcMem, 0, NT5_TOP_BORDER_HEIGHT, bitmap.bmWidth, bitmap.bmHeight, hTempDC, 0, 0, SRCCOPY); /* Delete the DC */ DeleteDC(hTempDC); } /* Delete the bitmap */ DeleteObject(hTempBitmap); } } /* Draw the top border */ { HBITMAP hTempBitmap; HBRUSH hBrush; BITMAP bitmap; HDC hTempDC; /* Create the blue brush and paint the top bar */ hBrush = CreateSolidBrush(RGB(0, 48, 156)); SelectObject(hdcMem, hBrush); PatBlt(hdcMem, 0, 0, g_pInfo->cx, NT5_TOP_BORDER_HEIGHT, PATCOPY); DeleteObject(hBrush); /* Load the top divider strip */ hTempBitmap = (HBITMAP)LoadImageW(g_pInfo->hInstance, MAKEINTRESOURCEW(IDB_TOP_DIVIDER_STRIP), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR); if (hTempBitmap) { /* Get the bitmap dimensions */ GetObjectW(hTempBitmap, sizeof(BITMAP), &bitmap); /* Create a temp DC for the bitmap */ hTempDC = CreateCompatibleDC(hdcDesktop); if (hTempDC) { /* Select the bitmap onto the temp DC */ SelectObject(hTempDC, hTempBitmap); /* Paint the bitmap */ StretchBlt(hdcMem, 0, NT5_TOP_BORDER_HEIGHT - bitmap.bmHeight, g_pInfo->cx, NT5_TOP_BORDER_HEIGHT, hTempDC, 0, 0, bitmap.bmWidth, NT5_TOP_BORDER_HEIGHT, SRCCOPY); /* Delete the DC */ DeleteDC(hTempDC); } /* Delete the bitmap */ DeleteObject(hTempBitmap); } } /* Draw the bottom border */ { HBITMAP hTempBitmap; TRIVERTEX vertex[2]; GRADIENT_RECT gRect; BITMAP bitmap; HDC hTempDC; /* * We paint the divider strip first as it's 3 * pixels high but MS only show 2 of them. */ /* Load the bottom divider strip */ hTempBitmap = (HBITMAP)LoadImage(g_pInfo->hInstance, MAKEINTRESOURCE(IDB_BOTTOM_DIVIDER_STRIP), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR); if (hTempBitmap) { /* Get the bitmap dimensions */ GetObjectW(hTempBitmap, sizeof(BITMAP), &bitmap); /* Create a temp DC for the bitmap */ hTempDC = CreateCompatibleDC(hdcDesktop); if (hTempDC) { /* Select the bitmap onto the temp DC */ SelectObject(hTempDC, hTempBitmap); /* Paint the bitmap */ StretchBlt(hdcMem, 0, g_pInfo->cy - NT5_BOTTOM_BORDER_HEIGHT, g_pInfo->cx, g_pInfo->cy - NT5_BOTTOM_BORDER_HEIGHT + bitmap.bmHeight, hTempDC, 0, 0, bitmap.bmWidth, g_pInfo->cy - NT5_BOTTOM_BORDER_HEIGHT + bitmap.bmHeight, SRCCOPY); /* Delete the DC */ DeleteDC(hTempDC); } /* Delete the bitmap */ DeleteObject(hTempBitmap); } /* Setup the left hand vertex */ vertex[0].x = 0; vertex[0].y = g_pInfo->cy - NT5_BOTTOM_BORDER_HEIGHT + 2; // paint over 1 pixel of the bitmap vertex[0].Red = 0x3900; vertex[0].Green = 0x3400; vertex[0].Blue = 0xAE00; vertex[0].Alpha = 0x0000; /* Setup the right hand vertex */ vertex[1].x = g_pInfo->cx; vertex[1].y = g_pInfo->cy; vertex[1].Red = 0x0000; vertex[1].Green = 0x3000; vertex[1].Blue = 0x9600; vertex[1].Alpha = 0x0000; /* Set the vertex structs */ gRect.UpperLeft = 0; gRect.LowerRight = 1; /* Paint the gradient across the bottom */ GradientFill(hdcMem, vertex, 2, &gRect, 1, GRADIENT_FILL_RECT_H); } /* Delete the bitmap */ DeleteObject(hBitmap); } } return hdcMem; }
static void drawButton( HDC hButtDc, wIcon_p bm, BOOL_T selected, BOOL_T disabled ) { HGDIOBJ oldBrush, newBrush; HPEN oldPen, newPen; RECT rect; COLORREF color1, color2; POS_T offw=5, offh=5; TRIVERTEX vert[2] ; GRADIENT_RECT gRect; COLORREF colL; COLORREF colD; COLORREF colF; #define LEFT (0) #define RIGHT (bm->w+10) #define TOP (0) #define BOTTOM (bm->h+10) /* get the lightest and the darkest color to use */ colL = GetSysColor( COLOR_BTNHIGHLIGHT ); colD = GetSysColor( COLOR_BTNSHADOW ); colF = GetSysColor( COLOR_BTNFACE ); /* define the rectangle for the button */ rect.top = TOP; rect.left = LEFT; rect.right = RIGHT; rect.bottom = BOTTOM; /* fill the button with the face color */ newBrush = CreateSolidBrush( colF ); oldBrush = SelectObject( hButtDc, newBrush ); FillRect( hButtDc, &rect, newBrush ); DeleteObject( SelectObject( hButtDc, oldBrush ) ); /* disabled button remain flat */ if( !disabled ) { /* select colors for the gradient */ if( selected ) { color1 = colD; color2 = colL; } else { color1 = colL; color2 = colD; } #define GRADIENT_WIDTH 6 /* first draw the top gradient this always ends in the button face color starting color depends on button state (selected or not) */ vert [0] .x = LEFT; vert [0] .y = TOP; vert [0] .Red = GetRValue( color1 )* 256; vert [0] .Green = GetGValue( color1 )* 256; vert [0] .Blue = GetBValue( color1 )* 256; vert [0] .Alpha = 0x0000; vert [1] .x = RIGHT; vert [1] .y = TOP + GRADIENT_WIDTH; vert [1] .Red = GetRValue( colF )* 256; vert [1] .Green = GetGValue( colF )* 256; vert [1] .Blue = GetBValue( colF )* 256; vert [1] .Alpha = 0x0000; gRect.UpperLeft = 0; gRect.LowerRight = 1; GradientFill(hButtDc, vert, 2, &gRect, 1, GRADIENT_FILL_RECT_V); /* now draw the bottom gradient this always starts with the button face color ending color depends on button state (selected or not) */ vert [0] .x = LEFT; vert [0] .y = BOTTOM - GRADIENT_WIDTH; vert [0] .Red = GetRValue( colF )* 256; vert [0] .Green = GetGValue( colF )* 256; vert [0] .Blue = GetBValue( colF )* 256; vert [0] .Alpha = 0x0000; vert [1] .x = RIGHT; vert [1] .y = BOTTOM; vert [1] .Red = GetRValue( color2 )* 256; vert [1] .Green = GetGValue( color2 )* 256; vert [1] .Blue = GetBValue( color2 )* 256; vert [1] .Alpha = 0x0000; gRect.UpperLeft = 0; gRect.LowerRight = 1; GradientFill(hButtDc, vert, 2, &gRect, 1, GRADIENT_FILL_RECT_V); } /* draw delimiting lines in shadow color */ newPen = CreatePen( PS_SOLID, 0, colD ); oldPen = SelectObject( hButtDc, newPen ); MoveTo( hButtDc, LEFT, TOP ); LineTo( hButtDc, LEFT, BOTTOM ); MoveTo( hButtDc, RIGHT, TOP ); LineTo( hButtDc, RIGHT, BOTTOM ); DeleteObject( SelectObject( hButtDc, oldPen ) ); color2 = GetSysColor( COLOR_BTNSHADOW ); color1 = RGB( bm->colormap[ 1 ].rgbRed, bm->colormap[ 1 ].rgbGreen, bm->colormap[ 1 ].rgbBlue ); if (selected) { offw++; offh++; } mswDrawIcon( hButtDc, offw, offh, bm, disabled, color1, color2 ); }
void TaskSortFieldSelector::PaintBuffer(HWND hwnd, HDC dc, int width, int height) { SelectObject(dc, GetStockObject(DC_BRUSH)); SelectObject(dc, GetStockObject(DC_PEN)); SetDCBrushColor(dc, 0x00eaeade); SetDCPenColor(dc, 0x00eaeade); Rectangle(dc, 0, 0, width, height); TRIVERTEX vert[2] ; GRADIENT_RECT gRect; vert [0] .x = 0; vert [0] .y = 0; vert [0] .Red = 0xdb00; vert [0] .Green = 0xdb00; vert [0] .Blue = 0xdb00; vert [0] .Alpha = 0x0000; vert [1] .x = width; vert [1] .y = height; vert [1] .Red = 0xfd00; vert [1] .Green = 0xfd00; vert [1] .Blue = 0xfd00; vert [1] .Alpha = 0x0000; gRect.UpperLeft = 0; gRect.LowerRight = 1; GradientFill(dc,vert,2,&gRect,1,GRADIENT_FILL_RECT_H); SelectObject(dc, s_hfont); long h = Util::CalcFontHeight(dc) + 4; long x = 4; long y = 2; SetBkMode(dc, TRANSPARENT); RECT rs = { x, y, width - x, y + h }; for(int i = COMPARE_NONE; i < COMPARE_COUNT; i++) { RECT rb = {0, rs.top, width, rs.top + h}; if(hilite == i) { vert [0] .x = rb.left; vert [0] .y = rb.top; vert [0] .Red = 0xfe00; vert [0] .Green = 0xfe00; vert [0] .Blue = 0xfe00; vert [0] .Alpha = 0x0000; vert [1] .x = rb.right; vert [1] .y = rb.bottom; vert [1] .Red = 0xe000; vert [1] .Green = 0xe000; vert [1] .Blue = 0xe000; vert [1] .Alpha = 0x0000; GradientFill(dc,vert,2,&gRect,1,GRADIENT_FILL_RECT_H); } ExtTextOut(dc, rs.left, rs.top, ETO_CLIPPED, &rs, m_pStrings->m_sbStrings[i], m_pStrings->m_sbStrings[i].getLength(), 0); itemRects[i].left = rs.left; itemRects[i].top = rs.top; itemRects[i].right = rs.right; itemRects[i].bottom = rs.bottom; OffsetRect(&rs, 0, h); } }
LRESULT CALLBACK DlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { char sTitle[100]="title"; PAINTSTRUCT ps; static HDC dc; static RECT r; LPDRAWITEMSTRUCT dItem; char text[20]; int len; SIZE sz; HBRUSH hB; // brush handle static HINSTANCE hInst; static RECT btnrect; // The struct that WM_DRAWITEM needs: static DRAWITEMSTRUCT* pdis; // Width and height of the client area: static long cxClient, cyClient; TCHAR s[BUFFSIZE]; int iResult; HWND hLevelUpButton,hLevelDnButton; HWND hButton; switch (uMsg) { case WM_INITDIALOG:// WM_INITDIALOG message is sent before dialog is displayed { hButton = CreateWindow(TEXT("button"), TEXT("Beep"), WS_VISIBLE | WS_CHILD , 20, 50, 80, 25, hwndDlg, (HMENU) 1, NULL, NULL); GetWindowText(hButton,sTitle,sizeof(sTitle)/sizeof(char)); //~ MessageBoxPrintf("hi",sTitle); hButton = CreateWindow(TEXT("button"), TEXT("Quit!"), WS_VISIBLE | WS_CHILD|BS_OWNERDRAW, 120, 50, 80, 25, hwndDlg, (HMENU) 2, NULL, NULL); //~ // 2. A button with style BS_OWNERDRAW //~ // This is what the article is about :) //~ hLevelUpButton = CreateWindow(_T("button"), TEXT("Beep"), //~ WS_CHILD | WS_VISIBLE|BS_OWNERDRAW, //~ 0,0,40,30, //~ hwndDlg, //~ (HMENU) IDC_BUTTON1, //~ hInst, //~ NULL); //~ if (NULL == hLevelUpButton) { //~ _stprintf(s, _T("! hLevelUpButton NULL")); //~ myWriteToLog(s); //~ } //~ // 3. Second owner draw button: //~ hLevelDnButton = CreateWindow(_T("button"), NULL, //~ WS_CHILD | WS_VISIBLE | BS_OWNERDRAW, //~ 0,0,0,0, //~ hwndDlg, //~ (HMENU) IDC_BUTTON2, //~ hInst, //~ NULL); //~ if (NULL == hLevelDnButton) { //~ _stprintf(s, _T("! hLevelDnButton NULL")); //~ myWriteToLog(s); //~ } return TRUE; } break; case WM_DRAWITEM: dItem = (DRAWITEMSTRUCT*)lParam; SetBkColor(dItem->hDC, RGB(255,0,0)); SetTextColor(dItem->hDC, RGB(0,0,0xFF)); memset(text, '\0', 20); GetWindowText(dItem->hwndItem, text, 20); len=lstrlen(text); GetTextExtentPoint32(dItem->hDC, text, len, &sz); ExtTextOut( dItem->hDC, ((dItem->rcItem.right - dItem->rcItem.left) / 2) + dItem->rcItem.left - (sz.cx / 2), ((dItem->rcItem.bottom - dItem->rcItem.top) / 2) + dItem->rcItem.top - (sz.cy / 2), ETO_OPAQUE | ETO_CLIPPED, &dItem->rcItem, text, len, NULL); DrawEdge( dItem->hDC, &dItem->rcItem, (dItem->itemState & ODS_SELECTED ? BDR_SUNKENOUTER : BDR_RAISEDOUTER), BF_RECT); return DefWindowProc(hwndDlg, uMsg, wParam, lParam); break; case WM_CREATE: { //~ DRAWITEMSTRUCT *dis = (LPDRAWITEMSTRUCT)lParam; //~ HDC hDC = dis->hDC; //~ HWND hwndDlg = dis->hwndItem; //~ RECT r; //~ GetClientRect(hwndDlg, &r); //~ FrameRect(hDC,&r,(HBRUSH)GetStockObject(BLACK_BRUSH)); // 2. A button with style BS_OWNERDRAW // This is what the article is about :) } break; case WM_COMMAND:// { switch(wParam) { case IDC_BUTTON1: { //~ MessageBoxPrintf("hi","%s\n",buff); } break; case IDC_BUTTON2: { } break; default: break; } return TRUE; } break; case WM_CLOSE://Massage for terminate/exit (may close button clicked on title bar) { //Close dialog EndDialog(hwndDlg,0); break; } //~ case WM_CTLCOLORDLG: //set its text and background colors using the specified display device context handle. case WM_CTLCOLORBTN: { hB = CreateSolidBrush(RGB(255,0,0)); return (LONG)hB; break; } case WM_PAINT: { PAINTSTRUCT ps; TRIVERTEX vert[2]; RECT r; GRADIENT_RECT gRect; HDC hDC = BeginPaint(hwndDlg,&ps); GetClientRect(hwndDlg,&r); vert[0].Alpha = 0x0000; vert[0].Red = 0xff00; vert[0].Green = 0x0000; vert[0].Blue = 0x8800; vert[0].x = r.left; vert[0].y = r.top; vert[1].Alpha = 0x0000; vert[1].Red = 0xff00; vert[1].Green = 0xff00; vert[1].Blue = 0xff00; vert[1].x = r.right; vert[1].y = r.bottom; gRect.UpperLeft = 0; gRect.LowerRight = 1; GradientFill(hDC,vert,2,&gRect,1,GRADIENT_FILL_RECT_H); EndPaint(hwndDlg,&ps); break; } case WM_CTLCOLORSTATIC: //可以控制静态控件的颜色 { break; } default: break; } return FALSE; }