Re[5]: перерисовка квадрата в новое место
От: Аноним  
Дата: 15.06.05 14:39
Оценка:
Здравствуйте, Аноним, Вы писали:

А>A kak создать контекст в памяти


Создать контекст не сложно, только я не понимаю, на каком языке ты пишешь — похоже и на С++ и на С#.... Это Java ?
Но так так ты пользуешься API, то разницы особой не будет. В каких местах писать и объявлять данные, разберешься сам

HDC m_dc;         // контекст в памяти
CSize m_dcSize;   // его размер (он может у тебя меняться при резайзе окна - если требуется)
HBRUSH m_brBack;  // кисть для залива фоном
HBRUSH m_brSquare; // кисть для залива квадрата

    //  конструктор
{
     m_dc = NULL;
     m_brBack = CreateSolidBrush (RGB (/* bkColor */));
     m_brSquare = CreateSolidBrush (RGB (/* sqColor */));
}
    // деструктор
{
     DeleteObject (m_brBack);
     DeleteObject (m_brSquare);
     if (m_dc)
          DeleteObject (m_dc);
}
    // функция-инициализатор. Окно еще не показалось, но уже существует. В MFC - это OnInitDialog
{
     RECT r;
     GetClientRect (&r);
     m_dcSize.cx = r.right - r.left;
     m_dcSize.cy = t.bottom - r.top;       // размер контекста у нас будет равен размеру окна

     HDC dc = GetDC (m_hWnd);

              // создаем контекст
     HBITMAP bitm = CreateCompatibleBitmap (dc, m_dcSize.cx, m_dcSize.cy);
     m_dc = CreateCompatibleDC (dc);
     SelectObject (m_dc, bitm);

              // контекст окна больше не нужен
     ReleaseDC (m_hWnd, dc);

               // контекст в памяти создан и находится уже в рабочем состоянии. 
               // Инициализируем его фоновым цветом
     FillRect (m_dc, CRect (0, 0, m_dcSize.cx, m_dcSize.cy), m_brBack);
}

         // рисуем
Draw (HDC dc, ...) {

     if (!m_dc)     // если все сделать правильно, условие никогда не сработает
        return;
 
                    // копируем на контекст диалога наш контекст в памяти
     ::BitBlt (dc, 0, 0, m_dcSize.cx, m_dcSize.cy, m_dc, 0, 0, SRCCOPY);
  
}

        // лучше создать отдельную функцию для рисования, но в данном случае это не принципиально
Timer () {

      static y = 0;
      static x = 0;
      y += 10;
      x += 10;

      FillRect (m_dc, CRect (0, 0, m_dcSize.cx, m_dcSize.cy), m_brBack);
      FillRect (m_dc, CRect (x, y, x + 20, y + 20), m_brSquare);

         // неважно, на чем ты пишешь, но вызывать непосредственно функцию Draw () не рекомендуется
         // посно послать сообщение WM_PAINT, можно вызвать функцию принудительной перерисовки
      Invalidate ();    
}


Все, вроде ничего не упустил. Писал прямо тут , не в редакторе, так что не ругайся если чего
Но это общий случай, если у тебя серьезное рисование. В твоем случае можно все сильно упростить.
Создает контекст в памяти размером квадрата — CSize (20, 20). Сразу заливаем его цветом квадрата и нафиг забываем о нем (вернее, о его перерисовке). Т.е. квадрат нарисован всего один раз, и этого достаточно
В таймере, как у тебя и было в первый раз, меняем значение y. А в Draw меняем его расположение:

Draw (HDC dc, float y) {

     RECT r;
     GetClientRect (&r);
     FillRect (dc, &r, m_brBack);      // запомни эти три строчки. Здесь мы заливаем диалог фоновым цветом

     if (!m_dc)     // если все сделать правильно, условие никогда не сработает
        return;
 
               // копируем на контекст диалога наш контекст в памяти. 
             // координаты копирования - измененные x и y
     ::BitBlt (dc, x, y, m_dcSize.cx, m_dcSize.cy, m_dc, 0, 0, SRCCOPY);
}


У меня сильное подозрение, что ты рисуешь не в стандартном обработчике рисования, иначе у тебя не было бы проблем с остающимся квадратом. Не майся глупостью Создай обработчик перерисовки (OnDraw, по видимому), и те первые три строчки, на которые я обратил внимание, не нужны будут
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.