Jak narysować komponent tak aby wychodził poza formę?

Jak narysować komponent tak aby wychodził poza formę?
KR
  • Rejestracja:prawie 21 lat
  • Ostatnio:prawie 3 lata
0

Chodzi o coś takiego jak np. ComboBox, który po rozwinięciu wychodzi poza formę, na której został położony.
Jak zrobić by np. po naciśnięciu guzika pojawił się striggrid (to nie problem), który wyjdzie poza formę i będzie poza nią widoczny i tu kłopot.

edytowany 1x, ostatnio: krzynio
flowCRANE
Moderator Delphi/Pascal
  • Rejestracja:ponad 13 lat
  • Ostatnio:około 7 godzin
  • Lokalizacja:Tuchów
  • Postów:12156
1

Żaden komponent nie może wystawać poza obszar rodzica (komponentu grupującego lub całego formularza), bo zostanie ucięty. To co wystaje poza formularz to nic innego jak osobne okno w stylu popup. W podobny sposób realizowane jest wyświetlanie menu głównego, menu kontekstowych, tak samo jak wszelkich hintów i temu podobnych baloników.

Tak więc jeśli potrzebujesz zrobić obszar wysuwany poza formularz, to musi on być osobnym oknem.

Wszystko zależy od wymagań, bo można też posłużyć się sztuczkami implementacyjnymi w celu stworzenia jedynie efektu wystawania. Jakiś czas temu pokazałem w jaki sposób zrobiłem formularz z wystającymi panelami. Fizycznie te panele w całości znajdują się w oknie-rodzicu i nie wystają poza jego obszar – po prostu formularzowi ustala się nieregularny kształt.


Pracuję nad własną, arcade'ową, docelowo komercyjną grą z gatunku action/adventure w stylu retro (pixel art), programując silnik i powłokę gry od zupełnych podstaw, przy użyciu Free Pascala i SDL3. Więcej informacji znajdziesz na moim mikroblogu.
edytowany 2x, ostatnio: flowCRANE
cerrato
Moderator Kariera
  • Rejestracja:około 7 lat
  • Ostatnio:około 17 godzin
  • Lokalizacja:Poznań
  • Postów:8758
0

Zgadza się, ta wystająca lista z ComboBox jest osobnym oknem, które dziedziczy w 2 pokoleniu po TWinControl, w związku z tym tak, jak piszesz - jest osobnym oknem jakby "nałożonym" na formatkę, dlatego może wystawać poza jej obrys.

ALE...

TStringGrid to typ, który jest 6 poziomów dziedziczenia pod TWinControl, więc w sumie także jest oknem, a nie jakimś "rysunkowym wytworem" istniejącym tylko na Canvasie swojego rodzica. W związku z tym pytanie - dlaczego jeden potomek TWinControl może wystawać poza swoje okno nadrzędne, natomiast inny już nie? Masz pomysł @furious programming dlaczego tak się dzieje? (Sprawdzałem genealogię komponentów w Lazarusie, ale podejrzewam, że w Delphi struktura dziedziczenia jest podobna).

A teraz coś dla OP - nie wiem dokładnie, co chcesz osiągnąć, ale może rozwiązaniem Twojego problemu będzie stworzenie kolejnego okna z BorderStyle := bsNone o szerokości i wysokości równej rozmiarom stringgrida, w którym osadzisz sobie właśnie tego grida. Po wciśnięciu przycisku, tamto okno będzie się pokazywać w wymagany przez Ciebie sposób, może się przesuwać razem z oknem "głównym", okno główne możesz blokować na czas wyświetlania okna z tabelką albo nadal pozostawić aktywne. Opcji jest wiele, wszystko zależy od Ciebie, w każdym razie - masz pomysł, jak podejść do tematu.


flowCRANE
Moderator Delphi/Pascal
  • Rejestracja:ponad 13 lat
  • Ostatnio:około 7 godzin
  • Lokalizacja:Tuchów
  • Postów:12156
0
cerrato napisał(a):

TStringGrid to typ, który jest 6 poziomów dziedziczenia pod TWinControl, więc w sumie także jest oknem, a nie jakimś "rysunkowym wytworem" istniejącym tylko na Canvasie swojego rodzica.

Tak, wszystko co dziedziczy po TWinControl jest oknem, tyle że nomenklatura w tym przypadku może być myląca. Dla systemu wszystko co posiada własny uchwyt jest oknem, czyli formularze oraz wszystkie komponenty dziedziczące po TWinControl. O tym właśnie informuje prefiks Win – okienko – ale to w kontekście Lazarusa czy Delphi, bo system nie operuje na klasach.

W związku z tym pytanie - dlaczego jeden potomek TWinControl może wystawać poza swoje okno nadrzędne, natomiast inny już nie?

To że dany element dziedziczy z klasy TWinControl nie oznacza automatycznie, że staje się on niezależnym oknem. Zwykłe komponenty muszą być osadzone w innym (kontrolce lub formularzu) – jeśli się tego nie zrobi to komponent w ogóle nie będzie renderowany.

Odpowiedzi należy szukać w klasie TCustomForm, jako bazowej klasie dla wszystkich formularzy. Do przekopania są tysiące linii kodu, więc trzeba będzie się trochę pomęczyć, aby poznać prawdę. ;)

Ewentualnie można się zapoznać z niskopoziomowym tworzeniem okien i ich zawartości za pomocą czystego WinAPI – tam również można znaleźć odpowiedź na to pytanie. W końcu klasy z LCL są jedynie wrapperami na wywołania funkcji systemowych, które wołane są pośrednio za pomocą bieżącego widgetsetu.


Pracuję nad własną, arcade'ową, docelowo komercyjną grą z gatunku action/adventure w stylu retro (pixel art), programując silnik i powłokę gry od zupełnych podstaw, przy użyciu Free Pascala i SDL3. Więcej informacji znajdziesz na moim mikroblogu.
edytowany 7x, ostatnio: flowCRANE
cerrato
Moderator Kariera
  • Rejestracja:około 7 lat
  • Ostatnio:około 17 godzin
  • Lokalizacja:Poznań
  • Postów:8758
0

Wiem, że można przeglądać sobie po kolei źródła i szukać natchnienia ;) Po prostu miałem nadzieję, że Ty jako osoba z pewnym doświadczeniem w tworzeniu komponentów już miałeś z tym wcześniej styczność i będziesz coś wiedział w temacie.

Żeby było śmieszniej - ani grid, ani combobox nie mają po swojej "drodze" do TWinControl nigdzie TCustomForm, więc nie daje to prostego wytłumaczenia. Jakby jeden z tych dwóch komponentów miał customform'a jako rodzica, a drugi nie, to byśmy mieli sprawę jasną. Ale w obecnej postaci to nadal nie wiadomo, z czego ta różnica wynika :(

W końcu LCL jest jedynie wrapperem na wywołania funkcji systemowych

Tylko pamiętajmy, że LCL jest wieloplaformowe, a WinApi to stricte Windows


edytowany 1x, ostatnio: cerrato
flowCRANE
Moderator Delphi/Pascal
  • Rejestracja:ponad 13 lat
  • Ostatnio:około 7 godzin
  • Lokalizacja:Tuchów
  • Postów:12156
1

Pamiętaj, że kontrolki typu TComboBox czy TStringGrid do komponenty stricte systemowe, których zawartością, działaniem i renderowaniem w dużej mierze zajmuje się system. Klasa opisująca taką kontrolkę służy głównie do gromadzenia jej ustawień i definicji pewnych metod pozwalających na manipulowanie nią (np. renderowaniem zawartości pola edycyjnego lub pozycji w rozwijalnym menu).

Dlatego np. w klasie TCustomComboBox nie znajdziesz pola z referencją okienka, które jest wysuwane po kliknięciu w przycisk strzałeczki. Referencji do przycisku strzałki też nie znajdziesz w tej klasie ani żadnej innej znajdującej się na drodze dziedziczenia pomiędzy TWinControl a TComboBox.

cerrato napisał(a):

Tylko pamiętajmy, że LCL jest wieloplaformowe, a WinApi to stricte Windows

Dlatego napisałem w dalszej części cytowanego zdania, że robi to pośrednio za pomocą bieżącego widgetsetu. A to który widgetset zostanie utworzony i przypisany do globalnej zmiennej w module Interfaces zależy od wielu ustawień projektu i kompilatora.


Nigdy nie kopałem na tyle głęboko, aby poznać tego typu szczegóły. Ale z drugiej strony, miałem już okazję ręcznie implementować tego typu funkcjonalności, gdzie zachowaniem, wyglądem i zawartością w całości zajmują się klasy własnych komponentów.

Przykładem jest własny mechanizm hintów dla mojej aplikacji. Tam można znaleźć wszystko – referencję okna hinta, timery, metody obsługujące timery i pokazujące/ukrywające okienko, renderujące jego zawartość itd. Customowy interfejs i pisane od podstaw komponenty wykluczają konieczność tworzenia wrapperów na elementy systemowe i pozbawiają systemu kontroli nad nim, ale z drugiej strony taki wybór zmusza do pisania masy kodu zarządzającego tym wszystkim. No ale albo rybki, albo akwarium. ;)


Pracuję nad własną, arcade'ową, docelowo komercyjną grą z gatunku action/adventure w stylu retro (pixel art), programując silnik i powłokę gry od zupełnych podstaw, przy użyciu Free Pascala i SDL3. Więcej informacji znajdziesz na moim mikroblogu.
edytowany 8x, ostatnio: flowCRANE
KR
  • Rejestracja:prawie 21 lat
  • Ostatnio:prawie 3 lata
0

Bardzo dziękuję za szczegółowe wyjaśnienie i rzeczową dyskusję.
Na co dzień nie mam zbyt wiele czasu by kopać w komponentach, ale pierwsze co przyszło mi do głowy, to właśnie budowa komponentu na TForm albo na TFrame.
Zbudowałem sobie taki bardziej skomplikowany ComboBox i DBComboBox złożony z kilku kontrolek ale jako podstawy użyłem TPanel i właśnie głównym problemem jest to, że komponent umieszczony u dołu okna zwykle po rozwinięciu bywa za krótki. Spróbuję podjeść do tematu raz jeszcze, tym razem na bazie TCustomForm. Nie mam tylko natenczas jeszcze koncepcji jak przykleić jedną formę do drugiej, tak by można je było razem przesuwać. W ostateczności użyję zwykłe ShowModal, tak by rodzic się nie przesuwał, gdy ComboBox będzie rozwinięty.

flowCRANE
Moderator Delphi/Pascal
  • Rejestracja:ponad 13 lat
  • Ostatnio:około 7 godzin
  • Lokalizacja:Tuchów
  • Postów:12156
0
krzynio napisał(a):

Zbudowałem sobie taki bardziej skomplikowany ComboBox i DBComboBox złożony z kilku kontrolek ale jako podstawy użyłem TPanel i właśnie głównym problemem jest to, że komponent umieszczony u dołu okna zwykle po rozwinięciu bywa za krótki.

Zawsze możesz go wyświetlać w całości w obrębie formularza. I tak musisz walidować jego pozycję, tak aby okno po wysunięciu w całości mieściło się na ekranie (dla stanowiska jednoekranowego) lub na pulpicie (w przypadku stanowiska wieloekranowego).

Spróbuję podjeść do tematu raz jeszcze, tym razem na bazie TCustomForm.

Nie musi to być koniecznie TCustomForm – możesz dziedziczyć bezpośrednio z TForm. Obie te klasy zawierają praktycznie taką samą funkcjonalność, tyle że TForm posiada właściwości przesunięte z sekcji public do published, dzięki czemu m.in. są one widoczne w oknie inspektora obiektów.

Nie mam tylko natenczas jeszcze koncepcji jak przykleić jedną formę do drugiej, tak by można je było razem przesuwać.

Od biedy możesz sobie oprogramować zdarzenie Form.OnChangeBounds i z jego poziomu powiadamiać komponent, aby zaktualizował pozycję wysuniętego okienka. Ale to biedne rozwiązanie, bo zmusza do umieszczenia takiego kodu w klasie formularza, a nie komponentu zarządzającego wysuwanym okienkiem. Musisz zagłębić się w kod komponentu i wybadać czy jakaś metoda zostaje wywołana podczas przesuwania okna.

Przy czym domyślnie ComboBox zwija swoje okienko, jeśli to traci focusa – tak standardowo działają okienka typu popup. Takie rzeczy oprogramowane są najprawdopodobniej w metodzie obsługi komunikatu WM_KILLFOCUS.


Pracuję nad własną, arcade'ową, docelowo komercyjną grą z gatunku action/adventure w stylu retro (pixel art), programując silnik i powłokę gry od zupełnych podstaw, przy użyciu Free Pascala i SDL3. Więcej informacji znajdziesz na moim mikroblogu.
edytowany 3x, ostatnio: flowCRANE
WI
  • Rejestracja:około 7 lat
  • Ostatnio:około 2 miesiące
  • Postów:138
0

Może dołożyc trzeba kolejną formę bez belki górnej, o wymiarach wyświetlanego komponentu, ktory ma wyjsc za formę główną programu i na niej umiescic komponent bliźniaczy do tego na formie głwnej, wtedy jak go nie ustawisz to bez problemu pojawi sie tam gdzie nadzasz wspolrzedne tej nowej formy... dodatkowo zyskasz mozliwosc ustawienia alphablend czyli przezroczystosci...

Gdyby efekt nie byl zadowalający mozesz jeszcze kopiowac obraz tła pod formą dodatkową i rysować go na canvasie tej formy. Albo użyć wątku pobocznego do ustalania rozmiaru formy dodatkowej w zaleznosci od stanu komponentu na nim rysowanego przez srodowisko.

edytowany 1x, ostatnio: flowCRANE
Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)