Форум программистов, компьютерный форум, киберфорум
Наши страницы
C++ и WinAPI
Войти
Регистрация
Восстановить пароль
 
Рейтинг: Рейтинг темы: голосов - 15, средняя оценка - 4.67
kravam
быдлокодер
1706 / 893 / 105
Регистрация: 04.06.2008
Сообщений: 5,524
#1

Не могу отправить окну сообщение WM_PAINT (точнее, не могу перерисовать окно) - C++ WinAPI

17.01.2013, 11:14. Просмотров 2411. Ответов 18
Метки нет (Все метки)

Смотрите оконную функцию она в самом низу. Всё остальное шаблонный код по созданию окна.

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
#include <windows.h>
#include <stdio.h>
 
 
LRESULT CALLBACK WndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
 
char ClassName       []= "SimpleWinClass";
char AppName         []= "Our First Window";
char OurText         []= "Win32 assembly is great and easy!";
 
 
//У айзелиона это есть, а тут оказалось ненужным
//Но по идее не нужны, но оставлю уж
HINSTANCE hInstance;
LPSTR CommandLine;
 
//+++++++++++++++++++++++++++++++++
 
int WINAPI WinMain (HINSTANCE hInst,
                    HINSTANCE hPrevInst,
                    LPSTR CmdLine,
                    int CmdShow)
 
{
 
 hInstance= hInst;
 CommandLine= CmdLine;
 
 //структуры
 WNDCLASSEX wc;
 MSG msg;
 HWND hwnd;
 
 //инициализация;
 wc.cbSize= sizeof (WNDCLASSEX);
 wc.style= CS_HREDRAW | CS_VREDRAW;
 wc.lpfnWndProc= WndProc;
 wc.cbClsExtra= 0;
 wc.cbWndExtra= 0;
 wc.hInstance= hInst;
 wc.hbrBackground= (HBRUSH)(COLOR_WINDOW+1);
 wc.lpszMenuName= 0;
 wc.lpszClassName= ClassName;
 wc.hIcon= LoadIcon (NULL,IDI_APPLICATION);
 wc.hIconSm= 0;
 wc.hCursor= LoadCursor (NULL,IDC_ARROW);
 
 
 RegisterClassEx (&wc);
 
 hwnd= CreateWindowEx (0, ClassName,AppName,\
           WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,\
           CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,\
           hInst,NULL);
 
 ShowWindow (hwnd,SW_SHOWNORMAL);
 UpdateWindow (hwnd);
 
 
 
 while (true) {
   if (!GetMessage (&msg,NULL,0,0))
     break;
    TranslateMessage (&msg);
    DispatchMessage  (&msg);
 }
 return msg.wParam;
}
 
//+++++++++++++++++++++++++++++++++++++++++++++++
//+++++++++++++++++++++++++++++++++++++++++++++++
//+++++++++++++++++++++++++++++++++++++++++++++++
//Оконая функция
LRESULT CALLBACK WndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
  static int i= 0;
  HDC hdc;
PAINTSTRUCT ps;
RECT rect;
  
  if (uMsg==WM_DESTROY) 
      PostQuitMessage (0);
  else if (uMsg==WM_PAINT) {
      printf ("%d\n", i);
      hdc= BeginPaint (hWnd, &ps);
      GetClientRect (hWnd, &rect);
      DrawText (hdc, &OurText[i++],-1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
      EndPaint (hWnd, &ps);
      UpdateWindow (hWnd);
  }
  else 
      return DefWindowProc (hWnd,uMsg,wParam,lParam );      
  return 0;
}
НУ и чё это за отрисовка? Я создаю консольное приложение, наряду с окном показывается консоль. Я вожу окном туда-сюда по рабочему столу, а оно ни фига не перерисовывается! Как была изначальная надпись так и остаётся. Если окно скрыть чем-нибудь, а потом снова показать- надпись изменится, да. Но такая отрисовка мне даром не нужна. Мне надо чтобы на моих глазах явно отрисовывалось, как задумываю.

Спасибо, кто откликнется.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
17.01.2013, 11:14
Я подобрал для вас темы с готовыми решениями и ответами на вопрос Не могу отправить окну сообщение WM_PAINT (точнее, не могу перерисовать окно) (C++ WinAPI):

Отправить сообщение окну
Нужно отправить сообщение о нажатие левой кнопки мыши окну Spy++ при клике в...

WM_PAINT перестает перерисовывать окно
Добрый вечер!!! Такая проблема...делаю игру на Visual C++...игра типа...

Перерисовать окно
Я нарисовал с помощью WinApi график функции мне надо чтобы при изменении...

перерисовать окно
В общем у меня есть вм_паинт case WM_PAINT: ///////////// PAINTSTRUCT ps;...

Перерисовать окно, где указывать InvalidateRect?
Помогите, не могу понять где нужно указать InvalidateRect(wnd,0,NULL); чтобы...

Не могу найти окно
всем привет! собственно код и вопрос: ....... wndChild =...

18
Digit@ll
Brainsbreaker
888 / 366 / 51
Регистрация: 01.02.2011
Сообщений: 1,586
17.01.2013, 13:45 #2
Тебе нужна бегущая строка? Тогда WM_PAINT не подойдет, как по мне. Ближе к вечеру постродаю с этим, если чё.
0
Somebody
2799 / 1610 / 251
Регистрация: 03.12.2007
Сообщений: 4,211
Завершенные тесты: 3
17.01.2013, 14:24 #3
i слишком быстро выходит за пределы строки, а старый текст нигде не стирается. А так всё более-менее.
И UpdateWindow просто вызывает WndProc с WM_PAINT, если есть неперерисованные части, так что в обработчике WM_PAINT он точно не нужен.
0
volvo
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
25616 / 17169 / 6827
Регистрация: 22.10.2011
Сообщений: 30,364
Записей в блоге: 6
17.01.2013, 14:59 #4
Цитата Сообщение от Somebody Посмотреть сообщение
А так всё более-менее.
За исключением того, что WM_PAINT не отсылается окну, пока оно не изменит размеры или не перекроется другим окном. Посему при простом таскании окно обновляться не будет, пока не обработано WM_MOVING, с вызовом в его обработчике InvalidateRect.
0
kravam
быдлокодер
1706 / 893 / 105
Регистрация: 04.06.2008
Сообщений: 5,524
17.01.2013, 15:50  [ТС] #5
Цитата Сообщение от Somebody Посмотреть сообщение
И UpdateWindow просто вызывает WndProc с WM_PAINT, если есть неперерисованные части, так что в обработчике WM_PAINT он точно не нужен.
поторопился с этим, согласен. Вызов UpdateWindow прост сводится к посылке WM_PAINT, как я понял.

Цитата Сообщение от UI Посмотреть сообщение
что WM_PAINT не отсылается окну, пока оно не изменит размеры или не перекроется другим окном
неправда ваша. Если бы WM_PAINT не посылалсь окну, я бы спросил- почему WM_PAINT не отсылается. В том-то и дело, что отсылается. Вы потаскайте, потаскайте окно ПОВЕРХ других окон поинтенсивнее за рамку. Только проект пусть будет консольным. Очень неплохо видно счётчик обработчиков вызовов WM_PAINT

Короче всё решилось так:

C++
1
2
3
4
5
6
7
8
9
  else if (uMsg==WM_PAINT) {
      printf ("%d\n", i);
      InvalidateRect (hWnd, NULL, true);
      hdc= BeginPaint (hWnd, &ps);
      GetClientRect (hWnd, &rect);
      DrawText (hdc, &OurText[i++],-1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
      EndPaint (hWnd, &ps);
      UpdateWindow (hWnd);
  }
Тупо вставил вызов InvalidateRect (hWnd, NULL, true); и всё на этом.
Но на самом деле это фигня, я это сделал неосмысленнно, я угадал. Почему я вижу это решение корявым? А вот:
"Функция InvalidateRect или InvalidateRgn может косвенно генерировать сообщения WM_PAINT для Ваших окон."
Понимаете, то есть я в обработчике WM_PAINT вызываю InvalidateRect, которая в свою очередь, отправляет WM_PAINT, в обработчике которого вызывается InvalidateRect, которая в свою очередь отправляет WM_PAINT, в обработчике которого вызывается...

Короче, как у меня стек не рушится- непонятно.
0
Somebody
2799 / 1610 / 251
Регистрация: 03.12.2007
Сообщений: 4,211
Завершенные тесты: 3
17.01.2013, 16:59 #6
Цитата Сообщение от kravam Посмотреть сообщение
Понимаете, то есть я в обработчике WM_PAINT вызываю InvalidateRect, которая в свою очередь, отправляет WM_PAINT, в обработчике которого вызывается InvalidateRect, которая в свою очередь отправляет WM_PAINT, в обработчике которого вызывается...
Вообще WM_PAINT в большинстве случаев не посылается непосредственно в очередь, а вместо этого ставится флажок, при наличии которого и отсутствии сообщений в очереди генерируется WM_PAINT.
(Аналогично, например, WM_QUIT: если после PostQuitMessage послать ещё какое-то сообщение, то оно обработается до WM_QUIT.)
Цитата Сообщение от kravam Посмотреть сообщение
Короче, как у меня стек не рушится- непонятно.
И даже если бы оно шло прямо в очередь, то тогда проблемы были бы с очередью, а не со стеком - тут же рекурсии нет.
0
volvo
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
25616 / 17169 / 6827
Регистрация: 22.10.2011
Сообщений: 30,364
Записей в блоге: 6
17.01.2013, 17:26 #7
Цитата Сообщение от kravam Посмотреть сообщение
Вы потаскайте, потаскайте окно ПОВЕРХ других окон поинтенсивнее за рамку.
И чего я вижу после двухминутного таскания, (если только не вылез за границы десктопа, соответственно, окно частично скрыто, и потом, когда оно заново отображается полностью, и его надо обновить)? А вот что: в консольном окне один-единственный ноль как был, так и есть.

Так что не надо вот этих вот догадок. Я знаю, как оно работает. Если задан стиль CS_HREDRAW | CS_VREDRAW - то сообщения не приходят при простом перемещении окна. Сделай размеры окошка в CreateWindow поменьше (скажем, 300x150, чтоб случайно не вылететь), и затаскайся по десктопу, ни одного WM_PAINT-а не увидишь...
0
kravam
быдлокодер
1706 / 893 / 105
Регистрация: 04.06.2008
Сообщений: 5,524
17.01.2013, 20:26  [ТС] #8
Ну хорошо, пусть окну не посылается WM_PAINT когда оно не не посылается. Согласен.

Фактически вы научили меня как таскать окно, чтобы к нему не приходили WM_PAINT и как таскать окно, чтобы к нему приходили WM_PAINT. Спасибо, за науку, а как на счёт вопроса?

Итак, таскаем окно, чтобы к нему приходили WM_PAINT- просто заводя его за края декстопа. Ну вот, собсно и всё. Вопрос- как сделать чтобы при отрисовке оно отрисовалось. То есть я задумываю при каждой обработке WM_PAINT уменьшить строчку на один символ, а не получается. От чего ушли к тому и пришли.

Я нашёл какой-то там способ (выше описал), но хотелось бы всё же осмысленное что-нибудь.
0
Somebody
2799 / 1610 / 251
Регистрация: 03.12.2007
Сообщений: 4,211
Завершенные тесты: 3
17.01.2013, 22:01 #9
А, забыл сказать. При использовании BeginPaint + EndPaint перерисовываются только те части окна, которые надо перерисовать, остальные отсекаются. Если угол окна был загорожен другим окном, то от перерисовки текста в середине результата не будет, потому что эта часть окна не была "испорчена".
Общая логика такая: событие, которое меняет какие-то данные, вызывает InvalidateRect, а получившийся WM_PAINT перерисовывает всё, что надо.
1
Digit@ll
Brainsbreaker
888 / 366 / 51
Регистрация: 01.02.2011
Сообщений: 1,586
17.01.2013, 22:02 #10
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
char OurText         []= "Win32 assembly is great and easy!   ";
 
LRESULT CALLBACK WndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    static int i=0;
    HDC hdc = GetWindowDC (hWnd);
    static RECT rect;
 
    if (uMsg == WM_CREATE)
    {
        SetRect (&rect, 290, 250, 500, 270);
        SetTimer (hWnd, 1, 200, 0);
    }
    else if (uMsg==WM_DESTROY)
        PostQuitMessage (0);
    else if (uMsg == WM_TIMER)
    {
        DrawText (hdc, &OurText[i++], -1, &rect, DT_SINGLELINE | DT_VCENTER);
        if (i == lstrlen(OurText))
        {
            KillTimer (hWnd, 1);
            ReleaseDC (hWnd, hdc);
        }
    }
    else 
        return DefWindowProc (hWnd,uMsg,wParam,lParam );      
    return 0;
}
0
Somebody
2799 / 1610 / 251
Регистрация: 03.12.2007
Сообщений: 4,211
Завершенные тесты: 3
17.01.2013, 22:09 #11
Digit@ll, GetWindowDC - всегда, а ReleaseDC - в if'е - не айс.

Добавлено через 3 минуты
Да и отрисовывать по WM_TIMER не очень хорошо, потому что если потом будет WM_PAINT, то он или затрёт всё, или в нём придётся писать тот же самый DrawText...
0
Digit@ll
Brainsbreaker
888 / 366 / 51
Регистрация: 01.02.2011
Сообщений: 1,586
17.01.2013, 22:17 #12
Да, возможно, я думал об этом, тогда добавь и ему статичности. И оставьте уже WM_PAINT, он безобидный, если его не трогать.
0
kravam
быдлокодер
1706 / 893 / 105
Регистрация: 04.06.2008
Сообщений: 5,524
17.01.2013, 22:24  [ТС] #13
Somebody,
Тогда я угадал с этим кодом.
C++
1
2
3
4
5
6
7
8
9
else if (uMsg==WM_PAINT) {
      printf ("%d\n", i);
      InvalidateRect (hWnd, NULL, true);
      hdc= BeginPaint (hWnd, &ps);
      GetClientRect (hWnd, &rect);
      DrawText (hdc, &OurText[i++],-1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
      EndPaint (hWnd, &ps);
      UpdateWindow (hWnd);
  }
Чё хотел, то и получил.
событие, которое меняет какие-то данные, вызывает InvalidateRect, а получившийся WM_PAINT перерисовывает всё, что надо.
0
Digit@ll
Brainsbreaker
888 / 366 / 51
Регистрация: 01.02.2011
Сообщений: 1,586
18.01.2013, 00:38 #14
Ну и kravam, сам себя хвалит. У-ха-ха.
0
kravam
быдлокодер
1706 / 893 / 105
Регистрация: 04.06.2008
Сообщений: 5,524
18.01.2013, 08:02  [ТС] #15
Я бы по-другому это назвал. Делаю выводы о правильности или неправильности своего решения.
0
Digit@ll
Brainsbreaker
888 / 366 / 51
Регистрация: 01.02.2011
Сообщений: 1,586
18.01.2013, 11:47 #16
Я это к тому, что у тебя мутотень в коде. Но по-правде сказать мне эта возня надоела, давай уже что-то новое.
0
kravam
быдлокодер
1706 / 893 / 105
Регистрация: 04.06.2008
Сообщений: 5,524
18.01.2013, 12:49  [ТС] #17
Это код Айзелиона, если ты знаешь, кто это такой. И я добавил туда лишь
C++
1
InvalidateRect (hWnd, NULL, true);
и изменение строки.
Убирается на раз. Ты не этого не сделал потому, что ты не умеешь. Тебе проще сказать "мутотень" нежели попытаться исправить- а это делается, потворю ОЧЕНЬ ЛЕГКО. Да и не факт, что править надо.

Вердикт: мутотень у меня в коде всяко лучше чем мутотень у тебя в голове.
0
Digit@ll
21.01.2013, 13:19
  #18

Не по теме:

Да, золотые слова. Пусть мутотень будет у тебя в кодах, чем у меня в голове. Всех благ.

0
kravam
21.01.2013, 13:32  [ТС]     Не могу отправить окну сообщение WM_PAINT (точнее, не могу перерисовать окно)
  #19

Не по теме:

Цитата Сообщение от Digit@ll Посмотреть сообщение
Пусть мутотень будет у тебя в кодах, чем у меня в голове.
не пойдёт. Пусть у тебя в голове будет мутотень, а у меня в кодах не будет. Привет.

0
21.01.2013, 13:32
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
21.01.2013, 13:32
Привет! Вот еще темы с ответами:

Не могу заставить окно двигаться
Здравствуйте! Есть такое задание: Написать приложение, обладающее ...

Не могу создать окно WINAPI
#define WIN32_LEAN_AND_MEAN #include&lt;cstdlib&gt; #include&lt;math.h&gt;...

не могу отправить сообщение
Здравствуйте! Пытаюсь написать чат на С под Linux. Имеется клиент и сервер. В...

Не могу отправить сообщение на почту mail.ru
Не могу отправить сообщение с помощью SMTP. У меня стоит 10 версия indy. Также...


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

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

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru