Problem z programem typu MDI

dział ogólny

Problem z programem typu MDI

Nowy postprzez kask18 » poniedziałek, 14 lipca 2008, 09:28

Cześć wszystkim, to na dzień dobry mam taki oto problem. Tworzę aplikacje typu MDI. Służy on do otwierania obrazów. Chciałbym zrobić w tym projekcie 2 rzeczy:

1. By tworzone okienka miałby BorderStyle identyczne jak Form1 (podstawowa forma) czyli
bsToolWindow.

2. kiedy przesuwam obrazek już wczytany po przestrzeni formy głównej to i dochodze do
krawędzi formy to pojawia się na dole Scroll. Chciałbym zrobić tak by krawędzie głównej
formy ograniczały mi przestrzeń przesuwania obrazka.


link do programu:
Program

z góry dzięki za pomoc :-)
Nie masz wystarczających uprawnień, aby zobaczyć pliki załączone do tego postu.
Avatar użytkownika
kask18
 
    NieznanyNieznana

Re: Problem z programem typu MDI (kask18)

Nowy postprzez Cyfrowy Baron » poniedziałek, 14 lipca 2008, 09:29

Co do pierwszego pytania, to jedyne co udało mi się uzyskać to okienko Child typu dialog poprzez zmianę stylu BorderStyle, niestety nie działa na ToolWindow, a ręczne ustawianie stylu z wykorzystaniem klasy TCreateParams też nic nie daje.

Co do drugiego pytania, to należy cały kod ograniczający obszar poruszania formularza Form2 po Form1 umieścić w zdarzeniu OnPaint dla formularza głównego czyli Form1:

Kod: Zaznacz cały
void __fastcall TForm1::FormPaint(TObject *Sender)
{
TRect R = Rect(0, 0, ClientWidth - Form2->Width - 4,
                 ClientHeight - Form2->Height - 4);

if(Form2->Left >= R.Right) Form2->Left = R.Right;
if(Form2->Left <= 0) Form2->Left = 0;

if(Form2->Top >= R.Bottom) Form2->Top = R.Bottom;
if(Form2->Top <= 0) Form2->Top = 0;
}
Nie masz wystarczających uprawnień, aby zobaczyć pliki załączone do tego postu.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4730
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 444
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    NieznanyNieznana

Re: Problem z programem typu MDI (kask18)

Nowy postprzez kask18 » wtorek, 15 lipca 2008, 22:33

mógł byś podać to na przykładzie mojego programu ?? Rozwiązanie które podałeś sprawdza się dla jednego okienka typu MDIChild natomiast w moim programie tworzone są dynamiczne te okienka i może być ich kilka. Jeśli da rade coś z tym fantem zakombinować było by fajnie. I dzięki za pomoc udzieloną droga mailową :)
Avatar użytkownika
kask18
 
    NieznanyNieznana

Re: Problem z programem typu MDI (kask18)

Nowy postprzez Cyfrowy Baron » wtorek, 15 lipca 2008, 23:06

Fakt tworzenia dynamicznie formularza nic nie zmienia. Przedstawiony kod odwołuje się do nazwy formularza, więc wystarczy podać właściwą nazwę, wymaga to oczywiście, żeby formularze były deklarowane jako globalne, co w przypadku aplikacji MDI może faktycznie stanowić problem.

Dziś już chce mi się spać więc nic nie wymyślę, ale jutro sprawdzę, czy nie dałoby się umieścić tego kodu w oknie CHILD a nie MDI, wtedy działałby niezależnie od formularz głównego (MDI).

Od razu dodam, że umieszczenie tego kodu w zdarzeniu OnPaint okna CHILD nie wywoła pożądanego efektu, gdyż to zdarzenie jest wywoływane tylko podczas odrysowywania okna, a więc nie podczas jego przesuwania, ale dopiero po zakończeniu ruchu.

Myślę że rozwiązaniem problemu będzie funkcja przechwytująca komunikaty i można tutaj stworzyć własną mapę komunikatów, lub posłużyć się komponentem TApplicationEvent, ale o tym jutro...
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4730
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 444
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    NieznanyNieznana

Rozwiązanie: Problem z programem typu MDI

Nowy postprzez Cyfrowy Baron » środa, 16 lipca 2008, 12:42

Tak więc mam rozwiązanie tego problemy, z wykorzystaniem komponentu TApplicationEvents, który znajdziesz na zakładce Additional.
Można by się posłużyć mapą komunikatów, ale to tylko skomplikowało by kod, w tym znaczeniu, że byłoby go więcej.

Umieść komponent ApplicationEvents1 na formularzu okna potomnego (Child), następnie utwórz dla niego zdarzenie OnMessage.
W pliku nagłówkowym (np. ChildWin.h) w sekcji public zadeklaruj obiekt typu TForm, posłuży on do śledzenia położenia i rozmiarów okna głównego (MDIForm).
Kod: Zaznacz cały
private:
   TForm *MyControl;

następnie w pliku źródłowym (np. ChildWin.cpp) w konstruktorze klasy trzeba podłączyć obiekt MyControl do formularz głównego programu (MDIForm):
Kod: Zaznacz cały
__fastcall TMDIChild::TMDIChild(TComponent *Owner)
   : TForm(Owner)
{
  MyControl =  Application->MainForm;
}

teraz w utworzonym wcześniej zdarzeniu OnMessage komponentu ApplicationEvents1 umieszczamy kod ograniczający obszar przemieszczania się okna:
Kod: Zaznacz cały
void __fastcall TMDIChild::ApplicationEvents1Message(tagMSG &Msg,
      bool &Handled)
{
try{
TRect R = Rect(0, 0, MyControl->ClientWidth - this->Width - GetSystemMetrics(SM_CXEDGE)*2,
         MyControl->BoundsRect.Bottom);

  if(this->Left >= R.Right) this->Left = R.Right;
  if(this->Left <= 0) this->Left = 0;

  if(this->Top + MyControl->Top + this->Height >= R.Bottom)
   this->Top = MyControl->ClientHeight - this->Height - GetSystemMetrics(SM_CYEDGE)*2 - 49;
  if(this->Top <= 0) this->Top = 0;
}catch(...){;}
}




Krótkie wyjaśnienie:

Funkcja GetSystemMetrics pobiera grubość ramki okna zdefiniowaną w systemie i odejmuje ją od wymiarów formularza głównego.
Struktura MyControl->BoundsRect.Bottom zwraca położenie okna głównego w odniesieniu do dołu ekranu. Jest to potrzebne gdyż występuje problem z obliczeniem obszaru poruszania się okna potomnego po oknie głównych, ze względu na to, że na oknie głównym mogą znajdować się komponenty ToolBar i StatusBar, które nie są uwzględniane przez funkcję ClientHeight, dlatego zrezygnowałem z użycia tej funkcji do obliczania obszaru roboczego okna.
W kodzie występuje jawnie określona wartość 49, jest to suma szerokości komponentów ToolBar (u mnie 30) i StatusBar (u mnie 19). Jeżeli więc u Ciebie występują lub nie jakieś komponenty na formularzu okna głównego (MDIForm) ograniczające obszar przemieszczania się okna potomnego to musisz odpowiednio zmodyfikować tą wartość.

Można by się pokusić o automatyczne określanie szerokości obszaru roboczego okna głównego, ale wymagałoby to stworzenia odrębnego algorytmu, więc jeżeli można określić ten wymiar jawnie, to nie ma sensu komplikować kodu.

Ograniczanie obszaru przemieszczania się formularza potomnego po głównym z wykorzystaniem przechwytywania komunikatów, nie zawsze może działać prawidłowo, gdyż przy większym obciążeniu systemu, do programu mogą nie dotrzeć komunikaty i w efekcie kod nie zadziała.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4730
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 444
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    NieznanyNieznana


  • Podobne tematy
    Odpowiedzi
    Wyświetlone
    Ostatni post

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 3 gości

cron