// Windows uses regions only to specify the clip mask of a window therefore // we must convert our bitmap to a region. // Much of this code is "borrowed" from the Windows version of GTK // (also LGPLed). Their code was based on code originally written by // Jean-Edouard Lachand-Robert. Ain't open source great? // // Modified by me to use an Fl_Bitmap, to not hog memory, to not leak memory // (I hope) and to allow bitmaps of arbitrary dimensions. -CET static HRGN bitmap2region(Fl_Bitmap* bitmap) { HRGN hRgn = 0; /* For better performances, we will use the ExtCreateRegion() * function to create the region. This function take a RGNDATA * structure on entry. We will add rectangles by amount of * ALLOC_UNIT number in this structure. */ #define ALLOC_UNIT 100 DWORD maxRects = ALLOC_UNIT; RGNDATA* pData = (RGNDATA*)malloc(sizeof(RGNDATAHEADER)+(sizeof(RECT)*maxRects)); pData->rdh.dwSize = sizeof(RGNDATAHEADER); pData->rdh.iType = RDH_RECTANGLES; pData->rdh.nCount = pData->rdh.nRgnSize = 0; SetRect(&pData->rdh.rcBound, MAXLONG, MAXLONG, 0, 0); // number of bytes per line of pixels const int bpl = (bitmap->width()+7)/8; BYTE* p8 = (BYTE*)bitmap->array; BYTE* p; for (int y = 0; y < bitmap->height(); y++) { /* Scan each bitmap row from left to right*/ for (int x = 0; x < bitmap->width(); x++) { /* Search for a continuous range of "non transparent pixels"*/ int x0 = x; while (x < bitmap->width()) { p = p8 + x / 8; /* This pixel is "transparent"*/ if (!((*p) & bit(x))) break; x++; } if (x > x0) { RECT* pr; /* Add the pixels (x0, y) to (x, y+1) as a new rectangle * in the region */ if (pData->rdh.nCount >= maxRects) { maxRects += ALLOC_UNIT; pData = (RGNDATA*)realloc(pData, sizeof(RGNDATAHEADER) + (sizeof(RECT)*maxRects)); } pr = (RECT*)&pData->Buffer; SetRect(&pr[pData->rdh.nCount], x0, y, x, y+1); if (x0 < pData->rdh.rcBound.left) pData->rdh.rcBound.left = x0; if (y < pData->rdh.rcBound.top) pData->rdh.rcBound.top = y; if (x > pData->rdh.rcBound.right) pData->rdh.rcBound.right = x; if (y+1 > pData->rdh.rcBound.bottom) pData->rdh.rcBound.bottom = y+1; pData->rdh.nCount++; /* On Windows98, ExtCreateRegion() may fail if the * number of rectangles is too large (ie: > * 4000). Therefore, we have to create the region by * multiple steps. */ if (pData->rdh.nCount == 2000) { HRGN h = ExtCreateRegion(NULL, sizeof(RGNDATAHEADER) + (sizeof(RECT)*maxRects), pData); if (hRgn) { CombineRgn(hRgn, hRgn, h, RGN_OR); DeleteObject(h); } else hRgn = h; pData->rdh.nCount = 0; SetRect(&pData->rdh.rcBound, MAXLONG, MAXLONG, 0, 0); } } } /* Go to next row */ p8 += bpl; } /* Create or extend the region with the remaining rectangles*/ HRGN h = ExtCreateRegion(NULL, sizeof(RGNDATAHEADER) + (sizeof(RECT)*maxRects), pData); if (hRgn) { CombineRgn(hRgn, hRgn, h, RGN_OR); DeleteObject(h); } else hRgn = h; free(pData); // I've created the region so I can free this now, right? return hRgn; }
HRGN CreateRgnFromBitmap(CDC *pDC, int iWidth, int iHeight, COLORREF color) { const DWORD RDHDR = sizeof(RGNDATAHEADER); const DWORD MAXBUF = 40; // size of one block in RECTs // (i.e. MAXBUF*sizeof(RECT) in bytes) LPRECT pRects; DWORD cBlocks = 0; // number of allocated blocks INT i, j; // current position in mask image INT first = 0; // left position of current scan line // where mask was found bool wasfirst = false; // set when if mask was found in current scan line bool ismask; // set when current color is mask color // allocate memory for region data RGNDATAHEADER* pRgnData = (RGNDATAHEADER*)new BYTE[ RDHDR + ++cBlocks * MAXBUF * sizeof(RECT) ]; memset( pRgnData, 0, RDHDR + cBlocks * MAXBUF * sizeof(RECT) ); // fill it by default pRgnData->dwSize = RDHDR; pRgnData->iType = RDH_RECTANGLES; pRgnData->nCount = 0; for ( i = 0; i < iHeight; i++ ) for ( j = 0; j < iWidth; j++ ){ // get color ismask=(pDC->GetPixel(j,iHeight-i-1)!=color); // place part of scan line as RECT region if transparent color found after mask color or // mask color found at the end of mask image if (wasfirst && ((ismask && (j==(iWidth-1)))||(ismask ^ (j<iWidth)))){ // get offset to RECT array if RGNDATA buffer pRects = (LPRECT)((LPBYTE)pRgnData + RDHDR); // save current RECT pRects[ pRgnData->nCount++ ] = CRect( first, iHeight - i - 1, j+(j==(iWidth-1)), iHeight - i ); // if buffer full reallocate it if ( pRgnData->nCount >= cBlocks * MAXBUF ){ LPBYTE pRgnDataNew = new BYTE[ RDHDR + ++cBlocks * MAXBUF * sizeof(RECT) ]; memcpy( pRgnDataNew, pRgnData, RDHDR + (cBlocks - 1) * MAXBUF * sizeof(RECT) ); delete[] pRgnData; pRgnData = (RGNDATAHEADER*)pRgnDataNew; } wasfirst = false; } else if ( !wasfirst && ismask ){ // set wasfirst when mask is found first = j; wasfirst = true; } } // create region /* Under WinNT the ExtCreateRegion returns NULL (by [email protected]) */ // HRGN hRgn = ExtCreateRegion( NULL, RDHDR + pRgnData->nCount * sizeof(RECT), (LPRGNDATA)pRgnData ); /* ExtCreateRegion replacement { */ HRGN hRgn=CreateRectRgn(0, 0, 0, 0); ASSERT( hRgn!=NULL ); pRects = (LPRECT)((LPBYTE)pRgnData + RDHDR); for(i=0;i<(int)pRgnData->nCount;i++) { HRGN hr=CreateRectRgn(pRects[i].left, pRects[i].top, pRects[i].right, pRects[i].bottom); VERIFY(CombineRgn(hRgn, hRgn, hr, RGN_OR)!=ERROR); if (hr) DeleteObject(hr); } ASSERT( hRgn!=NULL ); /* } ExtCreateRegion replacement */ delete[] pRgnData; return hRgn; }
/****************************************************************************** * SetBitmapBits [GDI32.@] * * Sets bits of color data for a bitmap. * * RETURNS * Success: Number of bytes used in setting the bitmap bits * Failure: 0 */ LONG WINAPI SetBitmapBits( HBITMAP hbitmap, /* [in] Handle to bitmap */ LONG count, /* [in] Number of bytes in bitmap array */ LPCVOID bits) /* [in] Address of array with bitmap bits */ { char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )]; BITMAPINFO *info = (BITMAPINFO *)buffer; BITMAPOBJ *bmp; DWORD err; int i, src_stride, dst_stride; struct bitblt_coords src, dst; struct gdi_image_bits src_bits; HRGN clip = NULL; if (!bits) return 0; bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP ); if (!bmp) return 0; if (count < 0) { WARN("(%d): Negative number of bytes passed???\n", count ); count = -count; } src_stride = get_bitmap_stride( bmp->dib.dsBm.bmWidth, bmp->dib.dsBm.bmBitsPixel ); count = min( count, src_stride * bmp->dib.dsBm.bmHeight ); dst_stride = get_dib_stride( bmp->dib.dsBm.bmWidth, bmp->dib.dsBm.bmBitsPixel ); src.visrect.left = src.x = 0; src.visrect.top = src.y = 0; src.visrect.right = src.width = bmp->dib.dsBm.bmWidth; src.visrect.bottom = src.height = (count + src_stride - 1 ) / src_stride; dst = src; if (count % src_stride) { HRGN last_row; int extra_pixels = ((count % src_stride) << 3) / bmp->dib.dsBm.bmBitsPixel; if ((count % src_stride << 3) % bmp->dib.dsBm.bmBitsPixel) FIXME( "Unhandled partial pixel\n" ); clip = CreateRectRgn( src.visrect.left, src.visrect.top, src.visrect.right, src.visrect.bottom - 1 ); last_row = CreateRectRgn( src.visrect.left, src.visrect.bottom - 1, src.visrect.left + extra_pixels, src.visrect.bottom ); CombineRgn( clip, clip, last_row, RGN_OR ); DeleteObject( last_row ); } TRACE("(%p, %d, %p) %dx%d %d bpp fetched height: %d\n", hbitmap, count, bits, bmp->dib.dsBm.bmWidth, bmp->dib.dsBm.bmHeight, bmp->dib.dsBm.bmBitsPixel, src.height ); if (src_stride == dst_stride) { src_bits.ptr = (void *)bits; src_bits.is_copy = FALSE; src_bits.free = NULL; } else { if (!(src_bits.ptr = HeapAlloc( GetProcessHeap(), 0, dst.height * dst_stride ))) { GDI_ReleaseObj( hbitmap ); return 0; } src_bits.is_copy = TRUE; src_bits.free = free_heap_bits; for (i = 0; i < count / src_stride; i++) memcpy( (char *)src_bits.ptr + i * dst_stride, (char *)bits + i * src_stride, src_stride ); if (count % src_stride) memcpy( (char *)src_bits.ptr + i * dst_stride, (char *)bits + i * src_stride, count % src_stride ); } /* query the color info */ info->bmiHeader.biSize = sizeof(info->bmiHeader); info->bmiHeader.biPlanes = 1; info->bmiHeader.biBitCount = bmp->dib.dsBm.bmBitsPixel; info->bmiHeader.biCompression = BI_RGB; info->bmiHeader.biXPelsPerMeter = 0; info->bmiHeader.biYPelsPerMeter = 0; info->bmiHeader.biClrUsed = 0; info->bmiHeader.biClrImportant = 0; info->bmiHeader.biWidth = 0; info->bmiHeader.biHeight = 0; info->bmiHeader.biSizeImage = 0; err = put_image_into_bitmap( bmp, 0, info, NULL, NULL, NULL ); if (!err || err == ERROR_BAD_FORMAT) { info->bmiHeader.biWidth = bmp->dib.dsBm.bmWidth; info->bmiHeader.biHeight = -dst.height; info->bmiHeader.biSizeImage = dst.height * dst_stride; err = put_image_into_bitmap( bmp, clip, info, &src_bits, &src, &dst ); } if (err) count = 0; if (clip) DeleteObject( clip ); if (src_bits.free) src_bits.free( &src_bits ); GDI_ReleaseObj( hbitmap ); return count; }
HRGN CTaskbarNotifier::CreateRgnFromBitmap(HBITMAP hBmp, COLORREF color) { if (!hBmp) return NULL; CDC* pDC = GetDC(); if (!pDC) return NULL; BITMAP bm; GetObject( hBmp, sizeof(BITMAP), &bm ); // get bitmap attributes CDC dcBmp; dcBmp.CreateCompatibleDC(pDC); //Creates a memory device context for the bitmap HGDIOBJ hOldBmp = dcBmp.SelectObject(hBmp); //selects the bitmap in the device context const DWORD RDHDR = sizeof(RGNDATAHEADER); const DWORD MAXBUF = 40; // size of one block in RECTs // (i.e. MAXBUF*sizeof(RECT) in bytes) LPRECT pRects; DWORD cBlocks = 0; // number of allocated blocks INT i, j; // current position in mask image INT first = 0; // left position of current scan line // where mask was found bool wasfirst = false; // set when if mask was found in current scan line bool ismask; // set when current color is mask color // allocate memory for region data RGNDATAHEADER* pRgnData = (RGNDATAHEADER*)new BYTE[ RDHDR + ++cBlocks * MAXBUF * sizeof(RECT) ]; memset( pRgnData, 0, RDHDR + cBlocks * MAXBUF * sizeof(RECT) ); // fill it by default pRgnData->dwSize = RDHDR; pRgnData->iType = RDH_RECTANGLES; pRgnData->nCount = 0; for ( i = 0; i < bm.bmHeight; i++ ) for ( j = 0; j < bm.bmWidth; j++ ){ // get color ismask=(dcBmp.GetPixel(j,bm.bmHeight-i-1)!=color); // place part of scan line as RECT region if transparent color found after mask color or // mask color found at the end of mask image if (wasfirst && ((ismask && (j==(bm.bmWidth-1)))||(ismask ^ (j<bm.bmWidth)))){ // get offset to RECT array if RGNDATA buffer pRects = (LPRECT)((LPBYTE)pRgnData + RDHDR); // save current RECT pRects[ pRgnData->nCount++ ] = CRect( first, bm.bmHeight - i - 1, j+(j==(bm.bmWidth-1)), bm.bmHeight - i ); // if buffer full reallocate it if ( pRgnData->nCount >= cBlocks * MAXBUF ){ LPBYTE pRgnDataNew = new BYTE[ RDHDR + ++cBlocks * MAXBUF * sizeof(RECT) ]; memcpy( pRgnDataNew, pRgnData, RDHDR + (cBlocks - 1) * MAXBUF * sizeof(RECT) ); delete[] pRgnData; pRgnData = (RGNDATAHEADER*)pRgnDataNew; } wasfirst = false; } else if ( !wasfirst && ismask ){ // set wasfirst when mask is found first = j; wasfirst = true; } } dcBmp.SelectObject(hOldBmp); dcBmp.DeleteDC(); //release the bitmap // create region /* Under WinNT the ExtCreateRegion returns NULL (by [email protected]) */ // HRGN hRgn = ExtCreateRegion( NULL, RDHDR + pRgnData->nCount * sizeof(RECT), (LPRGNDATA)pRgnData ); /* ExtCreateRegion replacement { */ HRGN hRgn=CreateRectRgn(0, 0, 0, 0); ASSERT( hRgn!=NULL ); pRects = (LPRECT)((LPBYTE)pRgnData + RDHDR); for(i=0;i<(int)pRgnData->nCount;i++) { HRGN hr=CreateRectRgn(pRects[i].left, pRects[i].top, pRects[i].right, pRects[i].bottom); VERIFY(CombineRgn(hRgn, hRgn, hr, RGN_OR)!=ERROR); if (hr) DeleteObject(hr); } ASSERT( hRgn!=NULL ); /* } ExtCreateRegion replacement */ delete[] pRgnData; ReleaseDC(pDC); return hRgn; }
LRESULT CFrameHolder::OnNcPaint(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { RecalculateFrameSizes(); if (!gpSet->isTabsInCaption) { LRESULT lRc = DefWindowProc(hWnd, uMsg, wParam, lParam); return lRc; } FrameDrawStyle fdt = gpConEmu->DrawType(); if (fdt == fdt_Aero || fdt == fdt_Win8) { LRESULT lRc = DefWindowProc(hWnd, uMsg, wParam, lParam); //TODO: Может быть на "стекле" сразу рисовать, а не в WM_PAINT? return lRc; } if (!gpSet->isTabs) { return DefWindowProc(hWnd, uMsg, wParam, lParam); } RECT dirty_box, dirty, wr = {}, tr = {}, cr = {}, xorRect; BOOL fRegionOwner = FALSE; HDC hdc; HRGN hrgn = (HRGN)wParam; GetWindowRect(hWnd, &wr); CalculateCaptionPosition(wr, &cr); CalculateTabPosition(wr, cr, &tr); // --- Регион формируем всегда сами, иначе в некоторых случаях (XP+ Theming) // --- при выезжании окна из-за пределов экрана (обратно в видимую область) // --- сильно мелькает текст в заголовке //Create a region which covers the whole window. This //must be in screen coordinates //if(TRUE || hrgn == (HRGN)1 || hrgn == NULL) { hrgn = CreateRectRgnIndirect(&wr); dirty_box = wr; fRegionOwner = TRUE; //#ifdef _DEBUG // wchar_t szDbg[255]; // wsprintf(szDbg, L"CFrameHolder::OnNcPaint - New region({%ix%i}-{%ix%i})\n", wr.left,wr.top,wr.right,wr.bottom); // OutputDebugStringW(szDbg); //#endif } //else //{ // GetRgnBox((HRGN)wParam, &dirty_box); // #ifdef _DEBUG // wchar_t szDbg[255]; // wsprintf(szDbg, L"CFrameHolder::OnNcPaint - Existing region({%ix%i}-{%ix%i})\n", dirty_box.left,dirty_box.top,dirty_box.right,dirty_box.bottom); // OutputDebugStringW(szDbg); // #endif //} xorRect = tr; xorRect.top = cr.top; if (gpConEmu->DrawType() == fdt_Aero) { } else if (gpConEmu->DrawType() == fdt_Themed) { xorRect.left = cr.left; xorRect.right = cr.right; } else { xorRect.left = cr.left; //xorRect.right = cr.right; } OffsetRect(&xorRect, wr.left, wr.top); if (IntersectRect(&dirty, &dirty_box, &xorRect)) { // This must be in screen coordinates HRGN hrgn1 = CreateRectRgnIndirect(&xorRect); //Cut out a button-shaped hole CombineRgn(hrgn, hrgn, hrgn1, RGN_XOR); DeleteObject(hrgn1); } //#ifdef _DEBUG //else //{ // OutputDebugStringW(L"CFrameHolder::OnNcPaint --- IntersectRect failed\n"); //} //#endif //if (!mb_NcAnimate) DefWindowProc(hWnd, uMsg, (WPARAM)hrgn, lParam); //#ifdef _DEBUG // Sleep(150); //#endif // Собственно отрисовка табов hdc = GetWindowDC(hWnd); //HRGN hdcrgn = CreateRectRgn(cr.left, cr.top, cr.right, tr.bottom); //hdc = GetDCEx(hWnd, hdcrgn, DCX_INTERSECTRGN); PaintDC dc = {}; gpConEmu->BeginBufferedPaint(hdc, cr, dc); gpConEmu->mp_TabBar->PaintTabs(dc, cr, tr); gpConEmu->EndBufferedPaint(dc, TRUE); //if (mb_WasGlassDraw && gpConEmu->isZoomed()) //{ // //mb_WasGlassDraw = FALSE; // // Какой-то странный глюк DWM. При отключении Glass несколько верхних строк // // клиентской области оказываются "разрушенными" - у них остается атрибут "прозрачности" // // хотя прозрачность (Glass) уже отключена. В результате эти строки - белесые // BITMAPINFOHEADER bi = {sizeof(BITMAPINFOHEADER)}; // bi.biWidth = cr.right-cr.left+1; // bi.biHeight = GetFrameHeight()+1; // bi.biPlanes = 1; // bi.biBitCount = 32; // COLORREF *pPixels = NULL; // HDC hdcPaint = CreateCompatibleDC(hdc); // HBITMAP hbmp = CreateDIBSection(hdcPaint, (BITMAPINFO*)&bi, DIB_RGB_COLORS, (void**)&pPixels, NULL, 0); // HBITMAP hOldBmp = (HBITMAP)SelectObject(hdcPaint, hbmp); // //memset(pPixels, 0xFF, bi.biWidth*bi.biHeight*4); // int i = 0; // for (int y = 0; y < bi.biHeight; y++) // { // for (int x = 0; x < bi.biWidth; x++) // { // pPixels[i++] = 0xFF000000; // } // } // BitBlt(hdc, cr.left, tr.bottom, bi.biWidth, bi.biHeight, hdcPaint, 0, 0, SRCCOPY); // SelectObject(hdcPaint, hOldBmp); // DeleteObject(hbmp); // DeleteDC(hdcPaint); //} ReleaseDC(hWnd, hdc); if(fRegionOwner) DeleteObject(hrgn); return 0; }
static LRESULT CALLBACK MainWindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { CvWindow* window = icvWindowByHWND( hwnd ); if( !window ) return DefWindowProc(hwnd, uMsg, wParam, lParam); switch(uMsg) { case WM_DESTROY: icvRemoveWindow(window); // Do nothing!!! //PostQuitMessage(0); break; case WM_GETMINMAXINFO: if( !(window->flags & CV_WINDOW_AUTOSIZE) ) { MINMAXINFO* minmax = (MINMAXINFO*)lParam; RECT rect; LRESULT retval = DefWindowProc(hwnd, uMsg, wParam, lParam); minmax->ptMinTrackSize.y = 100; minmax->ptMinTrackSize.x = 100; if( window->toolbar.first ) { GetWindowRect( window->toolbar.first->hwnd, &rect ); minmax->ptMinTrackSize.y += window->toolbar.rows*(rect.bottom - rect.top); minmax->ptMinTrackSize.x = MAX(rect.right - rect.left + HG_BUDDY_WIDTH, HG_BUDDY_WIDTH*2); } return retval; } break; case WM_WINDOWPOSCHANGED: { WINDOWPOS* pos = (WINDOWPOS*)lParam; // Update the toolbar position/size if(window->toolbar.toolbar) { RECT rect; GetWindowRect(window->toolbar.toolbar, &rect); MoveWindow(window->toolbar.toolbar, 0, 0, pos->cx, rect.bottom - rect.top, TRUE); } if(!(window->flags & CV_WINDOW_AUTOSIZE)) icvUpdateWindowPos(window); break; } case WM_ACTIVATE: if(LOWORD(wParam) == WA_ACTIVE || LOWORD(wParam) == WA_CLICKACTIVE) SetFocus(window->hwnd); break; case WM_ERASEBKGND: { RECT cr, tr, wrc; HRGN rgn, rgn1, rgn2; int ret; HDC hdc = (HDC)wParam; GetWindowRect(window->hwnd, &cr); icvScreenToClient(window->frame, &cr); if(window->toolbar.toolbar) { GetWindowRect(window->toolbar.toolbar, &tr); icvScreenToClient(window->frame, &tr); } else tr.left = tr.top = tr.right = tr.bottom = 0; GetClientRect(window->frame, &wrc); rgn = CreateRectRgn(0, 0, wrc.right, wrc.bottom); rgn1 = CreateRectRgn(cr.left, cr.top, cr.right, cr.bottom); rgn2 = CreateRectRgn(tr.left, tr.top, tr.right, tr.bottom); ret = CombineRgn(rgn, rgn, rgn1, RGN_DIFF); ret = CombineRgn(rgn, rgn, rgn2, RGN_DIFF); if(ret != NULLREGION && ret != ERROR) FillRgn(hdc, rgn, (HBRUSH)icvGetClassLongPtr(hwnd, CV_HBRBACKGROUND)); DeleteObject(rgn); DeleteObject(rgn1); DeleteObject(rgn2); } return 1; } return DefWindowProc(hwnd, uMsg, wParam, lParam); }
// //****************************************************************** // Function Name : OnNcPaint // Function : QA: 32574 // Param : HRGN hrgnUpdate // Return : LRESULT // Create : // Update : ±èÁ¤¹®, 2009/10/09 VS 2008 Upgrade¸¦ À§ÇÑ ÀÛ¾÷ // Comment : //****************************************************************** LRESULT SECTreeCtrl::OnNcPaint(HRGN hrgnUpdate) { if(!m_hTreeTheme) { #ifndef __RWUXTHEME_H m_hTreeTheme = RWOpenThemeData(m_hWnd, L"TREEVIEW"); #endif } if(m_hTreeTheme) { //---------------------// // Draw Themed Border // //---------------------// HDC hdc = ::GetWindowDC(m_hWnd); RECT rc; RECT rcWindow; DWORD state = ETS_NORMAL; HRGN hrgnClip; // State if(!::IsWindowEnabled(this->GetSafeHwnd())) { state = ETS_DISABLED; }else if(GetFocus() == this->GetParent()) { state = ETS_HOT; }else { state = ETS_NORMAL; } // Rect mapping ::GetWindowRect(m_hWnd, &rcWindow); ::GetClientRect(m_hWnd, &rc); ::ClientToScreen(m_hWnd, (POINT *)&rc.left); ::ClientToScreen(m_hWnd, (POINT *)&rc.right); rc.right = rcWindow.right - (rc.left - rcWindow.left); rc.bottom = rcWindow.bottom - (rc.top - rcWindow.top); // Region hrgnClip = CreateRectRgn(rc.left, rc.top, rc.right, rc.bottom); if(hrgnUpdate != (HRGN)1) CombineRgn(hrgnClip, hrgnClip, hrgnUpdate, RGN_AND); OffsetRect(&rc, -rcWindow.left, -rcWindow.top); ExcludeClipRect(hdc, rc.left, rc.top, rc.right, rc.bottom); OffsetRect(&rcWindow, -rcWindow.left, -rcWindow.top); //if (IsThemeBackgroundPartiallyTransparent (m_hTreeTheme, TVP_TREEITEM, state)) //RWDrawThemeParentBackground(m_hWnd, hdc, &rcWindow); #ifndef __RWUXTHEME_H RWDrawThemeBackground(m_hTreeTheme, hdc, TVP_TREEITEM, state, &rcWindow, NULL); #endif ::ReleaseDC(m_hWnd, hdc); } return 0; }
void ReorderWindows(ATTACHED_WINDOWS& atws, int& bRedraw, int &redo, HWND hParent) { std::vector<HWND_DEPENDENCY> dependencies; redo = 0; std::vector<ATTACHED_WINDOW>::iterator atw = atws.begin(); HRGN rgn_final = CreateRectRgn(0,0,0,0); /* iterate through all attachments */ for (; atw != atws.end(); atw++) { HWND_DEPENDENCY hwnd_dependency; hwnd_dependency.hWnd = atw->hWnd; RECT r_dest; GetWindowRect(atw->hWnd, &r_dest); int w_dest = r_dest.right - r_dest.left; int h_dest = r_dest.bottom - r_dest.top; if (atw->flags & ATTB_WIDTHRATIO) { RECT r; GetWindowRect(atw->hWndWidth, &r); int _w_dest = (int)((float)(r.right - r.left) * atw->width_ratio); if (_w_dest != w_dest) { hwnd_dependency.hWnd_depends_on.push_back(atw->hWndWidth); redo = 1; w_dest = _w_dest; } } if (atw->flags & ATTB_HEIGHTRATIO) { RECT r; GetWindowRect(atw->hWndHeight, &r); int _h_dest = (int)((float)(r.bottom - r.top) * atw->height_ratio); if (h_dest != _h_dest) { hwnd_dependency.hWnd_depends_on.push_back(atw->hWndHeight); h_dest = _h_dest; redo = 1; } } bool keep_width = (atw->flags & ATTB_LEFTRIGHT) != ATTB_LEFTRIGHT; bool keep_height = (atw->flags & ATTB_TOPBOTTOM) != ATTB_TOPBOTTOM; ScreenToClient(hParent, &r_dest); RECT r_old = r_dest; HRGN rgn_old = CreateRectRgn(r_dest.left, r_dest.top, r_dest.right - 2, r_dest.bottom - 2); HRGN rgn_upd = CreateRectRgn(0,0,0,0); // obtain border region HRGN rgn_border = CreateRectRgn(0,0,0,0); bool bError = false; if (rgn_old == ERROR || rgn_upd == ERROR || rgn_border == ERROR) bError = true; RECT r_client; GetClientRect(atw->hWnd, &r_client); ClientToScreen(atw->hWnd, &r_client); ScreenToClient(hParent, &r_client); HRGN rgn_clt = CreateRectRgn(r_client.left, r_client.top, r_client.right, r_client.bottom); if (rgn_clt == ERROR) bError = true; if (CombineRgn(rgn_border, rgn_clt, rgn_old, RGN_XOR) == ERROR) bError = true; std::vector<ATTACHED_BORDER>::iterator atb = atw->attached_borders.begin(); for (; atb != atw->attached_borders.end(); atb++) { RECT r_source; GetWindowRect(atb->hWndAttachedTo, &r_source); ScreenToClient(hParent, &r_source); int value1 = -1; int value2 = -1; LONG* target1 = NULL; LONG* target2 = NULL; switch (atb->border) { case ATTB_LEFT: case ATTB_HCENTER: target1 = &r_dest.left; if (keep_width) target2 = &r_dest.right; break; case ATTB_RIGHT: target1 = &r_dest.right; if (keep_width) target2 = &r_dest.left; break; case ATTB_TOP: case ATTB_VCENTER: target1 = &r_dest.top; if (keep_height) target2 = &r_dest.bottom; break; case ATTB_BOTTOM: target1 = &r_dest.bottom; if (keep_height) target2 = &r_dest.top; break; default: ASSERT(0); } switch (atb->target_border) { case ATTB_LEFT: case ATTB_RIGHT: case ATTB_HCENTER: if (atb->target_border == ATTB_LEFT) value1 = r_source.left + atb->distance; else if (atb->target_border == ATTB_RIGHT) value1 = r_source.right + atb->distance; else if (atb->target_border == ATTB_HCENTER) value1 = (r_source.left + r_source.right)/2 + atb->distance; else ASSERT(0); if (atb->border == ATTB_LEFT) value2 = value1 + w_dest; else if (atb->border == ATTB_RIGHT) value2 = value1 - w_dest; else if (atb->border == ATTB_HCENTER) { value1 = value1 - w_dest/2; value2 = value1 + w_dest; } else ASSERT(0); break; case ATTB_TOP: case ATTB_BOTTOM: case ATTB_VCENTER: if (atb->target_border == ATTB_TOP) value1 = r_source.top + atb->distance; else if (atb->target_border == ATTB_BOTTOM) value1 = r_source.bottom + atb->distance; else if (atb->target_border == ATTB_VCENTER) value1 = (r_source.bottom + r_source.top)/2 + atb->distance; else ASSERT(0); if (atb->border == ATTB_TOP) value2 = value1 + h_dest; else if (atb->border == ATTB_BOTTOM) value2 = value1 - h_dest; else if (atb->border == ATTB_VCENTER) { value1 = value1 - h_dest/2; value2 = value1 + h_dest; } else ASSERT(0); break; default: ASSERT(0); } *target1 = value1; if (target2) *target2 = value2; } MoveWindow(atw->hWnd, r_dest.left, r_dest.top, r_dest.right - r_dest.left, r_dest.bottom - r_dest.top, false); HRGN rgn_new = CreateRectRgn(r_dest.left, r_dest.top, r_dest.right + 1, r_dest.bottom + 1); if (rgn_new == ERROR) bError = true; if (CombineRgn(rgn_upd, rgn_old, rgn_new, RGN_XOR) == ERROR) bError = true; if (IsWindowVisible(atw->hWnd)) if (CombineRgn(rgn_final, rgn_final, rgn_upd, RGN_OR) == ERROR) bError = true; int border_size = 2; HRGN rgn_temp = CreateRectRgn(r_old.right - border_size, r_old.top, r_old.right + 1, r_old.bottom + 1); if (rgn_temp == ERROR) bError = true; if (IsWindowVisible(atw->hWnd)) if (CombineRgn(rgn_final, rgn_final, rgn_temp, RGN_OR) == ERROR) bError = true; DeleteObject(rgn_temp); rgn_temp = CreateRectRgn(r_old.left, r_old.bottom - border_size, r_old.right + 1, r_old.bottom + 1); if (rgn_temp == ERROR) bError = true; if (IsWindowVisible(atw->hWnd)) if (CombineRgn(rgn_final, rgn_final, rgn_temp, RGN_OR) == ERROR) bError = true;; DeleteObject(rgn_temp); if (!bError) if (IsWindowVisible(atw->hWnd)) if (CombineRgn(rgn_final, rgn_final, rgn_border, RGN_OR) == ERROR) bError = true; if (r_old.top != r_dest.top || r_old.left != r_dest.left) { if (IsWindowVisible(atw->hWnd)) CombineRgn(rgn_final, rgn_final, rgn_new, RGN_OR); } DeleteObject(rgn_old); DeleteObject(rgn_new); DeleteObject(rgn_upd); DeleteObject(rgn_border); DeleteObject(rgn_clt); if (!hwnd_dependency.hWnd_depends_on.empty()) dependencies.push_back(hwnd_dependency); } InvalidateRgn(hParent, rgn_final, true); ASSERT(!cross_dependencies(dependencies)); DeleteObject(rgn_final); bRedraw = 1; }
static GpStatus get_region_hrgn(struct region_element *element, GpGraphics *graphics, HRGN *hrgn) { switch (element->type) { case RegionDataInfiniteRect: *hrgn = NULL; return Ok; case RegionDataEmptyRect: *hrgn = CreateRectRgn(0, 0, 0, 0); return *hrgn ? Ok : OutOfMemory; case RegionDataPath: return get_path_hrgn(element->elementdata.path, graphics, hrgn); case RegionDataRect: { GpPath* path; GpStatus stat; GpRectF* rc = &element->elementdata.rect; stat = GdipCreatePath(FillModeAlternate, &path); if (stat != Ok) return stat; stat = GdipAddPathRectangle(path, rc->X, rc->Y, rc->Width, rc->Height); if (stat == Ok) stat = get_path_hrgn(path, graphics, hrgn); GdipDeletePath(path); return stat; } case CombineModeIntersect: case CombineModeUnion: case CombineModeXor: case CombineModeExclude: case CombineModeComplement: { HRGN left, right; GpStatus stat; int ret; stat = get_region_hrgn(element->elementdata.combine.left, graphics, &left); if (stat != Ok) { *hrgn = NULL; return stat; } if (left == NULL) { /* existing region is infinite */ switch (element->type) { case CombineModeIntersect: return get_region_hrgn(element->elementdata.combine.right, graphics, hrgn); case CombineModeXor: case CombineModeExclude: left = CreateRectRgn(-4194304, -4194304, 4194304, 4194304); break; case CombineModeUnion: case CombineModeComplement: *hrgn = NULL; return Ok; } } stat = get_region_hrgn(element->elementdata.combine.right, graphics, &right); if (stat != Ok) { DeleteObject(left); *hrgn = NULL; return stat; } if (right == NULL) { /* new region is infinite */ switch (element->type) { case CombineModeIntersect: *hrgn = left; return Ok; case CombineModeXor: case CombineModeComplement: right = CreateRectRgn(-4194304, -4194304, 4194304, 4194304); break; case CombineModeUnion: case CombineModeExclude: DeleteObject(left); *hrgn = NULL; return Ok; } } switch (element->type) { case CombineModeIntersect: ret = CombineRgn(left, left, right, RGN_AND); break; case CombineModeUnion: ret = CombineRgn(left, left, right, RGN_OR); break; case CombineModeXor: ret = CombineRgn(left, left, right, RGN_XOR); break; case CombineModeExclude: ret = CombineRgn(left, left, right, RGN_DIFF); break; case CombineModeComplement: ret = CombineRgn(left, right, left, RGN_DIFF); break; default: ret = ERROR; } DeleteObject(right); if (ret == ERROR) { DeleteObject(left); *hrgn = NULL; return GenericError; } *hrgn = left; return Ok; } default: FIXME("GdipGetRegionHRgn unimplemented for region type=%x\n", element->type); *hrgn = NULL; return NotImplemented; } }
static void draw_graphics(HDC hdc, BITMAPINFO *bmi, BYTE *bits, const char ***sha1) { DWORD dib_size = get_dib_size(bmi); HPEN solid_pen, dashed_pen, orig_pen; HBRUSH solid_brush, dib_brush, hatch_brush, orig_brush; INT i, y, hatch_style; HRGN hrgn, hrgn2; BYTE dib_brush_buf[sizeof(BITMAPINFO) + 256 * sizeof(RGBQUAD) + 16 * 16 * sizeof(DWORD)]; /* Enough for 16 x 16 at 32 bpp */ BITMAPINFO *brush_bi = (BITMAPINFO*)dib_brush_buf; BYTE *brush_bits; BOOL dib_is_1bpp = (bmi->bmiHeader.biBitCount == 1); memset(bits, 0xcc, dib_size); compare_hash(bmi, bits, sha1, "empty"); solid_pen = CreatePen(PS_SOLID, 1, RGB(0, 0, 0xff)); orig_pen = SelectObject(hdc, solid_pen); SetBrushOrgEx(hdc, 0, 0, NULL); /* horizontal and vertical lines */ for(i = 1; i <= 16; i++) { SetROP2(hdc, i); MoveToEx(hdc, 10, i * 3, NULL); LineTo(hdc, 100, i * 3); /* l -> r */ MoveToEx(hdc, 100, 50 + i * 3, NULL); LineTo(hdc, 10, 50 + i * 3); /* r -> l */ MoveToEx(hdc, 120 + i * 3, 10, NULL); LineTo(hdc, 120 + i * 3, 100); /* t -> b */ MoveToEx(hdc, 170 + i * 3, 100, NULL); LineTo(hdc, 170 + i * 3, 10); /* b -> t */ } compare_hash(bmi, bits, sha1, "h and v solid lines"); memset(bits, 0xcc, dib_size); /* diagonal lines */ SetROP2(hdc, R2_COPYPEN); for(i = 0; i < 16; i++) { double s = sin(M_PI * i / 8.0); double c = cos(M_PI * i / 8.0); MoveToEx(hdc, 200.5 + 10 * c, 200.5 + 10 * s, NULL); LineTo(hdc, 200.5 + 100 * c, 200.5 + 100 * s); } compare_hash(bmi, bits, sha1, "diagonal solid lines"); memset(bits, 0xcc, dib_size); for(i = 0; i < sizeof(bias_check) / sizeof(bias_check[0]); i++) { MoveToEx(hdc, bias_check[i].left, bias_check[i].top, NULL); LineTo(hdc, bias_check[i].right, bias_check[i].bottom); } compare_hash(bmi, bits, sha1, "more diagonal solid lines"); memset(bits, 0xcc, dib_size); /* solid brush PatBlt */ solid_brush = CreateSolidBrush(RGB(0x33, 0xaa, 0xff)); orig_brush = SelectObject(hdc, solid_brush); for(i = 0, y = 10; i < 256; i++) { BOOL ret; ret = PatBlt(hdc, 10, y, 100, 10, rop3[i]); if(rop_uses_src(rop3[i])) ok(ret == FALSE, "got TRUE for %x\n", rop3[i]); else { ok(ret, "got FALSE for %x\n", rop3[i]); y += 20; } } compare_hash(bmi, bits, sha1, "solid patblt"); memset(bits, 0xcc, dib_size); /* clipped lines */ hrgn = CreateRectRgn(10, 10, 200, 20); hrgn2 = CreateRectRgn(100, 100, 200, 200); CombineRgn(hrgn, hrgn, hrgn2, RGN_OR); SetRectRgn(hrgn2, 290, 100, 300, 200); CombineRgn(hrgn, hrgn, hrgn2, RGN_OR); ExtSelectClipRgn(hdc, hrgn, RGN_COPY); DeleteObject(hrgn2); for(i = 0; i < sizeof(hline_clips)/sizeof(hline_clips[0]); i++) { MoveToEx(hdc, hline_clips[i].left, hline_clips[i].top, NULL); LineTo(hdc, hline_clips[i].right, hline_clips[i].bottom); } compare_hash(bmi, bits, sha1, "clipped solid hlines"); memset(bits, 0xcc, dib_size); for(i = 0; i < sizeof(vline_clips)/sizeof(vline_clips[0]); i++) { MoveToEx(hdc, vline_clips[i].left, vline_clips[i].top, NULL); LineTo(hdc, vline_clips[i].right, vline_clips[i].bottom); } compare_hash(bmi, bits, sha1, "clipped solid vlines"); memset(bits, 0xcc, dib_size); for(i = 0; i < sizeof(line_clips)/sizeof(line_clips[0]); i++) { MoveToEx(hdc, line_clips[i].left, line_clips[i].top, NULL); LineTo(hdc, line_clips[i].right, line_clips[i].bottom); } compare_hash(bmi, bits, sha1, "clipped solid diagonal lines"); memset(bits, 0xcc, dib_size); /* clipped PatBlt */ for(i = 0; i < sizeof(patblt_clips) / sizeof(patblt_clips[0]); i++) { PatBlt(hdc, patblt_clips[i].left, patblt_clips[i].top, patblt_clips[i].right - patblt_clips[i].left, patblt_clips[i].bottom - patblt_clips[i].top, PATCOPY); } compare_hash(bmi, bits, sha1, "clipped patblt"); memset(bits, 0xcc, dib_size); /* clipped dashed lines */ dashed_pen = CreatePen(PS_DASH, 1, RGB(0xff, 0, 0)); SelectObject(hdc, dashed_pen); SetBkMode(hdc, TRANSPARENT); SetBkColor(hdc, RGB(0, 0xff, 0)); for(i = 0; i < sizeof(hline_clips)/sizeof(hline_clips[0]); i++) { MoveToEx(hdc, hline_clips[i].left, hline_clips[i].top, NULL); LineTo(hdc, hline_clips[i].right, hline_clips[i].bottom); } compare_hash(bmi, bits, sha1, "clipped dashed hlines"); memset(bits, 0xcc, dib_size); for(i = 0; i < sizeof(hline_clips)/sizeof(hline_clips[0]); i++) { MoveToEx(hdc, hline_clips[i].right - 1, hline_clips[i].bottom, NULL); LineTo(hdc, hline_clips[i].left - 1, hline_clips[i].top); } compare_hash(bmi, bits, sha1, "clipped dashed hlines r -> l"); memset(bits, 0xcc, dib_size); for(i = 0; i < sizeof(vline_clips)/sizeof(vline_clips[0]); i++) { MoveToEx(hdc, vline_clips[i].left, vline_clips[i].top, NULL); LineTo(hdc, vline_clips[i].right, vline_clips[i].bottom); } compare_hash(bmi, bits, sha1, "clipped dashed vlines"); memset(bits, 0xcc, dib_size); for(i = 0; i < sizeof(vline_clips)/sizeof(vline_clips[0]); i++) { MoveToEx(hdc, vline_clips[i].right, vline_clips[i].bottom - 1, NULL); LineTo(hdc, vline_clips[i].left, vline_clips[i].top - 1); } compare_hash(bmi, bits, sha1, "clipped dashed vlines b -> t"); memset(bits, 0xcc, dib_size); for(i = 0; i < sizeof(line_clips)/sizeof(line_clips[0]); i++) { MoveToEx(hdc, line_clips[i].left, line_clips[i].top, NULL); LineTo(hdc, line_clips[i].right, line_clips[i].bottom); } compare_hash(bmi, bits, sha1, "clipped dashed diagonal lines"); memset(bits, 0xcc, dib_size); SetBkMode(hdc, OPAQUE); for(i = 0; i < sizeof(line_clips)/sizeof(line_clips[0]); i++) { MoveToEx(hdc, line_clips[i].left, line_clips[i].top, NULL); LineTo(hdc, line_clips[i].right, line_clips[i].bottom); } compare_hash(bmi, bits, sha1, "clipped opaque dashed diagonal lines"); memset(bits, 0xcc, dib_size); ExtSelectClipRgn(hdc, NULL, RGN_COPY); /* 8888 DIB pattern brush */ brush_bi->bmiHeader = dib_brush_header_8888; brush_bits = (BYTE*)brush_bi + sizeof(BITMAPINFOHEADER); memset(brush_bits, 0, 16 * 16 * sizeof(DWORD)); brush_bits[2] = 0xff; brush_bits[6] = 0xff; brush_bits[14] = 0xff; brush_bits[65] = 0xff; brush_bits[69] = 0xff; brush_bits[72] = 0xff; dib_brush = CreateDIBPatternBrushPt(brush_bi, DIB_RGB_COLORS); SelectObject(hdc, dib_brush); SetBrushOrgEx(hdc, 1, 1, NULL); for(i = 0, y = 10; i < 256; i++) { BOOL ret; if(!rop_uses_src(rop3[i])) { ret = PatBlt(hdc, 10 + i, y, 100, 20, rop3[i]); ok(ret, "got FALSE for %x\n", rop3[i]); y += 25; } } compare_hash_broken_todo(bmi, bits, sha1, "top-down 8888 dib brush patblt", dib_is_1bpp ? 2 : 0, dib_is_1bpp); memset(bits, 0xcc, dib_size); SelectObject(hdc, orig_brush); DeleteObject(dib_brush); /* 8888 bottom-up DIB pattern brush */ brush_bi->bmiHeader.biHeight = -brush_bi->bmiHeader.biHeight; dib_brush = CreateDIBPatternBrushPt(brush_bi, DIB_RGB_COLORS); SelectObject(hdc, dib_brush); /* This used to set the x origin to 100 as well, but there's a Windows bug for 24 bpp where the brush's x offset is incorrectly calculated for rops that involve both D and P */ SetBrushOrgEx(hdc, 4, 100, NULL); for(i = 0, y = 10; i < 256; i++) { BOOL ret; if(!rop_uses_src(rop3[i])) { ret = PatBlt(hdc, 10 + i, y, 100, 20, rop3[i]); ok(ret, "got FALSE for %x\n", rop3[i]); y += 25; } } compare_hash_broken_todo(bmi, bits, sha1, "bottom-up 8888 dib brush patblt", dib_is_1bpp ? 2 : 0, dib_is_1bpp); memset(bits, 0xcc, dib_size); SelectObject(hdc, orig_brush); DeleteObject(dib_brush); /* 24 bpp dib pattern brush */ brush_bi->bmiHeader = dib_brush_header_24; brush_bits = (BYTE*)brush_bi + sizeof(BITMAPINFOHEADER); memset(brush_bits, 0, 16 * 16 * 3); brush_bits[0] = brush_bits[3] = brush_bits[6] = brush_bits[8] = 0xff; brush_bits[49] = brush_bits[52] = 0xff; dib_brush = CreateDIBPatternBrushPt(brush_bi, DIB_RGB_COLORS); SelectObject(hdc, dib_brush); SetBrushOrgEx(hdc, 1, 1, NULL); for(i = 0, y = 10; i < 256; i++) { BOOL ret; if(!rop_uses_src(rop3[i])) { ret = PatBlt(hdc, 10 + i, y, 100, 20, rop3[i]); ok(ret, "got FALSE for %x\n", rop3[i]); y += 25; } } compare_hash_broken_todo(bmi, bits, sha1, "top-down 24 bpp brush patblt", dib_is_1bpp ? 2 : 0, dib_is_1bpp); memset(bits, 0xcc, dib_size); SelectObject(hdc, orig_brush); DeleteObject(dib_brush); /* 555 dib pattern brush */ brush_bi->bmiHeader = dib_brush_header_555; brush_bits = (BYTE*)brush_bi + sizeof(BITMAPINFOHEADER); memset(brush_bits, 0, 16 * 16 * sizeof(WORD)); brush_bits[0] = brush_bits[1] = 0xff; brush_bits[32] = brush_bits[34] = 0x7c; dib_brush = CreateDIBPatternBrushPt(brush_bi, DIB_RGB_COLORS); SelectObject(hdc, dib_brush); SetBrushOrgEx(hdc, 1, 1, NULL); for(i = 0, y = 10; i < 256; i++) { BOOL ret; if(!rop_uses_src(rop3[i])) { ret = PatBlt(hdc, 10 + i, y, 100, 20, rop3[i]); ok(ret, "got FALSE for %x\n", rop3[i]); y += 25; } } compare_hash_broken_todo(bmi, bits, sha1, "top-down 555 dib brush patblt", dib_is_1bpp ? 1 : 0, dib_is_1bpp); memset(bits, 0xcc, dib_size); SelectObject(hdc, orig_brush); DeleteObject(dib_brush); SetBrushOrgEx(hdc, 0, 0, NULL); /* 8 bpp dib pattern brush */ brush_bi->bmiHeader = dib_brush_header_8; brush_bi->bmiHeader.biClrUsed = 3; memset(brush_bi->bmiColors, 0, brush_bi->bmiHeader.biClrUsed * sizeof(RGBQUAD)); brush_bi->bmiColors[0].rgbRed = 0xff; brush_bi->bmiColors[1].rgbRed = 0xff; brush_bi->bmiColors[1].rgbGreen = 0xff; brush_bi->bmiColors[1].rgbBlue = 0xff; brush_bits = (BYTE*)brush_bi + sizeof(BITMAPINFOHEADER) + brush_bi->bmiHeader.biClrUsed * sizeof(RGBQUAD); memset(brush_bits, 0, 16 * 16 * sizeof(BYTE)); brush_bits[0] = brush_bits[1] = 1; brush_bits[16] = brush_bits[17] = 2; brush_bits[32] = brush_bits[33] = 6; dib_brush = CreateDIBPatternBrushPt(brush_bi, DIB_RGB_COLORS); SelectObject(hdc, dib_brush); SetBrushOrgEx(hdc, 1, 1, NULL); for(i = 0, y = 10; i < 256; i++) { BOOL ret; if(!rop_uses_src(rop3[i])) { ret = PatBlt(hdc, 10 + i, y, 100, 20, rop3[i]); ok(ret, "got FALSE for %x\n", rop3[i]); y += 25; } } compare_hash_broken_todo(bmi, bits, sha1, "top-down 8 bpp dib brush patblt", dib_is_1bpp ? 2 : 0, dib_is_1bpp); memset(bits, 0xcc, dib_size); SelectObject(hdc, orig_brush); DeleteObject(dib_brush); /* 4 bpp dib pattern brush */ brush_bi->bmiHeader = dib_brush_header_4; dib_brush = CreateDIBPatternBrushPt(brush_bi, DIB_RGB_COLORS); SelectObject(hdc, dib_brush); SetBrushOrgEx(hdc, 1, 1, NULL); for(i = 0, y = 10; i < 256; i++) { BOOL ret; if(!rop_uses_src(rop3[i])) { ret = PatBlt(hdc, 10 + i, y, 100, 20, rop3[i]); ok(ret, "got FALSE for %x\n", rop3[i]); y += 25; } } compare_hash_broken_todo(bmi, bits, sha1, "top-down 4 bpp dib brush patblt", dib_is_1bpp ? 2 : 0, dib_is_1bpp); memset(bits, 0xcc, dib_size); SelectObject(hdc, orig_brush); DeleteObject(dib_brush); /* 1 bpp dib pattern brush */ brush_bi->bmiHeader = dib_brush_header_1; brush_bi->bmiHeader.biClrUsed = 2; memset(brush_bits, 0, 16 * 4); brush_bits[0] = 0xf0; brush_bits[4] = 0xf0; brush_bits[8] = 0xf0; dib_brush = CreateDIBPatternBrushPt(brush_bi, DIB_RGB_COLORS); SelectObject(hdc, dib_brush); for(i = 0, y = 10; i < 256; i++) { BOOL ret; if(!rop_uses_src(rop3[i])) { ret = PatBlt(hdc, 10 + i, y, 100, 20, rop3[i]); ok(ret, "got FALSE for %x\n", rop3[i]); y += 25; } } compare_hash_broken_todo(bmi, bits, sha1, "top-down 1 bpp dib brush patblt", dib_is_1bpp ? 2 : 0, dib_is_1bpp); memset(bits, 0xcc, dib_size); SelectObject(hdc, orig_brush); SetBrushOrgEx(hdc, 0, 0, NULL); /* Rectangle */ SelectObject(hdc, solid_pen); SelectObject(hdc, solid_brush); for(i = 0; i < sizeof(rectangles)/sizeof(rectangles[0]); i++) { Rectangle(hdc, rectangles[i].left, rectangles[i].top, rectangles[i].right, rectangles[i].bottom); } SelectObject(hdc, dashed_pen); for(i = 0; i < sizeof(rectangles)/sizeof(rectangles[0]); i++) { Rectangle(hdc, rectangles[i].left, rectangles[i].top + 150, rectangles[i].right, rectangles[i].bottom + 150); } compare_hash(bmi, bits, sha1, "rectangles"); memset(bits, 0xcc, dib_size); SelectObject(hdc, solid_pen); /* PaintRgn */ PaintRgn(hdc, hrgn); compare_hash(bmi, bits, sha1, "PaintRgn"); memset(bits, 0xcc, dib_size); /* RTL rectangles */ if( !pSetLayout ) { win_skip("Don't have SetLayout\n"); (*sha1)++; } else { pSetLayout(hdc, LAYOUT_RTL); PaintRgn(hdc, hrgn); PatBlt(hdc, 10, 250, 10, 10, PATCOPY); Rectangle(hdc, 100, 250, 110, 260); compare_hash(bmi, bits, sha1, "rtl"); memset(bits, 0xcc, dib_size); pSetLayout(hdc, LAYOUT_LTR); } for(i = 0, y = 10; i < 256; i++) { BOOL ret; if(!rop_uses_src(rop3[i])) { for(hatch_style = HS_HORIZONTAL; hatch_style <= HS_DIAGCROSS; hatch_style++) { hatch_brush = CreateHatchBrush(hatch_style, RGB(0xff, 0, 0)); SelectObject(hdc, hatch_brush); ret = PatBlt(hdc, 10 + i + 30 * hatch_style, y, 20, 20, rop3[i]); ok(ret, "got FALSE for %x\n", rop3[i]); SelectObject(hdc, orig_brush); DeleteObject(hatch_brush); } y += 25; } } compare_hash_broken_todo(bmi, bits, sha1, "hatch brushes", 1, FALSE); /* nt4 is different */ memset(bits, 0xcc, dib_size); SelectObject(hdc, orig_brush); SelectObject(hdc, orig_pen); DeleteObject(hrgn); DeleteObject(dib_brush); DeleteObject(dashed_pen); DeleteObject(solid_brush); DeleteObject(solid_pen); }
BOOL CALLBACK VBoxEnumFunc(HWND hwnd, LPARAM lParam) { PVBOX_ENUM_PARAM lpParam = (PVBOX_ENUM_PARAM)lParam; DWORD dwStyle, dwExStyle; RECT rectWindow, rectVisible; dwStyle = GetWindowLong(hwnd, GWL_STYLE); dwExStyle = GetWindowLong(hwnd, GWL_EXSTYLE); if ( !(dwStyle & WS_VISIBLE) || (dwStyle & WS_CHILD)) return TRUE; Log(("VBoxTray: VBoxEnumFunc %x\n", hwnd)); /* Only visible windows that are present on the desktop are interesting here */ if (GetWindowRect(hwnd, &rectWindow)) { char szWindowText[256]; szWindowText[0] = 0; OSVERSIONINFO OSinfo; HWND hStart = NULL; GetWindowText(hwnd, szWindowText, sizeof(szWindowText)); OSinfo.dwOSVersionInfoSize = sizeof (OSinfo); GetVersionEx (&OSinfo); if (OSinfo.dwMajorVersion >= 6) { hStart = ::FindWindowEx(GetDesktopWindow(), NULL, "Button", "Start"); if ( hwnd == hStart && szWindowText != NULL && !(strcmp(szWindowText, "Start")) ) { /* for vista and above. To solve the issue of small bar above * the Start button when mouse is hovered over the start button in seamless mode. * Difference of 7 is observed in Win 7 platform between the dimensionsof rectangle with Start title and its shadow. */ rectWindow.top += 7; rectWindow.bottom -=7; } } rectVisible = rectWindow; #ifdef LOG_ENABLED DWORD pid = 0; DWORD tid = GetWindowThreadProcessId(hwnd, &pid); #endif /* Filter out Windows XP shadow windows */ /** @todo still shows inside the guest */ if ( szWindowText[0] == 0 && ( (dwStyle == (WS_POPUP|WS_VISIBLE|WS_CLIPSIBLINGS) && dwExStyle == (WS_EX_LAYERED|WS_EX_TOOLWINDOW|WS_EX_TRANSPARENT|WS_EX_TOPMOST)) || (dwStyle == (WS_POPUP|WS_VISIBLE|WS_DISABLED|WS_CLIPSIBLINGS|WS_CLIPCHILDREN) && dwExStyle == (WS_EX_TOOLWINDOW | WS_EX_TRANSPARENT | WS_EX_LAYERED | WS_EX_NOACTIVATE)) || (dwStyle == (WS_POPUP|WS_VISIBLE|WS_CLIPSIBLINGS|WS_CLIPCHILDREN) && dwExStyle == (WS_EX_TOOLWINDOW)) )) { Log(("VBoxTray: Filter out shadow window style=%x exstyle=%x\n", dwStyle, dwExStyle)); Log(("VBoxTray: Enum hwnd=%x rect (%d,%d) (%d,%d) (filtered)\n", hwnd, rectWindow.left, rectWindow.top, rectWindow.right, rectWindow.bottom)); Log(("VBoxTray: title=%s style=%x exStyle=%x\n", szWindowText, dwStyle, dwExStyle)); Log(("VBoxTray: pid=%d tid=%d\n", pid, tid)); return TRUE; } /** @todo will this suffice? The Program Manager window covers the whole screen */ if (strcmp(szWindowText, "Program Manager")) { Log(("VBoxTray: Enum hwnd=%x rect (%d,%d) (%d,%d) (applying)\n", hwnd, rectWindow.left, rectWindow.top, rectWindow.right, rectWindow.bottom)); Log(("VBoxTray: title=%s style=%x exStyle=%x\n", szWindowText, dwStyle, dwExStyle)); Log(("VBoxTray: pid=%d tid=%d\n", pid, tid)); HRGN hrgn = CreateRectRgn(0,0,0,0); int ret = GetWindowRgn(hwnd, hrgn); if (ret == ERROR) { Log(("VBoxTray: GetWindowRgn failed with rc=%d\n", GetLastError())); SetRectRgn(hrgn, rectVisible.left, rectVisible.top, rectVisible.right, rectVisible.bottom); } else { /* this region is relative to the window origin instead of the desktop origin */ OffsetRgn(hrgn, rectWindow.left, rectWindow.top); } if (lpParam->hrgn) { /* create a union of the current visible region and the visible rectangle of this window. */ CombineRgn(lpParam->hrgn, lpParam->hrgn, hrgn, RGN_OR); DeleteObject(hrgn); } else lpParam->hrgn = hrgn; } else { Log(("VBoxTray: Enum hwnd=%x rect (%d,%d) (%d,%d) (ignored)\n", hwnd, rectWindow.left, rectWindow.top, rectWindow.right, rectWindow.bottom)); Log(("VBoxTray: title=%s style=%x\n", szWindowText, dwStyle)); Log(("VBoxTray: pid=%d tid=%d\n", pid, tid)); } } return TRUE; /* continue enumeration */ }
/********************************************************************** * ExtEscape (X11DRV.@) */ static INT X11DRV_ExtEscape( PHYSDEV dev, INT escape, INT in_count, LPCVOID in_data, INT out_count, LPVOID out_data ) { X11DRV_PDEVICE *physDev = get_x11drv_dev( dev ); switch(escape) { case QUERYESCSUPPORT: if (in_data && in_count >= sizeof(DWORD)) { switch (*(const INT *)in_data) { case X11DRV_ESCAPE: return TRUE; } } break; case X11DRV_ESCAPE: if (in_data && in_count >= sizeof(enum x11drv_escape_codes)) { switch(*(const enum x11drv_escape_codes *)in_data) { case X11DRV_SET_DRAWABLE: if (in_count >= sizeof(struct x11drv_escape_set_drawable)) { const struct x11drv_escape_set_drawable *data = in_data; physDev->dc_rect = data->dc_rect; physDev->drawable = data->drawable; XFreeGC( gdi_display, physDev->gc ); physDev->gc = XCreateGC( gdi_display, physDev->drawable, 0, NULL ); XSetGraphicsExposures( gdi_display, physDev->gc, False ); XSetSubwindowMode( gdi_display, physDev->gc, data->mode ); TRACE( "SET_DRAWABLE hdc %p drawable %lx dc_rect %s\n", dev->hdc, physDev->drawable, wine_dbgstr_rect(&physDev->dc_rect) ); return TRUE; } break; case X11DRV_GET_DRAWABLE: if (out_count >= sizeof(struct x11drv_escape_get_drawable)) { struct x11drv_escape_get_drawable *data = out_data; data->drawable = physDev->drawable; data->dc_rect = physDev->dc_rect; return TRUE; } break; case X11DRV_FLUSH_GL_DRAWABLE: if (in_count >= sizeof(struct x11drv_escape_flush_gl_drawable)) { const struct x11drv_escape_flush_gl_drawable *data = in_data; RECT rect = physDev->dc_rect; OffsetRect( &rect, -physDev->dc_rect.left, -physDev->dc_rect.top ); /* The GL drawable may be lagged behind if we don't flush first, so * flush the display make sure we copy up-to-date data */ XFlush( gdi_display ); XSetFunction( gdi_display, physDev->gc, GXcopy ); XCopyArea( gdi_display, data->gl_drawable, physDev->drawable, physDev->gc, 0, 0, rect.right, rect.bottom, physDev->dc_rect.left, physDev->dc_rect.top ); add_device_bounds( physDev, &rect ); return TRUE; } break; case X11DRV_START_EXPOSURES: XSetGraphicsExposures( gdi_display, physDev->gc, True ); physDev->exposures = 0; return TRUE; case X11DRV_END_EXPOSURES: if (out_count >= sizeof(HRGN)) { HRGN hrgn = 0, tmp = 0; XSetGraphicsExposures( gdi_display, physDev->gc, False ); if (physDev->exposures) { for (;;) { XEvent event; XWindowEvent( gdi_display, physDev->drawable, ~0, &event ); if (event.type == NoExpose) break; if (event.type == GraphicsExpose) { RECT rect; rect.left = event.xgraphicsexpose.x - physDev->dc_rect.left; rect.top = event.xgraphicsexpose.y - physDev->dc_rect.top; rect.right = rect.left + event.xgraphicsexpose.width; rect.bottom = rect.top + event.xgraphicsexpose.height; if (GetLayout( dev->hdc ) & LAYOUT_RTL) mirror_rect( &physDev->dc_rect, &rect ); TRACE( "got %s count %d\n", wine_dbgstr_rect(&rect), event.xgraphicsexpose.count ); if (!tmp) tmp = CreateRectRgnIndirect( &rect ); else SetRectRgn( tmp, rect.left, rect.top, rect.right, rect.bottom ); if (hrgn) CombineRgn( hrgn, hrgn, tmp, RGN_OR ); else { hrgn = tmp; tmp = 0; } if (!event.xgraphicsexpose.count) break; } else { ERR( "got unexpected event %d\n", event.type ); break; } } if (tmp) DeleteObject( tmp ); } *(HRGN *)out_data = hrgn; return TRUE; } break; default: break; } } break; } return 0; }
/*********************************************************************** * X11DRV_ExtTextOut */ BOOL CDECL X11DRV_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flags, const RECT *lprect, LPCWSTR wstr, UINT count, const INT *lpDx ) { unsigned int i; fontObject* pfo; XFontStruct* font; BOOL rotated = FALSE; XChar2b *str2b = NULL; BOOL dibUpdateFlag = FALSE; BOOL result = TRUE; HRGN saved_region = 0; if(physDev->has_gdi_font) return X11DRV_XRender_ExtTextOut(physDev, x, y, flags, lprect, wstr, count, lpDx); if (!X11DRV_SetupGCForText( physDev )) return TRUE; pfo = XFONT_GetFontObject( physDev->font ); font = pfo->fs; if (pfo->lf.lfEscapement && pfo->lpX11Trans) rotated = TRUE; TRACE("hdc=%p df=%04x %d,%d %s, %d flags=%d lpDx=%p\n", physDev->hdc, (UINT16)(physDev->font), x, y, debugstr_wn (wstr, count), count, flags, lpDx); if (lprect != NULL) TRACE("\trect=(%d,%d - %d,%d)\n", lprect->left, lprect->top, lprect->right, lprect->bottom ); /* Draw the rectangle */ if (flags & ETO_OPAQUE) { X11DRV_LockDIBSection( physDev, DIB_Status_GdiMod ); dibUpdateFlag = TRUE; wine_tsx11_lock(); XSetForeground( gdi_display, physDev->gc, physDev->backgroundPixel ); XFillRectangle( gdi_display, physDev->drawable, physDev->gc, physDev->dc_rect.left + lprect->left, physDev->dc_rect.top + lprect->top, lprect->right - lprect->left, lprect->bottom - lprect->top ); wine_tsx11_unlock(); } if (!count) goto END; /* Nothing more to do */ /* Set the clip region */ if (flags & ETO_CLIPPED) { HRGN clip_region; clip_region = CreateRectRgnIndirect( lprect ); /* make a copy of the current device region */ saved_region = CreateRectRgn( 0, 0, 0, 0 ); CombineRgn( saved_region, physDev->region, 0, RGN_COPY ); X11DRV_SetDeviceClipping( physDev, saved_region, clip_region ); DeleteObject( clip_region ); } /* Draw the text background if necessary */ if (!dibUpdateFlag) { X11DRV_LockDIBSection( physDev, DIB_Status_GdiMod ); dibUpdateFlag = TRUE; } /* Draw the text (count > 0 verified) */ if (!(str2b = X11DRV_cptable[pfo->fi->cptable].punicode_to_char2b( pfo, wstr, count ))) goto FAIL; wine_tsx11_lock(); XSetForeground( gdi_display, physDev->gc, physDev->textPixel ); wine_tsx11_unlock(); if(!rotated) { if (!lpDx) { X11DRV_cptable[pfo->fi->cptable].pDrawString( pfo, gdi_display, physDev->drawable, physDev->gc, physDev->dc_rect.left + x, physDev->dc_rect.top + y, str2b, count ); } else { XTextItem16 *items, *pitem; pitem = items = HeapAlloc( GetProcessHeap(), 0, count * sizeof(XTextItem16) ); if(items == NULL) goto FAIL; for(i = 0; i < count; i++) { pitem->chars = str2b + i; pitem->delta = lpDx[i]; pitem->nchars = 1; pitem->font = None; pitem++; } X11DRV_cptable[pfo->fi->cptable].pDrawText( pfo, gdi_display, physDev->drawable, physDev->gc, physDev->dc_rect.left + x, physDev->dc_rect.top + y, items, pitem - items ); HeapFree( GetProcessHeap(), 0, items ); } } else /* rotated */ { /* have to render character by character. */ double offset = 0.0; UINT i; for (i=0; i<count; i++) { int char_metric_offset = str2b[i].byte2 + (str2b[i].byte1 << 8) - font->min_char_or_byte2; int x_i = IROUND((double) (physDev->dc_rect.left + x) + offset * pfo->lpX11Trans->a / pfo->lpX11Trans->pixelsize ); int y_i = IROUND((double) (physDev->dc_rect.top + y) - offset * pfo->lpX11Trans->b / pfo->lpX11Trans->pixelsize ); X11DRV_cptable[pfo->fi->cptable].pDrawString( pfo, gdi_display, physDev->drawable, physDev->gc, x_i, y_i, &str2b[i], 1); if (lpDx) { offset += lpDx[i]; } else { offset += (double) (font->per_char ? font->per_char[char_metric_offset].attributes: font->min_bounds.attributes) * pfo->lpX11Trans->pixelsize / 1000.0; } } } HeapFree( GetProcessHeap(), 0, str2b ); if (flags & ETO_CLIPPED) { /* restore the device region */ X11DRV_SetDeviceClipping( physDev, saved_region, 0 ); DeleteObject( saved_region ); } goto END; FAIL: HeapFree( GetProcessHeap(), 0, str2b ); result = FALSE; END: if (dibUpdateFlag) X11DRV_UnlockDIBSection( physDev, TRUE ); return result; }
void UIMachineWindowSeamless::setMask(const QRegion &constRegion) { /* Could be unused under Mac: */ Q_UNUSED(constRegion); #ifndef Q_WS_MAC /* Copy mask: */ QRegion region = constRegion; /* Shift region if left spacer width is NOT zero or top spacer height is NOT zero: */ if (m_pLeftSpacer->geometry().width() || m_pTopSpacer->geometry().height()) region.translate(m_pLeftSpacer->geometry().width(), m_pTopSpacer->geometry().height()); /* Take into account mini tool-bar region: */ if (m_pMiniToolBar) { /* Move mini-toolbar region to mini-toolbar position: */ QRegion toolBarRegion(m_pMiniToolBar->rect()); toolBarRegion.translate(QPoint(m_pMiniToolBar->x(), m_pMiniToolBar->y())); /* Include mini-toolbar region into common one: */ region += toolBarRegion; } #endif /* !Q_WS_MAC */ #if defined (Q_WS_WIN) # if 0 /* This code is disabled for a long time already, need analisys... */ QRegion difference = m_prevRegion.subtract(region); /* Region offset calculation */ int fleft = 0, ftop = 0; /* Visible region calculation */ HRGN newReg = CreateRectRgn(0, 0, 0, 0); CombineRgn(newReg, region.handle(), 0, RGN_COPY); OffsetRgn(newReg, fleft, ftop); /* Invisible region calculation */ HRGN diffReg = CreateRectRgn(0, 0, 0, 0); CombineRgn(diffReg, difference.handle(), 0, RGN_COPY); OffsetRgn(diffReg, fleft, ftop); /* Set the current visible region and clean the previous */ SetWindowRgn(winId(), newReg, FALSE); RedrawWindow(0, 0, diffReg, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ALLCHILDREN); if (machineView()) RedrawWindow(machineView()->viewport()->winId(), 0, 0, RDW_INVALIDATE); m_prevRegion = region; # endif /* This code is disabled for a long time already, need analisys... */ UIMachineWindow::setMask(region); #elif defined (Q_WS_MAC) # if defined (VBOX_GUI_USE_QUARTZ2D) if (vboxGlobal().vmRenderMode() == Quartz2DMode) { /* If we are using the Quartz2D backend we have to trigger a repaint only. * All the magic clipping stuff is done in the paint engine. */ ::darwinWindowInvalidateShape(m_pMachineView->viewport()); } # endif /* VBOX_GUI_USE_QUARTZ2D */ # if 0 /* This code is disabled for a long time already, need analisys... */ /* This is necessary to avoid the flicker by an mask update. * See http://lists.apple.com/archives/Carbon-development/2001/Apr/msg01651.html for the hint. * There *must* be a better solution. */ // if (!region.isEmpty()) // region |= QRect(0, 0, 1, 1); // /* Save the current region for later processing in the darwin event handler. */ // mCurrRegion = region; // /* We repaint the screen before the ReshapeCustomWindow command. Unfortunately // * this command flushes a copy of the backbuffer to the screen after the new // * mask is set. This leads into a misplaced drawing of the content. Currently // * no alternative to this and also this is not 100% perfect. */ // repaint(); // qApp->processEvents(); // /* Now force the reshaping of the window. This is definitely necessary. */ // ReshapeCustomWindow(reinterpret_cast<WindowPtr>(winId())); // UIMachineWindow::setMask(region); // HIWindowInvalidateShadow(::darwinToWindowRef(mConsole->viewport())); # endif /* This code is disabled for a long time already, need analisys... */ #else /* !Q_WS_MAC */ UIMachineWindow::setMask(region); #endif }
void DSObjects::RMAIntersectRegion(REGION* reg1, REGION* reg2, REGION* regD) { CombineRgn((HRGN)regD->pOSRegion, (HRGN)reg1->pOSRegion, (HRGN)reg2->pOSRegion, RGN_AND); ExtractRects(regD); }
/***************************************************************************** * IDirectDrawClipper::GetClipList * * Retrieve a copy of the clip list * * Arguments: * rect: Rectangle to be used to clip the clip list or NULL for the * entire clip list. * clip_list: structure for the resulting copy of the clip list. * If NULL, fills Size up to the number of bytes necessary to hold * the entire clip. * clip_list_size: Size of resulting clip list; size of the buffer at clip_list * or, if clip_list is NULL, receives the required size of the buffer * in bytes. * * RETURNS * Either DD_OK or DDERR_* ************************************************************************/ static HRESULT WINAPI ddraw_clipper_GetClipList(IDirectDrawClipper *iface, RECT *rect, RGNDATA *clip_list, DWORD *clip_list_size) { struct ddraw_clipper *clipper = impl_from_IDirectDrawClipper(iface); HRGN region; TRACE("iface %p, rect %s, clip_list %p, clip_list_size %p.\n", iface, wine_dbgstr_rect(rect), clip_list, clip_list_size); wined3d_mutex_lock(); if (clipper->window) { if (!(region = get_window_region(clipper->window))) { wined3d_mutex_unlock(); WARN("Failed to get window region.\n"); return E_FAIL; } } else { if (!(region = clipper->region)) { wined3d_mutex_unlock(); WARN("No clip list set.\n"); return DDERR_NOCLIPLIST; } } if (rect) { HRGN clip_region; if (!(clip_region = CreateRectRgnIndirect(rect))) { wined3d_mutex_unlock(); ERR("Failed to create region.\n"); if (clipper->window) DeleteObject(region); return E_FAIL; } if (CombineRgn(clip_region, region, clip_region, RGN_AND) == ERROR) { wined3d_mutex_unlock(); ERR("Failed to combine regions.\n"); DeleteObject(clip_region); if (clipper->window) DeleteObject(region); return E_FAIL; } if (clipper->window) DeleteObject(region); region = clip_region; } *clip_list_size = GetRegionData(region, *clip_list_size, clip_list); if (rect || clipper->window) DeleteObject(region); wined3d_mutex_unlock(); return DD_OK; }
void Win32Graphics::drawBitmap( const GenericBitmap &rBitmap, int xSrc, int ySrc, int xDest, int yDest, int width, int height, bool blend ) { (void)blend; // check and adapt to source if needed if( !checkBoundaries( 0, 0, rBitmap.getWidth(), rBitmap.getHeight(), xSrc, ySrc, width, height ) ) { msg_Err( getIntf(), "empty source! pls, debug your skin" ); return; } // check destination if( !checkBoundaries( 0, 0, m_width, m_height, xDest, yDest, width, height ) ) { msg_Err( getIntf(), "out of reach destination! pls, debug your skin" ); return; } // Get a buffer on the image data uint8_t *pBmpData = rBitmap.getData(); if( pBmpData == NULL ) { // Nothing to draw return; } void *pBits; // pointer to DIB section // Fill a BITMAPINFO structure BITMAPINFO bmpInfo; memset( &bmpInfo, 0, sizeof( bmpInfo ) ); bmpInfo.bmiHeader.biSize = sizeof( BITMAPINFOHEADER ); bmpInfo.bmiHeader.biWidth = width; bmpInfo.bmiHeader.biHeight = -height; bmpInfo.bmiHeader.biPlanes = 1; bmpInfo.bmiHeader.biBitCount = 32; bmpInfo.bmiHeader.biCompression = BI_RGB; bmpInfo.bmiHeader.biSizeImage = width * height * 4; // Create a DIB (Device Independent Bitmap) and associate it with // a temporary DC HDC hDC = CreateCompatibleDC( m_hDC ); HBITMAP hBmp = CreateDIBSection( hDC, &bmpInfo, DIB_RGB_COLORS, &pBits, NULL, 0 ); SelectObject( hDC, hBmp ); // Mask for transparency HRGN mask = CreateRectRgn( 0, 0, 0, 0 ); // Skip the first lines of the image pBmpData += 4 * ySrc * rBitmap.getWidth(); // Copy the bitmap on the image and compute the mask for( int y = 0; y < height; y++ ) { // Skip uninteresting bytes at the beginning of the line pBmpData += 4 * xSrc; // Flag to say whether the previous pixel on the line was visible bool wasVisible = false; // Beginning of the current visible segment on the line int visibleSegmentStart = 0; for( int x = 0; x < width; x++ ) { uint8_t b = *(pBmpData++); uint8_t g = *(pBmpData++); uint8_t r = *(pBmpData++); uint8_t a = *(pBmpData++); // Draw the pixel ((UINT32 *)pBits)[x + y * width] = (a << 24) | (r << 16) | (g << 8) | b; if( a > 0 ) { // Pixel is visible if( ! wasVisible ) { // Beginning of a visible segment visibleSegmentStart = x; } wasVisible = true; } else { // Pixel is transparent if( wasVisible ) { // End of a visible segment: add it to the mask addSegmentInRegion( mask, visibleSegmentStart, x, y ); } wasVisible = false; } } if( wasVisible ) { // End of a visible segment: add it to the mask addSegmentInRegion( mask, visibleSegmentStart, width, y ); } // Skip uninteresting bytes at the end of the line pBmpData += 4 * (rBitmap.getWidth() - width - xSrc); } // Apply the mask to the internal DC OffsetRgn( mask, xDest, yDest ); SelectClipRgn( m_hDC, mask ); BLENDFUNCTION bf; // structure for alpha blending bf.BlendOp = AC_SRC_OVER; bf.BlendFlags = 0; bf.SourceConstantAlpha = 0xff; // don't use constant alpha bf.AlphaFormat = AC_SRC_ALPHA; // Blend the image onto the internal DC if( !AlphaBlend( m_hDC, xDest, yDest, width, height, hDC, 0, 0, width, height, bf ) ) { msg_Err( getIntf(), "AlphaBlend() failed" ); } // Add the bitmap mask to the global graphics mask CombineRgn( m_mask, m_mask, mask, RGN_OR ); // Do cleanup DeleteObject( hBmp ); DeleteObject( mask ); DeleteDC( hDC ); }
VOID ExtendSelection( IN PCONSOLE_INFORMATION Console, IN COORD CursorPosition ) /*++ This routine extends a selection region. --*/ { SMALL_RECT OldSelectionRect; HRGN OldRegion,NewRegion,CombineRegion; COORD FontSize; if (CursorPosition.X < 0) { CursorPosition.X = 0; } else if (CursorPosition.X >= Console->CurrentScreenBuffer->ScreenBufferSize.X) { CursorPosition.X = Console->CurrentScreenBuffer->ScreenBufferSize.X-1; } if (CursorPosition.Y < 0) { CursorPosition.Y = 0; } else if (CursorPosition.Y >= Console->CurrentScreenBuffer->ScreenBufferSize.Y) { CursorPosition.Y = Console->CurrentScreenBuffer->ScreenBufferSize.Y-1; } if (!(Console->SelectionFlags & CONSOLE_SELECTION_NOT_EMPTY)) { if (Console->CurrentScreenBuffer->Flags & CONSOLE_TEXTMODE_BUFFER) { // scroll if necessary to make cursor visible. MakeCursorVisible(Console->CurrentScreenBuffer,CursorPosition); ASSERT(!(Console->SelectionFlags & CONSOLE_MOUSE_SELECTION)); // // if the selection rect hasn't actually been started, // the selection cursor is still blinking. turn it off. // ConsoleHideCursor(Console->CurrentScreenBuffer); } Console->SelectionFlags |= CONSOLE_SELECTION_NOT_EMPTY; Console->SelectionRect.Left =Console->SelectionRect.Right = Console->SelectionAnchor.X; Console->SelectionRect.Top = Console->SelectionRect.Bottom = Console->SelectionAnchor.Y; // invert the cursor corner if (Console->CurrentScreenBuffer->Flags & CONSOLE_TEXTMODE_BUFFER) { MyInvert(Console,&Console->SelectionRect); } } else { if (Console->CurrentScreenBuffer->Flags & CONSOLE_TEXTMODE_BUFFER) { // scroll if necessary to make cursor visible. MakeCursorVisible(Console->CurrentScreenBuffer,CursorPosition); } } // // update selection rect // OldSelectionRect = Console->SelectionRect; if (CursorPosition.X <= Console->SelectionAnchor.X) { Console->SelectionRect.Left = CursorPosition.X; Console->SelectionRect.Right = Console->SelectionAnchor.X; } else if (CursorPosition.X > Console->SelectionAnchor.X) { Console->SelectionRect.Right = CursorPosition.X; Console->SelectionRect.Left = Console->SelectionAnchor.X; } if (CursorPosition.Y <= Console->SelectionAnchor.Y) { Console->SelectionRect.Top = CursorPosition.Y; Console->SelectionRect.Bottom = Console->SelectionAnchor.Y; } else if (CursorPosition.Y > Console->SelectionAnchor.Y) { Console->SelectionRect.Bottom = CursorPosition.Y; Console->SelectionRect.Top = Console->SelectionAnchor.Y; } // // change inverted selection // if (Console->CurrentScreenBuffer->Flags & CONSOLE_TEXTMODE_BUFFER) { FontSize = Console->CurrentScreenBuffer->BufferInfo.TextInfo.FontSize; } else { FontSize.X = 1; FontSize.Y = 1; } CombineRegion = CreateRectRgn(0,0,0,0); OldRegion = CreateRectRgn((OldSelectionRect.Left-Console->CurrentScreenBuffer->Window.Left)*FontSize.X, (OldSelectionRect.Top-Console->CurrentScreenBuffer->Window.Top)*FontSize.Y, (OldSelectionRect.Right-Console->CurrentScreenBuffer->Window.Left+1)*FontSize.X, (OldSelectionRect.Bottom-Console->CurrentScreenBuffer->Window.Top+1)*FontSize.Y ); NewRegion = CreateRectRgn((Console->SelectionRect.Left-Console->CurrentScreenBuffer->Window.Left)*FontSize.X, (Console->SelectionRect.Top-Console->CurrentScreenBuffer->Window.Top)*FontSize.Y, (Console->SelectionRect.Right-Console->CurrentScreenBuffer->Window.Left+1)*FontSize.X, (Console->SelectionRect.Bottom-Console->CurrentScreenBuffer->Window.Top+1)*FontSize.Y ); CombineRgn(CombineRegion,OldRegion,NewRegion,RGN_XOR); InvertRgn(Console->hDC,CombineRegion); DeleteObject(OldRegion); DeleteObject(NewRegion); DeleteObject(CombineRegion); }
/************************************************************************* * ScrollDC (X11DRV.@) */ BOOL X11DRV_ScrollDC( HDC hdc, INT dx, INT dy, const RECT *lprcScroll, const RECT *lprcClip, HRGN hrgnUpdate, LPRECT lprcUpdate ) { RECT rcSrc, rcClip, offset; INT dxdev, dydev, res; HRGN DstRgn, clipRgn, visrgn; INT code = X11DRV_START_EXPOSURES; TRACE("dx,dy %d,%d rcScroll %s rcClip %s hrgnUpdate %p lprcUpdate %p\n", dx, dy, wine_dbgstr_rect(lprcScroll), wine_dbgstr_rect(lprcClip), hrgnUpdate, lprcUpdate); /* enable X-exposure events */ if (hrgnUpdate || lprcUpdate) ExtEscape( hdc, X11DRV_ESCAPE, sizeof(code), (LPSTR)&code, 0, NULL ); /* get the visible region */ visrgn=CreateRectRgn( 0, 0, 0, 0); GetRandomRgn( hdc, visrgn, SYSRGN); if( !(GetVersion() & 0x80000000)) { /* Window NT/2k/XP */ POINT org; GetDCOrgEx(hdc, &org); OffsetRgn( visrgn, -org.x, -org.y); } /* intersect with the clipping Region if the DC has one */ clipRgn = CreateRectRgn( 0, 0, 0, 0); if (GetClipRgn( hdc, clipRgn) != 1) { DeleteObject(clipRgn); clipRgn=NULL; } else CombineRgn( visrgn, visrgn, clipRgn, RGN_AND); /* only those pixels in the scroll rectangle that remain in the clipping * rect are scrolled. */ if( lprcClip) rcClip = *lprcClip; else GetClipBox( hdc, &rcClip); rcSrc = rcClip; OffsetRect( &rcClip, -dx, -dy); IntersectRect( &rcSrc, &rcSrc, &rcClip); /* if an scroll rectangle is specified, only the pixels within that * rectangle are scrolled */ if( lprcScroll) IntersectRect( &rcSrc, &rcSrc, lprcScroll); /* now convert to device coordinates */ LPtoDP(hdc, (LPPOINT)&rcSrc, 2); TRACE("source rect: %s\n", wine_dbgstr_rect(&rcSrc)); /* also dx and dy */ SetRect(&offset, 0, 0, dx, dy); LPtoDP(hdc, (LPPOINT)&offset, 2); dxdev = offset.right - offset.left; dydev = offset.bottom - offset.top; /* now intersect with the visible region to get the pixels that will * actually scroll */ DstRgn = CreateRectRgnIndirect( &rcSrc); res = CombineRgn( DstRgn, DstRgn, visrgn, RGN_AND); /* and translate, giving the destination region */ OffsetRgn( DstRgn, dxdev, dydev); if( TRACE_ON( scroll)) dump_region( "Destination scroll region: ", DstRgn); /* if there are any, do it */ if( res > NULLREGION) { RECT rect ; /* clip to the destination region, so we can BitBlt with a simple * bounding rectangle */ if( clipRgn) ExtSelectClipRgn( hdc, DstRgn, RGN_AND); else SelectClipRgn( hdc, DstRgn); GetRgnBox( DstRgn, &rect); DPtoLP(hdc, (LPPOINT)&rect, 2); TRACE("destination rect: %s\n", wine_dbgstr_rect(&rect)); BitBlt( hdc, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, hdc, rect.left - dx, rect.top - dy, SRCCOPY); } /* compute the update areas. This is the combined clip rectangle * minus the scrolled region, and intersected with the visible * region. */ if (hrgnUpdate || lprcUpdate) { HRGN hrgn = hrgnUpdate; HRGN ExpRgn = 0; /* collect all the exposures */ code = X11DRV_END_EXPOSURES; ExtEscape( hdc, X11DRV_ESCAPE, sizeof(code), (LPSTR)&code, sizeof(ExpRgn), (LPSTR)&ExpRgn ); /* Intersect clip and scroll rectangles, allowing NULL values */ if( lprcScroll) if( lprcClip) IntersectRect( &rcClip, lprcClip, lprcScroll); else rcClip = *lprcScroll; else if( lprcClip) rcClip = *lprcClip; else GetClipBox( hdc, &rcClip); /* Convert the combined clip rectangle to device coordinates */ LPtoDP(hdc, (LPPOINT)&rcClip, 2); if( hrgn ) SetRectRgn( hrgn, rcClip.left, rcClip.top, rcClip.right, rcClip.bottom); else hrgn = CreateRectRgnIndirect( &rcClip); CombineRgn( hrgn, hrgn, visrgn, RGN_AND); CombineRgn( hrgn, hrgn, DstRgn, RGN_DIFF); /* add the exposures to this */ if( ExpRgn) { if( TRACE_ON( scroll)) dump_region( "Expose region: ", ExpRgn); CombineRgn( hrgn, hrgn, ExpRgn, RGN_OR); DeleteObject( ExpRgn); } if( TRACE_ON( scroll)) dump_region( "Update region: ", hrgn); if( lprcUpdate) { GetRgnBox( hrgn, lprcUpdate ); /* Put the lprcUpdate in logical coordinates */ DPtoLP( hdc, (LPPOINT)lprcUpdate, 2 ); TRACE("returning lprcUpdate %s\n", wine_dbgstr_rect(lprcUpdate)); } if( !hrgnUpdate) DeleteObject( hrgn); } /* restore original clipping region */ SelectClipRgn( hdc, clipRgn); DeleteObject( visrgn); DeleteObject( DstRgn); if( clipRgn) DeleteObject( clipRgn); return TRUE; }
static void stubSyncTrUpdateWindowCB(unsigned long key, void *data1, void *data2) { WindowInfo *pWindow = (WindowInfo *) data1; PVBOXCR_UPDATEWNDCB pCbData = (PVBOXCR_UPDATEWNDCB) data2; VBOXDISPMP_REGIONS *pRegions = &pCbData->Regions; bool bChanged = false, bDoMap = false; HRGN hNewRgn = INVALID_HANDLE_VALUE; if (pRegions->hWnd != pWindow->hWnd) { return; } stub.spu->dispatch_table.VBoxPackSetInjectID(pWindow->u32ClientID); if (!stubSystemWindowExist(pWindow)) { stubDestroyWindow(0, (GLint)pWindow->hWnd); return; } if (pRegions->pRegions->fFlags.bAddVisibleRects || pRegions->pRegions->fFlags.bSetViewRect) { if (!pWindow->mapped) { bDoMap = true; } /* ensure data integrity */ Assert(!pRegions->pRegions->fFlags.bAddHiddenRects); if (pRegions->pRegions->fFlags.bSetViewRect) { int winX, winY; unsigned int winW, winH; BOOL bRc; winX = pRegions->pRegions->RectsInfo.aRects[0].left; winY = pRegions->pRegions->RectsInfo.aRects[0].top; winW = pRegions->pRegions->RectsInfo.aRects[0].right - winX; winH = pRegions->pRegions->RectsInfo.aRects[0].bottom - winY; if (stub.trackWindowPos && (bDoMap || winX!=pWindow->x || winY!=pWindow->y)) { crDebug("Dispatched WindowPosition (%i)", pWindow->spuWindow); stub.spuDispatch.WindowPosition(pWindow->spuWindow, winX, winY); pWindow->x = winX; pWindow->y = winY; bChanged = true; } if (stub.trackWindowSize && (bDoMap || winW!=pWindow->width || winH!=pWindow->height)) { crDebug("Dispatched WindowSize (%i)", pWindow->spuWindow); stub.spuDispatch.WindowSize(pWindow->spuWindow, winW, winH); pWindow->width = winW; pWindow->height = winH; bChanged = true; } bRc = MoveWindow(pRegions->hWnd, winX, winY, winW, winH, FALSE /*BOOL bRepaint*/); if (!bRc) { DWORD winEr = GetLastError(); crWarning("stubSyncTrUpdateWindowCB: MoveWindow failed winEr(%d)", winEr); } } if (pRegions->pRegions->fFlags.bAddVisibleRects) { hNewRgn = stubMakeRegionFromRects(pRegions->pRegions, pRegions->pRegions->fFlags.bSetViewRect ? 1 : 0); } } else if (!pRegions->pRegions->fFlags.bHide) { Assert(pRegions->pRegions->fFlags.bAddHiddenRects); hNewRgn = stubMakeRegionFromRects(pRegions->pRegions, 0); } else { Assert(pRegions->pRegions->fFlags.bAddHiddenRects); hNewRgn = CreateRectRgn(pWindow->x, pWindow->y, pWindow->x + pWindow->width, pWindow->y + pWindow->height); } if (hNewRgn!=INVALID_HANDLE_VALUE) { if (pRegions->pRegions->fFlags.bAddVisibleRects) { HRGN hEmptyRgn = CreateRectRgn(0, 0, 0, 0); if (hEmptyRgn!=INVALID_HANDLE_VALUE) { if (pWindow->hVisibleRegion==INVALID_HANDLE_VALUE || EqualRgn(pWindow->hVisibleRegion, hEmptyRgn)) { pCbData->fSendUpdateMsg = true; } DeleteObject(hEmptyRgn); } else { crWarning("Failed to created empty region!"); } } OffsetRgn(hNewRgn, -pWindow->x, -pWindow->y); if (pWindow->hVisibleRegion!=INVALID_HANDLE_VALUE) { CombineRgn(hNewRgn, pWindow->hVisibleRegion, hNewRgn, pRegions->pRegions->fFlags.bAddHiddenRects ? RGN_DIFF:RGN_OR); if (!EqualRgn(pWindow->hVisibleRegion, hNewRgn)) { DeleteObject(pWindow->hVisibleRegion); pWindow->hVisibleRegion = hNewRgn; stubDispatchVisibleRegions(pWindow); bChanged = true; } else { DeleteObject(hNewRgn); } } else { if (pRegions->pRegions->fFlags.bAddVisibleRects) { pWindow->hVisibleRegion = hNewRgn; stubDispatchVisibleRegions(pWindow); bChanged = true; } } } if (bDoMap) { pWindow->mapped = GL_TRUE; bChanged = true; crDebug("Dispatched: WindowShow(%i, %i)", pWindow->spuWindow, pWindow->mapped); stub.spu->dispatch_table.WindowShow(pWindow->spuWindow, pWindow->mapped); } if (bChanged) { stub.spu->dispatch_table.Flush(); } }
void MWcanvas16::clip() { flush(); // ---- make sure there are multiple points ---- PathRenderInfo* p = &path_; POINT* pt = p->point_; int n = (int) (p->cur_point_ - p->point_); if (n <= 2) { return; } // // The path must be in terms of device units for specification of // clipping... so we transform the path specifications from logical // units (TWIPS) to device units before setting the clipping. // if(drawable_ == nil) // sometimes its null because of event input -- just ignore return; MWassert( LPtoDP(drawable_, pt, n) ); // ---- create a region to represent clipping ---- HRGN clip; if (xrect(pt, n)) { // ---- rectangular clipping area ---- RECT xr; xr.left = Math::min(pt[0].x, pt[2].x); xr.top = Math::min(pt[0].y, pt[2].y); xr.right = Math::max(pt[0].x, pt[2].x); xr.bottom = Math::max(pt[0].y, pt[2].y); clip = CreateRectRgn(xr.left, xr.top, xr.right, xr.bottom ); } else { clip = CreatePolygonRgn(pt, n, WINDING); } #if 1 // ---- merge with existing clipping area ---- HRGN intersect = CreateRectRgn(0,0,0,0); CombineRgn(intersect, clipping_, clip, RGN_AND); DeleteObject(clip); clip = intersect; #endif //DebugMessage // ---- set new clipping area ---- SelectClipRgn(drawable_, clip); DeleteObject(clipping_); clipping_ = clip; #ifdef DEBUG // ---- canvas debug ---- printf("clip "); for (int i = 0; i < n; i++) { printf("[%d,%d] ", pt[i].x, pt[i].y); } printf("\n"); #endif }
/* The function makes the window visible if it is hidden or is not yet shown. */ void SplashRedrawWindow(Splash * splash) { if (!SplashIsStillLooping(splash)) { KillTimer(splash->hWnd, 0); } if (splash->currentFrame < 0) { return; } SplashUpdateScreenData(splash); if (splash->isLayered) { BLENDFUNCTION bf; POINT ptSrc; HDC hdcSrc = CreateCompatibleDC(NULL), hdcDst; BITMAPINFOHEADER bmi; void *bitmapBits; HBITMAP hBitmap, hOldBitmap; RECT rect; POINT ptDst; SIZE size; bf.BlendOp = AC_SRC_OVER; bf.BlendFlags = 0; bf.AlphaFormat = AC_SRC_ALPHA; bf.SourceConstantAlpha = 0xFF; ptSrc.x = ptSrc.y = 0; memset(&bmi, 0, sizeof(bmi)); bmi.biSize = sizeof(BITMAPINFOHEADER); bmi.biWidth = splash->width; bmi.biHeight = -splash->height; bmi.biPlanes = 1; bmi.biBitCount = 32; bmi.biCompression = BI_RGB; // FIXME: this is somewhat ineffective // maybe if we allocate memory for all frames as DIBSections, // then we could select the frames into the DC directly hBitmap = CreateDIBSection(NULL, (BITMAPINFO *) & bmi, DIB_RGB_COLORS, &bitmapBits, NULL, 0); memcpy(bitmapBits, splash->screenData, splash->screenStride * splash->height); hOldBitmap = (HBITMAP) SelectObject(hdcSrc, hBitmap); hdcDst = GetDC(splash->hWnd); GetWindowRect(splash->hWnd, &rect); ptDst.x = rect.left; ptDst.y = rect.top; size.cx = splash->width; size.cy = splash->height; UpdateLayeredWindow(splash->hWnd, hdcDst, &ptDst, &size, hdcSrc, &ptSrc, 0, &bf, ULW_ALPHA); ReleaseDC(splash->hWnd, hdcDst); SelectObject(hdcSrc, hOldBitmap); DeleteObject(hBitmap); DeleteDC(hdcSrc); } else { InvalidateRect(splash->hWnd, NULL, FALSE); if (splash->maskRequired) { HRGN hRgn = CreateRectRgn(0, 0, 0, 0); CombineRgn(hRgn, splash->frames[splash->currentFrame].hRgn, splash->frames[splash->currentFrame].hRgn, RGN_COPY); SetWindowRgn(splash->hWnd, hRgn, TRUE); } else { SetWindowRgn(splash->hWnd, NULL, TRUE); } UpdateWindow(splash->hWnd); } if (!IsWindowVisible(splash->hWnd)) { POINT cursorPos; ShowWindow(splash->hWnd, SW_SHOW); // Windows won't update the cursor after the window is shown, // if the cursor is already above the window. need to do this manually. GetCursorPos(&cursorPos); if (WindowFromPoint(cursorPos) == splash->hWnd) { // unfortunately Windows fail to understand that the window // thread should own the cursor, even though the mouse pointer // is over the window, until the mouse has been moved. // we're using SetCursorPos here to fake the mouse movement // and enable proper update of the cursor. SetCursorPos(cursorPos.x, cursorPos.y); SetCursor(LoadCursor(NULL, IDC_WAIT)); } } if (SplashIsStillLooping(splash)) { int time = splash->time + splash->frames[splash->currentFrame].delay - SplashTime(); if (time < 0) time = 0; SetTimer(splash->hWnd, 0, time, NULL); } }
//创建区域 HRGN CSkinImage::CreateImageRegion(COLORREF cTranColor) { //判断状态 if (IsNull()==true) return NULL; //创建区域 HRGN hRgn=NULL; HDC hMemDC=::CreateCompatibleDC(NULL); if (hMemDC!=NULL) { void * pbits32=NULL; HBITMAP hBitmap=(HBITMAP)this; BITMAPINFOHEADER RGB32BITSBITMAPINFO={sizeof(BITMAPINFOHEADER),GetWidth(),GetHeight(),1,32,BI_RGB,0,0,0,0,0}; HBITMAP hbm32=CreateDIBSection(hMemDC,(BITMAPINFO *)&RGB32BITSBITMAPINFO,DIB_RGB_COLORS,&pbits32,NULL,0); if (hbm32) { HBITMAP holdBmp=(HBITMAP)SelectObject(hMemDC,hbm32); HDC hDC = CreateCompatibleDC(hMemDC); if (hDC) { BITMAP bm32; GetObject(hbm32,sizeof(bm32),&bm32); while (bm32.bmWidthBytes%4) bm32.bmWidthBytes++; HBITMAP holdBmp=(HBITMAP)SelectObject(hDC,hBitmap); ::BitBlt(hMemDC,0,0,GetWidth(),GetHeight(),hDC,0,0,SRCCOPY); DWORD maxRects=100; HANDLE hData=GlobalAlloc(GMEM_MOVEABLE,sizeof(RGNDATAHEADER)+(sizeof(RECT)*maxRects)); RGNDATA *pData=(RGNDATA *)GlobalLock(hData); pData->rdh.dwSize=sizeof(RGNDATAHEADER); pData->rdh.iType=RDH_RECTANGLES; pData->rdh.nCount=pData->rdh.nRgnSize=0; SetRect(&pData->rdh.rcBound, MAXLONG, MAXLONG, 0, 0); BYTE hr=GetRValue(cTranColor); BYTE hg=GetGValue(cTranColor); BYTE hb=GetBValue(cTranColor); BYTE * p32=(BYTE *)bm32.bmBits+(bm32.bmHeight-1)*bm32.bmWidthBytes; for (int y=0;y<GetHeight();y++) { for (int x=0;x<GetWidth();x++) { int x0=x; LONG *p=(LONG *)p32+x; while (x<GetWidth()) { BYTE b=GetRValue(*p); if ((b>=hr)&&(b<=hr)) { b=GetGValue(*p); if (b>=hg&&b<=hg) { b=GetBValue(*p); if (b>=hb&&b<=hb) break; } } p++; x++; } if (x>x0) { if (pData->rdh.nCount >= maxRects) { GlobalUnlock(hData); maxRects += 100; hData = GlobalReAlloc(hData, sizeof(RGNDATAHEADER) + (sizeof(RECT) * maxRects), GMEM_MOVEABLE); pData = (RGNDATA *)GlobalLock(hData); } RECT * pr = (RECT *)&pData->Buffer; SetRect(&pr[pData->rdh.nCount], x0, y, x, y+1); if (x0<pData->rdh.rcBound.left) pData->rdh.rcBound.left=x0; if (y<pData->rdh.rcBound.top) pData->rdh.rcBound.top=y; if (x>pData->rdh.rcBound.right) pData->rdh.rcBound.right=x; if (y+1>pData->rdh.rcBound.bottom) pData->rdh.rcBound.bottom = y+1; pData->rdh.nCount++; if (pData->rdh.nCount==2000) { HRGN h=ExtCreateRegion(NULL,sizeof(RGNDATAHEADER)+(sizeof(RECT)*maxRects),pData); if (hRgn) { CombineRgn(hRgn,hRgn,h,RGN_OR); DeleteObject(h); } else hRgn = h; pData->rdh.nCount=0; SetRect(&pData->rdh.rcBound,MAXLONG, MAXLONG,0,0); } } } p32 -= bm32.bmWidthBytes; } HRGN h=ExtCreateRegion(NULL,sizeof(RGNDATAHEADER)+(sizeof(RECT)*maxRects),pData); if (hRgn) { CombineRgn(hRgn,hRgn,h,RGN_OR); DeleteObject(h); } else hRgn=h; GlobalFree(hData); SelectObject(hDC,holdBmp); DeleteDC(hDC); } DeleteObject(SelectObject(hMemDC, holdBmp)); } DeleteDC(hMemDC); } return hRgn; }
void CardWindow::PaintCardRgn(HDC hdc, int dx, int dy, int width, int height, int sx, int sy) { RECT rect; //if just a solid background colour if(hbmBackImage == 0) { SetRect(&rect, dx, dy, dx+width, dy+height); /*if(GetVersion() < 0x80000000) { PaintRect(hdc, &rect, MAKE_PALETTERGB(crBackgnd)); } else*/ { HBRUSH hbr = CreateSolidBrush(MAKE_PALETTERGB(crBackgnd)); FillRect(hdc, &rect, hbr); DeleteObject(hbr); } } //otherwise, paint using the bitmap else { // Draw whatever part of background we can BitBlt(hdc, dx, dy, width, height, hdcBackImage, sx, sy, SRCCOPY); // Now we need to paint any area outside the bitmap, // just in case the bitmap is too small to fill whole window if(0)//sx + width > bm.bmWidth || sy + height > bm.bmHeight) { // Find out size of bitmap BITMAP bm; GetObject(hbmBackImage, sizeof(bm), &bm); HRGN hr1 = CreateRectRgn(sx, sy, sx+width, sy+height); HRGN hr2 = CreateRectRgn(0, 0, bm.bmWidth, bm.bmHeight); HRGN hr3 = CreateRectRgn(0,0, 1, 1); HRGN hr4 = CreateRectRgn(0,0, 1, 1); CombineRgn(hr3, hr1, hr2, RGN_DIFF); GetClipRgn(hdc, hr4); CombineRgn(hr3, hr4, hr3, RGN_AND); SelectClipRgn(hdc, hr3); // Fill remaining space not filled with bitmap HBRUSH hbr = CreateSolidBrush(crBackgnd); FillRgn(hdc, hr3, hbr); DeleteObject(hbr); // Clean up SelectClipRgn(hdc, hr4); DeleteObject(hr1); DeleteObject(hr2); DeleteObject(hr3); DeleteObject(hr4); } } }
static void winShadowUpdateDDNL (ScreenPtr pScreen, shadowBufPtr pBuf) { winScreenPriv(pScreen); winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; RegionPtr damage = shadowDamage(pBuf); HRESULT ddrval = DD_OK; RECT rcDest, rcSrc; POINT ptOrigin; DWORD dwBox = RegionNumRects (damage); BoxPtr pBox = RegionRects (damage); HRGN hrgnTemp = NULL, hrgnCombined = NULL; /* * Return immediately if the app is not active * and we are fullscreen, or if we have a bad display depth */ if ((!pScreenPriv->fActive && pScreenInfo->fFullScreen) || pScreenPriv->fBadDepth) return; /* Return immediately if we didn't get needed surfaces */ if (!pScreenPriv->pddsPrimary4 || !pScreenPriv->pddsShadow4) return; /* Get the origin of the window in the screen coords */ ptOrigin.x = pScreenInfo->dwXOffset; ptOrigin.y = pScreenInfo->dwYOffset; MapWindowPoints (pScreenPriv->hwndScreen, HWND_DESKTOP, (LPPOINT)&ptOrigin, 1); /* * Handle small regions with multiple blits, * handle large regions by creating a clipping region and * doing a single blit constrained to that clipping region. */ if (pScreenInfo->dwClipUpdatesNBoxes == 0 || dwBox < pScreenInfo->dwClipUpdatesNBoxes) { /* Loop through all boxes in the damaged region */ while (dwBox--) { /* Assign damage box to source rectangle */ rcSrc.left = pBox->x1; rcSrc.top = pBox->y1; rcSrc.right = pBox->x2; rcSrc.bottom = pBox->y2; /* Calculate destination rectangle */ rcDest.left = ptOrigin.x + rcSrc.left; rcDest.top = ptOrigin.y + rcSrc.top; rcDest.right = ptOrigin.x + rcSrc.right; rcDest.bottom = ptOrigin.y + rcSrc.bottom; /* Blit the damaged areas */ ddrval = IDirectDrawSurface4_Blt (pScreenPriv->pddsPrimary4, &rcDest, pScreenPriv->pddsShadow4, &rcSrc, DDBLT_WAIT, NULL); if (FAILED (ddrval)) { static int s_iFailCount = 0; if (s_iFailCount < FAIL_MSG_MAX_BLT) { ErrorF ("winShadowUpdateDDNL - IDirectDrawSurface4_Blt () " "failed: %08x\n", (unsigned int) ddrval); ++s_iFailCount; if (s_iFailCount == FAIL_MSG_MAX_BLT) { ErrorF ("winShadowUpdateDDNL - IDirectDrawSurface4_Blt " "failure message maximum (%d) reached. No " "more failure messages will be printed.\n", FAIL_MSG_MAX_BLT); } } } /* Get a pointer to the next box */ ++pBox; } } else { BoxPtr pBoxExtents = RegionExtents(damage); /* Compute a GDI region from the damaged region */ hrgnCombined = CreateRectRgn (pBox->x1, pBox->y1, pBox->x2, pBox->y2); dwBox--; pBox++; while (dwBox--) { hrgnTemp = CreateRectRgn (pBox->x1, pBox->y1, pBox->x2, pBox->y2); CombineRgn (hrgnCombined, hrgnCombined, hrgnTemp, RGN_OR); DeleteObject (hrgnTemp); pBox++; } /* Install the GDI region as a clipping region */ SelectClipRgn (pScreenPriv->hdcScreen, hrgnCombined); DeleteObject (hrgnCombined); hrgnCombined = NULL; #if CYGDEBUG winDebug ("winShadowUpdateDDNL - be x1 %d y1 %d x2 %d y2 %d\n", pBoxExtents->x1, pBoxExtents->y1, pBoxExtents->x2, pBoxExtents->y2); #endif /* Calculating a bounding box for the source is easy */ rcSrc.left = pBoxExtents->x1; rcSrc.top = pBoxExtents->y1; rcSrc.right = pBoxExtents->x2; rcSrc.bottom = pBoxExtents->y2; /* Calculating a bounding box for the destination is trickier */ rcDest.left = ptOrigin.x + rcSrc.left; rcDest.top = ptOrigin.y + rcSrc.top; rcDest.right = ptOrigin.x + rcSrc.right; rcDest.bottom = ptOrigin.y + rcSrc.bottom; /* Our Blt should be clipped to the invalidated region */ ddrval = IDirectDrawSurface4_Blt (pScreenPriv->pddsPrimary4, &rcDest, pScreenPriv->pddsShadow4, &rcSrc, DDBLT_WAIT, NULL); /* Reset the clip region */ SelectClipRgn (pScreenPriv->hdcScreen, NULL); } }
static void winShadowUpdateGDI (ScreenPtr pScreen, shadowBufPtr pBuf) { winScreenPriv(pScreen); winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; RegionPtr damage = shadowDamage(pBuf); DWORD dwBox = RegionNumRects (damage); BoxPtr pBox = RegionRects (damage); int x, y, w, h; HRGN hrgnTemp = NULL, hrgnCombined = NULL; #ifdef XWIN_UPDATESTATS static DWORD s_dwNonUnitRegions = 0; static DWORD s_dwTotalUpdates = 0; static DWORD s_dwTotalBoxes = 0; #endif BoxPtr pBoxExtents = RegionExtents(damage); /* * Return immediately if the app is not active * and we are fullscreen, or if we have a bad display depth */ if ((!pScreenPriv->fActive && pScreenInfo->fFullScreen) || pScreenPriv->fBadDepth) return; #ifdef XWIN_UPDATESTATS ++s_dwTotalUpdates; s_dwTotalBoxes += dwBox; if (dwBox != 1) { ++s_dwNonUnitRegions; ErrorF ("winShadowUpdatGDI - dwBox: %d\n", dwBox); } if ((s_dwTotalUpdates % 100) == 0) ErrorF ("winShadowUpdateGDI - %d%% non-unity regions, avg boxes: %d " "nu: %d tu: %d\n", (s_dwNonUnitRegions * 100) / s_dwTotalUpdates, s_dwTotalBoxes / s_dwTotalUpdates, s_dwNonUnitRegions, s_dwTotalUpdates); #endif /* XWIN_UPDATESTATS */ /* * Handle small regions with multiple blits, * handle large regions by creating a clipping region and * doing a single blit constrained to that clipping region. */ if (!pScreenInfo->fMultiWindow && (pScreenInfo->dwClipUpdatesNBoxes == 0 || dwBox < pScreenInfo->dwClipUpdatesNBoxes)) { /* Loop through all boxes in the damaged region */ while (dwBox--) { /* * Calculate x offset, y offset, width, and height for * current damage box */ x = pBox->x1; y = pBox->y1; w = pBox->x2 - pBox->x1; h = pBox->y2 - pBox->y1; BitBlt (pScreenPriv->hdcScreen, x, y, w, h, pScreenPriv->hdcShadow, x, y, SRCCOPY); /* Get a pointer to the next box */ ++pBox; } } else if (!pScreenInfo->fMultiWindow) { /* Compute a GDI region from the damaged region */ hrgnCombined = CreateRectRgn (pBox->x1, pBox->y1, pBox->x2, pBox->y2); dwBox--; pBox++; while (dwBox--) { hrgnTemp = CreateRectRgn (pBox->x1, pBox->y1, pBox->x2, pBox->y2); CombineRgn (hrgnCombined, hrgnCombined, hrgnTemp, RGN_OR); DeleteObject (hrgnTemp); pBox++; } /* Install the GDI region as a clipping region */ SelectClipRgn (pScreenPriv->hdcScreen, hrgnCombined); DeleteObject (hrgnCombined); hrgnCombined = NULL; /* * Blit the shadow buffer to the screen, * constrained to the clipping region. */ BitBlt (pScreenPriv->hdcScreen, pBoxExtents->x1, pBoxExtents->y1, pBoxExtents->x2 - pBoxExtents->x1, pBoxExtents->y2 - pBoxExtents->y1, pScreenPriv->hdcShadow, pBoxExtents->x1, pBoxExtents->y1, SRCCOPY); /* Reset the clip region */ SelectClipRgn (pScreenPriv->hdcScreen, NULL); } #ifdef XWIN_MULTIWINDOW /* Redraw all multiwindow windows */ if (pScreenInfo->fMultiWindow) EnumThreadWindows (g_dwCurrentThreadID, winRedrawDamagedWindowShadowGDI, (LPARAM)pBoxExtents); #endif }
//////////////////////////////////////////////////////////// // Strip_Setup : Sizes and masks the strip and loads the skin /// ARGS //////////////////////////////////////////////////// // dlg : Handle of the window to apply all this to void Strip_Setup(HWND dlg){ unsigned char i=0,q=0,r=0; unsigned int hky=0; HBITMAP bmp; HRGN rgn; // // Get the number of rows if(vr.btns%cf.cols){ vr.rows=(vr.btns/cf.cols)+1; }else{vr.rows=vr.btns/cf.cols;} // Size the window if(vr.btns>cf.cols){ // Calculate row count vr.rct.right=mx.arx+(cf.cols*mx.bnx); vr.rct.bottom=mx.iny+(mx.bny*vr.rows); }else{ // 1 row vr.rct.right=mx.arx+(vr.btns*mx.bnx); vr.rct.bottom=mx.bny+mx.iny; } // Mask out the un-needed part rgn=CreateRectRgn(0,0,vr.rct.right,vr.rct.bottom); CombineRgn(rgn,rgn,CreateRectRgn(0,mx.ary,mx.arx,vr.rct.bottom),RGN_DIFF); if(vr.btns>cf.infw&&cf.cols>cf.infw){ // Only mask out the info section if there is space to hide CombineRgn(rgn,rgn,CreateRectRgn(0,vr.rct.bottom-mx.iny,vr.rct.right-(mx.bnx*cf.infw),vr.rct.bottom),RGN_DIFF); } SetWindowRgn(dlg,rgn,1); // Move to the right side Strip_Position(dlg); // Load the theme stuff // Skin vr.gfx=CreateCompatibleDC(GetDC(dlg)); /* * The code below creates a memory leak * \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ */ if(Bio_IsFile(cf.skin)){ bmp=LoadImage(GetModuleHandle(0),cf.skin,IMAGE_BITMAP,0,0,LR_LOADFROMFILE); }else{bmp=LoadBitmap(GetModuleHandle(0),MAKEINTRESOURCE(BMP_GFX));} DeleteObject(SelectObject(vr.gfx,bmp)); DeleteObject(bmp); // Font DeleteObject(SelectObject(GetDC(dlg),CreateFont(mx.txt,0,0,0,(mx.txa&KS_TXA_BOLD)?FW_BOLD:0,(mx.txa&KS_TXA_ITALIC)?1:0,0,0,0,0,0,0,0,cf.fnt))); /* * /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ * The code above creates a memory leak */ SetTextColor(GetDC(dlg),mx.txc); SetBkMode(GetDC(dlg),TRANSPARENT); SetStretchBltMode(GetDC(dlg),HALFTONE); // Create buttons vr.arw=CreateWindow("bncls","Arrow",WS_VISIBLE|WS_CHILD,0,0,mx.arx,mx.ary,dlg,0,GetModuleHandle(0),0); for(i=0;i<vr.btns;i++){ itm[i].wnd=CreateWindow("bncls","Button",WS_VISIBLE|WS_CHILD,mx.arx+(mx.bnx*q),mx.bny*r,mx.bnx,mx.bny,dlg,0,GetModuleHandle(0),0); q++;if(q>=cf.cols){r++;q=0;} } // Set hotkey if(cf.disp==KS_DSP_KEY){ // Translate the modifier key types if(HIBYTE(cf.hkey)&HOTKEYF_ALT){hky|=MOD_ALT;} if(HIBYTE(cf.hkey)&HOTKEYF_SHIFT){hky|=MOD_SHIFT;} if(HIBYTE(cf.hkey)&HOTKEYF_CONTROL){hky|=MOD_CONTROL;} RegisterHotKey(dlg,1,hky,LOBYTE(cf.hkey)); } }
void DSObjects::RMASubtractRegion(REGION* regM, REGION* regS, REGION* regD) { CombineRgn((HRGN)regD->pOSRegion, (HRGN)regM->pOSRegion, (HRGN)regS->pOSRegion, RGN_DIFF); ExtractRects(regD); }
static void wf_rail_window_common(rdpContext* context, WINDOW_ORDER_INFO* orderInfo, WINDOW_STATE_ORDER* windowState) { wfRailWindow* railWindow = NULL; wfContext* wfc = (wfContext*) context; RailClientContext* rail = wfc->rail; UINT32 fieldFlags = orderInfo->fieldFlags; PrintRailWindowState(orderInfo, windowState); if (fieldFlags & WINDOW_ORDER_STATE_NEW) { HANDLE hInstance; WCHAR* titleW = NULL; WNDCLASSEX wndClassEx; railWindow = (wfRailWindow*) calloc(1, sizeof(wfRailWindow)); if (!railWindow) return; railWindow->wfc = wfc; railWindow->dwStyle = windowState->style; railWindow->dwStyle &= ~RAIL_DISABLED_WINDOW_STYLES; railWindow->dwExStyle = windowState->extendedStyle; railWindow->dwExStyle &= ~RAIL_DISABLED_EXTENDED_WINDOW_STYLES; railWindow->x = windowState->windowOffsetX; railWindow->y = windowState->windowOffsetY; railWindow->width = windowState->windowWidth; railWindow->height = windowState->windowHeight; if (fieldFlags & WINDOW_ORDER_FIELD_TITLE) { char* title = NULL; ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) windowState->titleInfo.string, windowState->titleInfo.length / 2, &title, 0, NULL, NULL); railWindow->title = title; } else { railWindow->title = _strdup("RdpRailWindow"); } ConvertToUnicode(CP_UTF8, 0, railWindow->title, -1, &titleW, 0); hInstance = GetModuleHandle(NULL); ZeroMemory(&wndClassEx, sizeof(WNDCLASSEX)); wndClassEx.cbSize = sizeof(WNDCLASSEX); wndClassEx.style = 0; wndClassEx.lpfnWndProc = wf_RailWndProc; wndClassEx.cbClsExtra = 0; wndClassEx.cbWndExtra = 0; wndClassEx.hIcon = NULL; wndClassEx.hCursor = NULL; wndClassEx.hbrBackground = NULL; wndClassEx.lpszMenuName = NULL; wndClassEx.lpszClassName = _T("RdpRailWindow"); wndClassEx.hInstance = hInstance; wndClassEx.hIconSm = NULL; RegisterClassEx(&wndClassEx); railWindow->hWnd = CreateWindowExW( railWindow->dwExStyle, /* dwExStyle */ _T("RdpRailWindow"), /* lpClassName */ titleW, /* lpWindowName */ railWindow->dwStyle, /* dwStyle */ railWindow->x, /* x */ railWindow->y, /* y */ railWindow->width, /* nWidth */ railWindow->height, /* nHeight */ NULL, /* hWndParent */ NULL, /* hMenu */ hInstance, /* hInstance */ NULL /* lpParam */ ); SetWindowLongPtr(railWindow->hWnd, GWLP_USERDATA, (LONG_PTR) railWindow); HashTable_Add(wfc->railWindows, (void*) (UINT_PTR) orderInfo->windowId, (void*) railWindow); free(titleW); UpdateWindow(railWindow->hWnd); return; } else { railWindow = (wfRailWindow*) HashTable_GetItemValue(wfc->railWindows, (void*) (UINT_PTR) orderInfo->windowId); } if (!railWindow) return; if ((fieldFlags & WINDOW_ORDER_FIELD_WND_OFFSET) || (fieldFlags & WINDOW_ORDER_FIELD_WND_SIZE)) { if (fieldFlags & WINDOW_ORDER_FIELD_WND_OFFSET) { railWindow->x = windowState->windowOffsetX; railWindow->y = windowState->windowOffsetY; } if (fieldFlags & WINDOW_ORDER_FIELD_WND_SIZE) { railWindow->width = windowState->windowWidth; railWindow->height = windowState->windowHeight; } SetWindowPos(railWindow->hWnd, NULL, railWindow->x, railWindow->y, railWindow->width, railWindow->height, 0); } if (fieldFlags & WINDOW_ORDER_FIELD_OWNER) { } if (fieldFlags & WINDOW_ORDER_FIELD_STYLE) { railWindow->dwStyle = windowState->style; railWindow->dwStyle &= ~RAIL_DISABLED_WINDOW_STYLES; railWindow->dwExStyle = windowState->extendedStyle; railWindow->dwExStyle &= ~RAIL_DISABLED_EXTENDED_WINDOW_STYLES; SetWindowLongPtr(railWindow->hWnd, GWL_STYLE, (LONG) railWindow->dwStyle); SetWindowLongPtr(railWindow->hWnd, GWL_EXSTYLE, (LONG) railWindow->dwExStyle); } if (fieldFlags & WINDOW_ORDER_FIELD_SHOW) { ShowWindow(railWindow->hWnd, windowState->showState); } if (fieldFlags & WINDOW_ORDER_FIELD_TITLE) { char* title = NULL; WCHAR* titleW = NULL; ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) windowState->titleInfo.string, windowState->titleInfo.length / 2, &title, 0, NULL, NULL); free(railWindow->title); railWindow->title = title; ConvertToUnicode(CP_UTF8, 0, railWindow->title, -1, &titleW, 0); SetWindowTextW(railWindow->hWnd, titleW); free(titleW); } if (fieldFlags & WINDOW_ORDER_FIELD_CLIENT_AREA_OFFSET) { } if (fieldFlags & WINDOW_ORDER_FIELD_CLIENT_AREA_SIZE) { } if (fieldFlags & WINDOW_ORDER_FIELD_WND_CLIENT_DELTA) { } if (fieldFlags & WINDOW_ORDER_FIELD_RP_CONTENT) { } if (fieldFlags & WINDOW_ORDER_FIELD_ROOT_PARENT) { } if (fieldFlags & WINDOW_ORDER_FIELD_WND_RECTS) { UINT32 index; HRGN hWndRect; HRGN hWndRects; RECTANGLE_16* rect; if (windowState->numWindowRects > 0) { rect = &(windowState->windowRects[0]); hWndRects = CreateRectRgn(rect->left, rect->top, rect->right, rect->bottom); for (index = 1; index < windowState->numWindowRects; index++) { rect = &(windowState->windowRects[index]); hWndRect = CreateRectRgn(rect->left, rect->top, rect->right, rect->bottom); CombineRgn(hWndRects, hWndRects, hWndRect, RGN_OR); DeleteObject(hWndRect); } SetWindowRgn(railWindow->hWnd, hWndRects, TRUE); DeleteObject(hWndRects); } } if (fieldFlags & WINDOW_ORDER_FIELD_VIS_OFFSET) { } if (fieldFlags & WINDOW_ORDER_FIELD_VISIBILITY) { } UpdateWindow(railWindow->hWnd); }
static void _AniAva_RenderAvatar(ANIAVA_WINDOWINFO * dat, HDC hdcParent /* = NULL*/, RECT * rcInParent /* = NULL */ ) { if (dat->bPaused>0) { dat->bPended=TRUE; return; } else dat->bPended=FALSE; if ( IMMEDIATE_DRAW && hdcParent == NULL ) return; GdiFlush(); #ifdef _DEBUG __AniAva_DebugRenderStrip(); #endif if (dat->bPlaying && IsWindowVisible(dat->hWindow)) { POINT ptWnd={0}; SIZE szWnd={dat->rcPos.right-dat->rcPos.left,dat->rcPos.bottom-dat->rcPos.top}; BLENDFUNCTION bf={AC_SRC_OVER, 0,g_CluiData.bCurrentAlpha*dat->bAlpha/256, AC_SRC_ALPHA }; POINT pt_from={0,0}; HDC hDC_animation=GetDC(NULL); HDC copyFromDC; RECT clistRect; HDC tempDC=NULL; HBITMAP hBmp; HBITMAP hOldBmp; /* int x=bf.SourceConstantAlpha; x=(49152/(383-x))-129; x=min(x,255); x=max(x,0); bf.SourceConstantAlpha=x; */ if ( AniAva.bFlags == 0 ) //simple and fastest method - no borders, round corners and etc. just copy { pt_from.x=dat->ptFromPoint.x+dat->currentFrame*dat->sizeAvatar.cx; pt_from.y=dat->ptFromPoint.y; copyFromDC=AniAva.hAniAvaDC; } else { // ... need to create additional hDC_animation HRGN hRgn=NULL; int cornerRadius= AniAva.cornerRadius; tempDC = CreateCompatibleDC( NULL ); hBmp = ske_CreateDIB32( szWnd.cx, szWnd.cy ); hOldBmp = (HBITMAP)SelectObject(tempDC,hBmp); if ( AniAva.bFlags & AAO_ROUND_CORNERS ) { if (!cornerRadius) //auto radius cornerRadius = min(szWnd.cx, szWnd.cy )/5; } if ( AniAva.bFlags & AAO_HAS_BORDER ) { // if has borders - create region (round corners) and fill it, remember internal as clipping HBRUSH hBrush = CreateSolidBrush( AniAva.borderColor ); HBRUSH hOldBrush = (HBRUSH)SelectObject( tempDC, hBrush ); HRGN rgnOutside = CreateRoundRectRgn( 0, 0, szWnd.cx+1, szWnd.cy+1, cornerRadius<<1, cornerRadius<<1); hRgn=CreateRoundRectRgn( 1, 1, szWnd.cx, szWnd.cy, cornerRadius<<1, cornerRadius<<1); CombineRgn( rgnOutside,rgnOutside,hRgn,RGN_DIFF); FillRgn( tempDC, rgnOutside, hBrush); ske_SetRgnOpaque( tempDC, rgnOutside, TRUE); SelectObject(tempDC, hOldBrush); DeleteObject(hBrush); DeleteObject(rgnOutside); } else if ( cornerRadius > 0 ) { // else create clipping area (round corners) hRgn=CreateRoundRectRgn(0, 0, szWnd.cx+1, szWnd.cy+1, cornerRadius<<1, cornerRadius<<1); } else { hRgn=CreateRectRgn(0, 0, szWnd.cx+1, szWnd.cy+1); } // select clip area if ( hRgn ) ExtSelectClipRgn(tempDC, hRgn, RGN_AND); if ( AniAva.bFlags & AAO_OPAQUE) { // if back color - fill clipping area HBRUSH hBrush = CreateSolidBrush( AniAva.bkgColor ); HBRUSH hOldBrush = (HBRUSH)SelectObject( tempDC, hBrush ); FillRgn( tempDC, hRgn, hBrush ); ske_SetRgnOpaque( tempDC, hRgn, TRUE ); } // draw avatar if ( !(AniAva.bFlags & AAO_OPAQUE) ) BitBlt(tempDC,0, 0, szWnd.cx, szWnd.cy , AniAva.hAniAvaDC , dat->ptFromPoint.x+dat->sizeAvatar.cx*dat->currentFrame, dat->ptFromPoint.y, SRCCOPY); else { BLENDFUNCTION abf={AC_SRC_OVER, 0, 255, AC_SRC_ALPHA }; ske_AlphaBlend(tempDC,0, 0, szWnd.cx, szWnd.cy , AniAva.hAniAvaDC, dat->ptFromPoint.x+dat->sizeAvatar.cx*dat->currentFrame, dat->ptFromPoint.y, szWnd.cx, szWnd.cy, abf); } // reset clip area if ( hRgn ) { DeleteObject(hRgn); hRgn = CreateRectRgn(0, 0, szWnd.cx, szWnd.cy); SelectClipRgn(tempDC, hRgn); DeleteObject(hRgn); } if ( ( AniAva.bFlags & AAO_HAS_OVERLAY ) && ( dat->overlayIconIdx != -1 ) && ( AniAva.overlayIconImageList ) ) { // if overlay - draw overlay icon // position - on avatar int x=szWnd.cx-ICON_WIDTH; int y=szWnd.cy-ICON_HEIGHT; ske_ImageList_DrawEx(AniAva.overlayIconImageList, dat->overlayIconIdx&0xFFFF, tempDC, x, y, ICON_WIDTH, ICON_HEIGHT, CLR_NONE, CLR_NONE, ILD_NORMAL); } copyFromDC=tempDC; } // intersect visible area // update layered window GetWindowRect(pcli->hwndContactTree, &clistRect); if (dat->rcPos.top<0) { pt_from.y+=-dat->rcPos.top; szWnd.cy+=dat->rcPos.top; } if (dat->rcPos.bottom>clistRect.bottom-clistRect.top) { szWnd.cy-=(dat->rcPos.bottom-(clistRect.bottom-clistRect.top)); } ptWnd.x=dat->rcPos.left+clistRect.left; ptWnd.y=(dat->rcPos.top>0 ? dat->rcPos.top :0)+clistRect.top; if (szWnd.cy>0) { if ( hdcParent && rcInParent && IMMEDIATE_DRAW ) { if ( AniAva.bFlags & AAO_OPAQUE ) BitBlt( hdcParent, rcInParent->left, rcInParent->top, szWnd.cx, szWnd.cy, copyFromDC, pt_from.x, pt_from.y, SRCCOPY); else { BLENDFUNCTION abf={AC_SRC_OVER, 0, 255, AC_SRC_ALPHA }; ske_AlphaBlend( hdcParent, rcInParent->left, rcInParent->top, szWnd.cx, szWnd.cy, copyFromDC, pt_from.x, pt_from.y, szWnd.cx, szWnd.cy, abf); } } else if (!g_proc_UpdateLayeredWindow(dat->hWindow, hDC_animation, &ptWnd, &szWnd, copyFromDC, &pt_from, RGB(0,0,0), &bf, ULW_ALPHA )) { LONG exStyle; exStyle=GetWindowLong(dat->hWindow,GWL_EXSTYLE); exStyle|=WS_EX_LAYERED; SetWindowLong(dat->hWindow,GWL_EXSTYLE,exStyle); if ( !IMMEDIATE_DRAW ) SetWindowPos( pcli->hwndContactTree, dat->hWindow, 0, 0, 0, 0, SWP_ASYNCWINDOWPOS | SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOSENDCHANGING ); g_proc_UpdateLayeredWindow(dat->hWindow, hDC_animation, &ptWnd, &szWnd, copyFromDC, &pt_from, RGB(0,0,0), &bf, ULW_ALPHA ); } g_CluiData.fAeroGlass = false; CLUI_UpdateAeroGlass(); } else { dat->bPlaying=FALSE; } ReleaseDC(NULL,hDC_animation); if (tempDC) { SelectObject(tempDC, hOldBmp); DeleteObject(hBmp); DeleteDC(tempDC); } } if (!dat->bPlaying) { ShowWindow(dat->hWindow, SW_HIDE); KillTimer(dat->hWindow,2); //stop animation till set pos will be called } GdiFlush(); }