Форум: "Прочее";
Текущий архив: 2007.05.20;
Скачать: [xml.tar.bz2];
ВнизЗнаю, что решение совсем простое, но... Найти похожие ветки
← →
ProgRAMmer Dimonych © (2007-04-22 16:39) [0]найти чего-то не могу.
Стоит задача: написание компонента-наследника TCustomPanel. Контрол сам на себе рисует с помощью OpenGL. Когда происходит инициализация OpenGL, то переменной типа HDC присваивается значение, возвращаемое функцией GetDC. А при деинициализации вызывается ReleaseDC. Т.е. всё по учебнику.
Проблема в том, что при завершении приложения сначала удаляется форма, а затем происходит вызов деструктора моего контрола. В результате при вызове ReleaseDC программа вылетает с ошибкой о том, что контрол не имеет родительского окна.
Как устранить эту проблему?
Заранее спс.
← →
ferr © (2007-04-22 16:47) [1]> Проблема в том, что при завершении приложения сначала удаляется
> форма, а затем происходит вызов деструктора моего контрола.
сомнительно.
← →
Gero © (2007-04-22 16:50) [2]> Как устранить эту проблему?
Найти ошибку в своем коде.
← →
ProgRAMmer Dimonych © (2007-04-22 16:54) [3]> ferr © (22.04.07 16:47) [1]
> сомнительно.
Я тоже думал, что должно быть по-другому, но...
Я создал обработчик OnDestroy главной формы, на которой находится мой контрол, написал туда Form1.Hint:=""; (чтобы было на что поставить брякпоинт). После выполнения процедуры TForm1.Form1Destroy() происходит вызов деструктора...
destructor TOGLPanel.Destroy;
begin
DeInitOpenGL;
{Ещё всякие мелочи}
inherited Destroy;
end;
А DeInitOpenGL, вот он...
procedure TOGLPanel.DeInitOpenGL;
begin
wglMakeCurrent(0,0);
wglDeleteContext(hrc);
ReleaseDC(Self.Handle,DC);
end;
И вот этот-то ReleaseDC вылетает с EInvalidOp, хотя ещё в OnDestroy-процедуре Watch показывал Form1.OGLPanel1.Handle=<Некоторому числу>.
:(
← →
ProgRAMmer Dimonych © (2007-04-22 17:35) [4]Давно не прибегал к этому методу выведения вопроса на первую строчку, но здесь времени нет.
Подскажите, пожалуйста, хотя бы в каком направлении искать?
← →
_Аноним (2007-04-22 17:38) [5]Делай инийиализацию\деинициализацию не в конструктор \ деструкторе
а в CreateWnd \ DestroyWnd
← →
ProgRAMmer Dimonych © (2007-04-22 17:40) [6]> _Аноним (22.04.07 17:38) [5]
> Делай инийиализацию\деинициализацию не в конструктор \ деструкторе
> а в CreateWnd \ DestroyWnd
Прошу прощения, за отсутствием достаточного опыта работы со вскими хэндлами окон и т.п. не понял Вашего совета. Объясните, пожалуйста, подробнее.
← →
_Аноним (2007-04-22 17:41) [7]Что кстати правильно и по другой причине
Борланд любит время от времени пересоздать окно,
после того, как это случится, ты будешь иметь невалидный хендл
← →
ProgRAMmer Dimonych © (2007-04-22 18:08) [8]Прямо не знаю, что делать.
Выкидываю исходник, пусть каждый укажет, что может быть причиной ошибки. Это то, что я наэкспериментировал. В оригинале был именно TPanel и override"нный метод Paint.unit DSChart;
interface
uses
SysUtils, Classes, Controls, OpenGL, Windows, ExtCtrls, Messages;
type
TDSChart = class(TWinControl)
private
FData:array of Extended;
//
DC:HDC;
hrc:HGLRC;
{ Private declarations }
protected
procedure PixelFormat;
procedure InitOpenGL;
procedure DeInitOpenGL;
procedure Paint(var Message:TWMPaint); message WM_PAINT;
{ Protected declarations }
public
constructor Create(AOwner:TComponent); override;
destructor Destroy; override;
//
procedure ClearData;
procedure Add(Value:Extended);
procedure AddEx0(Value:Extended; Position:Integer);
procedure AddEx1(Value:Extended; Position:Integer);
{ Public declarations }
published
{ Published declarations }
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents("DimonSoft", [TDSChart]);
end;
//
//
//
procedure TDSChart.PixelFormat;
var
nPixelFormat:Integer;
pfd:TPixelFormatDescriptor;
begin
ZeroMemory(@pfd,SizeOf(pfd));
pfd.nSize:=SizeOf(pfd);
pfd.nVersion:=1;
pfd.dwFlags:=PFD_DOUBLEBUFFER or PFD_SUPPORT_OPENGL or PFD_DRAW_TO_WINDOW;
pfd.iPixelType:=PFD_TYPE_RGBA;
pfd.cColorBits:=24;
pfd.cAlphaBits:=64;
pfd.cAccumBits:=64;
pfd.cDepthBits:=32;
pfd.cStencilBits:=64;
pfd.iLayerType:=PFD_MAIN_PLANE;
nPixelFormat:=ChoosePixelFormat(DC,@pfd);
if nPixelFormat=0 then Exception.Create("Unable to set pixel format!!!");
SetPixelFormat(DC,nPixelFormat,@pfd);
end;
procedure TDSChart.InitOpenGL;
var
W,H:Integer;
begin
DC:=GetDC(Self.Handle);
PixelFormat;
hrc:=wglCreateContext(DC);
wglMakeCurrent(DC,hrc);
//
W:=Self.Width; H:=Self.Height;
glMatrixMode(GL_PROJECTION);
glLoadIdentity;
if W<=H then
glOrtho(-2,2,-2*H/W,2*H/W,-10,10)
else
glOrtho(-2*W/H,2*W/H,-2,2,-10,10);
glViewPort(0,0,W,H);
end;
procedure TDSChart.DeInitOpenGL;
begin
wglMakeCurrent(0,0);
wglDeleteContext(hrc);
ReleaseDC(Self.Handle,DC);
end;
procedure TDSChart.Paint;
var
ps:TPaintStruct;
begin
BeginPaint(Self.Handle,ps);
glClearColor(1,0.5,0.5,1);
glClear(GL_COLOR_BUFFER_BIT);
glPointSize(10);
glColor3f(0,1,0);
glBegin(GL_POINTS);
glVertex3f(1.25,1.25,0);
glVertex3f(-1.25,-1.25,0);
glEnd;
glEnable(GL_POINT_SMOOTH);
glColor3f(1,0,0);
glBegin(GL_POINTS);
glVertex3f(1.25,-1.25,0);
glVertex3f(-1.25,1.25,0);
glEnd;
glDisable(GL_POINT_SMOOTH);
glColor3f(0,0,1);
glBegin(GL_LINES);
glVertex3f(1,-1,0);
glVertex3f(-1,1,0);
glVertex3f(1,1,0);
glVertex3f(-1,-1,0);
glEnd;
glFlush;
SwapBuffers(DC);
EndPaint(Self.Handle,ps);
end;
//
//
//
constructor TDSChart.Create(AOwner:TComponent);
begin
inherited Create(AOwner);
MessageBox(0,PChar(IntToStr(Self.Handle)),"",64);
SetLength(FData,0);
InitOpenGL;
end;
destructor TDSChart.Destroy;
begin
DeInitOpenGL;
SetLength(FData,0);
inherited Destroy;
end;
procedure TDSChart.ClearData;
begin
SetLength(FData,0);
end;
procedure TDSChart.Add(Value:Extended);
var
L:Integer;
begin
L:=Length(FData); SetLength(FData,L+1); FData[L]:=Value;
end;
procedure TDSChart.AddEx0(Value:Extended; Position:Integer);
var
L:Integer;
begin
L:=Length(FData);
if Position>=L then
SetLength(FData,Position+1);
FData[Position]:=Value;
end;
procedure TDSChart.AddEx1(Value:Extended; Position:Integer);
begin
AddEx0(Value,Position-1);
end;
end.
Страницы: 1 вся ветка
Форум: "Прочее";
Текущий архив: 2007.05.20;
Скачать: [xml.tar.bz2];
Память: 0.48 MB
Время: 0.044 c