Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Помогите обуздать родительское окно

49K
10 декабря 2011 года
execoma
10 / / 13.06.2009
Здравствуйте, уважаемые форумчане!
Задача очень проста. Создается обычное приложение с одним главным (Form1) и одним дочерним окном (Form2). В этом случае при сворачивании главного окна сворачивается и дочерние. Чтобы дочернее окно не зависело от главного, в него добавляется специальная функция CreateParams(), которая представлена ниже. Данная функция делает родительским окном Form2 рабочий стол, а также для Form2 добавляет свою кнопку на панель задач. Теперь Form2 не зависит от Form1. Но! Есть проблема! Если из Form2 вызывается какое-либо специальное окно, например, OpenDialog, тогда Form2 проваливается под Form1, а этого нужно как-то избежать. Мучения к положительному результату не привели, а это критично для разрабатываемого приложения.

Form1
Код:
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
#include "Unit2.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
        Form2->Show();
}
//---------------------------------------------------------------------------


Form2
Код:
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Unit2.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm2 *Form2;
//---------------------------------------------------------------------------
__fastcall TForm2::TForm2(TComponent* Owner)
        : TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm2::CreateParams(Controls::TCreateParams &Params)
{
        TForm::CreateParams(Params);
 
        // сделать родительским окном рабочий стол
        Params.WndParent = GetDesktopWindow();
 
        // создать кнопку в таскбаре для Form 2
        Params.ExStyle = WS_EX_APPWINDOW;
}
//---------------------------------------------------------------------------
void __fastcall TForm2::Button1Click(TObject *Sender)
{
        OpenDialog1->Execute();
}
//---------------------------------------------------------------------------


Суть проблемы в том, что главное окно приложения (в C++ Builder всегда есть главное окно) активизируется на передний план при создании дочернего окна, поэтому мое отвязанное окно от главного окна и привязанное к рабочему столу, проваливается. По идеи это какое-то API свойство главного окна (свойство активизации при таких обстоятельствах), как бы сбросить его...

Проект прикреплен в аттаче (создан в C++ Builder XE).
1
11 декабря 2011 года
kot_
7.3K / / 20.01.2000
сделать окно модальным?
49K
11 декабря 2011 года
execoma
10 / / 13.06.2009
Конечно, это решит проблему, но дело именно в том, что нужно два окна, которые были бы как бы независимыми друг от друга. В данном случае вообще не понятно, почему окно OpenDialog вызывается относительно главного окна, а не того в котором вызывается по факту.
1
11 декабря 2011 года
kot_
7.3K / / 20.01.2000
попробуй создать OpenDialog динмически и укажи в качестве родителя this. Результат будет тот же? Я так думаю что причина именно в том, что диалог создается в design-time - и ему в качестве родителя устанавливается MainForm
49K
11 декабря 2011 года
execoma
10 / / 13.06.2009
Цитата: kot_
попробуй создать OpenDialog динмически и укажи в качестве родителя this. Результат будет тот же? Я так думаю что причина именно в том, что диалог создается в design-time - и ему в качестве родителя устанавливается MainForm



Выполнение из Form2 следующего кода

TOpenDialog *OpenDialog1 = new TOpenDialog(this);
OpenDialog1->Execute();
delete OpenDialog1;

дало тот же самый результат.

Злобная какая-та проблема, хотя казалось бы ерунда.

1
11 декабря 2011 года
kot_
7.3K / / 20.01.2000
ну тогда остается установить вторую форму поверх вручную.
49K
11 декабря 2011 года
execoma
10 / / 13.06.2009
Цитата: kot_
ну тогда остается установить вторую форму поверх вручную.



Если делать так:

OpenDialog1->Execute();
SetForegroundWindow(Form2->Handle);

то Form2 провалится за Form1, а после закрытия OpenDialog вернется на передний план, но это все равно ерунда.

Дело в том, что это не учебный, а боевой проект. OpenDialog это только пример. На деле Form2 это редактор с Ribbon-интерфейсом, в котором вызываются различные второстепенные окошки типа выбора цвета, вставка таблицы путем заполнения кубиков и т.д. и впринципе нельзя, чтобы такие "полуокна" вызывали исчезновение Form2 хоть и на время.

327
11 декабря 2011 года
UserNet2008
748 / / 03.04.2010
в С++ TopMost
Определяет, отображается ли данная
форма поверх других форм, для которых
данное свойство не имеет значение true.

this->TopMost = true;
49K
11 декабря 2011 года
execoma
10 / / 13.06.2009
Цитата: UserNet2008
в С++ TopMost
Определяет, отображается ли данная
форма поверх других форм, для которых
данное свойство не имеет значение true.
this->TopMost = true;



Я не нашёл такого свойства, но как я понял по описанию это this->FormStyle = fsStayOnTop. В этом случае для Form2 будет вообще все плохо, оно хоть и не проваливается под Form1, но под него самого проваливается OpenDialog))

327
11 декабря 2011 года
UserNet2008
748 / / 03.04.2010
[COLOR="blue"]fsMDIChild[/COLOR] Эта форма является дочерней MDI формой
[COLOR="blue"]fsMDIForm[/COLOR] Эта форма является основным окном MDI приложения
[COLOR="blue"]fsNormal[/COLOR] Это обычная форма. Она не является ни родительским ни дочерним MDI окном
[COLOR="blue"]fsStayOnTop[/COLOR] Эта форма является самой верхней формой в приложении если стиль других форм не установлен в [COLOR="#ff8c00"]fsStayOnTop[/COLOR]
[COLOR="#006400"]Значение по умолчанию — fsNormal[/COLOR]

this->FormStyle = fsNormal;

// сделать родительским окном рабочий стол
[COLOR="red"]//[/COLOR] Params.WndParent = GetDesktopWindow();:confused:

Цитата:
то Form2 провалится за Form1, а после закрытия OpenDialog вернется на передний план, но это все равно ерунда.



Form2->FormStyle = fsNormal; //пробуем так
Form2->FormStyle = fsStayOnTop;

49K
11 декабря 2011 года
execoma
10 / / 13.06.2009
Я же это и попробовал в предыдущем сообщении. fsNormal ничего не дает, он и был по умолчанию, а fsStayOnTop приводит к тому, что OpenDialog появляется под окном. В самом первом сообщении аттач с проектом, там всего 2 формы и OpenDialog. Если открыта и Form1 и Form2, то при OpenDialog Form1 выносится на передний план, хотя вызов OpenDialog был с Form2. FormStyle решить проблему не удалось.

Я попытался даже перехватывать и блокировать сообщения приходящие в Form1, в надежде определить и заблокировать то сообщение, которое заставляет Form1 активизироваться. Попробовал блокировать по очереди все сообщения приходящие в Form1 после OpenDialog->Execute(), ничего не вышло, все равно лезет на передний план.
10
11 декабря 2011 года
Freeman
3.2K / / 06.03.2004
Цитата: execoma
Я попытался даже перехватывать и блокировать сообщения приходящие в Form1, в надежде определить и заблокировать то сообщение, которое заставляет Form1 активизироваться.


Вообще-то, за это время можно было бы всё 10 раз посмотреть отладчиком, собрав с отладочными DCU.

Помнится, VCL перещёлкивал окна внутренней служебной процедурой, описанной в Forms. Она называлась как-то вроде AlignTopMosts или как-то так. Уже не пишу на Delphi.

Это родовое пятно VCL -- отдельное окно нулевой размерности у Application -- именно его кнопка видна на панели задач. А главная форма окном приложения в терминах Windows не является. Видимо, даже в XE всё по-прежнему.

Давным-давно в какой-то программе мы делали интерфейс а-ля Office 2000. Упёрлись в то же самое. По-моему, всё решилось написанием своего аналога AlignTopMosts и кучей обходного кода, чтобы стандартный не вызывался. Или плюнули, не помню уже.

327
11 декабря 2011 года
UserNet2008
748 / / 03.04.2010
Borland C++ Builder нет под рукой, а в VS2011 такой проблемы нет что в VB, С#, C++, this->TopMost = true;
задается проблема тянется от сюда [COLOR="red"]Form2->Show();[/COLOR]

Вот еще
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
[COLOR="blue"]#include "Unit1.h"[/COLOR]
#include "Unit2.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm2 *Form2;
//---------------------------------------------------------------------------
__fastcall TForm2::TForm2(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm2::CreateParams(Controls::TCreateParams &Params)
{
TForm::CreateParams(Params);

// создать кнопку в таскбаре для Form 2
Params.ExStyle = WS_EX_APPWINDOW;
}
//---------------------------------------------------------------------------
void __fastcall TForm2::Button1Click(TObject *Sender)
{
[COLOR="blue"] Form1->FormStyle = fsMDIForm;
Form2->FormStyle = fsMDIChild;[/COLOR]

OpenDialog1->Execute();

[COLOR="blue"]Form1->FormStyle = fsNormal;
Form2->FormStyle = fsStayOnTop;[/COLOR]
}
49K
13 декабря 2011 года
execoma
10 / / 13.06.2009
Вот что получается :)


;(((
327
13 декабря 2011 года
UserNet2008
748 / / 03.04.2010
Это правда C#
{
form2 = new Form2();[COLOR="red"] пробуйте так[/COLOR]
form2.Show();//метод для отображения второй формы
}
327
13 декабря 2011 года
UserNet2008
748 / / 03.04.2010
Что форма2 лезит под кнопку формы1?
49K
13 декабря 2011 года
execoma
10 / / 13.06.2009
Цитата:
Что форма2 лезит под кнопку формы1?


Да)

И создавать форму 2 пробовал самостоятельно. Все так же.

Только что удалось решить проблему!!!

В настройках проекта отключил автоматическое создание окон. Написал создание окон самостоятельно в сердце программы в Project.cpp.

Код:
WINAPI _tWinMain(HINSTANCE, HINSTANCE, LPTSTR, int)
{
    try
    {
        Application->Initialize();
        Application->MainFormOnTaskBar = true;
        Form1 = new TForm1(Application);
        Form2 = new TForm2(Application);
        Form1->ShowModal();
        Application->Run();
        delete Form1;
        delete Form2;
    }
    catch (Exception &exception)
    {
        Application->ShowException(&exception);
    }
    catch (...)
    {
        try
        {
            throw Exception("");
        }
        catch (Exception &exception)
        {
            Application->ShowException(&exception);
        }
    }
    return 0;
}
//---------------------------------------------------------------------------


Пример работает, но пока не ясна корректность такого решения, т.к. программа выполняется фактически без

Application->Run();

т.к. Application->Run(); стартует только после закрытия Form1 и тут же завершается, и вообще если Run закомментировать, то все также работает. Что это за функция и зачем она нужна я пока не разобрался, возможно она выполняет тоже самое что я написал вокруг неё, а может и ещё что-то..
327
13 декабря 2011 года
UserNet2008
748 / / 03.04.2010
Пробуйте найти другую версию редактора ВС++ или хотя переустановите что имеете. У вас ось не х64. Может в настройках что найти?
в help что пишет?
49K
13 декабря 2011 года
execoma
10 / / 13.06.2009
С другой версией не вариант, все лицензионное, да и думаю, что все там будет также.
Попробую переписать что получилось в боевой проект, там будет сразу понятно есть какие-то проблемы с таким решением или все нормально, т.к. приложение достаточно большое и тяжелое с кучей окон и third-part компонентов (под Intel Core i5 2500k и SSD накопителем build занимает 1.35 минуты). По результатам отпишусь
14
13 декабря 2011 года
Phodopus
3.3K / / 19.06.2008
Делайте MainForm-ой десятую левую форму приложения, делайте ее 0-го размера и манипулируйте логикой основной формы самостоятельно
327
15 декабря 2011 года
UserNet2008
748 / / 03.04.2010
Посмотрите может поможет правда это Delpvi
49K
15 декабря 2011 года
execoma
10 / / 13.06.2009
Всем спасибо! Я решил проблему путем создания трех форм. Та которая главная, её нужно вообще не отображать, она нужна только для того чтобы была. Зато теперь остальные окна ведут себя как надо, т.к. они на равных правах относительно друг друга :)
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог