Анимация с компонентом 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 a
TPanelor similar VCL control, you should subclass its
WindowProcproperty 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();
}