Close button w TabSheet/PageControl

0

Witam serdecznie.
Może ktoś podrzucić rozwiązanie następującego problemu?
Chciałbym stworzyć na TabSheecie przycisk umożliwiający jego zamknięcie (vide FF 2.0 ;) ).
Nie chodzi mi o kod zamykający TS. Chciałbym się dowiedzieć, w jaki sposób wygenerować button umieszczony w lewym rogu każdej karty. Będę bardzo wdzięczny za pomoc.

0

Cóż, ja mam koncepcję trochę prymitywną, ale może to wystarczy. Ogólna idea jest taka, żeby samodzielnie rysować zakładki. A więc ustalamy rozmiar zakładek na sztywno (TabWidth), żeby oprócz napisu było również miejsce na "przycisk". Żeby samemu rysować, ustawiamy OwnerDraw na true i obsługujemy zdarzenie OnDrawTab. W zdarzeniu będziemy pisać tytuł i rysować bitmapę, która będzie udawać przycisk. Zależnie od właściwości Tag danej zakładki rysowany będzie przycisk zwykły albo wciśnięty. Bitmapki z grafiką przechowujemy sobie gdziekolwiek i jakkolwiek. Żeby wykrywać, że użytkownik wcisnął przycisk napiszemy obsługę zdarzeń OnMouseDown i OnMouseUp.

Szkielet kodu wygląda tak. Komponent PageControl nazwałem pc. Używam dwóch zmiennych btnUp i btnDn przechowujących bitmapy z wyglądem przycisku. We właściwości Tag komponentu przechowuję nr wciśniętej zakładki. Na początku żadna nie jest wciśnięta, więc w inspektorze obiektów ustawiamy Tag na -1.

W zdarzeniu OnDrawTab komponentu PageControl:

begin
// wypisujemy Caption
Control.Canvas.Brush.Color := clBtnFace;
Control.Canvas.FillRect(Rect);
Control.Canvas.TextOut(Rect.Left+3,Rect.Top+3,pc.Pages[TabIndex].Caption);

// sprawdzamy, czy przycisk na zakładce jest wciśnięty...
if pc.Pages[TabIndex].Tag=0 then
   // rysujemy przycisk zwykły
   Control.Canvas.Draw(Rect.Right-btnUp.Width-2,Rect.Top+3,btnUp)
else
   // albo wciśnięty
   Control.Canvas.Draw(Rect.Right-btnDn.Width-2,Rect.Top+3,btnDn);
end;

W zdarzeniu OnMouseDown komponentu PageControl

var tab:integer;   
begin
// pobieramy indeks klikniętej zakładki
tab := pc.IndexOfTabAt(X,Y);
// sprawdzamy, czy kliknięto zakładkę w odległości mniejszej niż 16px od prawego brzegu
if (tab<>-1) and (pc.TabRect(tab).Right-X<16) then begin
   // zapisuję indeks zakładki z wciśniętym przyciskiem
   pc.Tag:=tab;
   // ustawiam w zakładce informację potrzebną podczas rysowania (przycisk wciśnięty)
   pc.Pages[tab].Tag:=1;
   // przerysowuję
   pc.Repaint;
end;

W zdarzeniu OnMouseUp komponentu PageControl

var tab:integer;
begin
// jeśli wcześniej nie wciśnięto przycisku to zignoruj zdarzenie
if pc.Tag<>-1 then begin
   // poprzednio wciśnięty przycisk wraca do normalne pozycji
   pc.Pages[pc.Tag].Tag:=0;
   pc.Repaint;
   // na której zakładce puszczono przycisk
   tab := pc.IndexOfTabAt(X,Y);
   // jeśli na tej samej zakładce wciśnięto i puszczono klawisz myszy
   // w odległości mniejszej niż 16px od prawego brzegu...
   if (tab=pc.Tag) and (pc.TabRect(tab).Right-X < 16) then begin
      // to reagujemy na kliknięcie - tutaj umieść kod zamykania zakładki
      ShowMessage('Zamykam!');
   end;
0

Witam
Dziękuję za odpowiedź, masz ciekawą koncepcję.
Wieczorem zobaczę czy się uda ;)

Pozdrawiam

0

Dzięki wielkie, to.. działa ;)
pozdrawiam ;)

0

Nie, nie, nie ;) To ja dziękuję - jeszcze kilka dni na tym forum i może w końcu się Delphi nauczę, bo w tej chwili pisanie kodu Pascalowego idzie mi jak krew z nosa i co chwilę muszę zaglądać do dokumentacji języka ;-)

0

Może i głupie pytanie ale w jaki sposób przechować obrazek w zmiennej btnUp i btnDn?

0

gdzieś w module:

var btnUp : TBitmap;

w OnCreate formy:

btnUp := TBitmap.Create;
btnUp.LoadFromFile( 'file.bmp' );

w OnDestroy formy:

btnUp.Destroy; // a może btnUp.Free ?

Niech się ludzie od Delphi wypowiedzą, bo nie pisałem nic sensownego w Delphi od ponad dwóch lat - a to piszę z pamięci, bez kompilatora i dokumentacji.

0
Ranides napisał(a)
btnUp := TBitmap.Create;
btnUp.LoadFromFile( 'file.bmp' );

Sypnęło błędami. :-/ Za namową debuggera zmieniłem ten kod na:

btnUp := TImage.Create(btnUp);
btnUp.Picture.LoadFromFile('1.bmp');
btnDn := TImage.Create(btnDn);
btnDn.Picture.LoadFromFile('2.bmp');

Ale jedynie zmniejszyło to nieco liczbę błędów. W liniach:

Control.Canvas.Draw(Rect.Right-btnUp.Width-2,Rect.Top+3,btnUp)
Control.Canvas.Draw(Rect.Right-btnDn.Width-2,Rect.Top+3,btnDn)

wciąż wywoływany jest błąd:
[Error] Unit1.pas(): Incompatible types: 'TGraphic' and 'TImage'

0

A to fascynujące, bo aż się zdziwiłem, siadłem do kompa z kompilatorem, i nie sypie żadnymi błędami elementarny kod:

procedure TForm1.Button1Click(Sender: TObject);
var
  btn : TBitmap;
begin
  btn := TBitmap.Create;
  btn.LoadFromFile('c:\test.bmp');
  Form1.Canvas.Draw(5,5, btn);
  btn.Destroy;
end;

Na pewno nie można zamieniać bitmapy na komponent wizualny typu TImage :| No bez jaj.

0

Hm, rzuciłem jeszcze raz okiem na kod w programie, który chce skompilować i jest on identyczny z twoim, a wciąż występuje błąd:

[Error] Unit1.pas(456): Incompatible types: 'TImage' and 'TBitmap'
[Error] Unit1.pas(457): Undeclared identifier: 'LoadFromFile'

Z ciekawości sprawdziłem kod, który podałeś przed chwilą w nowym projekcie i ten chodzi idealnie, mimo iż są identyczne...

Wiem, że może być ciężko w to uwierzyć, dlatego w załączniku zamieszczam mój kod: http://[już nieważne ;)] Będę wdzięczny jeśli rzucisz okiem.

0

Bo jak ja cię kopnę, ale tak z pasją ;] Weź wywal z formy komponenty Timage z łaski swojej o nazwach btnUp, btnDn. Weź wstaw na początku modułu var btnUp, btnDn : TBitmap;

0

Aj, cholera, to faktycznie fail z mojej strony. ;)

0

A tak z ciekawości zapytam, bo mi się nie chce sprawdzać. Czy takie ręczne malowanie, nie psuje wyglądu zakładek ? Chodzi mi o wygląd z włączonymi stylami XP ?

b

0

Zdaje się, że psuje. Może coś się da pokombinować - w każdym razie ustawienie "OwnerDraw" powoduje powrót do "brzydkiego stylu".

0

Ano OwnerDraw=True "psuje" style. Kiedyś zacząłem się coś bawić ThemeServices ale nic z tego nie wyszło, ale czuje że to dobry trop.

b

0
Ranides napisał(a)

Zdaje się, że psuje. Może coś się da pokombinować - w każdym razie ustawienie "OwnerDraw" powoduje powrót do "brzydkiego stylu".

Właśnie odkryłem sposób jak to ujarzmić. :)

Zamiast stosować komponent PageControl należy użyć JvgPageControl z paczki Jedi, ustawić Glypha i w zdarzeniu OnMouseDown wstawić:

if (JvgPageControl.PageCount <> 1) and (JvgPageControl.TabRect(Tabs.IndexOfTabAt(X,Y)).Right-X < 18) then
  JvgPageControl.ActivePage.Free;
0

Dobry wieczór

Mam zamiar hobby Delphi Turbo Explorer

jeśli dobrze rozumiem, tej dyskusji wyjaśniono, jak wstawić przycisk "Zamknij" w zakładce kontroli TPageControl

Ponieważ nie jestem ekspertem, i zdałem sobie sprawę, jedną trzecią tego, co czytają, proszę wypełnić plan studiów.

mój adres e-mail jest [email protected]

Dzięki

0

gfantuzzi: if you do not know polish write post once again in english because you probable used some web
like google translator ot something like that and your post in polish is very hard to understand. Write it once
again in english and describe your problem. Then someone from this forum can help you. Whole thread is
about adding close button to new Tab in PageControl Component.and suggest to use one from Jedi package.

0

I apologize

in fact I used google translate because I think it is better than my English ..

I use - for hobby - Delphi Turbo Explorer so I can't install component with features I wish.

I'm interested to know how is possible insert a 'Close' button in the tab of the TPageControl.

Could you please send me an essential Delphi project with your solution, so I can study it.

Thanks in advance in any case.

Giovanni

0

gfantuzzi: now I know what you mean. And as I check, this post is on top in google when someone search
for example of adding close button to PageControl TabSheets. So I used code by Ranides and added small
bitmap with X sign made in Pain, beacause I'm not grahican. Bitmaps for button up and button down are
the same. But you can make it in different way or add to resourcess in exe file as you wish. I uploaded a
full code with compiled exe file at following address. The file is on Collectors Account so link probable do
not expire too fast. I hope this can help you understund how to do it in own application. I also added three
spaces after TabSheet Caption to seperate text from button and make them visible much better. Remember
to set OwnerDraw property to True for PageControl if you use this code from start desing in your Delphi. And
code is made in Delphi 7 but should compile in any future versions without problems. Ah and remember one
more thing never use google or other translator in foregin forum if you do not have a basic foregin language
knowledge because phase "Ponieważ nie jestem ekspertem, i zdałem sobie sprawę, jedną trzecią tego, co
czytają, proszę wypełnić plan studiów." mens somethins like that (my english is poor but it sound like say)
"I'm not expert, and I realize 1/3 that what they read, please fill studies plan". So like you see there is no
sense in this phase in my opinion. And I thought you looking for some help to pass studies exam from some
computer studies. In that case we do not help even polish dudes if they do not shown own code and place
where they stuck. If some one want ready to run code without any own work he/she need write in "Praca"
(job offers) subforum and pay for ready solutions. Because we do not support lazy ignoramuses here :) Link:

http://rapidshare.com/files/285460570/pagecontrol2.rar

I hope this post will be still to found for foregin people with problem and link above will be some solution.

0

Hello Olesio
Thank you very much for helping me and I think that many others will thank you after me.
I will study the solution in the coming days and, for not being an ignorant lazy, I'll try to personalize the results. I hope I can repay the favor in the future.
Thank's a lot also for your suggestions about the use of translators online. Bye.

Giovanni
http://gfantuzzi.altervista.org

1 użytkowników online, w tym zalogowanych: 0, gości: 1