Zabawa z formularzem (formą)

vegat
Ten artykuł wymaga dopracowania!

Jeżeli możesz popraw ten artykuł według zaleceń, które możesz znaleźć na stronie [[Artykuły do poprawy]]. Po dopracowaniu tego tekstu można usunąć ten komunikat.

Witam!

W tym artykule przedstawię zagadnienia dotyczące pracy z formą (formularzem) w Delphi.
Standardowo mamy ustawioną formę tak jak większość aplikacji w Windows - prostokątne pole, z ramką u góry (tytuł) oraz efektami 3D (:)) na brzegach (różne w zależności od wersji naszej windy).

No więc w standardowej aplikacji typu notatnik to nie przeszkadza - możemy łatwo zmieniać rozmiar, w tytule możemy podać np. nazwę otwartego pliku. Co jednak mają zrobić osoby piszące np. odtwarzacz wideo? Pełny ekran z ramką i paskiem zadań u góry nie jest zbyt efektowny. Innym problemem są osoby, które chcą wyposażyć swoje aplikacje w okna o niestandardowych kształtach, z własną powłoką graficzną (np. Winamp, czy choćby Windows Media Player > 6.0).

Uruchamiając Delphi mamy domyślną formę, a obok Object Inspectora z właściwościami formy. Przedstawię teraz większość z opcji z OI.:
W wersji 7.0 jest dodatkowa opcja Active Control , jednak ją pomijam, gdyż nie ma wpływu na wygląd formy.

Właściwość Opis
Align ułożenie formy, możemy wybrać następujące opcje:
alNone - nie będzie się dopasowywała do dostępnej przestrzeni na pulpicie - pozostanie w takich rozmiarach, w jakich ją zostawiliśmy
alClient - forma wypełni całą dostępną przestrzeń na pulpicie
alTop - formularz zostanie rozciągnięty wypełniając całą górną przestrzeń aż do dolnego brzegu formy (tzn. gdy dolna krawędź formy w trybie edycji będzie w punkcie X, to po uruchomieniu wypełniona zostanie cała górna przestrzeń pulpitu, zaczynając od punktu X)
alBottom - formularz zostanie rozciągnięty wypełniając całą dolną przestrzeń od górnego brzegu formy
alLeft - zajęta zostanie przestrzeń od prawego brzegu formy do lewej krawędzi ekranu
alRight - forma zajmie obszar od lewego brzegu formularza do prawej krawędzi ekranu
alCustom - forma pozostanie w takich samych rozmiarach jak w trybie edycji, a do tego nie będzie można jej przesuwać
AlphaBlend wprowadzone bodajże w wersji 7.0 Delphi parametr określający czy forma jest przezroczysta
AlphaBlendValue określa poziom przezroczystości (od 0 do 255 - 0 - całkiem przezroczyste, 255 - brak przezroczystości)
BorderIcons ta wartość definiuje, jakie ikonki ma zawierać pasek tytułowy naszej formy. Mamy do wyboru:
biMinimize - ikonka minimalizacji okna
biMaximize - maksymalizacja okna
biHelp - ikonka pomocy (patrz w apletach windowsowych, np.właściwości ekranu)
biSystemMenu - menu podręczne pokazujące się po kliknięciu w ikonkę aplikacji
BorderStyle jedna z najciekawszych opcji - możemy tu wybrać typ obramowania okna (domyślnie jest wybrane bsSizeable, ale do wyboru mamy również:
bsDialog - ma tylko ikonkę zamknij, nie ma ikony aplikacji, nie można zmieniac rozmiaru okna
bsNone - brak obramowania, brak jakichkolwiek ikonek, brak systemowego menu (doskonale komponuje się z opcją WindowState ustawioną na wmMaximized)
bsSingle - wybrane ikonki, menu systemowe, obramowanie. (nie można zmienić rozmiaru okna - można tylko je przesuwać)
bsSizeToolWin - okienko narzędzia - cieńkie obramowanie, można zmieniać rozmiar, ikonka zamknij
bsToolWindow - to samo co wyżej, tylko nie można zmieniać rozmiaru
BorderWidth szerokość ramki wewnątrz formy (wbrew pozorom nie zmienia to rozmiaru efektu 3d obramowania)
Caption napis na pasku tytułowym formy, przydaje się do wyświetlenia np. tytułu otwartego dokumentu. Dla upiększenia aplikacji można pokusić się o scrolowanie (przewijanie) napisu na tytule formy
Color właściwość ta przydaje się, gdy samodzielnie robimy grafikę (nie korzystamy z windowsowych grafik) lub gdy robimy np. pełnoekranowy podgląd
Constrainst pozwala nam określić maksymalną i minimalną wielkość okna (domyślnie jest zero, co znaczy, że nie ma żadnych ograniczeń), poszczególne wartości:
MaxWidth - maksymalna szerokość
MaxHeight - maksymalna wysokość
MinWidth - minimalna szerokość
MinHeight - minimalna wysokość
Cursor pozwala zmienić domyślny kursor (strzałkę) na inny, na liście mamy zainstalowane kursory systemowe
Enabled wartość ustawiona na True pozwala nam na klikanie elementów, ustawiona na False ignoruje akcje użytkownika (z górnym paskiem tytułowym włącznie)
Font ta opcja pozwala nam zmienić czcionkę domyślną formy. Jej zmiana zmieni parametry czcionki na wszystkich komponentach znajdujęcych się na formie. Wyróżniamy następujące opcje czcionki:
Charset - zestaw znaków
Color - zmienia kolor czcionki (poza zdefiniowanymi kolorami, można też wybrać swoje)
Height - wysokość napisu, od własności Size różni się tym, że w przypadku dużych liter będą widoczne postrzępienia (litery są powiększane)
Name - nazwa czcionki
Size - wielkość napisu (w odróżnieniu od własności Height ta nie strzępi brzegów napisu)
Style - efekty czcionki, dostępne wartości zbioru: fsBold - pogrubienie, fsItalic - kursywa, fsUnderline - podkreślenie oraz fsStrikeOut - przekreślenie
Hint "dymek" nad formą i nad wszystkimi komponentami, które dymku nie mają, a właściwość ParentShowHint mają ustawioną na True
Icon ikonka na pasku tytułowym okna (można ją także zmienić w Project/Options/Application)
Position pozycja okna, do wyboru:
poDefault - ustawia okno w pozycji domyślnej (lewy górny róg) oraz nadaje domyślne rozmiary
poDefaultPosOnly - nie będzie zmiany rozmiaru okna
poDefaultSizeOnly - nie będzie zmiany położenia okna (formy) aplikacji
poDesigned - pozostawia wielkość i położenie formy w tym samym trybie, w jakim mamy ją w trybie edycji formularza
peDesktopCenter - okno zostanie wycentrowane względem pulpitu
poMainFormCenter - wycentruje nam formę podrzędną względem formy głównej (gdy jej nie ma (tzn. sama jest formą główną), forma nie zmieni swojej pozycji)
poOwnerFormCenter - ustawi formę na środku formy nadrzędnej (nie głównej!)
poScreenCenter - ustawi formę na środku ekranu
WindowState "status" okna, dostępne wartości:
wsNormal - forma nie zmienia swoich rozmiarów
wsMinimized - forma wystartuje zminimalizowana
wsMaximized - maksymalizuje formę
Teraz kod, który spowoduje, że forma przybierze kształt bitmapy. Zastrzegam, że kod nie jest w 100% napisany przeze mnie, lecz ja go zdecydowanie zmieniłem i poprawiłem (chyba) na lepsze:). Na formę wrzuć TImage. We właściwości Picture ustaw twoją bitmapę. kolorem przezroczystym jest domyślnie kolor biały. Możesz go oczywiście zmienić. Oto kod - wrzuć go do OnCreate formy:
var
  { regiony typu Canvas, więcej w helpie }
  tot_reg, tmp_reg: HRGN;
  color, fill, x_a, x_b: Integer;
  { kolor przezroczysty }
  transparent: TColor;
  linia: PByteArray;
  Virtual_Image: TBitmap;
begin
  tot_reg := CreateRectRgn(0, 0, Image1.Width, Image1.Height);
  Virtual_Image := Image1.Picture.BitMap;
  linia := Virtual_Image.ScanLine[0];
  transparent := linia[0];

  { skanujemy po koleji całą formę(tzn nasz obrazek) linia po linii }
  for fill := 0 to (Virtual_Image.Height-1) do
    begin
      { zmienna linia przyjmuje wartość ciągu bitów określających kolory }
      { pikseli w danej linii                                            }
      linia := Virtual_Image.ScanLine[fill];
      color := 0;
      x_a := color;

      { póki nie skończy nam się obrazek (nie dojdziemy do brzegu) w pętli }
      { sprawdzamy czy dany piksel ma wyświetlać to co jest pod nim, czyli }
      { być teoretycznie przezroczysty                                     }
      while (color >= (Virtual_Image.Width - 1)) do
        begin
          x_b := TColor(linia[color]);

          { jeśli nie jest przezroczysty }
          if (x_b <> transparent) then
            begin
              tmp_reg := CreateRectRgn(x_a, fill, color, fill+1);

              { łączymy mapę wynikową z tymczasową (zawierającą 1 linie) metodą xor }
              CombineRgn(tot_reg, tot_reg, tmp_reg, RGN_XOR);
              DeleteObject(tmp_reg);

              { omijamy piksele, aż trafimy na ten, który ma być przezroczysty, lub }
              { skończy nam sie obrazek (tzn linia)                                 }
              repeat
                Inc(color);
              until ((TColor(linia[color]) = transparent) or (color = Virtual_Image.Width - 1));

              x_a := color;
            end;

          Inc(color);
        end;

      { Jeżeli napotkany piksel ma być transparentny (przezroczysty) }
      if TColor(linia[color-1])=transparent then
        begin
          tmp_reg := CreateRectRgn(x_a, fill, color+1, fill+1);
          { metodą xor różnicujemy (odejmujemy od siebie) obydwie mapy }
          CombineRgn(tot_reg, tot_reg, tmp_reg, RGN_XOR);
          { usuwamy obiekt z pamięci }
          DeleteObject(tmp_reg);
        end;
    end;

  { definiujemy obszar (nieregularny) który jest naszą aplikacją (Można za pomocą właściwości }
  { Handle zmienić kształt np. worda)                                                         }
  SetWindowRgn(form1.Handle, tot_reg, true);
  { czyścimy pamięć }
  deleteobject(tot_reg);
end;

Więcej artykułów na www.vxcdelphi.prv.pl

21 komentarzy

wsMaximized maksymalizuje formę. W połączeniu z ustawieniem koloru formy na czarny, usunięciem obramowania (border style) daje efekt pełnego ekranu.

A co ma do tego czarny kolor?

Czy ja wiem, czy to taka zabawa z formą... może praca z formą ?? Przekształcenia ?? Tytuł taki... nieprofesjonalny.

Na przykład

procedure TForm1.Button1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  if Button = mbLeft then begin
    ReleaseCapture;
    PostMessage(Handle, WM_SYSCOMMAND, SC_MOVE + 2, 0);
  end;
end;

Lub

procedure WMNCHitTest(var Msg: TWMNCHitTest) ; message WM_NCHitTest; 
//[...]
    procedure TForm1.WMNCHitTest(var Msg: TWMNCHitTest) ;
    begin
       inherited;
       if Msg.Result = htClient then Msg.Result := htCaption;
    end; 

Takie pytania to na google lub forum, nie w komentarzach.

A jak zrobić by kliknięciem i przytrzymaniem w dowolną część formy zmienić jej pozycję? - też się dorzucam do tego pytania!
Ps. poprawiłem "Delphiego" na "Delphi"

A jak zrobić by kliknięciem i przytrzymaniem w dowolną część formy zmienić jej pozycję?

Nie to ja akurat wiem, ale ciekawa mogła by być możliwośc dla niektórych coderów stworzenia formy o dowolnym kształcie, nie gwiada, nie trójkąt, nie elipsa ;). No, a poprostu uważam, że ten kod można trochę poprawić to wszystko :p.

michalfo: jak chcesz zaokraglone rogi, to do OnCreate daj:

 SetWindowRgn( Handle, CreateRoundRectRgn( 0,0,width,height,20,20 ),true );

sosik: zamień "<" na "<", bo to jest znak specjalny html... I nie najwięcej, tylko dwa :D

Ten "poprawiony" kod coś się nie kompiluje :) (w d7). Najwięcej błędów wyskakuje przy " &lt ". Pozatym do miejsca gdzie umieściłeś kod to chyba każdy l@mer (np. taki jak ja :) )bez czytania twojego tekstu dałby sobie doskonale rade (Caption... lol dziwne?? itd... przypomina mi się KS-Ekspert, nie wiem czemu :], może dlatego, że to lamerska gazeta i tam tak chyba właśnie wszystko opisują jak coś robią w delphim... przypisz do wartości Caption, From1 wartość... plepleple).
No to chyba wszystko
Pozdrawiam

Przydało by się jeszcze zaokrąglanie formy, tzn. rogów. Jak to zrobić przy border innym niż none

nie, no bezpośredniego Alpha blendów D5 nie ma... ale zrobić się da, tylko troche trzeba sie napisać :P

na windowsie ME też nie działa AlphaBlending. only NT >= 5.0

Spoko art, napewno się komuś przyda.
Co do alpha blend... ja tez mam zastrzezenia. Nie pamietam dokladnie, ale chyba widzialem to nawet w D5 :D
Przezroczystosc formy mozna wykorzystywac w systemach serii NT (Windows 2000 [NT 5.0]; Windows XP [NT 5.1]; Windows 2003 [NT 5.2] i nowszych :)) oraz (glowy nie dam) Windows ME [9x 4.90].

hey, a co jeszcze napisać mam? Prawie cały Object Inspector jest tu opisany... poza tym to, jak już wspomniałem, mój pierwszy art, a ja mam jeszcze szkołe... (w tym roku egzamin:))

Kodzik radził sobie u mnie z owalami, trapezami, a nawet bardziej skomplikowanymi kształtami.... faktem jest, że czasem to nawet kwadrat źle rysuje...

Jak dla mnie to kod nie radzi sobie nawet z trapezem wiec ...

Hmm.. szkoda, że tak mało tych opisów - brak jest znacznej częsci.. wysilił byś się i opisał wszystkie :) ...

no, czasem kodzik sobie ze skomplikowanymi kształtami nie radzi, ale działać działa:) to mój pierwszy art na 4p, proszę więc o ocenę

  1. Dlaczego? Delphi, nie Delphiego. Już mnie to naprawdę denerwuje. Sorki vegat, trafiło na Ciebie :|

delphi nie odmienia sie w jezyku polskim, nazwa wlasna sory

delphi nie odmienia sie w jezyku polskim, nazwa wlasna sory

"ALPHA BLEND - wprowadzone bodajże w wersji 7.0"
w 6 tez jest :) to czy bedzie wykorzystywane zalezy od windy :)