Данный код сперва конвертирует Ваш текст в DIB, а затем DIB в иконку и далее в ресурс. После этого изображение иконки отображается в System Tray.
Вызов просходит следующим образом....
StringToIcon('This Is Made By Ruslan K. Abu Zant');
N.B>> Не забудьте удалить объект HIcon, после вызова функции...
Code: |
unit MainForm;
interface
uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls;
type TForm1 = class(TForm) Button1: TButton; Image1: TImage; Timer1: TTimer; procedure Button1Click(Sender: TObject); procedure Timer1Timer(Sender: TObject); private function StringToIcon(const st: string): HIcon; public { Public declarations } end;
var Form1: TForm1;
implementation
{$R *.DFM}
type ICONIMAGE = record Width, Height, Colors: DWORD; // Ширина, Высота и кол-во цветов lpBits: PChar; // указатель на DIB биты dwNumBytes: DWORD; // Сколько байт? lpbi: PBitmapInfoHeader; // указатель на заголовок lpXOR: PChar; // указатель на XOR биты изображения lpAND: PChar; // указатель на AND биты изображения end;
function CopyColorTable(var lpTarget: BITMAPINFO; const lpSource: BITMAPINFO): boolean; var dc: HDC; hPal: HPALETTE; pe: array[0..255] of PALETTEENTRY; i: Integer; begin result := False; case (lpTarget.bmiHeader.biBitCount) of 8: if lpSource.bmiHeader.biBitCount = 8 then begin Move(lpSource.bmiColors, lpTarget.bmiColors, 256 * sizeof(RGBQUAD)); result := True end else begin dc := GetDC(0); if dc <> 0 then try hPal := CreateHalftonePalette(dc); if hPal <> 0 then try if GetPaletteEntries(hPal, 0, 256, pe) <> 0 then begin for i := 0 to 255 do begin lpTarget.bmiColors[i].rgbRed := pe[i].peRed; lpTarget.bmiColors[i].rgbGreen := pe[i].peGreen; lpTarget.bmiColors[i].rgbBlue := pe[i].peBlue; lpTarget.bmiColors[i].rgbReserved := pe[i].peFlags end; result := True end finally DeleteObject(hPal) end finally ReleaseDC(0, dc) end end;
4: if lpSource.bmiHeader.biBitCount = 4 then begin Move(lpSource.bmiColors, lpTarget.bmiColors, 16 * sizeof(RGBQUAD)); result := True end else begin hPal := GetStockObject(DEFAULT_PALETTE); if (hPal <> 0) and (GetPaletteEntries(hPal, 0, 16, pe) <> 0) then begin for i := 0 to 15 do begin lpTarget.bmiColors[i].rgbRed := pe[i].peRed; lpTarget.bmiColors[i].rgbGreen := pe[i].peGreen; lpTarget.bmiColors[i].rgbBlue := pe[i].peBlue; lpTarget.bmiColors[i].rgbReserved := pe[i].peFlags end; result := True end end; 1: begin i := 0; lpTarget.bmiColors[i].rgbRed := 0; lpTarget.bmiColors[i].rgbGreen := 0; lpTarget.bmiColors[i].rgbBlue := 0; lpTarget.bmiColors[i].rgbReserved := 0; i := 1; lpTarget.bmiColors[i].rgbRed := 255; lpTarget.bmiColors[i].rgbGreen := 255; lpTarget.bmiColors[i].rgbBlue := 255; lpTarget.bmiColors[i].rgbReserved := 0; result := True end; else result := True end end;
function WidthBytes(bits: DWORD): DWORD; begin result := ((bits + 31) shr 5) shl 2 end;
function BytesPerLine(const bmih: BITMAPINFOHEADER): DWORD; begin result := WidthBytes(bmih.biWidth * bmih.biPlanes * bmih.biBitCount) end;
function DIBNumColors(const lpbi: BitmapInfoHeader): word; var dwClrUsed: DWORD; begin dwClrUsed := lpbi.biClrUsed; if dwClrUsed <> 0 then result := Word(dwClrUsed) else case lpbi.biBitCount of 1: result := 2; 4: result := 16; 8: result := 256 else result := 0 end end;
function PaletteSize(const lpbi: BitmapInfoHeader): word; begin result := DIBNumColors(lpbi) * sizeof(RGBQUAD) end;
function FindDIBBits(const lpbi: BitmapInfo): PChar; begin result := @lpbi; result := result + lpbi.bmiHeader.biSize + PaletteSize(lpbi.bmiHeader) end;
function ConvertDIBFormat(var lpSrcDIB: BITMAPINFO; nWidth, nHeight, nbpp: DWORD; bStretch: boolean): PBitmapInfo; var lpbmi: PBITMAPINFO; lpSourceBits, lpTargetBits: Pointer; DC, hSourceDC, hTargetDC: HDC; hSourceBitmap, hTargetBitmap, hOldTargetBitmap, hOldSourceBitmap: HBITMAP; dwSourceBitsSize, dwTargetBitsSize, dwTargetHeaderSize: DWORD; begin result := nil; // Располагаем и заполняем структуру BITMAPINFO для нового DIB // Обеспечиваем достаточно места для 256-цветной таблицы dwTargetHeaderSize := sizeof(BITMAPINFO) + (256 * sizeof(RGBQUAD)); GetMem(lpbmi, dwTargetHeaderSize); try lpbmi^.bmiHeader.biSize := sizeof(BITMAPINFOHEADER); lpbmi^.bmiHeader.biWidth := nWidth; lpbmi^.bmiHeader.biHeight := nHeight; lpbmi^.bmiHeader.biPlanes := 1; lpbmi^.bmiHeader.biBitCount := nbpp; lpbmi^.bmiHeader.biCompression := BI_RGB; lpbmi^.bmiHeader.biSizeImage := 0; lpbmi^.bmiHeader.biXPelsPerMeter := 0; lpbmi^.bmiHeader.biYPelsPerMeter := 0; lpbmi^.bmiHeader.biClrUsed := 0; lpbmi^.bmiHeader.biClrImportant := 0; // Заполняем в таблице цветов if CopyColorTable(lpbmi^, lpSrcDIB) then begin DC := GetDC(0); hTargetBitmap := CreateDIBSection(DC, lpbmi^, DIB_RGB_COLORS, lpTargetBits, 0, 0); hSourceBitmap := CreateDIBSection(DC, lpSrcDIB, DIB_RGB_COLORS, lpSourceBits, 0, 0);
try if (dc <> 0) and (hTargetBitmap <> 0) and (hSourceBitmap <> 0) then begin hSourceDC := CreateCompatibleDC(DC); hTargetDC := CreateCompatibleDC(DC); try if (hSourceDC <> 0) and (hTargetDC <> 0) then begin // Flip the bits on the source DIBSection to match the source DIB dwSourceBitsSize := DWORD(lpSrcDIB.bmiHeader.biHeight) * BytesPerLine(lpSrcDIB.bmiHeader); dwTargetBitsSize := DWORD(lpbmi^.bmiHeader.biHeight) * BytesPerLine(lpbmi^.bmiHeader); Move(FindDIBBits(lpSrcDIB)^, lpSourceBits^, dwSourceBitsSize);
// Select DIBSections into DCs hOldSourceBitmap := SelectObject(hSourceDC, hSourceBitmap); hOldTargetBitmap := SelectObject(hTargetDC, hTargetBitmap);
try if (hOldSourceBitmap <> 0) and (hOldTargetBitmap <> 0) then begin // Устанавливаем таблицу цветов для DIBSections if lpSrcDIB.bmiHeader.biBitCount <= 8 then SetDIBColorTable(hSourceDC, 0, 1 shl lpSrcDIB.bmiHeader.biBitCount, lpSrcDIB.bmiColors);
if lpbmi^.bmiHeader.biBitCount <= 8 then SetDIBColorTable(hTargetDC, 0, 1 shl lpbmi^.bmiHeader.biBitCount, lpbmi^.bmiColors);
// If we are asking for a straight copy, do it if (lpSrcDIB.bmiHeader.biWidth = lpbmi^.bmiHeader.biWidth) and (lpSrcDIB.bmiHeader.biHeight = lpbmi^.bmiHeader.biHeight) then BitBlt(hTargetDC, 0, 0, lpbmi^.bmiHeader.biWidth, lpbmi^.bmiHeader.biHeight, hSourceDC, 0, 0, SRCCOPY) else if bStretch then begin SetStretchBltMode(hTargetDC, COLORONCOLOR); StretchBlt(hTargetDC, 0, 0, lpbmi^.bmiHeader.biWidth, lpbmi^.bmiHeader.biHeight, hSourceDC, 0, 0, lpSrcDIB.bmiHeader.biWidth, lpSrcDIB.bmiHeader.biHeight, SRCCOPY) end else BitBlt(hTargetDC, 0, 0, lpbmi^.bmiHeader.biWidth, lpbmi^.bmiHeader.biHeight, hSourceDC, 0, 0, SRCCOPY);
GDIFlush; GetMem(result, Integer(dwTargetHeaderSize + dwTargetBitsSize));
Move(lpbmi^, result^, dwTargetHeaderSize); Move(lpTargetBits^, FindDIBBits(result^)^, dwTargetBitsSize) end finally if hOldSourceBitmap <> 0 then SelectObject(hSourceDC, hOldSourceBitmap); if hOldTargetBitmap <> 0 then SelectObject(hTargetDC, hOldTargetBitmap); end end finally if hSourceDC <> 0 then DeleteDC(hSourceDC); if hTargetDC <> 0 then DeleteDC(hTargetDC) end end; finally if hTargetBitmap <> 0 then DeleteObject(hTargetBitmap); if hSourceBitmap <> 0 then DeleteObject(hSourceBitmap); if dc <> 0 then ReleaseDC(0, dc) end end finally FreeMem(lpbmi) end end;
function DIBToIconImage(var lpii: ICONIMAGE; var lpDIB: BitmapInfo; bStretch: boolean): boolean; var lpNewDIB: PBitmapInfo; begin result := False; lpNewDIB := ConvertDIBFormat(lpDIB, lpii.Width, lpii.Height, lpii.Colors, bStretch); if Assigned(lpNewDIB) then try
lpii.dwNumBytes := sizeof(BITMAPINFOHEADER) // Заголовок + PaletteSize(lpNewDIB^.bmiHeader) // Палитра + lpii.Height * BytesPerLine(lpNewDIB^.bmiHeader) // XOR маска + lpii.Height * WIDTHBYTES(lpii.Width); // AND маска // Если здесь уже картинка, то освобождаем её if lpii.lpBits <> nil then FreeMem(lpii.lpBits);
GetMem(lpii.lpBits, lpii.dwNumBytes); Move(lpNewDib^, lpii.lpBits^, sizeof(BITMAPINFOHEADER) + PaletteSize (lpNewDIB^.bmiHeader)); // Выравниваем внутренние указатели/переменные для новой картинки lpii.lpbi := PBITMAPINFOHEADER(lpii.lpBits); lpii.lpbi^.biHeight := lpii.lpbi^.biHeight * 2;
lpii.lpXOR := FindDIBBits(PBitmapInfo(lpii.lpbi)^); Move(FindDIBBits(lpNewDIB^)^, lpii.lpXOR^, lpii.Height * BytesPerLine (lpNewDIB^.bmiHeader));
lpii.lpAND := lpii.lpXOR + lpii.Height * BytesPerLine (lpNewDIB^.bmiHeader); Fillchar(lpii.lpAnd^, lpii.Height * WIDTHBYTES(lpii.Width), $00);
result := True finally FreeMem(lpNewDIB) end end;
function TForm1.StringToIcon(const st: string): HIcon; var memDC: HDC; bmp: HBITMAP; oldObj: HGDIOBJ; rect: TRect; size: TSize; infoHeaderSize: DWORD; imageSize: DWORD; infoHeader: PBitmapInfo; icon: IconImage; oldFont: HFONT;
begin result := 0; memDC := CreateCompatibleDC(0); if memDC <> 0 then try bmp := CreateCompatibleBitmap(Canvas.Handle, 16, 16); if bmp <> 0 then try oldObj := SelectObject(memDC, bmp); if oldObj <> 0 then try rect.Left := 0; rect.top := 0; rect.Right := 16; rect.Bottom := 16; SetTextColor(memDC, RGB(255, 0, 0)); SetBkColor(memDC, RGB(128, 128, 128)); oldFont := SelectObject(memDC, font.Handle); GetTextExtentPoint32(memDC, PChar(st), Length(st), size); ExtTextOut(memDC, (rect.Right - size.cx) div 2, (rect.Bottom - size.cy) div 2, ETO_OPAQUE, @rect, PChar(st), Length(st), nil); SelectObject(memDC, oldFont); GDIFlush;
GetDibSizes(bmp, infoHeaderSize, imageSize); GetMem(infoHeader, infoHeaderSize + ImageSize); try GetDib(bmp, SystemPalette16, infoHeader^, PChar(DWORD(infoHeader) + infoHeaderSize)^);
icon.Colors := 4; icon.Width := 32; icon.Height := 32; icon.lpBits := nil; if DibToIconImage(icon, infoHeader^, True) then try result := CreateIconFromResource(PByte(icon.lpBits), icon.dwNumBytes, True, $00030000); finally FreeMem(icon.lpBits) end finally FreeMem(infoHeader) end
finally SelectObject(memDC, oldOBJ) end finally DeleteObject(bmp) end finally DeleteDC(memDC) end end;
procedure TForm1.Button1Click(Sender: TObject); begin Application.Icon.Handle := StringToIcon('0'); Timer1.Enabled := True; Button1.Enabled := False; end;
procedure TForm1.Timer1Timer(Sender: TObject); {Код исправлен by Alex (https://forum.vingrad.ru)} {$WRITEABLECONST ON} const i: Integer = 0; begin Inc(i); if i = 100 then i := 1; Application.Icon.Handle := StringToIcon(IntToStr(i)); {$WRITEABLECONST OFF} end; end. |
Автор: Ruslan Abu Zant
Просьба писать ваши замечания, наблюдения и все остальное,
что поможет улучшить предоставляемую информацию на этом сайте.
ВСЕ КОММЕНТАРИИ МОДЕРИРУЮТСЯ ВРУЧНУЮ, ТАК ЧТО СПАМИТЬ БЕСПОЛЕЗНО!