Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2007.05.20;
Скачать: CL | DM;

Вниз

Знаю, что решение совсем простое, но...   Найти похожие ветки 

 
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;
Скачать: CL | DM;

Наверх




Память: 0.5 MB
Время: 0.053 c
2-1178093914
Perf2k2
2007-05-02 12:18
2007.05.20
ListView: как проверить, выеделена ли пустая строка или нет?


2-1177755349
I-New
2007-04-28 14:15
2007.05.20
Что такое Build. И а зчем он нужен?


2-1177655849
OlegMV
2007-04-27 10:37
2007.05.20
Проблема с координатами


2-1178012859
Познающий
2007-05-01 13:47
2007.05.20
Вставка рисунка


15-1176885141
Карелин Артем
2007-04-18 12:32
2007.05.20
Вода из водопровода vs вода из бутыли.