Программы ассистенты

  • Автор темы Guest
  • Дата начала
Статус
Закрыто для дальнейших ответов.
G

Guest

Гость
#1
Все знают десктопные программы-ассистенты (screenmates/deskmates, MS Agent). Весь вопрос, что качественных, без артифактов, достаточно мало. Для реализации экранного помошника есть 2 различных подхода (если знаете еще, подскажите): - рисовать поверх десктопа, запоминать-востанавливать фон и т.д. Здесь сложно уследить за случаями, когда другие окна перекрывают место, где выводится текущий кадр персонажа, если на десктопе идет своя жизнь (меняются-появляются иконки, молчу про Drag'n'Drop) - использовать регионы, примеры есть на codeguru, но это достаточно трудоемкая штука - идея проста: создать полностью прозрачное окно и рисовать в нем просто текущий кадр с действием персонажа, не заботясь о том, на каком фоне его рисуешь, ведь окно прозрачное! Т.е. программа может просто рисовать постоянно меняющиеся картинки в таком прозрачном окне и это создаст эффект анимации персонажа, главное тут, чтобы любые изменения фона не влияли, т.е. просто добавление атрибута WS_EX_TRANSPARENT - это не то что нужно
Так вот, внимание, вопрос!
Знает ли кто, как можно создать такое полностью прозрачное-невидимое окно, которое при перемещении по экрану не тащит за собой кусок фона с предыдущего местоположения?
Кстати, на кодегуру прямого примера нет точно, а то что есть о том как рисовать прозрачные штучки -не то.
 
G

Guest

Гость
#2
Нужно для каждой картинки, входящей в анимацию, делать для окна специальный регион, который включал бы в себя точки, принадлежащие изображению и не включал все остальные. Это можно сделать так (source ниже) : Создать пустой регион, выбрать картинку (bitmap), выбрать прозрачный цвет, проитись по bitmap и для каждого непрозрачного участка в каждой строке bitmap создать регион высотой 1 пиксел и прикомбинировать его к исходному региону. В конце операции установить получившийся регион окну.

void MakeBitmapRegion (HWND hwnd, int bmp_id)
{
COLORREF back_color;
CBitmap bmp;
if (!bmp.LoadBitmap (bmp_id)) return;
BITMAP bmp_o;
bmp.GetObject (sizeof(BITMAP), (LPSTR)&bmp_o);
int w = bmp_o.bmWidth;
int h = bmp_o.bmHeight;

HDC wnd_dc = GetDC(hwnd);
if (hwnd == NULL) return;
if (wnd_dc == NULL) return;

HDC hdc_bmp = CreateCompatibleDC (wnd_dc);
SelectObject (hdc_bmp, HBITMAP (bmp));
back_color = GetPixel(hdc_bmp, 0, 0);

int x, x0, y;
HRGN tmp_rgn, wnd_rgn;
wnd_rgn = CreateRectRgn(0,0,0,0);

x = y = 0;
for (y; y
 
G

Guest

Гость
#3
Как сделать полностью прозрачное окно, которое не тащит за собою кусок
фона - понятно. Нужно просто перехватить сообщение WM_WINDOWPOSCHANGING и
сказать системе, чтобы она не копировала содержимое окна. Для этого в
структуре WINDOWPOS, указатель на которую передаётся в функцию окна,
предусмотрен флаг SWP_NOCOPYBITS. В MFC обработчик может выглядеть примерно
так:


void CMyWnd::OnWindowPosChanging(WINDOWPOS FAR* lpwndpos)
{
lpwndpos->flags |= SWP_NOCOPYBITS;
CWnd::OnWindowPosChanging(lpwndpos);
}


Другой вопрос, что этого явно не достаточно для реализации прозрачного окна.
Ведь полностью пустое окно мало кого заинтересует, а если нарисовать в нём
что-то, а затем сдвинуть окно, за ним потянется шлейф с нарисованным
изображением.

Если прозрачные области в окне статические, то есть
способ лучше - воспользоваться SetWindowRgn. Об этой функции писалось в 7-м
выпуске рассылки. Но если требуется организовать анимацию на фоне рабочего
стола, то, вероятно, не обойтись без сохранения фона с его последующим
восстановлением. Дело в том, что многие программы очень медленно
перерисовывают свои окна, и поручать им обновление фона под нашим окном не
представляется возможным.
 
Статус
Закрыто для дальнейших ответов.