我想用 CreateIconIndirect 手動創建一個圖示,如下所示:
HDC hDC = ::CreateCompatibleDC( nullptr );
BITMAPINFO bmiMask = {};
bmiMask.bmiHeader.biSize = sizeof( bmiMask.bmiHeader );
bmiMask.bmiHeader.biWidth = 16;
bmiMask.bmiHeader.biHeight = -16; // starts with top row
bmiMask.bmiHeader.biPlanes = 1;
bmiMask.bmiHeader.biBitCount = 32;
BYTE *byMask = nullptr;
HBITMAP hbmMask = ::CreateDIBSection( hDC, &bmiMask, DIB_RGB_COLORS,
reinterpret_cast< void** >( &byMask ),
nullptr, 0 );
BYTE bgraMask[] = { 0x00, 0x00, 0x00, 0x00 };
for( int i = 0; i < 16 * 16; i )
for( int j = 0; j < 4; j )
byMask[ i * 4 j ] = bgraMask[ j ];
byMask[ 0 ] = 0x00; byMask[ 1 ] = 0x00; byMask[ 2 ] = 0x00; byMask[ 3 ] = 0x00;
BITMAPINFO bmiColor = {};
bmiColor.bmiHeader.biSize = sizeof( bmiColor.bmiHeader );
bmiColor.bmiHeader.biWidth = 16;
bmiColor.bmiHeader.biHeight = -16; // starts with top row
bmiColor.bmiHeader.biPlanes = 1;
bmiColor.bmiHeader.biBitCount = 32;
BYTE *byColor = nullptr;
HBITMAP hbmColor = ::CreateDIBSection( hDC, &bmiColor, DIB_RGB_COLORS,
reinterpret_cast< void** >( &byColor ),
nullptr, 0 );
BYTE bgraColor[] = { 0xff, 0xff, 0xff, 0xff };
for( int i = 0; i < 16 * 16; i )
for( int j = 0; j < 4; j )
byColor[ i * 4 j ] = bgraColor[ j ];
byColor[ 0 ] = 0x00; byColor[ 1 ] = 0x00; byColor[ 2 ] = 0x00; byColor[ 3 ] = 0x00;
ICONINFO ii = {};
ii.fIcon = TRUE;
ii.xHotspot = ii.yHotspot = 0;
ii.hbmMask = hbmMask;
ii.hbmColor = hbmColor;
HICON hIcon = ::CreateIconIndirect( &ii );
::SendMessage( hwndDialog, WM_SETICON, ICON_SMALL,
reinterpret_cast< LPARAM >( hIcon ) );
根據 MSDN ( https://docs.microsoft.com/en-us/previous-versions/dd183376(v=vs.85) ),每個像素的資料由 4 個位元組組成:藍色、綠色、紅色和一個未使用的位元組。
我通過更改 byMask 和 byColor 的值對資料進行了一些實驗,然后進行螢屏截圖并在 MS Paint 中讀取確切的 RGB 值。(每次我將記事本直接放在應用程式的視窗后面,以獲得最終的透明/Alpha 通道效果的恒定背景。)
首先我只改變了左上角,而其余的資料是 0x00 的遮罩和 0xff 的顏色。結果:大部分圖示是白色的(正如預期的那樣),左上角的像素有以下顏色:
MR MA CR CA OR OG OB
00 00 00 ff 00 00 00
00 00 00 00 d3 e9 fe
00 00 ff 00 d3 e9 fe (a)
ff 00 00 00 d3 e9 fe
ff ff 00 00 d3 e9 fe
00 ff 00 00 d3 e9 fe
00 00 ff ff ff 00 00 (b)
ff 00 ff ff ff 00 00
ff ff ff ff ff 00 00
00 ff ff ff ff 00 00
之后,我將兩個位圖中的每個像素更改為相同的值。(并使用 MS Paint 的填充工具檢查圖片只有一種顏色。)
MR MA CR CA OR OG OB
00 00 00 ff 00 00 00
00 00 00 00 00 00 00
00 00 ff 00 ff 00 00 (c)
ff 00 00 00 00 00 00
ff ff 00 00 00 00 00
00 ff 00 00 00 00 00
00 00 ff ff ff 00 00 (d)
ff 00 ff ff ff 00 00 (d)
ff ff ff ff ff 00 00 (d)
00 ff ff ff ff 00 00 (d)
縮寫:M=mask C=Color O=Observation R=red G=green B=blue A=alpha/4.byte
我不明白以下內容(字母指的是上表中的行):
- 如果 4. 位元組被忽略,而不是 alpha 通道,為什么像素 (a) 不像 (b) 那樣 ff0000?
- 如果我只改變其他像素,為什么第一個改變:(c) vs (a)?
- 為什么所有標有(d)的行的結果都一樣,為什么這里掩碼沒有效果?
我的代碼中有錯誤嗎?我看錯了 MSDN 頁面嗎?
uj5u.com熱心網友回復:
好的,我想通了。由于歷史原因,32位/像素位圖有兩種型別:一種是使用3個位元組表示3種顏色,最后一種未使用(通常設定為0),另一種使用第四個位元組表示alpha通道.
問題是該型別沒有由任何欄位指示,但如果所有第 4 個位元組都為零,Windows 將其作為舊格式位圖(無 alpha),并將其視為新格式(帶 alpha),如果任何第四個位元組與零。所以這將導致一個全黑的圖示:
for( int i = 0; i < 16 * 16; i )
for( int j = 0; j < 4; j )
byColor[ i * 4 j ] = 0x00;
但是如果我在上面添加這一行,整個圖示就會變得透明*:
byColor[ 7 * 16 7 0 ] = 0x01;
* 除了第 7 行第 7 列的像素,它只會是 255/256 透明。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/376685.html
標籤:登录
