Форум программистов, компьютерный форум, киберфорум
C++ Builder
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.94/18: Рейтинг темы: голосов - 18, средняя оценка - 4.94
18 / 18 / 7
Регистрация: 20.03.2012
Сообщений: 531
1

Drag'n'Dock Мерцание и тормоза при перерисовки рамки окна

07.11.2012, 18:58. Показов 3501. Ответов 10
Метки нет (Все метки)

Подскажите, пожалуйста, как избавиться от мерцания и "тормозов" при рисовании рамки окна, когда оно перемещается пользователем (DragKind = dkDock). А еще лучше, чтобы рисовалась не рамка, а прозрачный прямоугольник, как это, например, происходит при перемещении окон "Structure" (и т.п.) среды разработки Embarcadero 2010.
__________________
Помощь в написании контрольных, курсовых и дипломных работ здесь
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
07.11.2012, 18:58
Ответы с готовыми решениями:

Drag'n'Dock, bsToolWindow и кнопка "фиксации" окна
Подскажите, пожалуйста, как добавить кнопку "фиксации" окна (которая изображается в виде...

Пропадает таб при перетаскивании его в PageControl. Drag & Dock
Здравствуйте! Работаю с Delphi6. Суть проблемы: Я хватаю таб из PageControl и передвигаю его ниже...

Drag Drop Dock
есть ли толковая литература или интересные статьи по этому методу мне нужно просто реализовать...

Drag@Dock и минимзация
Уважаемые форумчане! Делаю программу для создания и выведения на декстоп стикеров. Есть главная...

10
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
31467 / 20514 / 7988
Регистрация: 22.10.2011
Сообщений: 35,647
Записей в блоге: 7
08.11.2012, 01:04 2
Лучший ответ Сообщение было отмечено как решение

Решение

Тормозов не вижу, но если надо рисовать не стандартную рамку, а что-то своё - то в событии OnStartDock создавай DragObject как экземпляр наследника TDragDockObjectEx, в котором реализуй ImageList типа TDragImageList. В конструкторе класса просто создавай сам List, и добавляй в него одну-единственную картинку: синий прямоугольник. То есть, сам наследник будет выглядеть как-то так (тестировалось на RAD 2009) :

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
class TMyDragDock : public TDragDockObjectEx
{
protected:
    virtual TDragImageList* __fastcall GetDragImages(void)
    {
        // зачем Control->Tag - поймешь, когда тебе понадобится
        // в процедуре EraseDragDockImage того контрола, который перетаскивается,
        // имея только указатель на TDragDockObject, вытащить этот самый DragImageList
        return (TDragImageList*)(Control->Tag);
    }
public:
    __fastcall virtual TMyDragDock(TControl* AControl);
    inline __fastcall virtual ~TMyDragDock(void)
    {
        delete ((TDragImageList*)(Control->Tag));
    }
};
 
__fastcall TMyDragDock::TMyDragDock(TControl* AControl) : TDragDockObjectEx(AControl)
{
    TDragImageList* FDragImageList = new TDragImageList(AControl->Width, AControl->Height);
    FDragImageList->Masked = true;
 
    FDragImageList->Clear();
    std::auto_ptr<Graphics::TBitmap> bmp(new Graphics::TBitmap()); // #include <memory>
    bmp->SetSize(AControl->Width, AControl->Height);
    bmp->Canvas->Brush->Style = bsSolid;
    bmp->Canvas->Brush->Color = clBlue;
    bmp->Canvas->FillRect(bmp->Canvas->ClipRect);
 
    FDragImageList->Add(bmp.get(), 0);
    Control->Tag = (int)FDragImageList;
}
Осталось только переопределить в том контроле, который Dock-ится, необходимые методы. Их, на самом деле, всего 2: EraseDragDockImage, чтобы убрать изображение, когда контрол отпущен, и DefaultDockImage, чтобы не рисовать эту злосчастную стандартную рамку. Вот так я это сделал:

<Unit1.h>
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class TPanel : public Extctrls::TPanel
{
protected:
    DYNAMIC void __fastcall EraseDragDockImage(TDragDockObject* DragDockObject)
    {
        if(DragDockObject->Cancelling)
        {
            ((TDragImageList*)(DragDockObject->Control->Tag))->EndDrag();
        }
    }
    DYNAMIC void __fastcall DefaultDockImage(TDragDockObject* DragDockObject, bool Erase)
    {
        // Не рисовать рамку !!!
    }
};
 
class TForm1 : public TForm
{
__published:    // IDE-managed Components
    TPanel *Panel1;
    ::TPanel *Panel2; // Панель с переопределенными методами !!!
    void __fastcall Panel2StartDock(TObject *Sender, TDragDockObject *&DragObject);
 
private:    // User declarations
public: // User declarations
    __fastcall TForm1(TComponent* Owner);
};
, ну, и реализация OnStartDock панели:
C++
1
2
3
4
void __fastcall TForm1::Panel2StartDock(TObject *Sender, TDragDockObject *&DragObject)
{
    DragObject = new TMyDragDock(Panel2);
}
, теперь при перетягивании появляется нормальный синий прямоугольник:
Миниатюры
Drag'n'Dock Мерцание и тормоза при перерисовки рамки окна  
4
18 / 18 / 7
Регистрация: 20.03.2012
Сообщений: 531
08.11.2012, 18:12  [ТС] 3
Сделал все как описано, только не с панелями, а с окнами. Есть два нюанса: 1) Прямоугольник рисуется начиная с местоположения мыши, а не с местоположения окна. 2) Прямоугольник вообще не рисуется, когда окно находиться над док-понелью и готово "причалить".
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
31467 / 20514 / 7988
Регистрация: 22.10.2011
Сообщений: 35,647
Записей в блоге: 7
08.11.2012, 18:26 4
Цитата Сообщение от znseday Посмотреть сообщение
Прямоугольник вообще не рисуется, когда окно находиться над док-понелью и готово "причалить".
В этот момент должно работать OnDockOver приемника, то есть, когда форма готова причалить, рисовать место причаливания должен не источник, а приемник.

Вот тут я показывал (правда на Дельфи), как подсветить "причал": Как перетащить и подсветить область, куда перетаскиваем объект
1
18 / 18 / 7
Регистрация: 20.03.2012
Сообщений: 531
08.11.2012, 19:07  [ТС] 5
Вот тут я показывал (правда на Дельфи), как подсветить "причал":
Такой способ для меня не подойдет, т.к. на панели уже есть пару причаленных окна, а я хочу на нее причалить еще и третье (т.е. произойдет перегруппировка окон). Как подсветить именно ту область, где окажется причаленное окно?
(Хочу реализовать такой же интерфейс, как в среде разработки Embarcadero Studio)
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
31467 / 20514 / 7988
Регистрация: 22.10.2011
Сообщений: 35,647
Записей в блоге: 7
08.11.2012, 20:45 6
Цитата Сообщение от znseday Посмотреть сообщение
Как подсветить именно ту область, где окажется причаленное окно?
Ты вообще у приемника пробовал включать DragMode = dmAutomatic? Попробуй. Тогда система сама будет делать то, что тебе нужно. Прямоугольник, в который будет помещен новый элемент, хранится в Source.DockRect.

Тебе останется в Panel1DockOver просто отрисовывать прямоугольник, заданный этим самым Source.DockRect. Любым способом. Хочешь - создавай временную канву для панели, хочешь - рисуй через WinAPI.
0
18 / 18 / 7
Регистрация: 20.03.2012
Сообщений: 531
09.11.2012, 14:05  [ТС] 7
Цитата Сообщение от UI Посмотреть сообщение
Ты вообще у приемника пробовал включать DragMode = dmAutomatic? Попробуй.
Попробовал, не помогло. А вот кол-во глюков (которых и без того много) увеличилось, в частности, теперь не работают автоматические сплиттеры изменений размеров окон (когда несколько окон причалено на одну панель и они делят между собой пространство). Причем либо вылетает Access Violation, либо Exception c пустой строкой.

Добавлено через 1 час 0 минут
Цитата Сообщение от znseday Посмотреть сообщение
Сделал все как описано, только не с панелями, а с окнами. Есть два нюанса: 1) Прямоугольник рисуется начиная с местоположения мыши, а не с местоположения окна.
Как можно исправить эту ситуацию?
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
31467 / 20514 / 7988
Регистрация: 22.10.2011
Сообщений: 35,647
Записей в блоге: 7
09.11.2012, 18:43 8
znseday, вот эту программку погоняй, тут по-моему, все реализовано, о чем ты спрашивал. Я ее тестировал под XP, собиралось всё под 2009-ым Билдером.
Вложения
Тип файла: zip dock_test.zip (11.6 Кб, 80 просмотров)
0
18 / 18 / 7
Регистрация: 20.03.2012
Сообщений: 531
09.11.2012, 21:17  [ТС] 9
Все супер, но после нескольких причаливаний и отчаливаний (общее число окон всегда не больше трех), все равно слетает с Access Vialation когда изменяешь размеры автоматически создаваемыми сплиттерами.
У меня Studio 2010, Win7.

Добавлено через 17 минут
Я обратил внимание, что в Вашем проекте все DragMode = dmManual. Это ли влияет на то, что нельзя изменить порядок расположения причаленных окон (т.е. например причалено два окна, одно расположено сверху, другое снизу). Я хочу мышкой перетащить верхнее окно на место нижнего, чтобы они поменялись местами. В Вашем проекте это можно сделать только если вытащить одно окно (двойным нажатием мыши по заголовку) и причалить его заново на новое место.

Добавлено через 40 минут
Цитата Сообщение от znseday Посмотреть сообщение
Я хочу мышкой перетащить верхнее окно на место нижнего, чтобы они поменялись местами. В Вашем проекте это можно сделать только если вытащить одно окно (двойным нажатием мыши по заголовку) и причалить его заново на новое место.
Задал DragMode = dmAutomatic для Dock-окна, теперь работает так, как хочу, но при отчаливании рисуется гигантский прямоугольник размером с DockPanel и рисуется не там где нужно. Попробую исправить.

Вопрос оффтопом: как перехватить событиe OnClick для pin-button? Или вопрос иначе: как скрывать и отображать всю DockTabSet, когда она пуста и когда появляются на вкладке новое окно, соответсвенно?
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
31467 / 20514 / 7988
Регистрация: 22.10.2011
Сообщений: 35,647
Записей в блоге: 7
09.11.2012, 21:45 10
Цитата Сообщение от znseday Посмотреть сообщение
как скрывать и отображать всю DockTabSet, когда она пуста и когда появляются на вкладке новое окно, соответсвенно?
У DockTabSet есть события OnTabAdded и OnTabRemoved:

C++
1
2
3
4
5
6
7
8
9
void __fastcall TForm1::DockTabSet1TabRemoved(TObject *Sender)
{
    DockTabSet1->Visible = DockTabSet1->Tabs->Count;
}
 
void __fastcall TForm1::DockTabSet1TabAdded(TObject *Sender)
{
    DockTabSet1->Visible = True;
}
0
18 / 18 / 7
Регистрация: 20.03.2012
Сообщений: 531
10.11.2012, 21:42  [ТС] 11
Цитата Сообщение от znseday Посмотреть сообщение
Задал DragMode = dmAutomatic для Dock-окна, теперь работает так, как хочу, но при отчаливании рисуется гигантский прямоугольник размером с DockPanel и рисуется не там где нужно. Попробую исправить.
Вместо
C++
1
2
    pos.x -= this->Left;
    pos.y -= this->Top;
Нужно написать
C++
1
2
3
4
    TRect rect;
    GetWindowRect(this->Handle, &rect);
    pos.x -= rect.left;
    pos.y -= rect.top;
Тогда все работает как нужно.

Добавлено через 8 минут
Кстати, Access Vailation вылетает, когда меняешь размеры окна в режиме его привязке к DockTabSet, срываешь, причаливаешь, а затем опять пытаешься изменить размеры.

Добавлено через 23 часа 4 минуты
По поводу Access Vailation. Простой эксперимент. Запускаем проект, добавляем два окна, причаливаем их на панель (одно слева, второй справа, появляется вертикальный сплиттер), немного изменяем размеры окон (немного сдвигам сплиттер влево/вправо). Раскрываем главное окно на весь экран. Дотрагиваемся до сплиттера - Access Vailation.

Добавлено через 23 минуты
Все. Разобрался. Access Vailation срабатывает, когда сплиттер отпускаешь (отпускаешь нажатую кнопку мыши) над pin-buttin'ом. Даже сама Embarcadero Studio (2010) ломается, когда делаешь то же самое с ее интерфейсом.
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
10.11.2012, 21:42

ТЕСТ НА DELPHI (DRAG&DOCK)
Мне нужно разработать программу на Delphi Тест на технологии Drag and Drop(скорее всего Drag and...

Drag & Dock для динамически созданных форм
Здравствуйте! Использую Delphi 6. По кнопке создаю несколько форм, в их onCreate прописываю для...

Мерцание при перерисовке окна
Я хочу заменить одно из дочерних окон Outlook своим. Делаю это так: отлавливаю дескрипторы, мое...

Мерцание окна при работе макроса
Здравствуйте! Как убрать мерцание окна, если макрос работает с несколькими книгами? Он сначала...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2022, CyberForum.ru