CYFROWY BARON • PROGRAMOWANIE • Zobacz wątek - Pozycjonowanie okna ShowMessage

Pozycjonowanie okna ShowMessage

dział ogólny

Pozycjonowanie okna ShowMessage

Nowy postprzez politech » niedziela, 8 sierpnia 2010, 21:03

Mam pytanie: da się zmienić pozycję pojawiania się okna wywołanego ShowMessage();? Poki co wyskakuje centralnie w odniesieniu nie do okna programu ale ekranu
Avatar użytkownika
politech
Homos antropiczny
Homos antropiczny
 
Posty: 56
Dołączył(a): poniedziałek, 26 lipca 2010, 13:21
Podziękował : 0
Otrzymał podziękowań: 0
System operacyjny: Windows XP Pro SP2
Kompilator: C++ Builder 2006
Gadu Gadu: 0
    Windows XPFirefox

Re: Pozycjonowanie okna ShowMessage

Nowy postprzez Cyfrowy Baron » poniedziałek, 9 sierpnia 2010, 11:43

Można to zrobić, ale trzeba w tym celu przechwytywać komunikaty. Dla maksymalnego uproszczenia, proponuję w tym celu umieścić na formularzu komponent TApplicationEvents (zakładka Additional) i utworzyć w komponencie ApplicationEvents1 zdarzenie OnMessage.
Teraz wystarczy umieścić w tym zdarzeniu kod odpowiedzialny za pobranie uchwytu to okna komunikatu. W tym celu należy posłużyć się funkcją FindWindow przekazując jej jako pierwszy argument nazwę klasy okna komunikatu i dla ShowMessage jest to TMessageForm, oraz nazwę okna komunikatu i dla ShowMessage jest to tytuł aplikacji. Zdarzenie OnMessage będzie przechwytywać komunikat o wyświetleniu okienka komunikatu i za pomocą funkcji SetWindowPos zmieni jego pozycję:


KOD cpp:     UKRYJ  
void __fastcall TForm1::ApplicationEvents1Message(tagMSG &Msg, bool &Handled)
{
 HWND hwndDlg = FindWindow("TMessageForm", Application->Title.c_str()); /* dla c++builder 2009 i 2010 - (L"TMessageForm" Application->Title.t_str()) */
 
 if(hwndDlg == NULL) return;

 SetWindowPos(hwndDlg,
              HWND_TOPMOST,
              10,   // nowa pozycja X
              10,   // nowa pozycja Y
              0, 0, // rozmiar cx, cy
              SWP_NOSIZE // flaga blokująca zmianę rozmiaru
             );
}




Trochę inaczej sprawa ma się z komunikatem Application->MessageBox, wywołanie tego okna komunikatu blokuje aplikację, blokując jednocześnie przechwytywanie przez nią komunikatów, tak samo wygląda sprawa z MessageBox i nie mam na razie pomysłu na rozwiązanie tego problemu, poza instalowaniem haka systemowego, ale nie wiem czy i to by rozwiązało problem.



Jeżeli chcesz mieć pełną kontrolę na sposobem i wyglądem okna komunikatu to proponuję skorzystać z funkcji CreateMessageDialog, która zadziała na pewno zarówno w starszych jak i w nowszych wersjach środowiska:

KOD cpp:     UKRYJ  
void __fastcall ShowMessage(HWND hWnd, String Caption, String Title, int pX,
        int pY, TMsgDlgType msgType, TMsgDlgButtons msgButton)
{
 TForm *frmDlg = CreateMessageDialog(Title, msgType, msgButton);

 frmDlg->Caption = Caption;
 frmDlg->Left = pX;
 frmDlg->Top  = pY;
 frmDlg->ShowModal();
 delete frmDlg;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button3Click(TObject *Sender)
{
 ShowMessage(NULL, Application->Title, "Treść komunikatu", 10, 20,
             mtInformation, TMsgDlgButtons() << mbOK);
}

W tym przypadku można sterować również kolorem okna komunikatu, rozmiarem czcionki itp. czyli wszystkimi właściwościami formularza.



Jeszcze innym prostym sposobem na wywołanie komunikatu w wybranej pozycji jest skorzystanie z funkcji MessageDlgPos:

KOD cpp:     UKRYJ  
 MessageDlgPos("Treść komunikatu", mtInformation, mbYesNo, 0, 10, 20, mbYes);




Materiały uzupełniające:
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: Pozycjonowanie okna ShowMessage

Nowy postprzez marsianinek » piątek, 13 sierpnia 2010, 11:22

Drogi Baronie, w powyższym kodzie zrobiłeś błąd tworząc obiekt TForm. W następnej linii nadpisujesz wskaźnik nowo stworzonym dialogiem:
KOD cpp:     UKRYJ  
 TForm *frmDlg = new TForm(hWnd);
 frmDlg = CreateMessageDialog(Title, msgType, msgButton);

W tym momencie masz leak w pamięci w postaci zgubionego wskaźnika do obiektu TForm. Funkcja CreateMessageDialog nie wymaga tworzenia tego obiektu, ona sama taki tworzy. Powinno być po prostu tak:
KOD cpp:     UKRYJ  
 TForm *frmDlg = CreateMessageDialog(Title, msgType, msgButton);
Ostatnio edytowano piątek, 27 sierpnia 2010, 11:02 przez marsianinek, łącznie edytowano 1 raz
Avatar użytkownika
marsianinek
 
    Windows XPFirefox

Re: Pozycjonowanie okna ShowMessage

Nowy postprzez Cyfrowy Baron » piątek, 13 sierpnia 2010, 12:13

Zgadza się. :oops: Drobne przeoczenie. :? Już poprawiłem. Jako ciekawostkę powiem, że można wogóle zrezygnować z definiowania obiektu klasy TForm:

KOD cpp:     UKRYJ  
void __fastcall TForm1::Button1Click(TObject *Sender)
{
 CreateMessageDialog("Treść komunikatu", mtInformation, TMsgDlgButtons() << mbOK)->ShowModal();
}


Można też tak:

KOD cpp:     UKRYJ  
#include <memory>
std::auto_ptr<TForm> frmDlg(CreateMessageDialog("Treść komunikatu", mtInformation, TMsgDlgButtons() << mbOK));
frmDlg->Caption = "Tytuł okna";
frmDlg->ShowModal();
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: Pozycjonowanie okna ShowMessage

Nowy postprzez marsianinek » piątek, 27 sierpnia 2010, 11:02

Niestety co do pierwszego to się nie zgodzę - owszem zadziała, ale nie usunąłeś obiektu. Drugi przykład usunie, ponieważ tym się zajmie auto_ptr. W pierwszym przykładzie trzeba będzie stworzyć jednak wskaźnik na TForm, gdyż funkcja CreateMessageDialog nie usuwa stworzonego przez siebie obiektu:
KOD cpp:     UKRYJ  
void __fastcall TForm1::Button1Click(TObject *Sender)
{
   TForm* f = CreateMessageDialog("Treść komunikatu", mtInformation, TMsgDlgButtons() << mbOK);
   f->ShowModal();
   delete f;
}
Baronie, we wcześniejszym Twoim poście zrobiłeś dobrze i dodałeś delete.
Avatar użytkownika
marsianinek
 
    Windows XPFirefox

Re: Pozycjonowanie okna ShowMessage

Nowy postprzez Cyfrowy Baron » piątek, 27 sierpnia 2010, 11:05

KOD cpp:     UKRYJ  
 CreateMessageDialog("Treść komunikatu", mtInformation, TMsgDlgButtons() << mbOK)->ShowModal();


Rzeczywiście program tworzy za każdym razem nowe okno, ale go nie usuwa.
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: Pozycjonowanie okna ShowMessage

Nowy postprzez Cyfrowy Baron » piątek, 27 sierpnia 2010, 11:47

marsianinek napisał(a):Drogi Baronie, w powyższym kodzie zrobiłeś błąd tworząc obiekt TForm. W następnej linii nadpisujesz wskaźnik nowo stworzonym dialogiem:

KOD cpp:     UKRYJ  
 TForm *frmDlg = new TForm(hWnd);
 frmDlg = CreateMessageDialog(Title, msgType, msgButton);


W tym momencie masz leak w pamięci w postaci zgubionego wskaźnika do obiektu TForm.


Z testów wynika, że wyciek pamięci (leak) nie ma miejsca. Po wywołaniu funkcji delete obiekt jest niszczony.

Przed wywołaniem komunikatu:
message1.png


Po wywołaniu okna komunikatu:
message2.png


Po zamknięciu okna komunikatu:
message3.png


Nic nie pozostało po klasie frmDlg.
Nie masz wystarczających uprawnień, aby zobaczyć pliki załączone do tego postu.
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: Pozycjonowanie okna ShowMessage

Nowy postprzez marsianinek » piątek, 27 sierpnia 2010, 12:47

Powyższy test zrobiłeś bez delete i bez auto_ptr? Ciekawe, możliwe, że klasa okna komunikatu (TMessageForm - potomna po TForm) ma w obsłudze zdarzenia OnClose zwolnienie pamięci po sobie, np. Free(), lub inny motyw. Ja bym po prostu dał delete dla zasady i nie zastanawiał się. Będę się upierał, że to okno zostaje w pamięci ale tylko do czasu kiedy obiekt główny Application nie zostanie usunięty. Potwierdza to fakt, że kod:
KOD cpp:     UKRYJ  
        TForm* f = CreateMessageDialog("???", mtWarning, TMsgDlgButtons() << mbOK);
        f->ShowModal();
        f->ShowModal();
        f->ShowModal();
        delete f;

Kod wykona się prawidłowo i wyświetli 3x ten dialog, więc nie zostaje on usunięty automatycznie. Podejrzałem kod tej funkcji i jest tam tworzone okno TMessageForm z właścicielem (Owner) ustawionym na Application. To powoduje, że gdy aplikacja się kończy nasze okienko zostaje usunięte automatycznie. Tak samo działa cały mechanizm VCL odnośnie kontrolek na formie, gdy nawet jak utworzymy je dynamicznie to nie musimy ich defakto usuwać, gdyż konstruktor: TLabel* l = new TLabel(TComponent* AOwner) wymusza podanie właściciela. Taki Owner gdy jest usuwany usuwa wszystkie swoje kontrolki "dzieci" (chyba, że podamy tam NULL to usunięciem będziemy musieli się zająć sami).
Przyznam, że ciekawa dyskusja ale wychodzi ona poza temat za co z góry przepraszam bo sam się przyczyniłem. Myślę, że temat pozycjonowania okna został wyjaśniony.
Avatar użytkownika
marsianinek
 
    Windows XPFirefox

Re: Pozycjonowanie okna ShowMessage

Nowy postprzez Cyfrowy Baron » piątek, 27 sierpnia 2010, 13:14

Po pierwsze pisałem o takiej sytuacji:

KOD cpp:     UKRYJ  
        TForm* f = new TForm(this);
   f = CreateMessageDialog("???", mtWarning, TMsgDlgButtons() << mbOK);
        f->ShowModal();
        delete f;

i tej Twojej wcześniejszej wypowiedzi odnośnie powyższej sytuacji:

marsianinek napisał(a):W tym momencie masz leak w pamięci w postaci zgubionego wskaźnika do obiektu TForm.


Twoje wypowiedź odnośnie tego mojego postu.

Jeżeli zrobisz tak jak to podałeś:
KOD cpp:     UKRYJ  
TForm* f = CreateMessageDialog("???", mtWarning, TMsgDlgButtons() << mbOK);
        f->ShowModal();
        f->ShowModal();
        f->ShowModal();
        delete f;


To utworzysz trzy okna komunikatów, a usunięte zostanie tylko jedno.

W swoim poście podałem taki kod:

KOD cpp:     UKRYJ  
void __fastcall ShowMessage(HWND hWnd, String Caption, String Title, int pX,
        int pY, TMsgDlgType msgType, TMsgDlgButtons msgButton)
{
 TForm *frmDlg = new TForm(hWnd);
  frmDlg = CreateMessageDialog(Title, msgType, msgButton);

 frmDlg->Caption = Caption;
 frmDlg->Left = pX;
 frmDlg->Top  = pY;
 frmDlg->ShowModal();
 delete frmDlg;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button3Click(TObject *Sender)
{
 ShowMessage(NULL, Application->Title, "Treść komunikatu", 10, 20,
             mtInformation, TMsgDlgButtons() << mbOK);
}


Ty w swoim poście miałeś zastrzeżenie do tego fragmentu:

KOD cpp:     UKRYJ  
 TForm *frmDlg = new TForm(hWnd);
  frmDlg = CreateMessageDialog(Title, msgType, msgButton);


W moich testach wyszło - o czym piszę w swoim poprzednim poście, że nie ma tutaj miejsca wyciek pamięci, o którym Ty piszesz, gdyż testy wykazały, że delete usuwa wszystko.
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: Pozycjonowanie okna ShowMessage

Nowy postprzez marsianinek » piątek, 27 sierpnia 2010, 13:46

Należy rozróżnić ShowModal od Create, gdyż to pierwsze nie tworzy okna tylko je pokazuje (Show), po kliknięciu ono nadal jest tylko jest jako Hide. W moim przykładzie jest to nadal to samo jedno okno. Można zrobić taki przykład:
KOD cpp:     UKRYJ  
        TForm* f = CreateMessageDialog("???", mtWarning, TMsgDlgButtons() << mbOK);
        f->Caption = 1;
        f->ShowModal();
        ShowMessage(f->Caption);
        f->Caption = 2;
        f->ShowModal();
        ShowMessage(f->Caption);
        f->Caption = 3;
        f->ShowModal();
        ShowMessage(f->Caption);
        delete f;
 
Przykład wyjaśnia, że w każdym z trzech przypadków jest to nadal to samo okno, które jest jedynie pokazywane (Show) i ukrywane (Hide) 3 razy. Prześledziłem cały kod Debuggerem z włączoną opcją "Debug libraries". Prześledziłem krok po kroku co się dzieje w kodzie tej funkcji (Dialogs.hpp) oraz co się dzieje po kliknięciu na Ok. ShowModal tylko wyświetla i na koniec chowa okno. Usuwa dopiero linijka delete f;
Avatar użytkownika
marsianinek
 
    Windows XPFirefox

Re: Pozycjonowanie okna ShowMessage

Nowy postprzez polymorphism » piątek, 27 sierpnia 2010, 14:10

W moich testach wyszło - o czym piszę w swoim poprzednim poście, że nie ma tutaj miejsca wyciek pamięci, o którym Ty piszesz, gdyż testy wykazały, że delete usuwa wszystko.

Nie, usuwa tylko to, co zostało ostatnio przypisane wskaźnikowi, w tym przypadku będzie to wartość zwrócona przez CreateMessageDialog. Zatem wyciek jest.
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: Pozycjonowanie okna ShowMessage

Nowy postprzez Cyfrowy Baron » piątek, 27 sierpnia 2010, 14:28

Nie ma. Program do śledzenia procesów niczego nie odnajduje, co zresztą widać na załączonych screenach.
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: Pozycjonowanie okna ShowMessage

Nowy postprzez polymorphism » piątek, 27 sierpnia 2010, 14:30

KOD cpp:     UKRYJ  
TForm *frmDlg = new TForm(hWnd); //<--- to co usuwa ten obiekt?
frmDlg = CreateMessageDialog(...);
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: Pozycjonowanie okna ShowMessage

Nowy postprzez Cyfrowy Baron » piątek, 27 sierpnia 2010, 14:55

KOD cpp:     UKRYJ  
delete frmDlg;
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: Pozycjonowanie okna ShowMessage

Nowy postprzez polymorphism » piątek, 27 sierpnia 2010, 14:57

A niby jakim cudem, jeśli w linii z wywołaniem CreateMessageDialog nadpisujesz wskaźnik na ten obiekt?
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

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