Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Системное программирование и WinAPI > Нужна помощь анимация циклической сменой битмапов


Автор: Guest 10.12.2005, 01:09
Пишу анимацию циклической сменой битмапов. Битмапы сменяю по WM_TIMER. Вот код:
Код

LRESULT CALLBACK WndProc(HWND hWnd, UINT messg, WPARAM wParam, LPARAM lParam)
{
    static int x0, y0;      
    static int w0, h0;      
  int xDlg, yDlg;            
    int wDlg, hDlg;            
  RECT wnd_rect;            
  RECT PColorDlg_rect;  
  PAINTSTRUCT ps;
  BITMAP bm;
   

  hdc = hmdc = NULL;

  switch (messg)
    {
    case WM_CREATE:
      hwndMainDialog = CreateDialog((HINSTANCE)GetModuleHandle(NULL),
                  MAKEINTRESOURCE(IDD_DIALOG1), hWnd, (DLGPROC)MainDialog);
      
    break;

    case WM_PAINT:
      hdc = BeginPaint(hWnd, &ps);
      EndPaint(hWnd, &ps);
    break;

    case WM_TIMER:
      
      hdc = GetDC(hWnd);
      
      if (on)
      {
        
        hmdc = CreateCompatibleDC(hdc);
        
        GetWindowRect(hWnd, &wnd_rect);
        
        int w = wnd_rect.right - wnd_rect.left;
        int h = wnd_rect.bottom - wnd_rect.top;

        SelectObject(hmdc, bmps[frame]);
          
        GetObject(bmps[frame], sizeof(bm), (LPSTR)&bm);
         
        StretchBlt(hdc, 0, 0, w, h, hmdc, 
                  0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);
        
        //MessageBox(hWnd, "FUCK!", "Error", MB_OK);

        if (frame  == 8) 
          frame = 0;
        else                                
          frame++;

       }

    break;

    case WM_SIZE: case WM_MOVE:
      
      GetWindowRect(hWnd, &wnd_rect);
          
      x0 = wnd_rect.left;    
          y0 = wnd_rect.top;
          w0 = wnd_rect.right - x0;
          h0 = wnd_rect.bottom - y0;

      SetWindowPos(hWnd, NULL, 0, 0, w0, h0, SWP_NOMOVE);

          GetWindowRect(hwndMainDialog, &PColorDlg_rect);
          xDlg = PColorDlg_rect.left;    
          yDlg = PColorDlg_rect.top;
          wDlg = PColorDlg_rect.right - xDlg;
          hDlg = PColorDlg_rect.bottom - yDlg;

          MoveWindow(hwndMainDialog, x0 + w0, y0 + 45, wDlg, hDlg, TRUE);                          

    break;

    case WM_COMMAND:
      switch(LOWORD(wParam))
      {
      case ID_EXIT:
        PostQuitMessage(0);
      break;
      
      default:
        break;
      }
    break;
    
    case WM_DESTROY:
      DeleteDC(hmdc);
      DeleteDC(hdc);
      PostQuitMessage(0);
        break;
      
    default:
          return (DefWindowProc(hWnd, messg, wParam, lParam));
    }
    return (0);
}



Битмапы загружаю так:
Код

bmps[0] = LoadBitmap((HINSTANCE)GetModuleHandle(NULL), MAKEINTRESOURCE(FRAME1));
  bmps[1] = LoadBitmap((HINSTANCE)GetModuleHandle(NULL), MAKEINTRESOURCE(FRAME2));
  bmps[2] = LoadBitmap((HINSTANCE)GetModuleHandle(NULL), MAKEINTRESOURCE(FRAME3));
      
  bmps[3] = LoadBitmap((HINSTANCE)GetModuleHandle(NULL), MAKEINTRESOURCE(FRAME4));
  bmps[4] = LoadBitmap((HINSTANCE)GetModuleHandle(NULL), MAKEINTRESOURCE(FRAME5));
  bmps[5] = LoadBitmap((HINSTANCE)GetModuleHandle(NULL), MAKEINTRESOURCE(FRAME6));
  
  bmps[6] = LoadBitmap((HINSTANCE)GetModuleHandle(NULL), MAKEINTRESOURCE(FRAME7));
  bmps[7] = LoadBitmap((HINSTANCE)GetModuleHandle(NULL), MAKEINTRESOURCE(FRAME8));
  bmps[8] = LoadBitmap((HINSTANCE)GetModuleHandle(NULL), MAKEINTRESOURCE(FRAME9));


Если код загрузки поместить в WndProc, то прога через некоторое время виснет...Если поместить в WinMain, то показав один раз все картинки, на втором циле их показа они перестают отображаться...Собственно что не так и как сделать?

Автор: Aleksandor 10.12.2005, 01:22
Утечка идет... надо освобождать хэндлы объектов GDI
код такого плана:
Код

    width=50; height=50;
    hDC = GetWindowDC(hWnd);
    hBmp = CreateCompatibleBitmap(hDC, width, height);
    if ( hBmp )
    {
        hMemDC   = CreateCompatibleDC(hDC);
        HGDIOBJ hOld = SelectObject(hMemDC, hBmp);

        BitBlt(hMemDC, 0, 0, width, height,    hDC, 0, 0, SRCCOPY);

        SelectObject(hMemDC, hOld);
        DeleteObject(hMemDC);
    }
    
    ReleaseDC(hWnd, hDC);


правда здесь немного другое-участок экрана сохраняется в памяти,
но принцип тот же smile

Автор: Guest 10.12.2005, 01:52
Надо же было так глупо облажаться) Спасибо)

Автор: Fixin 10.12.2005, 02:51
Для улучшения работы анимации, лучше всего использовать списки изображений, но это довольно муторно. Проще самому единожды понаделасть совместимых контекстов с выбранными в них битмапами, а потом один раз освободить (например, при завершении пиложения).

Автор: En_t_end 10.12.2005, 11:50
А проще из нужных bmp сделать ролик avi. Это делается кстати не сложно и по-моему заюзано по дефолту в XP. А следом юзать спец. АПИ для проигрывания avi. ЗЫ по-моему где-то видел даже АПИ для склеивания bmp-шек.

Автор: Fixin 10.12.2005, 12:29
Цитата(En_t_end @ 10.12.2005, 12:50)
по-моему где-то видел даже АПИ для склеивания bmp-шек.
Угу, есть такие. У функций названия типа "CreateAVIStream" или как-то так. Если задаться целью, то можно найти.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)