Форум программистов, компьютерный форум, киберфорум
C++ Builder
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.68/40: Рейтинг темы: голосов - 40, средняя оценка - 4.68
Диссидент
Эксперт C
 Аватар для Байт
27714 / 17332 / 3810
Регистрация: 24.12.2010
Сообщений: 38,978

Постоянная перерисовка формы при изменении ее размеров

25.09.2012, 14:27. Показов 7648. Ответов 17
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Есть форма. (на ней некий график, не суть) Иногда хочется изменить ее размеры, потащив за рамку, например. Но при этом форма постоянно перерисовывается (довольно трудоемкая операция - открытие файла, масштабирование и тп). Пользователь получает раздражающее и бестолковое мигание. Как с этим бороться? (Бюльдер-6).
Где-то я читал, что можно запретить перерисовку формы на какое-то время, но забыл где. А может быть это относилось не к Бюльдеру, а к Qt? И как это сделать в случае плавного изменения размеров? Как поймать начало изменения и конец?
Наверное, есть очень простое решение проблемы... для тех, кто знает...
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
25.09.2012, 14:27
Ответы с готовыми решениями:

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

Масштабирование рисунка при изменении размеров формы
Есть форма, в которой находится изображение на канве. Требуется чтобы при изменении размеров формы изображение масштабировалось. Как это...

Изменение размеров кнопок при изменении самой формы
Когда я увеличиваю форму, то размер кнопок увеличивается неимоверно и они накладываются друг на друга, как сделать чтобы они оставались...

17
 Аватар для Gremlin
519 / 307 / 58
Регистрация: 30.07.2008
Сообщений: 607
25.09.2012, 16:26
C++
1
Form1->DoubleBuffered = true; // часто помогает избавиться от мигания
0
Диссидент
Эксперт C
 Аватар для Байт
27714 / 17332 / 3810
Регистрация: 24.12.2010
Сообщений: 38,978
25.09.2012, 17:46  [ТС]
Цитата Сообщение от Gremlin Посмотреть сообщение
C++
1
Form1->DoubleBuffered = true; // часто помогает избавиться от мигания
Не, не помогает. Вообще ведет себя странно. При движении рамки что-то рисует, а когда движение останавливается - пусто

Добавлено через 8 минут
Может быть, дело в том, что график я рисую не на форме, а на ее PaintBox.
Попытка поставить
C++
1
PaintBox1->DoubleBuffered=true
ни к чему хорошему не привела, тк это не его член...

Добавлено через 17 минут
Очень странно ведет себя эта DoubleBuffered...
Оставляет следы от прошлых прорисовок (это уже на форме)
Пока держу мышь на рамке - график на PaintBox1 виден. Отпустил - он стирается...
Нет, ребята, все не так...
0
 Аватар для BRcr
4043 / 2333 / 292
Регистрация: 03.02.2011
Сообщений: 5,066
Записей в блоге: 10
26.09.2012, 20:06
Невольно возникает недоумение - почему в процесс масштабирования графика вовлечена работа с файлами?
И как рисуешь, прямо на канву визуального контрола?
0
Диссидент
Эксперт C
 Аватар для Байт
27714 / 17332 / 3810
Регистрация: 24.12.2010
Сообщений: 38,978
26.09.2012, 20:40  [ТС]
Цитата Сообщение от BRcr Посмотреть сообщение
Невольно возникает недоумение - почему в процесс масштабирования графика вовлечена работа с файлами?
Ну, это совершенно не важно. Не суть. Да, храню график в файле, по старой досовской привычке память берегу. Масштабирование - чтобы график занимал почти все поле окна. Ерунда. Меня интересует другое. Почему при каждом движении рамки (OnResize) хоть на пиксель, график заново перерисовывается. И как с этим бороться.

Цитата Сообщение от BRcr Посмотреть сообщение
И как рисуешь, прямо на канву визуального контрола?
Да!
Но найдено очень смешное решение. В настройках рабочего стола - эффекты - снять галочку "Рисовать окно при перемещении" (или что-то в этом роде). И все стало хорошо! Значит у винды есть эта возможность, какая-то функция WinApi. Но вот я ее к сожалению, не знаю.
Наверное, можно и через таймер как-то, и через хук отпускания мыши, и еще как-то почесать левой ногой правое ухо.
Но ведь есть простая функция! Почему ее от меня скрывают?
Облазил кучу форумов, потрошил Гугл - все набрали в рот воды.
0
 Аватар для BRcr
4043 / 2333 / 292
Регистрация: 03.02.2011
Сообщений: 5,066
Записей в блоге: 10
26.09.2012, 20:56
Все логично, в общем-то, бережем память - теряем скорость и наоборот.

Если график хранится в виде изображения, то рисовать его на контрол напрямую вполне корректно. Если же, однако, в файле хранятся данные о том, как его рисовать, и прорисовка линий и прочего идет ручками с помощью методов канвы, то рисовать надо на канве временного tbitmap. Это азбука.

В винде есть возможность не отображать содержимое окна при изменении его формы и положения, но возможность эта может распространяться лишь на все окна сразу. Система просто не заточена на индивидуальное поведение относительно конкретного окна.
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33195 / 21491 / 8233
Регистрация: 22.10.2011
Сообщений: 36,879
Записей в блоге: 12
26.09.2012, 21:03
Цитата Сообщение от Байт Посмотреть сообщение
И все стало хорошо!
Это тебе стало хорошо. Потому что исправлять свои "старые досовские привычки" не надо. А пользователю оно на фиг не надо: имеет он на борту, к примеру, 4 Гб памяти, а производитель ПО ему заявляет: "а мне по барабану, сколько её у тебя. Чтоб моя программа работала ты должен всего лишь снять галочку". А я не заказывал такой кордебалет, меня как-то всё устраивает и без этой галочки. Галочка-то воздействует на все окна, а не только на твоё приложение

Не по теме:

А зачем, интересно, у меня 16 Гб памяти? Чтоб вот также какой-нибудь программист экономил байты и из-за этого тормозила перерисовка?

0
26.09.2012, 23:09

Не по теме:

Цитата Сообщение от UI Посмотреть сообщение
А зачем, интересно, у меня 16 Гб памяти?
Вообще-то и впрямь интересно - зачем? Солишь потихоньку?:D

0
Диссидент
Эксперт C
 Аватар для Байт
27714 / 17332 / 3810
Регистрация: 24.12.2010
Сообщений: 38,978
27.09.2012, 10:10  [ТС]
Цитата Сообщение от BRcr Посмотреть сообщение
Если график хранится в виде изображения, то рисовать его на контрол напрямую вполне корректно. Если же, однако, в файле хранятся данные о том, как его рисовать, и прорисовка линий и прочего идет ручками с помощью методов канвы, то рисовать надо на канве временного tbitmap. Это азбука.
Слушайте, давайте вынесем разговоры о том, как следует рисовать - прямо на канве или через Bitmap в отдельный топик!
Я очень сожалею, что в стартовом посте в скобках говорил о содержательной части задачи. О графиках, масштабировании, файлах и прочем. Это я для наглядности, что ли написал. Но проблема вовсе не в этом. Тут я уж справлюсь кое-как. Эта азбука мне известна и не составляет сложностей...

Цитата Сообщение от BRcr Посмотреть сообщение
В винде есть возможность не отображать содержимое окна при изменении его формы и положения, но возможность эта может распространяться лишь на все окна сразу. Система просто не заточена на индивидуальное поведение относительно конкретного окна.
Во! Об этом и речь!

Добавлено через 7 минут

Не по теме:

Это одна из неуклюжек Винды. А вообще-то этих неуклюжек - тьма! Может быть это от того, что набор функций WinAPI ведет свою родословную от Windows 3.1 ?
А вообще-то надо привести в порядок набор неуклюжек, с которыми мне приходилось сталкиваться, да и выложить на форум. Навярняка, многим есть что добавить. Но это конечно уже другая тема...:)

0
 Аватар для BRcr
4043 / 2333 / 292
Регистрация: 03.02.2011
Сообщений: 5,066
Записей в блоге: 10
27.09.2012, 14:09
А если сделать paintbox немасштабируемым, то бишь вырубить ему align и анкеры, моргание исчезает?
1
Диссидент
Эксперт C
 Аватар для Байт
27714 / 17332 / 3810
Регистрация: 24.12.2010
Сообщений: 38,978
27.09.2012, 15:52  [ТС]
Цитата Сообщение от BRcr Посмотреть сообщение
А если сделать paintbox немасштабируемым, то бишь вырубить ему align и анкеры, моргание исчезает?
Судя по всему, исчезнет. Но мне этот вариант совсем не подходит, тк основное требование заказчика - график во весь экран.
0
 Аватар для BRcr
4043 / 2333 / 292
Регистрация: 03.02.2011
Сообщений: 5,066
Записей в блоге: 10
27.09.2012, 16:43
Дык, я и не предлагаю совсем отключать. Можно отключать на время ресайза - в событии onresize отключаем масштабирование и запускаем таймер, проверяющий факт изменения размеров; если размеры не меняются в течение определенного времени, таймер включает масштабирование обратно.
Костыль, конечно, но моргание, как ты выразился, - судя по всему, исчезнет.
1
Диссидент
Эксперт C
 Аватар для Байт
27714 / 17332 / 3810
Регистрация: 24.12.2010
Сообщений: 38,978
27.09.2012, 18:02  [ТС]
Цитата Сообщение от BRcr Посмотреть сообщение
Дык, я и не предлагаю совсем отключать. Можно отключать на время ресайза - в событии onresize отключаем масштабирование и запускаем таймер, проверяющий факт изменения размеров; если размеры не меняются в течение определенного времени, таймер включает масштабирование обратно.
Костыль, конечно, но моргание, как ты выразился, - судя по всему, исчезнет.
Спасибо за участие!
Я тут придумал 2 возможных костыля.
1. Через таймер. OnResize включает таймер и блокирует перерисовку. По срабатыванию таймера блокировка снимается и вызывается Paint. Тут что может быть? User во время движения рамки задумался на 500 мсек - и бух - получает новую картинку. Не страшно.
2. Опять же OnResize блокирует перерисовку. А OnMouseUp ее разблокирует. Но OnMouseUp не данной формы, а всего приложения, типа ловушки (теорию хуков читал, но на практике не применял ни разу, даже любопытно попробовать)
Но все это - костыли, что обидно, так как навярняка есть и более прямой путь.
Сейчас это все лежит не в главном русле моей работы. Но вот поеду в деревню на последние денечки бабьего лета, прочищу бризом заплесневевшие мозги, может и придумается какой костыль (а главное - построится). Ночи начинаются рано, глядишь - может чего и накропается.
О результатах, буде они будут, обязательно всех оповещу.
0
 Аватар для Whatson
9 / 9 / 0
Регистрация: 18.11.2011
Сообщений: 55
24.12.2014, 16:55
Продолжая интересную тему...
Товарищи знатоки, а как же из C++ установить опцию "Отображать содержимое окон при перетаскивании"? Или хотя бы проверить её флаг?
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33195 / 21491 / 8233
Регистрация: 22.10.2011
Сообщений: 36,879
Записей в блоге: 12
24.12.2014, 17:56
За это в реестре отвечает ключ HKEY_CURRENT_USER\Control Panel\Desktop\DragFullWindows. Как прочитать значение из реестра (или установить его) - информации тьма...
1
Диссидент
Эксперт C
 Аватар для Байт
27714 / 17332 / 3810
Регистрация: 24.12.2010
Сообщений: 38,978
24.12.2014, 20:33  [ТС]
Whatson, как тут уже было сказано, изменяя в реестре этот ключ, ты меняешь поведение для всех программ на компе. А юзеру это надо?
0
 Аватар для Whatson2
8 / 8 / 1
Регистрация: 06.09.2014
Сообщений: 52
28.12.2014, 00:00
volvo, Байт, спасибо за ответ! Но, "чем дальше в лес, тем толще партизаны"... Расскажу всю предысторию:
На(!) форме есть некий компонент (TAdvSmoothDock), который при её перетаскивании, когда на компе отключено "Отображать содержимое окон при перетаскивании", не перерисовывается в конечное состояние (то есть не перемещается в соответствующее конечное положение на форме). Но его можно заставить это сделать дополнительным кликом по нему, когда он застрял на экране.
Потом оказалось, если включить "Отображать содержимое окон при перетаскивании" и опять отключить, то всё работает как положено до следующей перезагрузки XP x86. Я думаю, что эта проблема не критична для программы, но неприятна.


Также в режиме не "Отображать содержимое окон при перетаскивании" возник следующий интересный вопрос:
перестаёт работать залипание "формы" у краёв рабочего стола. Ни задаваемое в design-time опцией ScreenSnap/SnapBuffer, ни перехватом сообщения WM_WINDOWPOSCHANGING(которое наступает) с дальнейшей поправкой позиции формы в
C++
1
(WINDOWPOS*)Msg.LParam
"Формы" в кавычках, т.к. отображается некий прямоугольник вместо неё. Я копал в сторону NCCALCSIZE_PARAMS, но похоже это не тот прямоугольник!
Подскажите, кто знает, как им управлять при перетаскивании?
(То, что можно сделать прилипание видно на примере клиента Steam. Или они там всё сами рисовали? =*)
0
 Аватар для Whatson2
8 / 8 / 1
Регистрация: 06.09.2014
Сообщений: 52
01.01.2015, 13:25
Второй вопрос решил. Рамкой этой можно управлять через
C++
1
RECT *wp = (RECT*)Msg.LParam;  ,
отлавливая сообщение WM_MOVING.
полный код
Как я переписал прилипание формы, оооочень громоздко, но работает =*):
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
static struct _sPos {  //структурка нужна именно для случая прилипания рамки, а не формы
    bool bInL;         //в обл. прилипания у левой границы
    bool bOutL;       //вне обл. прилипания у левой границы
    bool bInT;         //в обл. прилипания у верхней границы
    bool bOutT;       //вне обл. прилипания у верхней границы
    bool bInR;         //в обл. прилипания у правой границы
    bool bOutR;       //вне обл. прилипания у правой границы
    bool bInB;         //в обл. прилипания у нижней границы
    bool bOutB;       //вне обл. прилипания у нижней границы
    int  dL;
    int  dT;             //соответствующие смещения курсора (при перемещении формы), 
    int  dR;             //когда форма "залипла" у соответствующего края
    int  dB;
} _Pos;
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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
void __fastcall TMainForm::CatchDragMove(TMessage &Msg)
{
    TForm::Dispatch(&Msg);
    switch (Msg.Msg)
    {
        case WM_WINDOWPOSCHANGING: { //Обычное прилипание
            RECT rcWorkArea = {0};
            if(SystemParametersInfo(SPI_GETWORKAREA, 0, &rcWorkArea, FALSE)) {
                WINDOWPOS *wp = (WINDOWPOS*)Msg.LParam;
                if(std::abs(wp->x - rcWorkArea.left) <= VO_SENSWORKAREA)
                    wp->x = rcWorkArea.left;
                if(std::abs(wp->y - rcWorkArea.top) <= VO_SENSWORKAREA)
                    wp->y = rcWorkArea.top;
                if(std::abs(wp->cx + wp->x - rcWorkArea.right) <= VO_SENSWORKAREA)
                    wp->x = rcWorkArea.right - wp->cx;
                if(std::abs(wp->cy + wp->y - rcWorkArea.bottom) <= VO_SENSWORKAREA)
                    wp->y = rcWorkArea.bottom - wp->cy;
            }
            }
            break;
        case WM_MOVING:                  //Прилипание рамки
            {
            RECT rcWorkArea = {0};
            if(SystemParametersInfo(SPI_GETWORKAREA, 0, &rcWorkArea, FALSE)) {
                RECT *wp = (RECT*)Msg.LParam;
                if(wp != NULL) {
                    if(!_Pos.bOutL && std::abs(wp->left - rcWorkArea.left) <= VO_SENSWORKAREA) {
                        int dl = wp->left - rcWorkArea.left;
                        wp->left = rcWorkArea.left;
                        wp->right -= dl;
                        if(!_Pos.bInL) {
                            _Pos.dL = Controls::Mouse->CursorPos.X;
                            _Pos.bInL = true;
                            _Pos.bOutL = false;
                        }
                    }
                    if(_Pos.bInL && std::abs(Controls::Mouse->CursorPos.X - _Pos.dL) > VO_SENSWORKAREA) {
                        _Pos.bOutL = true;
                        _Pos.bInL = false;
                    }
                    if(!_Pos.bOutT && std::abs(wp->top - rcWorkArea.top) <= VO_SENSWORKAREA) {
                        int dt = wp->top - rcWorkArea.top;
                        wp->top = rcWorkArea.top;
                        wp->bottom -= dt;
                        if(!_Pos.bInT) {
                            _Pos.dT = Controls::Mouse->CursorPos.Y;
                            _Pos.bInT = true;
                            _Pos.bOutT = false;
                        }
                    }
                    if(_Pos.bInT && std::abs(Controls::Mouse->CursorPos.Y - _Pos.dT) > VO_SENSWORKAREA) {
                        _Pos.bOutT = true;
                        _Pos.bInT = false;
                    }
                    if(!_Pos.bOutR && std::abs(wp->right - rcWorkArea.right) <= VO_SENSWORKAREA) {
                        int dr = wp->right - rcWorkArea.right;
                        wp->right = rcWorkArea.right;
                        wp->left -= dr;
                        if(!_Pos.bInR) {
                            _Pos.dR = Controls::Mouse->CursorPos.X;
                            _Pos.bInR = true;
                            _Pos.bOutR = false;
                        }
                    }
                    if(_Pos.bInR && std::abs(Controls::Mouse->CursorPos.X - _Pos.dR) > VO_SENSWORKAREA) {
                        _Pos.bOutR = true;
                        _Pos.bInR = false;
                    }
                    if(!_Pos.bOutB && std::abs(wp->bottom - rcWorkArea.bottom) <= VO_SENSWORKAREA) {
                        int db = wp->bottom - rcWorkArea.bottom;
                        wp->bottom = rcWorkArea.bottom;
                        wp->top -= db;
                        if(!_Pos.bInB) {
                            _Pos.dB = Controls::Mouse->CursorPos.Y;
                            _Pos.bInB = true;
                            _Pos.bOutB = false;
                        }
                    }
                    if(_Pos.bInB && std::abs(Controls::Mouse->CursorPos.Y - _Pos.dB) > VO_SENSWORKAREA) {
                        _Pos.bOutB = true;
                        _Pos.bInB = false;
                    }
                    if(std::abs(wp->left - rcWorkArea.left) > VO_SENSWORKAREA)
                        _Pos.bOutL = false;
                    if(std::abs(wp->top - rcWorkArea.top) > VO_SENSWORKAREA)
                        _Pos.bOutT = false;
                    if(std::abs(wp->right - rcWorkArea.right) > VO_SENSWORKAREA)
                        _Pos.bOutR = false;
                    if(std::abs(wp->bottom - rcWorkArea.bottom) > VO_SENSWORKAREA)
                        _Pos.bOutB = false;
                }
            }
            }
            break;
    }
}
Наверное можно и короче написать...
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
01.01.2015, 13:25
Помогаю со студенческими работами здесь

Изменение размера динамических объектов при изменении размеров формы
Доброго времени суток, у меня такой вопрос: Имеется главная форма. на ней размещен Scrollbox который прибит якорями к правому и...

Перерисовка при изменении размеров формы
Доброго утра! Я рисую несколько прямоугольников в случайном местоположении и случайного размера. При изменении размеров окна, происходит...

Перерисовка всех объектов формы при изменении ее размеров
создаю форму при помощи API следующим образом: // Заполняем структуру TWndClassEx with Wc do begin style := CS_HREDRAW...

Автоматическое изменение размеров компонентов при изменении размеров формы
Приветствую. Подскажите. Форма по умолчанию при запуске приложения открывается по центру. Если необходимо развернуть форму на весь экран,...

Изменение размеров элементов, сохраняя пропорции, при изменении размеров самой формы
Как изменять размеры элементов, сохраняя пропорции, при изменении размеров самой формы?


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

Или воспользуйтесь поиском по форуму:
18
Ответ Создать тему
Новые блоги и статьи
Кто-нибудь знает, где можно бесплатно получить настольный компьютер или ноутбук? США.
Programma_Boinc 26.12.2025
Кто-нибудь знает, где можно бесплатно получить настольный компьютер или ноутбук? США. Нашел на реддите интересную статью под названием «Кто-нибудь знает, где получить бесплатный компьютер или. . .
Thinkpad X220 Tablet — это лучший бюджетный ноутбук для учёбы, точка.
Programma_Boinc 23.12.2025
Рецензия / Мнение/ Перевод Нашел на реддите интересную статью под названием The Thinkpad X220 Tablet is the best budget school laptop period . Ниже её машинный перевод. Thinkpad X220 Tablet —. . .
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Как объединить две одинаковые БД Access с разными данными
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru