:: MVP ::
|
|
:: RSS ::
|
|
|
Как рассчитать размеры миниатюры, чтобы вписать ее в заданную область?
var
Bmp: TBitmap;
// Вычисление множителя для масштабирования картинки (миниатюры)
// SourceWidth, SourceHeight - размеры исходного изображения
// PreviewWidth, PreviewHeight - размеры, в которые изображение нужно вписать
function CalcFactor(SourceWidth, SourceHeight, PreviewWidth, PreviewHeight: Integer): Double;
begin
if (PreviewWidth < SourceWidth) or (PreviewHeight < SourceHeight) then
Result := Min(PreviewWidth / SourceWidth, PreviewHeight / SourceHeight)
else
Result := 1;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
Factor: Double;
NewWidth, NewHeight: Integer;
begin
// Допустим в переменной Bmp: TBitmap хранится изображение,
// для которого нужно вычислить размер его миниатюры
Factor := CalcFactor(Bmp.Width, Bmp.Height, 100, 100);
NewWidth := Round(Factor * Bmp.Width); // Ширина миниатюры
NewHeight := Round(Factor * Bmp.Height); // Высота миниатюры
end;
|
Как извлечь иконку из файла (.exe, .dll, .cpl и др.) по индексу?
// Способ первый
{$IFDEF UNICODE}
function PrivateExtractIcons(lpszFile: PChar; nIconIndex, cxIcon, cyIcon: integer; phicon: PHANDLE; piconid: PDWORD; nicon, flags: DWORD): DWORD;
stdcall ; external 'user32.dll' name 'PrivateExtractIconsW';
{$ELSE}
function PrivateExtractIcons(lpszFile: PChar; nIconIndex, cxIcon, cyIcon: integer; phicon: PHANDLE; piconid: PDWORD; nicon, flags: DWORD): DWORD;
stdcall ; external 'user32.dll' name 'PrivateExtractIconsA';
{$ENDIF}
function ExtractIcons(SourceFile: string; IconIndex, cxIcon, cyIcon: Integer;
TargetFile: string): Boolean;
var
hIcon: THandle;
nIconId: DWORD;
Icon: TIcon;
begin
Result := False;
if PrivateExtractIcons( PWideChar( SourceFile ), IconIndex, cxIcon, cyIcon, @hIcon,
@nIconId, 1, LR_LOADFROMFILE ) <> 0 then
try
Icon := TIcon.Create;
try
Icon.Handle := hIcon;
Icon.SaveToFile(TargetFile);
Result := True;
finally
Icon.Free;
end;
finally
DestroyIcon(hIcon);
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
if ExtractIcons('Shell32.dll', 15, 256, 256, 'c:\SavedIcon.ico') then
ShowMessage('Иконка сохранена.');
end;
// Способ второй
uses
{...,} ShellAPI;
procedure TForm1.Button1Click(Sender: TObject);
begin
Image1.Picture.Icon.Handle :=
ExtractIcon(HInstance, PChar('c:\Windows\explorer.exe'), 0);
end;
// Способ третий
uses
{...,} ShellAPI;
procedure TForm1.Button1Click(Sender: TObject);
const
FileName = 'c:\Windows\explorer.exe';
var
Icon: TIcon;
Icon32, Icon16: HICON;
i: Integer;
begin
try
// Так можно получить количество иконок в файле
// ExtractIconEx(PChar(FileName), -1, Icon16, Icon32, 0);
i := 0;
while Integer(ExtractIconEx(PChar(FileName), i, Icon16, Icon32, 1)) > 0 do
begin
Icon := TIcon.Create;
Icon.Handle := Icon32;
ImageList1.AddIcon(Icon);
Icon.Free;
Inc(i);
end;
except
on e: Exception do
//
end;
end;
|
Как нарисовать диск и окружность со сглаживаниему?
uses
{...,} Math;
type
TForm1 = class(TForm)
Button1: TButton;
imMain: TImage;
procedure Button1Click(Sender: TObject);
private
public
end;
implementation
procedure DrawDisk( Bitmap: TBitmap; CenterX, CenterY, Radius, Feather: Single );
// Draw a disk on Bitmap. Bitmap must be a 256 color (pf8bit) palette bitmap,
// and parts outside the disk will get palette index 0, parts inside will get
// palette index 255, and in the antialiased area (feather), the pixels will
// get values inbetween.
// ***Parameters***
// Bitmap:
// The bitmap to draw on
// CenterX, CenterY:
// The center of the disk (float precision). Note that [0, 0] would be the
// center of the first pixel. To draw in the exact middle of a 100x100 bitmap,
// use CenterX = 49.5 and CenterY = 49.5
// Radius:
// The radius of the drawn disk in pixels (float precision)
// Feather:
// The feather area. Use 1 pixel for a 1-pixel antialiased area. Pixel centers
// outside 'Radius + Feather / 2' become 0, pixel centers inside 'Radius - Feather/2'
// become 255. Using a value of 0 will yield a bilevel image.
// Copyright (c) 2003 Nils Haeck M.Sc. www.simdesign.nl
var
x, y: Integer;
LX, RX, LY, RY: Integer;
Fact: Integer;
RPF2, RMF2: Single;
P: PByteArray;
SqY, SqDist: Single;
sqX: array of Single;
begin
// Determine some helpful values (singles)
RPF2 := Sqr(Radius + Feather/2);
RMF2 := Sqr(Radius - Feather/2);
// Determine bounds:
LX := Max(Floor(CenterX - RPF2), 0);
RX := Min(Ceil(CenterX + RPF2), Bitmap.Width - 1);
LY := Max(Floor(CenterY - RPF2), 0);
RY := Min(Ceil(CenterY + RPF2), Bitmap.Height - 1);
// Optimization run: find squares of X first
SetLength(SqX, RX - LX + 1);
for x := LX to RX do
SqX[x-LX] := Sqr(x - CenterX);
// Loop through Y values
for y := LY to RY do
begin
P := Bitmap.Scanline[y];
SqY := Sqr(y - CenterY);
// Loop through X values
for x := LX to RX do
begin
// determine squared distance from center for this pixel
SqDist := SqY + SqX[x - LX];
// inside inner circle? Most often..
if sqdist < RMF2 then
begin
// inside the inner circle.. just give the scanline the new color
P[x] := 255
end
else
begin
// inside outer circle?
if sqdist < RPF2 then
begin
// We are inbetween the inner and outer bound, now mix the color
Fact := Round(((Radius - Sqrt(SqDist)) * 2 / Feather) * 127.5 + 127.5);
P[x] := Max(0, Min(Fact, 255)); // just in case limit to [0, 255]
end
else
P[x] := 0;
end;
end;
end;
end;
procedure DrawCircle(Bitmap: TBitmap; CenterX, CenterY, Radius, LineWidth, Feather: Single);
// Draw a circle on Bitmap. Bitmap must be a 256 color (pf8bit) palette bitmap,
// and parts outside the circle will get palette index 0, parts inside will get
// palette index 255, and in the antialiased area (feather), the pixels will
// get values inbetween.
// ***Parameters***
// Bitmap:
// The bitmap to draw on
// CenterX, CenterY:
// The center of the circle (float precision). Note that [0, 0] would be the
// center of the first pixel. To draw in the exact middle of a 100x100 bitmap,
// use CenterX = 49.5 and CenterY = 49.5
// Radius:
// The radius of the drawn circle in pixels (float precision)
// LineWidth
// The line width of the drawn circle in pixels (float precision)
// Feather:
// The feather area. Use 1 pixel for a 1-pixel antialiased area. Pixel centers
// outside 'Radius + Feather / 2' become 0, pixel centers inside 'Radius - Feather/2'
// become 255. Using a value of 0 will yield a bilevel image. Note that Feather
// must be equal or smaller than LineWidth (or it will be adjusted internally)
// Copyright (c) 2003 Nils Haeck M.Sc. www.simdesign.nl
var
x, y: Integer;
LX, RX, LY, RY: Integer;
Fact: Integer;
ROPF2, ROMF2, RIPF2, RIMF2: Single;
OutRad, InRad: Single;
P: PByteArray;
SqY, SqDist: Single;
sqX: array of Single;
begin
// Determine some helpful values (singles)
OutRad := Radius + LineWidth/2;
InRad := Radius - LineWidth/2;
ROPF2 := Sqr(OutRad + Feather/2);
ROMF2 := Sqr(OutRad - Feather/2);
RIPF2 := Sqr(InRad + Feather/2);
RIMF2 := Sqr(InRad - Feather/2);
// Determine bounds:
LX := Max(Floor(CenterX - ROPF2), 0);
RX := Min(Ceil(CenterX + ROPF2), Bitmap.Width - 1);
LY := Max(Floor(CenterY - ROPF2), 0);
RY := Min(Ceil(CenterY + ROPF2), Bitmap.Height - 1);
// Checks
if Feather > LineWidth then
Feather := LineWidth;
// Optimization run: find squares of X first
SetLength(SqX, RX - LX + 1);
for x := LX to RX do
SqX[x - LX] := Sqr(x - CenterX);
// Loop through Y values
for y := LY to RY do
begin
P := Bitmap.Scanline[y];
SqY := Sqr(y - CenterY);
// Loop through X values
for x := LX to RX do
begin
// determine squared distance from center for this pixel
SqDist := SqY + SqX[x - LX];
// now first check if we're completely inside (most often)
if SqDist < RIMF2 then
begin
// We're on the disk inside everything
P[x] := 0;
end
else
begin
// completely outside?
if SqDist < ROPF2 then
begin
// inside outer line - feather?
if SqDist < ROMF2 then
begin
// check if we're in inside feather area
if SqDist < RIPF2 then
begin
// We are in the feather area of inner line, now mix the color
Fact := Round(((Sqrt(SqDist) - InRad) * 2 / Feather) * 127.5 + 127.5);
P[x] := Max(0, Min(Fact, 255)); // just in case limit to [0, 255]
end
else
begin
// on the line
P[x] := 255;
end;
end
else
begin
// We are in the feather area of outer line, now mix the color
Fact := Round(((OutRad - Sqrt(SqDist)) * 2 / Feather) * 127.5 + 127.5);
P[x] := Max(0, Min(Fact, 255)); // just in case limit to [0, 255]
end;
end
else
begin
// outside everything
P[x] := 0;
end;
end;
end;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
// Create a 256-color bitmap and call the DrawCircle procedure
var
i, y: Integer;
ABitmap: TBitmap;
pal: PLogPalette;
hpal: HPALETTE;
ColRGB, BgrRGB: Integer;
ACenterX, ACenterY,
ARadius, AFeather,
ALineWidth: Single;
begin
ABitmap := TBitmap.Create;
try
// 8 bits per pixel
ABitmap.PixelFormat := pf8bit;
// Set width and height
ABitmap.Width := 300;
ABitmap.Height := 300;
// Create a gradient palette between foreground and background color
GetMem(pal, SizeOf(TLogPalette) + SizeOf(TPaletteEntry) * 255);
try
pal.palVersion := $300;
pal.palNumEntries := 256;
ColRGB := ColorToRGB(clWhite);
BgrRGB := ColorToRGB(clBlack);
for i := 0 to 255 do
begin
pal.palPalEntry[i].peRed := Round(i / 255 * (ColRGB and $FF) + (255 - i) / 255 * (BgrRGB and $FF));
pal.palPalEntry[i].peGreen := Round(i / 255 * (ColRGB shr 8 and $FF) + (255 - i) / 255 * (BgrRGB shr 8 and $FF));
pal.palPalEntry[i].peBlue := Round(i / 255 * (ColRGB shr 16 and $FF) + (255 - i) / 255 * (BgrRGB shr 16 and $FF));
end;
hpal := CreatePalette(pal^);
if hpal <> 0 then
ABitmap.Palette := hpal;
finally
FreeMem(pal);
end;
// Fill bitmap with background color
for y := 0 to ABitmap.Height-1 do
FillChar(ABitmap.Scanline[y]^, ABitmap.Width, 0);
// Get data from form
ACenterX := 150;
ACenterY := 150;
ARadius := 135.5;
ALineWidth := 10;
AFeather := 5;
// Рисуем диск
DrawDisk(ABitmap, ACenterX, ACenterY, ARadius, AFeather);
// Рисуем окружность
// DrawCircle(ABitmap, ACenterX, ACenterY, ARadius, ALineWidth, AFeather);
// Assign to image
imMain.Picture.Bitmap.Assign(ABitmap);
finally
ABitmap.Free;
end;
end;
|
Как вытащить маску из TIcon?
type
TForm1 = class(TForm)
procedure FormPaint(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
Mask: TBitmap;
public
end;
implementation
procedure TForm1.FormCreate(Sender: TObject);
var
IconInfo: TIconInfo;
begin
Mask := TBitmap.Create;
GetIconInfo(Application.Icon.Handle, IconInfo);
Mask.Handle := IconInfo.hbmMask;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
Mask.Free;
end;
procedure TForm1.FormPaint(Sender: TObject);
begin
BitBlt(Canvas.Handle, 0, 0, Mask.Width, Mask.Height,
Mask.Canvas.Handle, 0, 0, SRCCOPY);
end;
|
Как начертить hexagon?
uses
{...,} Math;
procedure PlotPolygon(const Canvas: TCanvas; const N: Integer; const R: Single;
const XC: Integer; const YC: Integer);
type
TPolygon = array of TPoint;
var
Polygon: TPolygon;
I: Integer;
C: Extended;
S: Extended;
A: Single;
begin
SetLength(Polygon, N);
A := 2 * Pi / N;
for I := 0 to (N - 1) do
begin
SinCos(I * A, S, C);
Polygon[I].X := XC + Round(R * C);
Polygon[I].Y := YC + Round(R * S);
end;
Canvas.Polygon(Polygon);
end;
procedure TForm1.Button1Click(Sender: TObject);
var
W: Single;
H: Single;
X: Integer;
Y: Integer;
const
N = 6;
R = 10;
begin
W := 1.5 * R;
H := R * Sqrt(3);
for X := 0 to Round(ClientWidth / W) do
for Y := 0 to Round(ClientHeight / H) do
if Odd(X) then
PlotPolygon(Canvas, N, R, Round(X * W), Round((Y + 0.5) * H))
else
PlotPolygon(Canvas, N, R, Round(X * W), Round(Y * H));
end;
|
Как вывести надпись на Canvas с эффектом 3D?
procedure ExtFont(Canvas: TCanvas);
var
Font: HFONT;
FontName, Txt: PChar;
sSize: Size;
i: Integer;
Obj: LongWord;
begin
FontName := 'Tahoma';
Txt := 'www.decoding.dax.ru';
Font := CreateFont(60, 30, 0, 0, FW_BOLD, 0, 0, 0, DEFAULT_CHARSET,
OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
PROOF_QUALITY, DEFAULT_PITCH + FF_DONTCARE, FontName);
Obj := SelectObject(Canvas.Handle, Font);
SetBkMode(Canvas.Handle, TRANSPARENT);
GetTextExtentPoint32(Canvas.Handle, Txt, Length(Txt), sSize);
BeginPath(Canvas.Handle);
Canvas.Pen.Color:= clGreen; // Цвет текста
i := 1;
for i := 0 to 2 do // Глубина эффекта
// Позиция текста на форме
TextOut(Canvas.Handle, 5 + i, 10 + i, Txt, Length(Txt));
EndPath(Canvas.Handle);
// Canvas.Pen.Style := psDot; { Стиль }
StrokePath(Canvas.Handle);
SetBkMode(Canvas.Handle, OPAQUE);
DeleteObject(Obj);
DeleteObject(Font);
end;
procedure TForm1.FormPaint(Sender: TObject);
begin
ExtFont(Canvas);
end;
|
Как перевести пиксели в миллиметры?
// Способ первый
// Имеет меньшую точность и не реагирует на изменение разрешения экрана
function PixelsToMM(WidthInPixels: Cardinal): Extended;
begin
Result := WidthInPixels / Screen.PixelsPerInch * 25.4;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
ShowMessage(FloatToStr(PixelsToMM(10)));
end;
// Способ второй
// Имеет меньшую точность и не реагирует на изменение разрешения экрана
procedure PixelsToMM(DC: HDC; WidthInPixels: Cardinal;
var WidthInMM, HeightInMM: Extended);
begin
WidthInMM := WidthInPixels * 25.4 / GetDeviceCaps(DC, LOGPIXELSX);
HeightInMM := WidthInPixels * 25.4 / GetDeviceCaps(DC, LOGPIXELSY);
end;
procedure TForm1.Button1Click(Sender: TObject);
var
WidthInMM, HeightInMM: Extended;
begin
PixelsToMM(GetDC(HWND(nil) {0}), 10, WidthInMM, HeightInMM);
ShowMessage('W: ' + FloatToStr(WidthInMM) + ' H: ' + FloatToStr(HeightInMM));
end;
// Способ третий
// Имеет бОльшую точность
procedure PixelsToMM(DC: HDC; WidthInPixels, HeightInPixels: Cardinal;
var WidthInMM, HeightInMM: Extended);
var
HRes, VRes, HSiz, VSiz: Integer;
begin
HRes := GetDeviceCaps(DC, HORZRES);
VRes := GetDeviceCaps(DC, VERTRES);
HSiz := GetDeviceCaps(DC, HORZSIZE);
VSiz := GetDeviceCaps(DC, VERTSIZE);
WidthInMM := WidthInPixels / (HRes / HSiz);
HeightInMM := HeightInPixels / (VRes / VSiz);
end;
procedure TForm1.Button1Click(Sender: TObject);
var
WidthInMM, HeightInMM: Extended;
begin
PixelsToMM(GetDC(HWND(nil) {0}), 10, 10, WidthInMM, HeightInMM);
ShowMessage('W: ' + FloatToStr(WidthInMM) + ' H: ' + FloatToStr(HeightInMM));
end;
|
Как перевести миллиметры в пиксели?
// Способ первый
// Имеет меньшую точность и не реагирует на изменение разрешения экрана
function MMToPixels(WidthInMM: Extended): Cardinal;
begin
Result := Round(Screen.PixelsPerInch / 25.4 * WidthInMM);
end;
procedure TForm1.Button4Click(Sender: TObject);
begin
ShowMessage(IntToStr(MMToPixels(2.64583333333333)));
end;
// Способ второй
// Имеет меньшую точность и не реагирует на изменение разрешения экрана
procedure MMToPixels( DC: HDC; WidthInMM: Extended;
var WidthInPixels, HeightInPixels: Cardinal );
begin
WidthInPixels := Round(GetDeviceCaps(DC, LOGPIXELSX) / 25.4 * WidthInMM);
HeightInPixels := Round(GetDeviceCaps(DC, LOGPIXELSY) / 25.4 * WidthInMM);
end;
procedure TForm1.Button4Click(Sender: TObject);
var
WidthInPixels, HeightInPixels: Cardinal;
begin
MMToPixels(GetDC(HWND(nil) {0}), 2.64583333333333, WidthInPixels, HeightInPixels);
ShowMessage('W: ' + IntToStr(WidthInPixels) + ' H: ' + IntToStr(HeightInPixels));
end;
// Способ третий
// Имеет бОльшую точность
procedure MMToPixels(DC: HDC; WidthInMM, HeightInMM: Extended;
var WidthInPixels, HeightInPixels: Cardinal);
var
HRes, VRes, HSiz, VSiz: Integer;
begin
HRes := GetDeviceCaps(DC, HORZRES);
VRes := GetDeviceCaps(DC, VERTRES);
HSiz := GetDeviceCaps(DC, HORZSIZE);
VSiz := GetDeviceCaps(DC, VERTSIZE);
WidthInPixels := Round(WidthInMM * (HRes / HSiz));
HeightInPixels := Round(HeightInMM * (VRes / VSiz));
end;
procedure TForm1.Button4Click(Sender: TObject);
var
WidthInPixels, HeightInPixels: Cardinal;
begin
MMToPixels(GetDC(HWND(nil) {0}), 3.52604166666667, 3.52777777777778, WidthInPixels, HeightInPixels);
ShowMessage('W: ' + IntToStr(WidthInPixels) + ' H: ' + IntToStr(HeightInPixels));
end;
|
Как рассчитать переходный цвет между двумя исходными?
uses
Math;
const
C1: TColor = clRed;
C2: TColor = clLime;
function getNearestColor(const aColor1, aColor2: TColor; const aRate: Single): TColor;
var
r, r1,
g, g1,
b, b1: Byte;
begin
Assert((aRate >= 0) and (aRate <= 100), 'Изменение цвета должно быть меньше 100% разницы цветов');
// Раскладываем цвета на компоненты
r := GetRValue(aColor2);
g := GetGValue(aColor2);
b := GetBValue(aColor2);
r1 := GetRValue(aColor1);
g1 := GetGValue(aColor1);
b1 := GetBValue(aColor1);
Result:= RGB(r1 - Floor((r1 - r) * (aRate / 100)),
g1 - Floor((g1 - g) * (aRate / 100)),
b1 - Floor((b1 - b) * (aRate / 100)));
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
Canvas.Brush.Color := getNearestColor(C1, C2, 50);
Canvas.FillRect(ClientRect);
end;
|
Как рассчитать последовательность переходных цветов между двумя исходными?
type
TForm1 = class(TForm)
Image1: TImage;
Image2: TImage;
Image3: TImage;
Image4: TImage;
Image5: TImage;
Image6: TImage;
Image7: TImage;
Image8: TImage;
Image9: TImage;
Image10: TImage;
procedure FormCreate(Sender: TObject);
private
GradArr: array[1..10] of TColor;
public
end;
implementation
uses
Math;
function GetColorInterval(Color1, Color2: TColor; IntervalCount, IntervalIndex: Byte): TColor;
const
STEP = 256;
var
// Компоненты цвета
r1, r2,
g1, g2,
b1, b2: Byte;
begin
r1 := GetRValue(Color1);
g1 := GetGValue(Color1);
b1 := GetBValue(Color1);
r2 := GetRValue(Color2);
g2 := GetGValue(Color2);
b2 := GetBValue(Color2);
Result := RGB(Byte(Floor(r1 + (r2 - r1) * Trunc(STEP / (IntervalCount + 1) * IntervalIndex) / STEP)),
Byte(Floor(g1 + (g2 - g1) * Trunc(STEP / (IntervalCount + 1) * IntervalIndex) / STEP)),
Byte(Floor(b1 + (b2 - b1) * Trunc(STEP / (IntervalCount + 1) * IntervalIndex) / STEP)));
end;
procedure TForm1.FormCreate(Sender: TObject);
var
i: Integer;
Img: TImage;
begin
GradArr[1] := clYellow; // Начальный цвет
GradArr[10] := clRed; // Конечный цвет
for i := 1 to 8 do // Нам нужно 8 градаций
GradArr[i+1] := GetColorInterval(GradArr[1], GradArr[10], 8, i);
for i := 1 to 10 do
begin
Img := TImage(FindComponent('Image' + IntToStr(i)));
if Assigned(Img) then
begin
Img.Canvas.Brush.Color := GradArr[i];
Img.Canvas.FillRect(Rect(0, 0, Img.Width, Img.Height));
end;
end;
end;
|
При использовании материала - ссылка на сайт обязательна
|
|