Форум программистов, компьютерный форум, киберфорум
C/C++: WinAPI
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.55/40: Рейтинг темы: голосов - 40, средняя оценка - 4.55
0 / 0 / 1
Регистрация: 13.11.2015
Сообщений: 10

WM_SIZE и перерисовка окна

02.05.2016, 11:23. Показов 7713. Ответов 5
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Добрый день. Всех с праздником!
Возникла такая проблема: при максимизации\минимизации или любом другом изменении размеров окна, или при перетаскивании всего окна за границы экрана из клиентской части пропадает все нарисованные примитивы. В какой-то теме здесь на форуме человеку с аналогичным вопросом посоветовали при получении сообщения WM_SIZE делать InvalidateRect с ложным булевым параметром. У меня такое решение не сработало. Подскажите, пожалуйста, как с этим бороться?
Вот кусок кода, где по идее это все должно быть реализовано.
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
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    int wmId, wmEvent;
    PAINTSTRUCT ps;
    HDC hdc;
 
    switch (message)
    {
    case WM_COMMAND:
        wmId = LOWORD(wParam);
        wmEvent = HIWORD(wParam);
        // Разобрать выбор в меню:
        switch (wmId)
        {
        case IDM_ABOUT:
            DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
            break;
        case IDM_DIA:
            DialogBox(hInst, MAKEINTRESOURCE(IDD_DIA), hWnd, Dia);
            break;
        case IDM_EXIT:
            DestroyWindow(hWnd);
            break;
            // тут новые пункты
    
        case WM_SIZE:
            InvalidateRect(hWnd, NULL, false);
                break;
             case ID_ELLIPSE:
            InvalidateRect(hWnd, NULL, false);
            figure = 1;
            break;
        case ID_CIRCLE:
            InvalidateRect(hWnd, NULL, false);
            figure = 2;
            break;
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
02.05.2016, 11:23
Ответы с готовыми решениями:

Как помимо сообщения WM_SIZE получить размеры клиентской области окна?
Как помимо сообщения WM_SIZE получить размеры клиенсткой области окна?

Перерисовка окна
Рисую в окне мышкой, естественно через события мыши, но стоит только развернуть окно на весь экран или задвинуть часть окна за экран как...

Перерисовка окна
Помогите реализовать двойную буферизацию для программы. У меня следующая проблема: написан код который рисует изображение с помощью...

5
 Аватар для rao
903 / 424 / 159
Регистрация: 02.04.2014
Сообщений: 1,206
03.05.2016, 07:45
Invalidate - это всего лишь способ вручную вызвать обработчик WM_PAINT, (то есть вызов перерисовки окна). Поэтому, что бы такой способ работал, рисование фигур должно происходить в WM_PAINT. А где у тебя WM_PAINT?
Судя по всему ты рисуешь свои фигуры просто в контекст окна при нажатии кнопки. Конечно при перерисовке окно очищая фон всё сотрет и они пропадут.
И как то странно у тебя "case WM_SIZE" затесался в switch от "case WM_COMMAND". Его там быть не должно.
0
0 / 0 / 1
Регистрация: 13.11.2015
Сообщений: 10
03.05.2016, 17:22  [ТС]
Спасибо большое, что ответили!!!

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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    int wmId, wmEvent;
    PAINTSTRUCT ps;
    HDC hdc;
 
    switch (message)
    {
    case WM_COMMAND:
        wmId = LOWORD(wParam);
        wmEvent = HIWORD(wParam);
        // Разобрать выбор в меню:
        switch (wmId)
        {
        case IDM_ABOUT:
            DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
            break;
        case IDM_DIA:
            DialogBox(hInst, MAKEINTRESOURCE(IDD_DIA), hWnd, Dia);
            break;
        case IDM_EXIT:
            DestroyWindow(hWnd);
            break;
            // тут новые пункты
    
        case ID_ELLIPSE:
            InvalidateRect(hWnd, NULL, false);
            figure = 1;
            break;
        case ID_CIRCLE:
            InvalidateRect(hWnd, NULL, false);
            figure = 2;
            break;
 
        case ID_PIE:
            InvalidateRect(hWnd, NULL, false);
            figure = 3;
            break;
 
        case ID_HALF:
            InvalidateRect(hWnd, NULL, false);
            figure = 4;
            break;
 
        case ID_FLASH:
            InvalidateRect(hWnd, NULL, false);
            figure = 5;
            break;
 
        case ID_DRAW:
            InvalidateRect(hWnd, NULL, false);
            figure = 6;
            break;
        case ID_TEXT:
            InvalidateRect(hWnd, NULL, false);
            figure = 7;
            break;
        case ID_CLEAR:
            InvalidateRect(hWnd, NULL, false);
            figure = 8;
            break;
        case ID_SOLPEN:
            pen1 = 1;
            break;
        case ID_DASPEN:
            pen1 = 2;
            break;
        case ID_DOTPEN:
            pen1 = 3;
            break;
        case ID_SOLBRU:
            brush1 = 1;
            break;
        case ID_VERBRU:
            brush1 = 2;
            break;
        case ID_HORBRU:
            brush1 = 3;
            break;
        case ID_CROBRU:
            brush1 = 4;
            break;
        case ID_DIABRU:
            brush1 = 5;
            break;
        case ID_TULBRU:
            brush1 = 6;
            break;
        case ID_COLPEN:
            c = 1;
            InvalidateRect(hWnd, NULL, false);
            colorp = getColor(hWnd, 0);
            break;
        case ID_COLBRU:
            c = 2;
            InvalidateRect(hWnd, NULL, false);
            colorb = getColor(hWnd, 0);
            break;
        case ID_CLRSCR:
            InvalidateRect(hWnd, NULL, true);
            break;
 
        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
        }
 
        break;
 
    case WM_LBUTTONDOWN:
            draw = true;
            x = LOWORD(lParam);
            y = HIWORD(lParam);
            ox = x;
            oy = y;
            InvalidateRect(hWnd, NULL, false);
        break;
 
    case WM_MOUSEMOVE:
        if (draw) {
            ox = x;
            oy = y;
            x = LOWORD(lParam);
            y = HIWORD(lParam);
            InvalidateRect(hWnd, NULL, false);
        }
        break;
 
    case WM_LBUTTONUP:
        draw = false;
        break;
 
    case WM_PAINT:
        hdc = BeginPaint(hWnd, &ps);
        // TODO: добавьте любой код отрисовки...
        HPEN pen;
        HBRUSH brush;
 
        if ((c == 1) && (ChooseColor(&cc) == true)) rgbCurrent = cc.rgbResult;
        
        switch (pen1)
        {
        case 1:
            pen = CreatePen(PS_SOLID, width, colorp);
            SelectObject(hdc, pen);
            break;
        case 2:
            pen = CreatePen(PS_DASH, 1, colorp);
            SelectObject(hdc, pen);
            break;
        case 3:
            pen = CreatePen(PS_DOT, 1, colorp);
            SelectObject(hdc, pen);
            break;
        }
 
        switch (brush1)
        {
        case 1:
            brush = CreateSolidBrush(colorb);
            SelectObject(hdc, brush);
            break;
        case 2:
            brush = CreateHatchBrush(HS_VERTICAL, colorb);
            SelectObject(hdc, brush);
            break;
        case 3:
            brush = CreateHatchBrush(HS_HORIZONTAL, colorb);
            SelectObject(hdc, brush);
            break;
        case 4:
            brush = CreateHatchBrush(HS_CROSS, colorb);
            SelectObject(hdc, brush);
            break;
        case 5:
            brush = CreateHatchBrush(HS_DIAGCROSS, colorb);
            SelectObject(hdc, brush);
            break;
        }
 
        switch (figure)
        {
        case 1:
            if(draw)
                Ellipse(hdc, x-75, y-100, x + 75, y + 100);
            break;
        case 2:
            if (draw)
                Ellipse(hdc, x-100, y-100, x + 100, y + 100);
            break;
        case 3:
            if (draw)
                Pie(hdc, x-100, y-150, x + 100, y + 150, x + 170, y + 100, x + 100, y + 150);
            break;
        case 4:
            if (draw)
                Chord(hdc, x-50, y-50, x + 50, y + 50, x - 50, y - 50, x + 50, y + 50);
            break;
        case 5:
            if (draw)
            {
//------------------------ Желтая внешняя окружность --------------------------------------------------
                brush = CreateSolidBrush(RGB(255, 223, 0));
                SelectObject(hdc, brush);
                Ellipse(hdc, x-50, y-50, x+50 , y+50);                          
//-----------------------------------------------------------------------------------------------------
 
//------------------------ Белая внутренняя окружность ------------------------------------------------
                brush = CreateSolidBrush(RGB(255, 255, 255));
                SelectObject(hdc, brush);
                Ellipse(hdc, x - 45, y - 45, x + 45, y + 45);
//-----------------------------------------------------------------------------------------------------
 
//------------------------ Желтая молния --------------------------------------------------------------
                brush = CreateSolidBrush(RGB(255, 223, 0));
                SelectObject(hdc, brush);
 
                POINT a[10];
 
                a[0].x = x + 30;                                                
                a[0].y = y + 70;                                                
                                                                            
                a[1].x = x - 20;
                a[1].y = y + 10;
                
                a[2].x = x;
                a[2].y = y + 10;
                
                a[3].x = x - 20;
                a[3].y = y - 20;
                
                a[4].x = x;
                a[4].y = y - 20;
 
                a[5].x = x - 30;
                a[5].y = y - 70;
                
                a[6].x = x + 20;
                a[6].y = y - 10;
                
                a[7].x = x;
                a[7].y = y - 10;
 
                a[8].x = x + 20;
                a[8].y = y + 20;
 
                a[9].x = x;
                a[9].y = y + 20;
 
                Polygon(hdc, a, 10);
//-----------------------------------------------------------------------------------------------------
            }
        break;
        case 6:
            if (draw)
            {
                MoveToEx(hdc, ox, oy, NULL);
                LineTo(hdc, x, y);
            }
            break;
        case 7:
            if (draw)
            {
                Font1 = CreateFont(width, 0, 0, 0, 0, 0, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, NULL);
                SelectObject(hdc, Font1);
                SetTextColor(hdc, RGB(red, green, blue));
                SetBkColor(hdc, RGB(255, 255, 255));
                TextOut(hdc, 100, 100, ttext, _tcsclen(ttext));
            }
            break;
        case 8:
            if (draw)
            {
                pen = CreatePen(PS_SOLID, width, RGB(255, 255, 255));
                SelectObject(hdc, pen);
                brush = CreateSolidBrush(RGB(255, 255, 255));
                SelectObject(hdc, brush);
                Ellipse(hdc, x - 50, y - 50, x + 50, y + 50);
            }
        }
 
        /*pen = CreatePen(PS_DOT, 3, RGB(250, 250, 0));
        SelectObject(hdc, pen);
        brush = CreateSolidBrush(RGB(250, 0, 0));
        SelectObject(hdc, brush);
        //Rectangle(hdc, 100, 100, 400, 300);
        Chord(hdc, 200, 400, 300, 500, 270, 480, 230, 420);
        brush = CreateSolidBrush(RGB(0, 0, 250));
        SelectObject(hdc, brush);
        POINT a[5];
        a[0].x = 100;
        a[0].y = 100;
        a[1].x = 225;
        a[1].y = 150;
        a[2].x = 75;
        a[2].y = 150;
        a[3].x = 200;
        a[3].y = 100;
        a[4].x = 150;
        a[4].y = 200;
        Polygon(hdc, a, 5);
        brush = CreateSolidBrush(RGB(250, 250, 200));
        SelectObject(hdc, brush);
        Ellipse(hdc, 500, 100, 700, 300);
        Ellipse(hdc, 900, 150, 750, 350);
        pen = CreatePen(PS_DOT, 3, RGB(250, 250, 0));
        SelectObject(hdc, pen);
        brush = CreateSolidBrush(RGB(250, 250, 0));
        SelectObject(hdc, brush);
        Pie(hdc, 500, 400, 700, 700, 670, 500, 600, 550); */
        EndPaint(hWnd, &ps);
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}
Вот полная функция WndProc. Рисую вроде в WM_PAINT.
Насчет case WM_SIZE - я когда у преподавателя попросил помощи по этому же вопросу, он сказал сделай обработку сообщения WM_SIZE, а на мой вопрос, куда впихнуть эту обработку, он сказал в switch(wmId). Ну, как сказал, я так и сделал.
0
 Аватар для rao
903 / 424 / 159
Регистрация: 02.04.2014
Сообщений: 1,206
04.05.2016, 19:36
Да, рисуешь правильно, а WM_SIZE не может быть внутри WM_COMMAND. То ли препод чего-то сморозил, то ли ты не так его понял. Это же самостоятельное сообщение, а не подпараметр WM_COMMAND'а. Поэтому твой обработчик WM_SIZE никогда не срабатывает и передается в DefWindowProc. (Поставь в нем брекпоинт и сам это увидишь.)

Сделай обработчик WM_SIZE отдельным, т.е. таким же как обработчики WM_MOUSEMOVE, WM_PAINT и др. (в смысле вынеси его из switch'а WM_COMMAND), тогда должно заработать.

Если не получится очисти проект, заархивируй и прикрепи во вложение, а то так на пальцах трудно разбираться.
1
0 / 0 / 1
Регистрация: 13.11.2015
Сообщений: 10
04.05.2016, 20:32  [ТС]
Да это я, наверное, не правильно понял преподавателя. Сделал как вы сказали и все действительно получилось, правда теперь появилась новая проблема: при изменении размеров окна теперь сохраняется только последний нарисованный объект, т.е., если я подряд нарисую 10 эллипсов, то потом, изменив размер окна, на экране сохранится только последний 10-ый эллипс.

Прикрепил проект.
Вложения
Тип файла: rar Win32Project1_2.rar (2.28 Мб, 18 просмотров)
0
 Аватар для Izual
143 / 122 / 21
Регистрация: 13.11.2012
Сообщений: 1,564
04.05.2016, 21:09
Цитата Сообщение от IOPROC Посмотреть сообщение
на экране сохранится только последний 10-ый эллипс
Потому что у тебя единичная переменная под фигуру ( figure ), а нужно сделать динамический массив.
Твой WM_PAINT перерисовывает только ту часть окна, которая стала поверх другого. Т.е. то что у тебя сохраняются старые фигуры - это иллюзия, на самом деле фигуры уже нет, если ты частично сдвинеш другое окно на своё, то увидиш, что останутся части старых фигур.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
04.05.2016, 21:09
Помогаю со студенческими работами здесь

Перерисовка окна
Рисую эллипс. При нажатии не системной клавиши, он должен перерисовываться с другими размерами. В общем, он не перерисовывается сразу. Но...

Перерисовка окна
Дано: оконная программа, главное окно разделено пополам двумя дочерними. Рисуешь в одном дочернем окне, рисунок автоматически дублируется...

Перерисовка окна
Здравствуйте. Нужно создать приложение, которое в случайном порядке скрывает кнопки калькулятора. Приложение написал, кнопки исчезают, но...

Перерисовка окна
Подскажите, как по нажатию клавиши перерисовать окно

Перерисовка окна
Есть небольшой графический редактор с элементами меню. После изменения окна ( минимизация, максимизация) пропадает все нарисованное. Как...


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

Или воспользуйтесь поиском по форуму:
6
Ответ Создать тему
Новые блоги и статьи
http://iceja.net/ математические сервисы
iceja 20.01.2026
Обновила свой сайт http:/ / iceja. net/ , приделала Fast Fourier Transform экстраполяцию сигналов. Однако предсказывает далеко не каждый сигнал (см ограничения http:/ / iceja. net/ fourier/ docs ). Также. . .
http://iceja.net/ сервер решения полиномов
iceja 18.01.2026
Выкатила http:/ / iceja. net/ сервер решения полиномов (находит действительные корни полиномов методом Штурма). На сайте документация по API, но скажу прямо VPS слабенький и 200 000 полиномов. . .
Расчёт переходных процессов в цепи постоянного тока
igorrr37 16.01.2026
/ * Дана цепь постоянного тока с R, L, C, k(ключ), U, E, J. Программа составляет систему уравнений по 1 и 2 законам Кирхгофа, решает её и находит переходные токи и напряжения на элементах схемы. . . .
Восстановить юзерскрипты Greasemonkey из бэкапа браузера
damix 15.01.2026
Если восстановить из бэкапа профиль Firefox после переустановки винды, то список юзерскриптов в Greasemonkey будет пустым. Но восстановить их можно так. Для этого понадобится консольная утилита. . .
Сукцессия микоризы: основная теория в виде двух уравнений.
anaschu 11.01.2026
https:/ / rutube. ru/ video/ 7a537f578d808e67a3c6fd818a44a5c4/
WordPad для Windows 11
Jel 10.01.2026
WordPad для Windows 11 — это приложение, которое восстанавливает классический текстовый редактор WordPad в операционной системе Windows 11. После того как Microsoft исключила WordPad из. . .
Classic Notepad for Windows 11
Jel 10.01.2026
Old Classic Notepad for Windows 11 Приложение для Windows 11, позволяющее пользователям вернуть классическую версию текстового редактора «Блокнот» из Windows 10. Программа предоставляет более. . .
Почему дизайн решает?
Neotwalker 09.01.2026
В современном мире, где конкуренция за внимание потребителя достигла пика, дизайн становится мощным инструментом для успеха бренда. Это не просто красивый внешний вид продукта или сайта — это. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru