CYFROWY BARON • PROGRAMOWANIE • Zobacz wątek - Tworzenie nowych okien - formularzy

Tworzenie nowych okien - formularzy

dział ogólny

Tworzenie nowych okien - formularzy

Nowy postprzez Darek_C++ » sobota, 20 listopada 2010, 11:14

Witam ponownie,
Formularz utworzony w BCB przenosze do - Auto-create forms: odnajdujemy wpis Form2, a nastęnie przenosimy go do okna: Available forms, bo ma być tworzony dynamicznie. Jego wywołanie standardowo:

KOD cpp:     UKRYJ  
void __fastcall TForm1::Button1Click(TObject *Sender)
{
        TForm2 *frm = new TForm2(this);   //Tworzenie formularza Form2 poprzez zdefiniowanie nowego obiektu frm.

        frm->Caption = "Formularz nr: "+(String) nr;
        frm->Show();

        nr++;
}
Formularze się tworzą itd...

Problem jest taki, że w tych nowych oknach ma być podgląd strony www wybrany w TListViev i chodzi o to, że tak otwierane okna nie mają swojego [przycisku] na dolnym pasku stanu

Obrazek

tylko wszystkie są w ramach [Project1] co jest w tym wypadku niewygodne.

Pytanie brzmi czy w ramach programu można otwierać/wywoływać/tworzyć nowe okna formularzy tak by pojawiały się na pasku stanu, ale po zamknięciu głównego programu też się zamykały ?
Avatar użytkownika
Darek_C++
Elektrowied
Elektrowied
 
Posty: 454
Dołączył(a): piątek, 25 lipca 2008, 14:33
Podziękował : 66
Otrzymał podziękowań: 4
System operacyjny: Windows XP Pro SP2
Kompilator: Turbo Explorer C++
Gadu Gadu: 0
    Windows XPFirefox

Re: Tworzenie nowych okien - formularzy

Nowy postprzez Cyfrowy Baron » sobota, 20 listopada 2010, 12:44

Nowo okno programu tworzysz w miarę prawidłowo, powinieneś jednak wiedzieć, że jeżeli tworzysz je wewnątrz jakiegokolwiek zdarzenia, funkcji itp. i nie umieszczasz deklaracji w pliku nagłówkowym w sekcji private lub public, to do takiego okna masz dostęp tylko lokalnie, czyli wewnątrz zdarzenia w którym je utworzyłeś. Okno będzie oczywiście istnieć poza tym zdarzeniem, gdyż zostało już utworzone, ale w żaden sposób nie uzyskasz do niego dostępu w jakimkolwiek innym zdarzeniu.
Kolejna sprawa, to nie możesz tworzyć wielu okien o tej samej nazwie. Tworzysz nowe okno o nazwie frm (dobrze), ale każde kolejne nie może być tak tworzone, gdyż tworząc drugie okno o tej samej nazwie (źle), porzucasz okno pierwsze. Następuje wyciek pamięci, pierwsze okno wciąż istnieje, ale program nie może już nic w nim zrobić. U Ciebie nawet z dwóch powodów, po pierwsze okno tworzone jest jako obiekt lokalny, po wtóre utworzenie drugiego okna o tej samej nazwie tworzy dla tego obiektu nowy adres na stosie pamięci, a pierwszy adres nie jest już dostępny.

Chcesz tworzyć dynamicznie nieokreślona liczbę obiektów, zapoznaj się z tym wątkiem: Tworzenie dynamiczne komponentów o nieznanej jeszcze liczbie

W Twoim przypadku mogłoby to wyglądać tak:


Plik nagłówkowy np. Unit1.h:
KOD cpp:     UKRYJ  
/* tym razem plik Unit2.h, czyli plik nagłówkowy formularza TForm2 musisz umieścić w sekcji include pliku nagłówkowego, a nie źródłowego, gdyż deklaracja wektora wymaga informacji o takim formularzu */
#include "Unit2.h"
#include <vector>
//...
private:
        std::vector<TForm2 *> FormList;
Plik źródłowy np. Unit1.cpp:
KOD cpp:     UKRYJ  
void __fastcall TForm1::Button1Click(TObject *Sender)
{
  FormList.push_back( new TForm2(this) ) ;


  String fCaption = "Formularz nr: "+(String) nr;
  String fName = "myForm" + (String)nr;

  /* iterator dajacy dostęp do aktualnie utworzonego formularza na liście */
  std::vector<TForm2 *>::iterator itForm = FormList.end() - 1;

  (*itForm)->Name = fName;
  (*itForm)->Caption = fCaption;

  (*itForm)->Show();

  nr++;  
}


Dostęp do okna uzyskujesz podając jego numer na liście:

KOD cpp:     UKRYJ  
void __fastcall TForm1::Button3Click(TObject *Sender)
{
  int nr_form = 2; /* podajesz numer okna na liście, do którego chcesz się odwołać
                    lista odlicza od 0, więc 2 oznacza trzeci formularz  */


  std::vector<TForm2 *>::iterator itForm = FormList.begin() + nr_form;

  if(itForm > FormList.end() - 1)
  {
   ShowMessage("Taki formularz nie istnieje");
   return;
  }

  FormList[ nr_form ]->Close();  // tylko zamykasz, nie nieszczysz
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button4Click(TObject *Sender)
{
  int nr_form = 2;

  std::vector<TForm2 *>::iterator itForm = FormList.begin() + nr_form;

  if(itForm > FormList.end() - 1)
  {
   ShowMessage("Taki formularz nie istnieje");
   return;
  }

  FormList[ nr_form ]->Show();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button5Click(TObject *Sender)
{
  int nr_form = 2;

  std::vector<TForm2 *>::iterator itForm = FormList.begin() + nr_form;

  if(itForm > FormList.end() - 1)
  {
   ShowMessage("Taki formularz nie istnieje");
   return;
  }

  delete FormList[ nr_form ];  // niszczysz obiekt
  FormList.erase( itForm ); /* trzeba usunąć indeks z listy, tylko jeżeli niszczysz  */
}


można jeszcze ewentualnie tak:

KOD cpp:     UKRYJ  
void __fastcall TForm1::Button3Click(TObject *Sender)
{
  int nr_form = 2;

  std::vector<TForm2 *>::iterator itForm = FormList.begin();

  itForm = itForm + nr_form;

  if(itForm > FormList.end() - 1)
  {
   ShowMessage("Taki formularz nie istnieje");
   return;
  }

  FormList[ nr_form ]->Close();  // tylko zamykasz, nie nieszczysz
}




Teraz możemy przejść do problemu braku przycisków okien wtórnych na pasku zadań. W pliku źródłowym np. Unit2.h dla formularza TForm2 umieszczasz taką deklarację w sekcji private:

KOD cpp:     UKRYJ  
private:        // User declarations
        void __fastcall CreateParams(TCreateParams &Params);


W pliku źródłowym np. Unit2.cpp dla tegoż samego formularza umieszczasz taki kod:

KOD cpp:     UKRYJ  
void __fastcall TForm2::CreateParams(TCreateParams &Params)
{
 TForm::CreateParams(Params);
 Params.ExStyle |= WS_EX_APPWINDOW;
 Params.WndParent = GetDesktopWindow();
}
To wszystko. Każde nowo tworzone okno będzie miało własny przycisk na pasku zadań, a minimalizacja okna głównego nie spowoduje minimalizacji okien wtórnych. Jednakże zamknięcie okna głównego, co zawsze powoduje zakończenie programu, spowoduje - co oczywiste - zamknięcie wszystkich okien wtórnych.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Tworzenie nowych okien - formularzy

Nowy postprzez polymorphism » sobota, 20 listopada 2010, 13:05

KOD cpp:     UKRYJ  
std::vector<TForm2 *>::iterator itForm = FormList.end() - 1;

Lepiej tak (pisałem już o tym w innym wątku):
KOD cpp:     UKRYJ  
TForm2 *ptr = FormList.back();

KOD cpp:     UKRYJ  
std::vector<TForm2 *>::iterator itForm = FormList.begin() + nr_form;
if(itForm > FormList.end() - 1)
...
 

A nie można po prostu:
KOD cpp:     UKRYJ  
if(nr_form >= FormList.size())
...

:?:
C++ Reference - opis wszystkich klas STL-a i funkcji C.

Za ten post autor polymorphism otrzymał podziękowanie od:
Darek_C++
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows XPFirefox

Re: Tworzenie nowych okien - formularzy

Nowy postprzez Cyfrowy Baron » sobota, 20 listopada 2010, 13:50

A nie można po prostu:
KOD cpp:     UKRYJ  
if(nr_form >= FormList.size())
...


Jak najbardziej można, ale najpierw napisałem sobie kod z usuwaniem formularza:

KOD cpp:     UKRYJ  
delete FormList[ nr_form ];
FormList.erase( itForm );


A potem to już tylko kopiowałem i zmieniałem bez zastanowienia.



Lepiej tak (pisałem już o tym w innym wątku):
KOD cpp:     UKRYJ  
TForm2 *ptr = FormList.back();


To prawda, że lepiej ale chciałem pokazać jak to robić z iteratorem, gdyż po tym co zobaczyłem w pierwszym poście autora wątku, nie chciałem wprowadzać rzutowania, by Darek_C++ nie uznał przypadkiem iż może poza zdarzeniem OnClick dla Button1 korzystać z obiektu na który rzutuje, lub by nie uznał go za samodzielny obiekt. Poza tym dobrze byłoby pokazać, jak to ma wyglądać w całości, gdyż autor wątku może mieć niewielkie lub żadne pojęcie o kontenerach:
KOD cpp:     UKRYJ  
void __fastcall TForm1::Button1Click(TObject *Sender)
{
  FormList.push_back( new TForm2(this) ) ;

  String fCaption = "Formularz nr: "+(String) nr;
  String fName = "myForm" + (String)nr;

  /*rzutowanie na obiekt tymczasowy, obiekt tmpForm nie istnieje poza tym zdarzeniem */
  TForm2 *tmpForm = FormList.back(); /* odwołanie się do ostatniego elementu z listy */

  tmpForm->Name = fName;
  tmpForm->Caption = fCaption;

  tmpForm->Show();

  nr++;  
}
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Tworzenie nowych okien - formularzy

Nowy postprzez Darek_C++ » sobota, 20 listopada 2010, 14:42

Panowie wielkie dzięki z tymi przyciskami okien dokładnie o to chodziło ;)
Ale teraz kwestia następująca - przyjmując wersją ostatnią tworzę formularze/nowe okna metodą:
KOD cpp:     UKRYJ  
void __fastcall TForm1::Button1Click(TObject *Sender)
{
        FormList.push_back( new TForm2(this) ) ;
        String fCaption = "Formularz nr: "+(String) nr;
        String fName = "myForm" + (String)nr;
        TForm2 *tmpForm = FormList.back();
        tmpForm->Name = fName;
        tmpForm->Caption = fCaption;
        tmpForm->Edit1->Text = fName;
        tmpForm->Show();
        nr++;
}

Nowe okna TForm2 z założenia będą zamykane tylko za pomocą ich ikonki [X] wiec w Fotm1 nie potrzebuje ich dodatkowej obsługi.
Pytane brzmi czy nie muszę/muszę osuwać ich z pamięci przy zamykaniu głównego okna programu kodem jaki wymyśliłem:
KOD cpp:     UKRYJ  
void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{
        for(int jj=0; FormList.size() > jj; jj++)
        {
                if(FormList[jj])
                {
                        delete FormList[jj];
                }
        }
}
Jeśli zamykam główne okno programu program zamyka się bez wyrzucania wyjątkami, ale czy tak jest poprawnie ?
Przy tworzeniu okien modalnych zawsze dawałem w dodatkowych formularzach Action = caFree;
KOD cpp:     UKRYJ  
void __fastcall TForm2::FormClose(TObject *Sender, TCloseAction &Action)
{
        Action = caFree;
}
Jak to prawidłowo obsłużyć ?
Avatar użytkownika
Darek_C++
Elektrowied
Elektrowied
 
Posty: 454
Dołączył(a): piątek, 25 lipca 2008, 14:33
Podziękował : 66
Otrzymał podziękowań: 4
System operacyjny: Windows XP Pro SP2
Kompilator: Turbo Explorer C++
Gadu Gadu: 0
    Windows XPFirefox

Re: Tworzenie nowych okien - formularzy

Nowy postprzez Cyfrowy Baron » sobota, 20 listopada 2010, 15:54

Po pierwsze chcesz okno zamknąć, czy je zniszczyć? Kliknięcie na przycisku X na pasku tytułowym nie niszczy okna, lecz je zamyka. Okno niszczy się funkcją delete. Pokazałem ci to w ostatnim poście:

KOD cpp:     UKRYJ  
  int nr_form = 2;

  std::vector<TForm2 *>::iterator itForm = FormList.begin() + nr_form;

  if(itForm > FormList.end() - 1)
  {
   ShowMessage("Taki formularz nie istnieje");
   return;
  }

  delete FormList[ nr_form ];  // niszczysz obiekt
  FormList.erase( itForm );


Dlatego podałem również kod na zamknięcie i ponowne przywołanie okna:

KOD cpp:     UKRYJ  
void __fastcall TForm1::Button3Click(TObject *Sender)
{
  int nr_form = 2; /* podajesz numer okna na liście, do którego chcesz się odwołać
                    lista odlicza od 0, więc 2 oznacza trzeci formularz  */


  std::vector<TForm2 *>::iterator itForm = FormList.begin() + nr_form;

  if(itForm > FormList.end() - 1)
  {
   ShowMessage("Taki formularz nie istnieje");
   return;
  }

  FormList[ nr_form ]->Close();  // tylko zamykasz, nie nieszczysz
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button4Click(TObject *Sender)
{
  int nr_form = 2;

  std::vector<TForm2 *>::iterator itForm = FormList.begin() + nr_form;

  if(itForm > FormList.end() - 1)
  {
   ShowMessage("Taki formularz nie istnieje");
   return;
  }

  FormList[ nr_form ]->Show();
}
//---------------------------------------------------------------------------


Jeżeli w zdarzeniu OnClose formularza TForm2 umieścisz:

KOD cpp:     UKRYJ  
void __fastcall TForm2::FormClose(TObject *Sender, TCloseAction &Action)
{
 Action = caFree;
}


To przy zamknięciu okna będzie ono niszczone, to oznacza, że ten kod:

KOD cpp:     UKRYJ  
  delete FormList[ nr_form ];  // niszczysz obiekt


nie może być użyty, gdyż okno zostało już zniszczone, trzeba jednak usunąć okno z listy FormList, czyli:

KOD cpp:     UKRYJ  
  FormList.erase( itForm );


Pozostaje więc kwestia wykrycia, które okno zostało zniszczone oraz kiedy to sprawdzać i na to chwilowo nie mam pomysłu, muszę to przemyśleć.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Tworzenie nowych okien - formularzy

Nowy postprzez polymorphism » sobota, 20 listopada 2010, 17:00

Niech się podepnie pod zdarzenie TForm::OnDestroy, w nim poszuka Sendera i usunie go z FormList.
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows XPFirefox

Re: Tworzenie nowych okien - formularzy

Nowy postprzez Cyfrowy Baron » sobota, 20 listopada 2010, 17:08

Mógłbyś jaśniej, bo próbuję właśnie coś w tym rodzaju, ale wogóle mi to nie wychodzi. Do czego mam przekazać wartość Sender?!
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Tworzenie nowych okien - formularzy

Nowy postprzez polymorphism » sobota, 20 listopada 2010, 18:05

Nie przekazać, tylko poszukać w FormList, czyli mniej więcej coś takiego:

KOD cpp:     UKRYJ  
std::vector<TForm2*>::iterator it = std::find(FormList.begin(), FormList.end(), (TForm2*)Sender);
if(it != FormList.end()) FormList.erase(it);
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows XPFirefox

Dynamiczne tworzenie okien z wykorzystaniem kontenerów

Nowy postprzez Cyfrowy Baron » sobota, 20 listopada 2010, 18:26

To rzeczywiście rozwiązuje problem. Koncepcja programu ulegnie niewielkiej zmianie. Przede wszystkim wektor należy zadeklarować w pliku nagłówkowym formularza głównego nie w sekcji private, lecz public, by był dostępny dla innych formularzy:

Unit1.h
KOD cpp:     UKRYJ  
#include <vector>
#include "Unit2.h"
// ...
public:         // User declarations
        __fastcall TForm1(TComponent* Owner);

        std:: vector<TForm2 *> FormList;
W pliku źródłowym w kwestii tworzenia nowych formularzy nic się w zasadzie nie zmienia:

Unit1.cpp
KOD cpp:     UKRYJ  
void __fastcall TForm1::Button1Click(TObject *Sender)
{
  FormList.push_back( new TForm2(this) ) ;

  String fCaption = "Formularz nr: "+(String) nr;
  String fName = "myForm" + (String)nr;

  TForm2 *tmpForm = FormList.back();
  tmpForm->Name = fName;
  tmpForm->Caption = fCaption;
  tmpForm->Show();

  nr++;
}


W pliku Unit2.h dla formularza Form2, tak jak to już wcześniej podałem deklarujemy:

Unit2.h
KOD cpp:     UKRYJ  
private:        // User declarations
        void __fastcall CreateParams(TCreateParams &Params);


W pliku Unit2.cpp dla formularza Form2 definiujemy funkcję z sekcji private oraz do zdarzenia OnClose dodajemy kod niszczący formularz po zamknięciu oraz czyszczący listę wektorów. Trzeba tutaj jeszcze w sekcji include dodać plik nagłówkowy formularza głównego:

Unit2.cpp
KOD cpp:     UKRYJ  
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit2.h"
#include "Unit1.h"
#include <algorithm>
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm2 *Form2;
//---------------------------------------------------------------------------
__fastcall TForm2::TForm2(TComponent* Owner)
        : TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm2::CreateParams(TCreateParams &Params)
{
 TForm::CreateParams(Params);
 Params.ExStyle |= WS_EX_APPWINDOW;
 Params.WndParent = GetDesktopWindow();
}
//---------------------------------------------------------------------------
void __fastcall TForm2::FormClose(TObject *Sender, TCloseAction &Action)
{
 std::vector<TForm2*>::iterator it =
 std::find(Form1->FormList.begin(), Form1->FormList.end(), (TForm2*)Sender);

 if(it != Form1->FormList.end()) Form1->FormList.erase(it);

 Action = caFree;
}
//---------------------------------------------------------------------------

Za ten post autor Cyfrowy Baron otrzymał podziękowanie od:
Darek_C++
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Tworzenie nowych okien - formularzy

Nowy postprzez Darek_C++ » sobota, 20 listopada 2010, 19:19

Cyfrowy Baron napisał(a):Po pierwsze chcesz okno zamknąć, czy je zniszczyć? .
Zasadniczo chodziło o jego zniszczenie zwolnienie zajmowanej przez niego pamięci, bo po jego zamknięciu już będzie niepotrzebne. Dlatego myślałem, że umieszczenie w:
KOD cpp:     UKRYJ  
void __fastcall TForm2::FormClose(TObject *Sender, TCloseAction &Action)
{
       Action = caFree;
}
załatwia sprawę i nie trzeba już robić dodatkowych operacji w Form1.
Czyli to nie wystarczy i by było prawidłowo muszę robić tak jak Pisaliście ?
Avatar użytkownika
Darek_C++
Elektrowied
Elektrowied
 
Posty: 454
Dołączył(a): piątek, 25 lipca 2008, 14:33
Podziękował : 66
Otrzymał podziękowań: 4
System operacyjny: Windows XP Pro SP2
Kompilator: Turbo Explorer C++
Gadu Gadu: 0
    Windows XPFirefox

Re: Tworzenie nowych okien - formularzy

Nowy postprzez Cyfrowy Baron » sobota, 20 listopada 2010, 20:21

Czyli to nie wystarczy i by było prawidłowo muszę robić tak jak Pisaliście ?


TAK! No chyba, że wyciek pamięci nie przeszkadza Tobie, wtedy zapomnij o kontenerach i rób po swojemu. Program oczywiście wcześniej lub później się posypie.



PS. Rób linię przerwy między tekstem i tagami BBCode, gdyż piszesz wszystko na kupie i jest to nieczytelne.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Tworzenie nowych okien - formularzy

Nowy postprzez Darek_C++ » sobota, 20 listopada 2010, 20:27

Dziękuję za pomoc :)
Avatar użytkownika
Darek_C++
Elektrowied
Elektrowied
 
Posty: 454
Dołączył(a): piątek, 25 lipca 2008, 14:33
Podziękował : 66
Otrzymał podziękowań: 4
System operacyjny: Windows XP Pro SP2
Kompilator: Turbo Explorer C++
Gadu Gadu: 0
    Windows XPFirefox

Re: Tworzenie nowych okien - formularzy

Nowy postprzez Darek_C++ » niedziela, 21 listopada 2010, 16:53

Pojawił się kolejny problem z tymi oknami, a mianowicie chodzi o przechwycenie wciśnięcia w klawisze - obsługi klawiatury.

Kod w formularzu:
KOD cpp:     UKRYJ  
__fastcall TForm4::TForm4(TComponent* Owner)
        : TForm(Owner)
{
        KeyPreview = true;
}

void __fastcall TForm4::FormKeyPress(TObject *Sender, char &Key)
{
        ShowMessage(Key);      
}
I ShowMessage tylko raz się pokazuje niezależnie od ilości wciśniętych klawiszy.
Sprawdzałem do formularza modalnego też tworzonego dynamicznie kodem:
KOD cpp:     UKRYJ  
TForm3 *Form3 = new TForm3(this);
Form3->Show();

i każde wciśnięcie wywołuje ShowMessage.

Co z tym fantem można zrobić ?
Avatar użytkownika
Darek_C++
Elektrowied
Elektrowied
 
Posty: 454
Dołączył(a): piątek, 25 lipca 2008, 14:33
Podziękował : 66
Otrzymał podziękowań: 4
System operacyjny: Windows XP Pro SP2
Kompilator: Turbo Explorer C++
Gadu Gadu: 0
    Windows XPFirefox

Re: Tworzenie nowych okien - formularzy

Nowy postprzez Cyfrowy Baron » niedziela, 21 listopada 2010, 17:22

Musisz podawać więcej informacji, gdyż zbyt dużo trzeba się tutaj domyślać. O wciśnięcie których klawiszy chodzi? Czy o wciśnięcie klawiszy w jakimś edytorze na formularz, np. Memo?

Po wciśnięciu klawisza wyskakuje okno komunikatu, więc okno programu w którym wcisnąłeś klawisz przestaje być aktywne, a tylko w aktywnym oknie będzie działać przechwytywanie komunikatu o wciśnięciu klawisza. By po zamknięciu komunikatu okno było ponownie aktywne, trzeba je przywołać na wierzch, ono może być na wierzchu, ale trzeba uczynić je aktywnym. Może to rozwiąże problem:

KOD cpp:     UKRYJ  
void BringWindowToFront(HWND hWnd)
{
 bool Result;
 DWORD ForegroundWindowThreadID;
 DWORD WindowThreadID;
 if(hWnd != GetForegroundWindow())
 {
  ForegroundWindowThreadID = GetWindowThreadProcessId(GetForegroundWindow(), NULL);
  WindowThreadID = GetWindowThreadProcessId(hWnd, NULL);
  if(ForegroundWindowThreadID != WindowThreadID)
  {
   AttachThreadInput(ForegroundWindowThreadID, WindowThreadID, true);
   SetForegroundWindow(hWnd);
   AttachThreadInput(ForegroundWindowThreadID, WindowThreadID, false);
  }
  else
   SetForegroundWindow(hWnd);
  ShowWindow(hWnd, SW_RESTORE);
 }
}
//-------------------------------------------------------------------------------------
void __fastcall TForm4::FormKeyPress(TObject *Sender, char &Key)
{
  ShowMessage(Key);  

  BringWindowToFront(this->Handle);  
}




Sprawdzałem do formularza modalnego też tworzonego dynamicznie kodem:
KOD cpp:     UKRYJ  
TForm3 *Form3 = new TForm3(this);
Form3->Show();


Funkcja Show wywołuje okno niemodalne, okno modalne wywołuje się funkcją ShowModal(). Zdecyduj się czy chodzi o okno modalne czy niemodalne. W przypadku okna modalnego, przechwytywanie działa, gdyż okno modalne zawsze jest aktywne, ponieważ modalne może być tylko jedno okno na raz.

Za ten post autor Cyfrowy Baron otrzymał podziękowanie od:
Darek_C++
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Następna strona

Powrót do Ogólne problemy z programowaniem

Kto przegląda forum

Użytkownicy przeglądający ten dział: Brak zalogowanych użytkowników i 1 gość

cron