Как сделать круглое окно, которое бы в центре было абсолютно непрозрачным, и абсолютно прозрачным на краях? Т. е. прозрачность должна градиентно увеличиваться от центра к краям. Есть хотя бы идеи, как такое реализовать?
Алгоритм то вроде прост: 1. Получаешь битмап, кот. находится за твоим окном. 2. Считаешь ручками цвет каждого пикселя, пользуясь формулой круга 3. Делаешь BitBlt
1. Как получить битмап изображения под моим окном? Ведь окна не отрисовывают ту свою часть, которая спрятана за другими окнами. И как отловить перерисовку нижележащих окон (неужели нужно хукать все окна в системе)? 2. Можно по-подробнее про формулу круга?
1. На счет отрисовки части окон, которые запрятаны, это ты верно подметил. Но ведь под 2000-XP есть layered windows =) И если его сделать полностью прозрачным, то.. я не проверял, но в DC мы должны получить то, что лежит под нашим окном. А дальше дело техники. 2. =)))))))))))))))))))))))))))))))))))))))))) (X-X0)*(X-X0) + (Y-Y0)*(Y-Y0) = R*R
Я писАл нечто подобное. Начиналось это с GetDC(0), заканчивалось GetDIBits. Код слишком велик, чтобы его тут приводить целиком.
vinnie_pooh Начиналось это с GetDC(0), заканчивалось GetDIBits. Imho. Код получения изображения с контекста дисплея не интересен. Интересно как определить момент, что надо осуществить grab'ление.
А... Кажется мы возвращаемся к теме топика "Что делает BeginPaint". Если теперь я понял правильно, то тут возникает две проблемы: 1)когда прозрачное окно перетаскивается и 2) когда оно активизируется. Первую вроде бы решает этот код (перед перетаскиванием запоминать содержимое всего экрана, после копировать на окно его часть): Код (Text): case WM_CREATE: hDesktopDC = GetDC(0); hStoreDC = CreateCompatibleDC(hDesktopDC); //тут надо бы определять истинные размеры экрана) hStoreBitmap = CreateCompatibleBitmap(hDesktopDC, 1024, 768); hOldBitmap = (HBITMAP)SelectObject(hStoreDC, hStoreBitmap); BitBlt(hStoreDC, 0, 0, 1024, 768, hDesktopDC, 0, 0, SRCCOPY); break; case WM_MOVE: InvalidateRect(hWnd, 0, 1); break; case WM_LBUTTONDOWN: ShowWindow(hWnd, SW_HIDE); BitBlt(hStoreDC, 0, 0, 1024, 768, hDesktopDC, 0, 0, SRCCOPY); ShowWindow(hWnd, SW_SHOWNORMAL); SendMessage(hWnd,WM_NCLBUTTONDOWN,HTCAPTION,lParam); break; case WM_DESTROY: SelectObject(hStoreDC, hOldBitmap); DeleteObject(hStoreBitmap); DeleteDC(hStoreDC); ReleaseDC(0, hDesktopDC); PostQuitMessage(0); break; case WM_PAINT: hDC = BeginPaint(hWnd,&ps); GetWindowRect(hWnd, &rect); BitBlt(hDC, 0, 0, 200, 70, hStoreDC, rect.left, rect.top, SRCCOPY); GetClientRect(hWnd,&rect); SetBkMode(hDC,TRANSPARENT); SetTextColor(hDC,RGB(255,0,0)); DrawText(hDC,"Test string",-1,&rect,DT_CENTER | DT_VCENTER | DT_SINGLELINE); EndPaint(hWnd,&ps); break; Только окно не дожно быть WS_EX_TRANSPARENT, иначе - лажа, а прозрачность уже и так реализована. Если еще добавить обработку WM_ACTIVATE, то, по-моему, все будет как надо.
vinnie_pooh Твой код не учитывает изменений на экране с момента запуска проги. А прога должна правильно отображать прозрачность даже если под её окном находится окно медиплеера (для начала можно не рассматривать варинат с DirectX) с постоянно меняющейся картинкой. Так что нужно найти способ заставить нижележащие окна перерисовать ту часть, которая находится под моим окном, на моём DC. Или хотя бы захватить кусок экрана под тем местом, куда перетаскивается окно, до того, как оно отрисуется
Нет, экран копируется перед перетаскиванием, а не перед запуском: Код (Text): case WM_LBUTTONDOWN: ShowWindow(hWnd, SW_HIDE); BitBlt(hStoreDC, 0, 0, 1024, 768, hDesktopDC, 0, 0, SRCCOPY); ShowWindow(hWnd, SW_SHOWNORMAL); Это так, но мне кажется, что это нереально, тем более если нужна полупрозрачность.