Прозрачный дочерний контроль - PullRequest
0 голосов
/ 24 октября 2009

Я пишу элемент управления, некоторые части которого могут быть прозрачными или полупрозрачными. В основном этот элемент управления показывает изображение PNG (с альфа-каналом). В родительском окне элемента управления есть немного графики. Следовательно, для правильной визуализации элемента управления png необходимо получить изображение того, что родительское окно будет рисовать под ним. Родительский диалог может иметь установленный флаг WS_CLIPCHILDREN, это означает, что родительское окно не будет ничего рисовать под управлением png, и в этом случае управление png не будет работать должным образом Этот элемент управления также должен работать в Windows Mobile, поэтому он не может иметь WS_EX_TRANSPARENT

Ответы [ 3 ]

0 голосов
/ 24 октября 2009

Я не занимаюсь c #, поэтому не думаю, что это может быть полезным. Я пытался изучить ваш код и не вижу ничего, что могло бы решить мою проблему, даже если вы выполняете ту же задачу, что и я. Чтобы дать больше деталей, мой элемент управления также поддерживает анимацию GIF, и я также использовал ту же нагрузку IImage из потока, что и вы в своем проекте. По моему опыту, загрузка IImage из потока - невероятный ненужный код, он очень медленный. Я понятия не имею, как это может быть так медленно. Загрузка 32x32 GIF с 31 кадром занимает 1,5 секунды, используя этот мусорный материал IImage. Я написал свой собственный загрузчик (используя некоторую gif-библиотеку с открытым исходным кодом) и без какой-либо оптимизации полное декодирование / загрузка gif-кадров занимает менее 100 мс. Я использую TouchPro2 ... Я не могу себе представить, насколько плохо этот код будет работать на младшем устройстве.

В качестве быстрой альтернативы вот возможное решение моего вопроса:

в обработчике WM_PAINT дочернего элемента управления, который рисует изображения (gif или png), я делаю следующее:

сначала я вызываю SetRedraw (false) для себя и для родительского окна. затем я скрываю дочерний элемент управления и отправляю WM_PAINT в родительское окно с дополнительным HDC (как wParam). В родительском окне все выводится на экранное растровое изображение (передаваемое через hdc в WM_PAINT), и после успешного возврата WM_PAINT я беру соответствующую часть закадрового растрового изображения. Затем я включаю показ дочернего окна и вызываю SetRedraw (true) как для дочернего, так и для родительского окна. Этот трюк работает, но, очевидно, имеет некоторые недостатки (мне нужно создать огромное закадровое растровое изображение, чтобы захватить всю область экрана, даже если мне нужно 32x32 пикселя от середины родительского окна).

код ниже:

bool pic_control::get_parent_bg(MyBitmap & bg)
{
    CWindow parent = GetParent();
    CClientDC dc(parent);
    bool is_visible = IsWindowVisible() && parent.IsWindowVisible();
    if(!is_visible){
        return false;
    }

    parent.SetRedraw(false);
    SetRedraw(false);

    CRect rect;
    parent.GetClientRect(rect);
    MyBitmap bmp;
    bmp.create(rect.Width(), rect.Height());

    ShowWindow(SW_HIDE);
    parent.SendMessage(WM_PAINT, (WPARAM)(HDC)bmp.dc());
    ShowWindow(SW_SHOW);

    GetWindowRect(rect);
    parent.ScreenToClient(rect);
    bg.create(rect.Width(), rect.Height());
    bg.dc().BitBlt(0, 0, rect.Width(), rect.Height(), bmp.dc(), rect.left, rect.top, SRCCOPY);

    IF_DEBUG SAL::saveHBITMAPToJpeg(bg.GetBitmap(), "frames/BG.jpg", 100);

    SetRedraw(true);
    parent.SetRedraw(true);
    return true;
}
0 голосов
/ 08 апреля 2010

WS_CLIPCHILDREN принудительно включен в WinCe, вы не можете переключать его. Я не знаю почему, может быть, это сделано из соображений производительности. Из моего опыта, что я сделал в этой ситуации. 1) Если родительское окно bacgkround является динамическим (например, окно, которое содержит карту, которую можно переместить), то оно сначала рисуется на холст памяти, затем на экран, и холст памяти сохраняется и используется для рисования прозрачных дочерних элементов. Холст памяти не будет содержать дыр вместо дочерних окон, поэтому его можно использовать для дальнейшего слияния пикселей. Недостатком здесь является потребление памяти для удержания холста в памяти.

2) Если фон родительского окна является статическим (диалоговое окно, меню и т. Д.), То вы можете сделать неоконные дочерние элементы.

class CImageButton
{
public:
bool IsPointInside(POINT pt);
void OnPaint(HDC canvas);
void OnClick();
void SetRect(RECT& rc);
private:
RECT m_rc;
};

Ваше родительское окно будет содержать массив таких объектов и перенаправлять WM_PAINT и мыши нажимают на них.

Отключение - это дополнительный код, который необходимо добавить в родительское окно, но вы можете создать базовый класс для всех ваших родительских окон, который бы обрабатывал проблемы с неокончатыми элементами управления.

0 голосов
/ 24 октября 2009

Забавно, что вы должны спросить. Я только что написал код, чтобы сделать это вчера. Он находится в базе кода для Project Resistance . Посмотрите, как ResistorView (который имеет PNG с прозрачностью) взаимодействует с MainForm (который имеет фоновое изображение).

...