Delphi 3. Библиотека программиста

Захват системной палитры


В этой главе я показал, как с помощью Delphi скопировать содержимое экрана. Все замечательно работает, если вы используете растровое изображение вскоре после его создания. Если же попытаться сохранить изображение в файле и загрузить его позднее, цветопередача искажается.

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

Следовательно, после копирования экрана мы должны создать новую палитру с системными цветами и назначить ее свойству Palette растра. При сохранении растрового изображения значения цветов будут сохранены вместе с ним. Функция GetSystemPalette из листинга 9.13 создает такую палитру и возвращает ее логический номер. Функция CaptureScreenRect из того же листинга показывает, как использовать GetSystemPalette со скопированным изображением.

Листинг 9.13. SYSPAL.SRC

function GetSystemPalette: HPalette; var PaletteSize: Integer; LogSize: Integer; LogPalette: PLogPalette; DC: HDC; Focus: HWND; begin Result := 0; Focus := GetFocus; { ...это необходимо для GetDC } DC := GetDC( Focus ); { ...это необходимо для GetDeviceCaps } try PaletteSize := GetDeviceCaps( DC, SIZEPALETTE ); LogSize := SizeOf( TLogPalette ) + ( PaletteSize - 1 ) * SizeOf( TPaletteEntry ); GetMem( LogPalette, LogSize ); try with LogPalette^ do begin palVersion := $0300; palNumEntries := PaletteSize; GetSystemPaletteEntries( DC, 0, PaletteSize, palPalEntry ); end; Result := CreatePalette( LogPalette^ ); finally FreeMem( LogPalette, LogSize ); end; finally ReleaseDC( Focus, DC ); end; end; { Воспользуемся GetSystemPalette для копирования прямоугольника... } function CaptureScreenRect( ARect: TRect ) : TBitmap; var ScreenDC: HDC; begin Result := TBitmap.Create; with Result, ARect do begin Width := Right - Left; Height := Bottom - Top; ScreenDC := GetDC( 0 ); try BitBlt( Canvas.Handle, 0, 0, Width, Height, ScreenDC, Left, Top, SRCCOPY ); finally ReleaseDC( 0, ScreenDC ); end; { Также сохраним системную палитру... } Palette := GetSystemPalette; end; end;

Палитра создается функцией API CreatePalette. Функция CreatePalette получает один параметр-запись, в котором указываются версия палитры, количество цветов и массив значений, определяющих каждый цвет.

В типе записи для этой «логической палитры» хватает места для хранения лишь одного элемента палитры. Сначала это может показаться странным, но на самом деле все логично — количество элементов палитры зависит от видеорежима. Следовательно, прежде всего необходимо определить размер палитры для текущего видеорежима. Затем мы используем указатель типа PLogPalette и выделяем область памяти, достаточную для хранения записи и всех элементов. Как видно из листинга 9.13, количество элементов палитры определяется функцией GetDeviceCaps.

Выделение памяти под логическую палитру — дело хлопотное, но зато дальше все просто. Мы получаем сами цветовые значения функцией GetSystem PaletteEntries, а затем передаем информацию о логической палитре функции CreatePalette и получаем необходимый логический номер (handle) палитры.



Содержание раздела