Перерисовка окна при момощи InvalidateRect

Тема в разделе "WASM.BEGINNERS", создана пользователем assch, 1 июл 2011.

  1. assch

    assch Member

    Публикаций:
    0
    Регистрация:
    17 мар 2011
    Сообщения:
    208
    Не подскажете как перерисовать окно.
    А именно окошко которое как видно в коде создаётся в приложении при нажатии
    на левую кнопку мышки (WM_LBUTTONDOWN) которое в свою очередь показывает картинку
    файл которого например как у меня в коде перетаскивается мышкой в окно приложения
    при помощи команды (WM_DROPFILES)
    Картинка показывается нормально только она не перерисованная, то есть при некоторых
    обстоятельствах (например зону картинки закроет другое окно) картинка исчезает.
    То есть зону картинки нужно перерисовать. Насколько я знаю это делается например
    с помощью фукнкции InvalidateRect.
    А вот как именно с этим у меня тормоза
    Подскажите пожалуйста.

    Код (Text):
    1. .if uMsg == WM_DROPFILES
    2.  
    3. invoke DragQueryFile,wParam,0,addr buffer,sizeof buffer
    4. invoke MultiByteToWideChar,0,0,addr buffer,-1,addr Unicod,addr Char
    5. invoke GdipLoadImageFromFile,addr Unicod, addr hImag
    6. invoke GdipGetImageWidth, hImag, addr sWidth
    7. invoke GdipGetImageHeight, hImag, addr sHeight
    8.  
    9. .elseif uMsg == WM_LBUTTONDOWN
    10.  
    11. invoke  DestroyWindow,hGif
    12. invoke CreateWindowEx,0,addr Static,0,WS_CHILD,50,50,sWidth,sHeight,hWinFun,0,0,0
    13. mov hGif,eax
    14. invoke ShowWindow,hGif,SW_SHOWNORMAL
    15. invoke UpdateWindow,hGif
    16.  
    17. invoke GetDC, hGif
    18. mov hDC, eax
    19. invoke GdipCreateFromHDC, hDC, addr pGraphics
    20. invoke GdipDrawImage, pGraphics,hImag,0,0
     
  2. dinoweb

    dinoweb Дмитрий

    Публикаций:
    0
    Регистрация:
    12 окт 2005
    Сообщения:
    129
    Адрес:
    Россия. Красноярск
    InvalidateRect инициирует отправку окну сообщения WM_PAINT, которое должно обрабатывать ваше приложение, и перерисовывать окно. Сама собой картинка не перерисуется.

    WM_PAINT автоматически отправляется системой при необходимости отрисовки участка (или всего окна). Оно поступает через функцию GetMessage, а далее функцией DispatchMessage передаётся обработчику окна.

    Вы должны установить обработчик сообщения для вашего Static окошка, например функцией SetWindowProc (или создавать окно на основе вашего собственного класса, для которого будет задан ваш обработчик), и написать в нём что-то вроде этого:
    Код (Text):
    1. .elseif uMsg == WM_PAINT
    2.  
    3. // рисуем картинку
    больше нигде рисовать не нужно, окно должно само себя рисовать.
     
  3. assch

    assch Member

    Публикаций:
    0
    Регистрация:
    17 мар 2011
    Сообщения:
    208
    Если я в коде в конце поставлю функцию InvalidateRect

    Код (Text):
    1. invoke GetDC, hGif
    2. mov hDC, eax
    3. invoke GdipCreateFromHDC, hDC, addr pGraphics
    4. invoke GdipDrawImage, pGraphics,hImag,0,0
    5. Invoke InvalidateRect,hGif,0,TRUE
    То картинка исчезает сразу
     
  4. dinoweb

    dinoweb Дмитрий

    Публикаций:
    0
    Регистрация:
    12 окт 2005
    Сообщения:
    129
    Адрес:
    Россия. Красноярск
    Так и должно быть :). InvalidateRect отправляет сообщение WM_PAINT стандартному обработчику класса Static, который в свою очередь рисует пустой статик.

    upd. Ошибся с функцией, давно на WinAPI не писал.

    Функция SetWindowLong с параметром GWL_WNDPROC. Причём, если вы хотите сохранить функциональность статика, то после обработки нужных вам сообщений, вы должны передать сообщение стандартному обработчику, иначе ничего кроме отрисовки картинки ваше окно делать не будет.
     
  5. assch

    assch Member

    Публикаций:
    0
    Регистрация:
    17 мар 2011
    Сообщения:
    208
    Не подскажите как и где именно воткнуть функцию SetWindowLong
    Она имеет три параметра

    Invoke SetWindowLong,hGif,?,?

    Первый я так понимаю хендл окошка (hGif)
    Вторым параметром идёт одно из этих значений
    GWL_EXSTYLE
    GWL_HINSTANCE
    GWL_ID
    GWL_STYLE
    GWL_USERDATA
    GWL_WNDPROC
    А третий параметр без понятия
    Подскажите пожалуйста
    Или это "чудо действие" с окошком класса Static проделать не удастся.
     
  6. dinoweb

    dinoweb Дмитрий

    Публикаций:
    0
    Регистрация:
    12 окт 2005
    Сообщения:
    129
    Адрес:
    Россия. Красноярск
    А далее идёт адрес вашей процедуры обработки сообщений, аналогичной процедуре для главного окна, с тем отличием, что необработанные сообщения она передаёт другой функции. У Iczelion'a есть примеры.
    Invoke SetWindowLong,hGif,GWL_WNDPROC, offset MyStaticProc
    воткнуть можно сразу после создания статика

    Код (Text):
    1. LRESULT CALLBACK WindowProc(
    2.   __in  HWND hwnd,
    3.   __in  UINT uMsg,
    4.   __in  WPARAM wParam,
    5.   __in  LPARAM lParam
    6. );
    Код (Text):
    1. MyStaticProc:
    2. ...
    3. .if uMsg == WM_PAINT
    4. // рисуем окно
    5. ...
    6. .else
    7. DefWindowProc, hWnd, uMsg, wParam, lParam
    8. ...
    Для более сложных случаев, вместо DefWindowProc, используется функция CallWindowProc
     
  7. assch

    assch Member

    Публикаций:
    0
    Регистрация:
    17 мар 2011
    Сообщения:
    208
    Спасибо dinoweb
    Попробую разобратся
    Попробую также посмотреть урок Iczelion'a
    Надеюсь эти уроки находятся на этом сайте
     
  8. dinoweb

    dinoweb Дмитрий

    Публикаций:
    0
    Регистрация:
    12 окт 2005
    Сообщения:
    129
    Адрес:
    Россия. Красноярск
    http://wasm.ru/article.php?article=1001020
     
  9. assch

    assch Member

    Публикаций:
    0
    Регистрация:
    17 мар 2011
    Сообщения:
    208
    Спасибо
     
  10. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    UpdateWindow не катит?
     
  11. assch

    assch Member

    Публикаций:
    0
    Регистрация:
    17 мар 2011
    Сообщения:
    208
    Просто поставить
    Код (Text):
    1. invoke UpdateWindow,hGif
    Не пойдёт
    Спасибо dinoweb подсказал как надо (В данном случае у окошка класса "Static" поменять оконную процедуру при помощи функции SetWindowLong)

    Код (Text):
    1. Invoke SetWindowLong,hGif,GWL_WNDPROC, offset MyStaticProc
     
  12. ASMatic

    ASMatic New Member

    Публикаций:
    0
    Регистрация:
    5 окт 2010
    Сообщения:
    233
    assch
    если вы юзаете static control то он может и сам все делать с картинками и ничего не нужно самому рисовать (собственно для этого и есть контролы,) STM_SETIMAGE установит контролу новый битмап и вы спокойно забываете об этом всем...А извраты с сабклассингом - на любителя.
    Можете сами рисовать себе на "обычном" окне...
    Код (Text):
    1. ...
    2. WM_PAINT:
    3.    hDC = BeginPaint( hWnd, &ps );
    4.    BitBlt( hDC,.., hImgDC, 0, 0);   //can use StratchBlt();
    5.    EndPaint( &ps );
    6.    break;
    7.  
    8. WM_CREATE:
    9.  hDC = GetDC( hWnd );
    10.  hImgDC = CreateCOmpatibleDC( hDC );
    11.  ReleaseDC( hWnd, hDC );
    12.  break;
    13.  
    14. WM_DROPFILES:
    15.   SelectObject( hImgDC, NewImageHandle );
    16.   GetObject( NewImageHandle, sizeof(BITMAP), &bmp );
    17.   rect.left = 0;
    18.   rect.top = 0;
    19.   rect.right = bmp.width;
    20.   rect.bottom = bmp.height;
    21.   InvalidateRect( hWnd, &rect, FALSE );
    22. ....
    чот вроде этого..
     
  13. assch

    assch Member

    Публикаций:
    0
    Регистрация:
    17 мар 2011
    Сообщения:
    208
    ASMatic
    Спасибо за отзыв. Только я попробывал и у меня не чего не получилось.
    Может я не правильно использовал .

    invoke SendMessage, hGif, STM_SETIMAGE, hImag, 0

    Не туда поставил или параметры не те или вообще не правильно понял вас насчёт STM_SETIMAGE (это я имею в виду если использовать static control )
    Не подскажете.




    Код (Text):
    1. .if uMsg == WM_DROPFILES
    2.  
    3. invoke DragQueryFile,wParam,0,addr buffer,sizeof buffer
    4.  
    5. invoke GdipDisposeImage,hImag
    6.  
    7. invoke MultiByteToWideChar,0,0,addr buffer,-1,addr Unicod,addr Char
    8. invoke GdipLoadImageFromFile,addr Unicod, addr hImag
    9. invoke GdipGetImageWidth, hImag, addr sWidth
    10. invoke GdipGetImageHeight, hImag, addr sHeight
    11.  
    12. invoke  DestroyWindow,hGif
    13. invoke CreateWindowEx,0,addr Static,0,WS_CHILD,50,50,sWidth,sHeight,hWin,0,0,0
    14. mov hGif,eax
    15. invoke ShowWindow,hGif,SW_SHOWNORMAL
    16. invoke UpdateWindow,hGif
    17.  
    18. invoke GetDC, hGif
    19. mov hDC, eax
    20. invoke GdipCreateFromHDC, hDC, addr pGraphics
    21. invoke GdipDrawImage, pGraphics,hImag,0,0
    22.  
    23. invoke SendMessage, hGif, STM_SETIMAGE, hImag, 0  ;??????????
     
  14. S_Alex

    S_Alex Alex

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

    Код (Text):
    1. invoke CreateWindowEx,0,addr Static,0,5000010Eh,50,50,sWidth,sHeight,hWin,0,0,0
    и ещё просмотрел

    Код (Text):
    1.  invoke  SendMessage,[hGif],STM_SETIMAGE,IMAGE_BITMAP,[hImag]
     
  15. assch

    assch Member

    Публикаций:
    0
    Регистрация:
    17 мар 2011
    Сообщения:
    208
    S_Alex
    Не получается (не перерисовывается)
     
  16. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    прежде чем слать STM_SETIMAGE, проверь на валидность hImag и hGif. И убедись, что статик виден (WS_VISIBLE и можно обойтись без ShowWindow/UpdateWindow). И предпоследний параметр CreateWindowEx неплохо бы указать, а не просто ноль.
     
  17. assch

    assch Member

    Публикаций:
    0
    Регистрация:
    17 мар 2011
    Сообщения:
    208
    Статик виден картинка тоже только не перерисовывается


    Код (Text):
    1. .if uMsg == WM_DROPFILES
    2.  
    3. invoke DragQueryFile,wParam,0,addr buffer,sizeof buffer
    4.  
    5. invoke GdipDisposeImage,hImag
    6.  
    7. invoke MultiByteToWideChar,0,0,addr buffer,-1,addr Unicod,addr Char
    8. invoke GdipLoadImageFromFile,addr Unicod, addr hImag
    9. invoke GdipGetImageWidth, hImag, addr sWidth
    10. invoke GdipGetImageHeight, hImag, addr sHeight
    11.  
    12. invoke  DestroyWindow,hGif
    13. invoke CreateWindowEx,0,addr Static,0,WS_CHILD,50,50,sWidth,sHeight,hWin,0,0,0
    14. mov hGif,eax
    15. invoke ShowWindow,hGif,SW_SHOWNORMAL
    16. invoke UpdateWindow,hGif
    17.  
    18. invoke GetDC, hGif
    19. mov hDC, eax
    20. invoke GdipCreateFromHDC, hDC, addr pGraphics
    21. invoke GdipDrawImage, pGraphics,hImag,0,0
    22.  
    23. invoke  SendMessage,hGif,STM_SETIMAGE,IMAGE_BITMAP,hImag
     
  18. ASMatic

    ASMatic New Member

    Публикаций:
    0
    Регистрация:
    5 окт 2010
    Сообщения:
    233
    *дел*
     
  19. dinoweb

    dinoweb Дмитрий

    Публикаций:
    0
    Регистрация:
    12 окт 2005
    Сообщения:
    129
    Адрес:
    Россия. Красноярск
    Так зачем вы рисуете, если решили переложить эту работу на стандартный функционал класса?
    Статик сам всё нарисует.

    Код (Text):
    1. #define SS_BITMAP 14
    Код (Text):
    1. invoke CreateWindowEx,0,addr Static,0,WS_CHILD|SS_BITMAP,50,50,sWidth,sHeight,hWin,0,0,0
    И ещё - функция GdipLoadImageFromFile загружает НЕ IMAGE_BITMAP, поэтому hImag не подоходит в качестве параметра для STM_SETIMAGE