VCL组件动画(WM_PAINT)

时间:2013-08-08 10:26:40

标签: opengl animation vcl tform wm-paint

问题是在TForm组件(边框,标题..)上单击任何鼠标按钮时,OpenGL动画停止。一旦鼠标按钮释放,动画就会继续。

// 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 个答案:

答案 0 :(得分:0)

这是因为在拖动/调整窗口窗口时,您的主消息循环被阻止,并且正在运行辅助消息循环。当菜单处于活动状态,显示模态对话框等时,会发生同样的事情。您无法做任何事情,这就是Windows的运作方式。

BTW,假设Panel3D is a TPanel or similar VCL control, you should subclass its WindowProc property instead of SetWindowsLong(), 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();
}