Перерисовка окна...

Тема в разделе "WASM.BEGINNERS", создана пользователем glukker, 8 июл 2008.

  1. glukker

    glukker New Member

    Публикаций:
    0
    Регистрация:
    14 фев 2008
    Сообщения:
    72
    Здравствуйте, подскажите возможно ли такое... Вообщем в программе в функции обработки сообщений окна обработчик WM_PAINT следущего вида:
    Код (Text):
    1. case WM_PAINT:
    2. {
    3.      hdc = BeginPaint(hwnd, &ps);
    4.  
    5.      EndPaint(hwnd, &ps);
    6. } break;
    В другом обработчике, например, WM_COMMAND вызываю TextOut (GetDC и ReleaseDC тоже всё как положено), но как только окно перекрывается другим или выходит за пределы экрана текст стирается...
    Возможно ли сделать так чтобы текст не стирался при манипуляции с окном, но не трограя обработчик WM_PAINT? (ну или на крайний случай трогая)

    P/S: припоминаю, что что то надо мутить с виртуальными окнами...
     
  2. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    в WM_PAINT как раз и надо прорисовывать всё. перемести туда вызов TextOut.
    точнее, сделай вывод по флагу. а флаг ставишь в WM_COMMAND

    когда окно затирается другими, вызывается именно WM_PAINT. так что рисовать все нужно там. а что рисовать - это уже надо думать
    если очень хочется рисовать из разных мест, делай в WM_PAINT отрисовку какогонибудь Bitmap-а временного в памяти, А из других мест рисуй в этот битмап и делай инвалидейт виндоу
     
  3. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    Создаётся DC с помощью CreateCompatibleDC, в разных частях программы рисуется в него, а в WM_PAINT делается BitBlt. А чтобы сразу после отрисовки отобразилась новая картинко, делается InvalidateRect.
     
  4. glukker

    glukker New Member

    Публикаций:
    0
    Регистрация:
    14 фев 2008
    Сообщения:
    72
    Great и Booster спасибо за ответы, но немогу понять, чего то я туплю =)
    У меня нарушение доступа выскакивает когда строку получаю в другом обработчике, а вывожу текст в WM_PAINT.
    Поэтому и решил в WM_PAINT не соваться, а сделать так... Вот кусок проги...
    Код (Text):
    1. LRESULT CALLBACK WindowFunc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    2. {
    3.  
    4.     PAINTSTRUCT ps;
    5.     HDC hdc;
    6.  
    7.         static  char  mystring[31];
    8.  
    9.     switch(message)
    10.     {
    11.         case WM_PAINT:
    12.             {
    13.                 hdc = BeginPaint(hwnd, &ps);
    14.  
    15.                 EndPaint(hwnd, &ps);
    16.             } break;
    17.  
    18.         case WM_COMMAND:
    19.             switch (LOWORD(wParam))
    20.             {
    21.                 case BN_CLICKED:
    22.                     if (hButton == (HWND)lParam)
    23.                         {
    24.                            
    25.                                    
    26.                                     hdc = GetDC (hwnd);
    27.                                                                                                     //
    28.                                                                                                     //
    29.                                                                                                     //
    30.                                                                                                     //
    31.                                                                                                     [b]ЗДЕСЬ ВСЯКИЕ МАТЕМАТИЧЕСКИЕ[/b]
    32.                                                                                                     [b]РАСЧЁТЫ[/b]
    33.                                                                                                     //
    34.                                                                                                     //
    35.                                                                                                     //
    36.                                                                                                     //
    37.                                                                                                     //
    38.  
    39.                                     memset (mystring, 0, sizeof(mystring));
    40.                                     wsprintf (mystring, "Диаметр окружности: %d", counter);
    41.  
    42.                                     TextOut(hdc, 10, 120, mystring, strlen(mystring));
    43.  
    44.                                     ReleaseDC (hwnd, hdc);
    45.                                     DeleteDC (hdc);
    46.  
    47.  
    48.                                 }
    49.                         }break;
    50.             } break;
    51.        
    52.         case WM_DESTROY:
    53.             PostQuitMessage(0);
    54.             break;
    55.  
    56.         default:
    57.             return DefWindowProc(hwnd, message, wParam, lParam);
    58.     }
    59.         return 0;
    60. }
     
  5. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    glukker
    Конечно это не верно, так как когда придёт WM_PAINT, придёт трындец. Access Violation надо бороть. А текст и не надо выводить в WM_PAINT, выводить надо задний DC, как я описал выше.
     
  6. glukker

    glukker New Member

    Публикаций:
    0
    Регистрация:
    14 фев 2008
    Сообщения:
    72
    Щас попробую замутить...
     
  7. mikityak

    mikityak Забанен

    Публикаций:
    0
    Регистрация:
    5 авг 2007
    Сообщения:
    160
    Код (Text):
    1. case WM_TIMER:
    2. ...
    3. RedrawWindow(hWnd, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
    4. ...
    [​IMG][​IMG]
     
  8. S_Alex

    S_Alex Alex

    Публикаций:
    0
    Регистрация:
    27 авг 2004
    Сообщения:
    561
    Адрес:
    Ukraine
    А вот этого DeleteDC (hdc) не надо.

    А если WM_PAINT не трогать, то так:


    Код (Text):
    1. invoke  LoadBitmap,hInstance,20
    2. mov hBMP,   eax
    3. invoke  CreatePatternBrush,hBMP
    4. mov hBrush, eax
    5. invoke  SetClassLong,hWin,GCL_HBRBACKGROUND,hBrush
    в этом случае система сама будет прорисовывать указанный hBrush.
    Не юзал с динамическим содержанием, но статической картинкой, выходит хорошо.
     
  9. glukker

    glukker New Member

    Публикаций:
    0
    Регистрация:
    14 фев 2008
    Сообщения:
    72
    Что то пока как то не очень получается :dntknw: Вообще не выводит ничего...
    Код (Text):
    1. LRESULT CALLBACK WindowFunc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    2. {
    3.  
    4.     PAINTSTRUCT ps;
    5.     HDC hdc, hMemDC;
    6.  
    7.         static  char  mystring[31];
    8.  
    9.     switch(message)
    10.     {
    11.         case WM_PAINT:
    12.             {
    13.                 hdc = BeginPaint(hwnd, &ps);
    14.  
    15.                 //а в WM_PAINT делается BitBlt.
    16.                 BitBlt ( hdc, 0, 0, 500, 300, hMemDC, 0, 0, SRCCOPY );
    17.  
    18.                 EndPaint(hwnd, &ps);
    19.             } break;
    20.  
    21.         case WM_COMMAND:
    22.             switch (LOWORD(wParam))
    23.             {
    24.                 case BN_CLICKED:
    25.                     if (hButton == (HWND)lParam)
    26.                         {
    27.                            
    28.                                    
    29.                                     hdc = GetDC (hwnd);
    30.  
    31.                                     //Создаётся DC с помощью CreateCompatibleDC
    32.                                     hMemDC = CreateCompatibleDC(hdc);
    33.  
    34.  
    35.                                     //
    36.                                     //
    37.                                     //   ЗДЕСЬ ВСЯКИЕ МАТЕМАТИЧЕСКИЕ
    38.                                     //                   РАСЧЁТЫ
    39.                                     //
    40.                                     //
    41.        
    42.  
    43.                                     memset (mystring, 0, sizeof(mystring));
    44.                                     wsprintf (mystring, "Диаметр окружности: %d", counter);
    45.  
    46.                                     //в разных частях программы рисуется в него
    47.                                     TextOut(hMemDC, 10, 120, mystring, strlen(mystring));
    48.  
    49.                                     //А чтобы сразу после отрисовки отобразилась новая картинко, делается InvalidateRect.
    50.                                     InvalidateRect(hwnd, NULL, true);
    51.  
    52.                                     ReleaseDC (hwnd, hdc);
    53.                                     DeleteDC (hdc);
    54.  
    55.  
    56.                                 }
    57.                         }break;
    58.             } break;
    59.        
    60.         case WM_DESTROY:
    61.             PostQuitMessage(0);
    62.             break;
    63.  
    64.         default:
    65.             return DefWindowProc(hwnd, message, wParam, lParam);
    66.     }
    67.         return 0;
    68. }
     
  10. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    Во первых делаем:
    Код (Text):
    1. static HDC hMemDC;
    Во вторых надо ещё сделать:
    Код (Text):
    1. static HBITMAP hBitm;
    2. hBitm = CreateCompatibleBitmap(hdc, xSize, ySize);
    3. SelectObject(hMemDC, bitm);
    Так же желательно, но не обязательно создать всякие HPEN, HBRUSH, HFONT, c помощью CreatePen, CreateSolidBrush и CreateFontA. А также выбрать их - SelectObject(hMemDC, hPen) и т.д для всего хозяйства.

    После всей инициализации DС, можно сделать очистку фона например в белый цет.
    Код (Text):
    1. hBrush = CreateSolidBrush(0xffffff);
    2. FillRect(hMemDC, &rect, hBrush);
    Да и инициализацию лучше делать в WM_CREATE.
     
  11. glukker

    glukker New Member

    Публикаций:
    0
    Регистрация:
    14 фев 2008
    Сообщения:
    72
  12. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    glukker
    Код (Text):
    1. hBitm = CreateCompatibleBitmap (hdc, 500, 300);
    2. SelectObject (hMemDC, hBitm);
    Перенеси из WM_PAINT, в WM_COMMAND. Создавать каждый раз новый битмап в WM_PAINT не стоит.

    А вообще вот это дело:
    Код (Text):
    1. hdc = GetDC (hwnd);
    2. hMemDC = CreateCompatibleDC (hdc);
    3. hBitm = CreateCompatibleBitmap (hdc, 500, 300);
    4. SelectObject (hMemDC, hBitm);                      
    5. ReleaseDC (hwnd, hdc);
    Надо перенести в WM_CREATE, по нажатию кнопки только пиши текст.

    DeleteDC (hdc); - не нужен, удали его.
     
  13. glukker

    glukker New Member

    Публикаций:
    0
    Регистрация:
    14 фев 2008
    Сообщения:
    72
    А как его можно перенести в WM_CREATE, если оно обрабатывается при создании окна...
    А выводить TextOut'ом нужно каждый раз когда на кнопку давить буду????
     
  14. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    Поправился, это конечно в обработчике.
    Код (Text):
    1. TextOut(hMemDC, 10, 10, "1234567890", 10);                         
    2. InvalidateRect(hwnd, NULL, true);
    Остальное, то есть инициализацию в WM_CREATE.

    Контекст в памяти и остальную лабуду (шрифты и прочее) нужно создавать один раз, при создании окна.
     
  15. glukker

    glukker New Member

    Публикаций:
    0
    Регистрация:
    14 фев 2008
    Сообщения:
    72
    А ещё вопрос чтобы не париться с размерами в функции CreateCompatibleBitmap как можно получить эти размеры, а то мало ли окно размер поменяет да и смотрится так кривовато...
     
  16. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    Глубоко не вдавался в этот вопрос, просто делал размером максимально возможного для окно. Можно наверно ещё пересоздавать в WM_SIZE и например копировать старый в новый.
     
  17. glukker

    glukker New Member

    Публикаций:
    0
    Регистрация:
    14 фев 2008
    Сообщения:
    72
    Вообще Booster спасибо за помощь всё выводит и не затирается, но после нажатия на кнопку всё окно становится чёрного цвета, почему?
    Код (Text):
    1. LRESULT CALLBACK WindowFunc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    2. {
    3.     PAINTSTRUCT ps;
    4.     HDC hdc;
    5.     static HDC hMemDC;
    6.     static HBITMAP hBitm;
    7.  
    8.     switch(message)
    9.     {
    10.         case WM_PAINT:
    11.             {
    12.                 hdc = BeginPaint(hwnd, &ps);
    13.                
    14.                 BitBlt (hdc, 0, 0, iWinX, iWinY, hMemDC, 0, 0, SRCCOPY);
    15.  
    16.                 EndPaint(hwnd, &ps);
    17.             } break;
    18.  
    19.         case WM_COMMAND:
    20.             switch (LOWORD(wParam))
    21.             {
    22.                 case BN_CLICKED:
    23.                     if (hButton == (HWND)lParam)
    24.                         {
    25.                             hdc = GetDC (hwnd);
    26.                             hMemDC = CreateCompatibleDC (hdc);     
    27.                             hBitm = CreateCompatibleBitmap (hdc, iWinX, iWinY);
    28.                             SelectObject (hMemDC, hBitm);
    29.  
    30.                             TextOut(hMemDC, 10, 120, "1234567890", 10);
    31.                            
    32.                             InvalidateRect(hwnd, NULL, true);
    33.                            
    34.                             ReleaseDC (hwnd, hdc);
    35.                             DeleteDC (hdc);
    36.                         }
    37.             }break;
    38.  
    39.         case WM_DESTROY:
    40.             PostQuitMessage(0);
    41.             break;
    42.  
    43.         default:
    44.                 return DefWindowProc(hwnd, message, wParam, lParam);
    45.     }
    46.         return 0;
    47. }
     
  18. DEEP

    DEEP Андрей

    Публикаций:
    0
    Регистрация:
    27 апр 2008
    Сообщения:
    491
    Адрес:
    г. Владимир
    glukker
    Дело в том, что когда вызывается Инвалидейт, окну приходит сообщение WM_PAINT, и WindowFunc вызывается ещё раз, причём со своим кадром стэка, отличным от кадра той функции, из-под к-рой был сопстно вызван InvalidateRect. Немудрено что hMemDC содержит какуюнить хрень, к делу отношения не имеющую =)

    Впрочем, я С не знаю, и утверждать наверняка не берусь. Что-то смущает меня директива static.
    ++ а битмап надобы освободить... да и DC из-под него тоже.
     
  19. glukker

    glukker New Member

    Публикаций:
    0
    Регистрация:
    14 фев 2008
    Сообщения:
    72
    Это мне посоветовали делать (товарищ Booster), правда я и сам кое где видел такое...
    Все разобрался причина была в отсутствии следущего кода:
    Код (Text):
    1. hBrush = CreateSolidBrush (0xFFFFFF);
    2. SetRect (&Rect, 0, 0, iWinX, iWinY);
    3. FillRect (hMemDC, &Rect, hBrush);
     
  20. glukker

    glukker New Member

    Публикаций:
    0
    Регистрация:
    14 фев 2008
    Сообщения:
    72
    Вот кому интересно полный рабочий код окно которое не затирает выводимый текст...
    Код (Text):
    1. LRESULT CALLBACK WindowFunc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    2. {
    3.     PAINTSTRUCT ps;
    4.     HDC hdc;
    5.     static HDC hMemDC;
    6.     static HBITMAP hBitm;
    7.  
    8.     HBRUSH hBrush;
    9.     RECT Rect;
    10.  
    11.     switch(message)
    12.     {
    13.         case WM_PAINT:
    14.             {
    15.                 hdc = BeginPaint(hwnd, &ps);
    16.                
    17.                 BitBlt (hdc, 0, 0, iWinX, iWinY, hMemDC, 0, 0, SRCCOPY);
    18.  
    19.                 EndPaint(hwnd, &ps);
    20.             } break;
    21.  
    22.         case WM_COMMAND:
    23.             switch (LOWORD(wParam))
    24.             {
    25.                 case BN_CLICKED:
    26.                     if (hButton == (HWND)lParam)
    27.                         {
    28.                             hdc = GetDC (hwnd);
    29.                             hMemDC = CreateCompatibleDC (hdc);     
    30.                             hBitm = CreateCompatibleBitmap (hdc, iWinX, iWinY);
    31.                             SelectObject (hMemDC, hBitm);
    32.  
    33.                             hBrush = CreateSolidBrush (0xFFFFFF);
    34.                             SetRect (&Rect, 0, 0, iWinX, iWinY);
    35.                             FillRect (hMemDC, &Rect, hBrush);
    36.  
    37.                             TextOut(hMemDC, 10, 120, "1234567890", 10);
    38.                            
    39.                             InvalidateRect(hwnd, NULL, true);
    40.                            
    41.                             ReleaseDC (hwnd, hdc);
    42.                             DeleteDC (hdc);
    43.                         }
    44.             }break;
    45.  
    46.         case WM_DESTROY:
    47.             PostQuitMessage(0);
    48.             break;
    49.  
    50.         default:
    51.                 return DefWindowProc(hwnd, message, wParam, lParam);
    52.     }
    53.         return 0;
    54. }