Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Системное программирование и WinAPI > Создание прозрачной иконки


Автор: suxxor 18.3.2012, 21:29
Нужно создать иконку (HICON) и отобразить её в трее.

Значок получаю так: (взято http://support.microsoft.com/kb/318876/en-us)
Код

HICON CreateAlphaIcon(void)
{
    DWORD dwWidth = 32, dwHeight = 32;
    BITMAPV5HEADER bi;
    void *lpBits;

    ZeroMemory(&bi,sizeof(BITMAPV5HEADER));
    
    bi.bV5Size           = sizeof(BITMAPV5HEADER);
    bi.bV5Width           = dwWidth;
    bi.bV5Height          = dwHeight;
    bi.bV5Planes = 1;
    bi.bV5BitCount = 32;
    bi.bV5Compression = BI_BITFIELDS;
    // The following mask specification specifies a supported 32 BPP
    // alpha format for Windows XP.
    bi.bV5RedMask   =  0x00FF0000;
    bi.bV5GreenMask =  0x0000FF00;
    bi.bV5BlueMask  =  0x000000FF;
    bi.bV5AlphaMask =  0xFF000000; 

    HDC hdc = GetDC(NULL);

    // Create the DIB section with an alpha channel.
    HBITMAP hBitmap = CreateDIBSection(hdc, (BITMAPINFO *)&bi, DIB_RGB_COLORS, 
        (void **)&lpBits, NULL, (DWORD)0);

    HDC hMemDC = CreateCompatibleDC(hdc);
    ReleaseDC(NULL,hdc);

    // Draw something on the DIB section.
    HBITMAP hOldBitmap = (HBITMAP)SelectObject(hMemDC, hBitmap);
    PatBlt(hMemDC,0,0,dwWidth,dwHeight,WHITENESS);
    SetTextColor(hMemDC,RGB(0,0,0));
    SetBkMode(hMemDC,TRANSPARENT);
    TextOut(hMemDC,0,9,"rgba",4);
    SelectObject(hMemDC, hOldBitmap);
    DeleteDC(hMemDC);

    // Create an empty mask bitmap.
    HBITMAP hMonoBitmap = CreateBitmap(dwWidth,dwHeight,1,1,NULL);

    // Set the alpha values for each pixel in the cursor so that
    // the complete cursor is semi-transparent.
    DWORD *lpdwPixel;
    lpdwPixel = (DWORD *)lpBits;
    for (DWORD x=0;x<dwWidth;x++)
       for (DWORD y=0;y<dwHeight;y++)
       {
           // Clear the alpha bits
           *lpdwPixel &= 0x00FFFFFF;
           // Set the alpha bits to 0x9F (semi-transparent)
           *lpdwPixel |= 0x9F000000;
           lpdwPixel++;
       }

    ICONINFO ii;
    ii.fIcon = TRUE;  // Change fIcon to TRUE to create an alpha icon
    ii.xHotspot = 0;
    ii.yHotspot = 0;
    ii.hbmMask = hMonoBitmap;
    ii.hbmColor = hBitmap;

    // Create the alpha icon with the alpha DIB section.
    HICON hAlphaIcon = CreateIconIndirect(&ii);

    DeleteObject(hBitmap);          
    DeleteObject(hMonoBitmap); 

    return hAlphaIcon;
}


на выходе получается иконка с серым фоном  и чёрным текстом, в чём проблема?

Автор: GremlinProg 19.3.2012, 08:58
Цитата(suxxor @  18.3.2012,  23:29 Найти цитируемый пост)
на выходе получается иконка с серым фоном  и чёрным текстом, в чём проблема?

ну а какой по твоему должен быть?

в коде чёрный текст так и задан,
а серый фон может получиться, если иконку на черный накладывать, например, на второй буфер, который, по умолчанию черный изначально

Добавлено через 8 минут и 59 секунд
Цитата(GremlinProg @  19.3.2012,  10:58 Найти цитируемый пост)
если иконку на черный накладывать

или на белый, смотря какой фон нарисован в иконке,
по идее - WHITENESS, т.е. белый независимо от выбранной кисти,
значит прозрачность его с 0x9F даст серый или грязный на любой темный цвет

Автор: suxxor 19.3.2012, 20:40
неважно какой цвет текста, интересует именно: что изменить в приведённой функции для получения прозрачного фона?

Автор: GremlinProg 20.3.2012, 07:25
Цитата(suxxor @  19.3.2012,  22:40 Найти цитируемый пост)
что изменить в приведённой функции для получения прозрачного фона?

если коротко, то альфу
 
здесь это 9F в 53 строке, поставишь FF, будет полностью прозрачный,
только он будет и правда полностью прозрачный, т.е. невидимый  smile 

поставь в цикле фильтр: если исходный цвет белый, значит поставить ему альфу FF, иначе - 0

или можешь полупрозрачность на текст наложить: вместо нуля что-нить вроде 7F

если тебе нужна простая иконка, без полутонов, то заморачиваться с BITMAPV5HEADER не было смысла,
обычная иконка, формируемая двумя растрами (через BITMAPINFOHEADER), и так имеет прозрачные зоны

Автор: Alca 6.2.2013, 03:33
Не получается сделать иконку прозрачной (маска прозрачности - черная)
при 16 битном цвете:

Код

HBITMAP dib = CreateDIBSection(NULL, &bmi, DIB_RGB_COLORS, (void **)&dst, NULL, 0);

bpl = 4 * bmp.bmWidth; /* bytes per line */
src = (UCHAR *)lpbitmap;
for (y = 0; y < bmp.bmHeight; y++, src += bpl) {
    tmp = src;
    for (x = 0; x < bmp.bmWidth; x++) {
        if (wBitsPixel > 16) {
            alpha = tmp[3];

            dst[0] = tmp[0] * alpha / 255;
            dst[1] = tmp[1] * alpha / 255;
            dst[2] = tmp[2] * alpha / 255;
            dst[3] = alpha;
        } else {
            /* ??????????????????? */
            dst[0] = tmp[0];
            dst[1] = tmp[1];
            dst[2] = tmp[2];
            dst[3] = tmp[3];
        }

        dst += 2;
        tmp += 4;
    }
}


Автор: Alca 12.2.2013, 06:50
После таких манипуляций (по другому это никак не назовешь):
Код

dst[0] = tmp[0];
dst[1] = tmp[1];
dst[2] = tmp[2];
dst[3] = tmp[2];  // <<<<

получилось вот это:

Автор: artsb 12.2.2013, 08:28
Я не помню где лежит альфа канал. Если последний, то можно попробовать так:
Код

dst[0] = tmp[0];
dst[1] = tmp[1];
dst[2] = tmp[2];
dst[3] = (tmp[3] > 255. / 2.)?255:0;  // <<<<

Автор: GremlinProg 12.2.2013, 08:38
Alca, а какой у тебя там biCompression?
Цитата(BITMAPINFOHEADER @  MSDN)

If the biCompression member of the BITMAPINFOHEADER is BI_BITFIELDS, the bmiColors member contains three DWORD color masks that specify the red, green, and blue components, respectively, of each pixel. Each WORD in the bitmap array represents a single pixel.


Автор: Alca 12.2.2013, 11:51
Цитата

Alca, а какой у тебя там biCompression?


Код

bi.biCompression = BI_RGB;
bmi.bmiHeader.biCompression = BI_RGB;


Цитата

If the biCompression member of the BITMAPINFOHEADER is BI_BITFIELDS, the bmiColors member contains three DWORD color masks that specify the red, green, and blue components, respectively, of each pixel. Each WORD in the bitmap array represents a single pixel.

Попробывать сделать с  BI_BITFIELDS ?





Автор: GremlinProg 12.2.2013, 12:13
Цитата(Alca @  12.2.2013,  13:51 Найти цитируемый пост)
Попробывать сделать с  BI_BITFIELDS ?

Да, думаю это будет правильней, чтобы не подбирать "эфемерную" маску прозрачности.

Только обращай внимание, что каждая маска размером с DWORD,
и тут нет комментария по поводу, должна ли быть четвертая маска в случае с наличием "альфы",
или ее следует формировать взаимоисключением остальных трех.

Возможно придется делать и так и так, пока не будет найдено верное решение.

Не проще ли было использовать 8- и менее- битный формат для предоставления флагов? Там же цветов: раз-два и обчелся, их можно бы было держать отдельно в палитре, которая в таком случае располагается после BITMAPINFOHEADER. Там это простые RGBQUAD, у которых нет такой неопределенности с альфой.

Автор: Alca 12.2.2013, 12:20
Цитата

Не проще ли было использовать 8- и менее- битный формат для предоставления флагов? Там же цветов: раз-два и обчелся, их можно бы было держать отдельно в палитре, которая в таком случае располагается после BITMAPINFOHEADER. Там это простые RGBQUAD, у которых нет такой неопределенности с альфой.

есть какой-то просто пример?

Автор: GremlinProg 12.2.2013, 13:15
Понятных примеров не нашел.

Здесь все то же самое, что ты сделал, но вместо bmi - выделяй память на
Код

sizeof( BITMAPINFOHEADER ) + 256 * sizeof( RGBQUAD )

BITMAPINFOHEADER заполняешь как раньше, только ставишь 8 бит,
а таблицу цветов ниже заполняешь цветами, которыми будешь использовать.

Когда создашь DIB, у тебя будет указатель на байтовый массив - аналогичный тому, который у тебя сейчас 16-битный,
расчитывай ширину строки и заполняй каждый байт номером цвета из той таблицы цветов, что ты заполнял при создании.

Соответственно, альфу уже можно задать только в таблице цветов, поэтому, если два пиксела имеют одинаковые цвета, но разные альфы, индексы у них тоже разные.

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

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)