Анимация с компонентом VCL (WM_PAINT)

Проблема заключается в том, что анимация OpenGL останавливается, когда на компонент TForm нажимается любая кнопка мыши (рамка, заголовок и т. Д.). Как только кнопка мыши отпущена, анимация продолжается.

// Drawing Scene 
 void TMainForm::DrawGLScene()
{
    glClearColor(1,1,1,1);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    DrawFigure();
    SwapBuffers(hDC);
}

// Catching WM_PAINT 
LRESULT CALLBACK NewWindowProcPanel3D(HWND hWnd, UINT msg, WPARAM w, LPARAM l)
{
    switch (msg)
    {
        case WM_ERASEBKGND :
        {
            return 1;
        }
        case WM_PAINT :
        {
            MainForm->DrawGLScene();
        }
        default: return CallWindowProc((FARPROC)MainForm->OldWindowProcPanel3D,
            hWnd, msg, w, l);
    }
    return 0;
}

// Creating OldWindowProcPanel3D -
 void __fastcall TMainForm::FormCreate(TObject *Sender)
{
    OldWindowProcPanel3D = (WNDPROC)SetWindowLong(Panel3D->Handle,
        GWL_WNDPROC, (long)NewWindowProcPanel3D);
}

// --------- *.h :
class TMainForm : public TForm
{
    private:
       HDC hDC;
    public:
        WNDPROC OldWindowProcPanel3D;
}

// Generation event WM_PAINT 
 void TMainForm::UpdateScene()
{
    InvalidateRect(Panel3D->Handle, NULL, false);
}

// Animation code ( turn on 'animation' if RadioButton is chosen) 
 void __fastcall TMainForm::RadioGroupClick(TObject *Sender)
{
    if (RadioGroup->ItemIndex == 0)
       animation = false;
    else if (RadioGroup->ItemIndex == 1)
        animation = true;
     if (animation)
    {
        while (animation)
       {
            Application->ProcessMessages();
            UpdateScene();
        }
    }
}

Что нужно сделать, чтобы не останавливать анимацию при изменении размеров формы, каких-либо полезных ссылок?

1 ответ

Это потому, что ваш основной цикл сообщений заблокирован, а дополнительный цикл сообщений работает во время перетаскивания / изменения размера окна. То же самое происходит, когда меню активны, отображаются модальные диалоговые окна и т. Д. С этим ничего не поделаешь, просто работает Windows.

Кстати, если предположить Panel3D is aTPanelor similar VCL control, you should subclass itsWindowProcproperty instead ofSetWindowsLong (), since theСвойство TWinControl::Handle` не является постоянным.

И вам нужно избавиться от вашего использования Application->ProcessMessages() в целом. Никогда не называйте это напрямую, если это абсолютно не необходимо.

Попробуйте это вместо этого:

class TMainForm : public TForm
{
private:
    HDC hDC;
    bool animation;
    TWndMethod OldWindowProcPanel3D;
    void DrawGLScene();
    void __fastcall NewWindowProcPanel3D(TMessage &Message);
public:
    __fastcall TMainForm(TComponent *Owner);
};

// Creating OldWindowProcPanel3D -
__fastcall TMainForm::TMainForm(TComponent *Owner)
    : TForm(Owner)
{
    OldWindowProcPanel3D = Panel3D->WindowProc;
    Panel3D->WindowProc = &NewWindowProcPanel3D;
}

// Drawing Scene 
void TMainForm::DrawGLScene()
{
    glClearColor(1,1,1,1);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    DrawFigure();
    SwapBuffers(hDC);
}

// Catching WM_PAINT 
void __fastcall TMainForm::NewWindowProcPanel3D(TMessage &Message)
{
    switch (Message.Msg)
    {
        case WM_ERASEBKGND :
        {
            Message.Result = 1;
            break;
        }

        case WM_PAINT :
        {
            DrawGLScene();
            if (animation)
                UpdateScene();
            break;
        }

        default:
        {
            OldWindowProcPanel3D(Message);
            break;
        }
    }
}

// Generation event WM_PAINT 
void TMainForm::UpdateScene()
{
    Panel3D->Invalidate();
}

// Animation code ( turn on 'animation' if RadioButton is chosen) 
void __fastcall TMainForm::RadioGroupClick(TObject *Sender)
{
    if (RadioGroup->ItemIndex == 0)
        animation = false;
    else if (RadioGroup->ItemIndex == 1)
        animation = true;

    if (animation)
        UpdateScene();
}
Другие вопросы по тегам