Створення непрямокутних форм в Delphi, Різне, Програмування, статті

Трохи про непрямокутних формах … Здається, весь світ зійшов з розуму по таким формам; всі форуми рясніють питаннями на цю тему Чи є складності при створенні непрямокутної форми? Ні … Майже … Справа в тому, що задати зовнішній вигляд форми можна, викликавши лише одну функцію SetWindowsRgn.

SetWindowsRgn(Form1.Handle, True);

Правда, перед цим потрібно створити відповідний регіон. Більшість з тих, хто працює на Delphi, не знають, що таке регіон, головним чином тому, що ця штука не знайшла свого відображення в VCL.

Документація стверджує, що регіон, це “прямокутник, багатокутник, еліпс або комбінація двох або більше фігур з наведеного списку”. Регіони використовуються для “заливки, відсікання (те, що по англійськи називається clipping) “та інших, не менш корисних операцій.

Для створення регіонів існують такі функції (з очевидним призначенням), як CreateRectRgn, CreateEllipticRgn, CreatePolygonRgn і кілька інших. Об’єднувати регіони між собою можна за допомогою функції CombineRgn.

На цьому теоретична частина могла б бути закінчена, якби не одне “але” … Це “але” я процитую окремо …

Але ж найчастіше непрямокутну форму потрібно побудувати на базі растрової картинки, задавши для неї прозорий колір! Як бути?

Це правда. Наскільки мені відомо, Windows не вміє цього робити, то є в ній немає функції CreateBitmapRgn. Тим не менш, можна створювати й такі регіони. Для цього необхідно пробігтися по всій зображенні зверху вниз, в кожному рядку знайти непрозорі області і зробити з них прямокутні регіони (ці прямокутники будуть заввишки в 1 піксель). Потім ми об’єднуємо ці регіони – і, вуаля – ось він, шуканий регіон!

Готовий посперечатися, ви думаєте, що це занадто складно … Перевіряємо …

function BitmapToRegion(Bitmap: TBitmap; TransColor: TColor): HRGN;
var
X, Y: Integer;
XStart: Integer;
begin
Result := 0;
with Bitmap do
for Y := 0 to Height – 1 do
begin
X := 0;
while X < Width do
begin
/ / Пропускаємо прозорі точки
while (X < Width) and (Canvas.Pixels[X, Y] = TransColor) do
Inc(X);
if X >= Width then
Break;
XStart := X;
/ / Пропускаємо непрозорі точки
while (X < Width) and (Canvas.Pixels[X, Y] <> TransColor) do
Inc(X);
/ / Створюємо новий прямокутний регіон і додаємо його до
/ / Регіону всієї картинки
if Result = 0 then
Result := CreateRectRgn(XStart, Y, X, Y + 1)
else
CombineRgn(Result, Result,
CreateRectRgn(XStart, Y, X, Y + 1), RGN_OR);
end;
end;
end;

Цей спосіб працює, звичайно, нешвидко, але він працює. Крім усього іншого, подивимося, як тягати форму лівою кнопкою миші (в сенсі, не тільки за заголовок вікна). Для цього нам потрібно створити свою власну процедуру обробки події WM_LBUTTONDOWN, Яке форма отримує всякий раз, коли на ній натискають ліву кнопку миші. Ось як ця процедура виглядає в описі форми:

type
TFormMain = class(TForm)
private
{ Private declarations }
procedure WMLButtonDown(var Msg: TMessage); message WM_LBUTTONDOWN;
public
{ Public declarations }
end;

Рядок, яку потрібно додати, виділена червоним кольором. У розділі реалізації ця функція виглядає так:

procedure TFormMain.WMLButtonDown(var Msg: TMessage);
begin
Perform(WM_NCLBUTTONDOWN, HTCAPTION, Msg.LParam);
end;

Форма посилає самій собі повідомлення WM_NCLBUTTONDOWN з wParam рівним HTCAPTION, Тобто емулює ситуацію, коли користувач натискає ліву кнопку миші на заголовку форми. Після цього форму можна спокійно переміщати за всю її область.

Як бачите, нічого складного у створенні прямокутних вікон. Такі вікна підкреслюють виразність програми і показують професіоналізм її творця …

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*