OpenGL是一个独立于窗口的图形库,而图形最终是在窗口系统里绘制出来的,那么OpenGL的绘图命令是怎么在窗口里生成输出的呢? 这就是各个系统上的OpenGL实现者需要做的工作了。在Windows里是通过wgl库完成的,在X-Windows里是通过glx服务器来完成的,至于这些OpenGL实现具体是怎么工作的,请参考sgi发布的sample
implement源码,不过那个代码是用C写的。 在MS-Windows里,wgl库负责将OpenGL的绘制设备RenderContext与GDI的DeviceContext联系起来,使得发到OpenGL的RC里的命令生成的位图能够在GDI
DC里绘制出来,你可以把它想象成OpenGL在RC里有一个FrameBuffer,记录着生成的图案,而wgl则负责把FrameBuffer的内容BitBlt到DC上。当然,这并不是它实际的工作方法,如果想了解更多请参考SGI发布的SDK资料或联系MS公司。 为了使GDI
DC能够接受OpenGL
RC的输出,必须为DC选定特别的像素格式,然后建立RC,再用wglMakeCurrent把当前要使用的RC和DC联系起来。此后我们就可以用OpenGL命令正常工作了。在一个程序里可以创建多个RC和多个DC,程序中的OpenGL命令会发到被wglMakeCurrent指定为当前的那一组合中。 我并不认为这个初始化过程是个很有意思的工作,这个世界上有很多聪明的程序员也这么想,所以他们发明了glaux库和glut库。glaux是在著名的OpenGL
Programmer
Guide里提出的,这本书是OpenGL编程的官方文档,因为它的封皮是红色的,所以通常简称为RedBook。故名思意,glaux是一套输助库,它使得你无须关心在具体窗口系统里初始化、消息响应的细节,而是使用传统的c/dos程序风格编制OpenGL程序。
int main(int argc, char** argv) { auxInitDisplayMode(
AUX_SINGLE|AUX_RGB|AUX_DEPTH16);//使用单缓冲、RGB彩色模式、16位浓度
auxInitPosition(0,0,250,250);
auxInitWindow("Title");//以上两行在(0,0)片建立了一个大小为250X250的窗口,其标题为"Title"。
myinit();//建立OpenGL透视投影环境 auxReshapeFunc(myReshape);//指定窗口大小变化的响应函数
auxMainLoop(display);//指定绘制函数 return 0; }
由于glaux是为教学目的开发的,所以实用价值很限,所以又有程序员开发了glut,这套库被广泛使用,它的工作方式与glaux极为类似,但功能完善得多,特别是对交互、全屏等的支持要理想得多,所以许多的OpenGL演示程序使用它,比如SGI网站
峁┑亩嗍菔境绦蚨夹枰褂盟M闭馓卓庖丫灰浦驳蕉嘀制教ㄉ希砸窍胗眉虻サ姆椒ǹ⒃趙indows/macos/os2/xwindows等系统上都能使用的程序,那么应该选择这套库。 我并不认为一个Delphi程序员会喜欢glaux或glut,因为那意味着你不能利用Delphi的可视开发能力,另外任何真正实用的Delphi程序想直接在其它操作系统上编译运行好象也不现实,即glut的跨平台能力也没有什么吸引力。我们应该开发一个VCL控件,把初始化工作封装起来。 我认为从TCustomPanel派生一个子类比较方便,让我们称它为TGLPanel吧。初始化过程要在WMCreate里完成,之所以要放在这里是因为这个时候Window
Handle已经建立,但还没启用。 在WMCreate中会 ①调用initDC完成DC调整工作,initDC会以本窗口使用的DC调用PreparePixelFormat,而PixelFormat则真正完成像素格式调整。 ②然后WMCreate会调用InitGL完成OpenGL透视投影环境的设定。 ③最后调用OnInit给用户一个调整透视投影环境的机会。
注意,如果要在MDI环境中的子窗体中使用OpenGL,还有些附加工作要做,这就是给窗口类的Params.Style加上WS_CLIPCHILDREN和WS_CLIPSIBLINGS属性,这得在Window
Handle建立之前就完成,因此要写在CreateParams里。由于SDI应用并不需要该代码,所以应该定义OnPreInit事件,让用户在需要的时候自己加上,在Create里调用OnPreInit。以下代码定义了OnPreInit,但并没有定义CreateParams,如果需要自己加上吧。 在TGLPanel类中实际所做工作的详细说明(按成员可见性组织): 私有 1、加入DC/RC/Pal私有变量 2、定义初始化DC/RC的私有方法
保护: 3、加入FOnPaint,FOnResize,FOnInit,FOnPreInit四个事件响应变量。 4、继承/重载虚方法CreateParams,Paint,Resize 5、响应以下消息 WM_CREATE,
TWMCreate, WMCreate WM_DESTROY, TWMDestroy, WMDestroy WM_PALETTECHANGED,
TWMPaletteChanged, WMPaletteChanged WM_QUERYNEWPALETTE, TWMQueryNewPalette,
WMQueryNewPalette WM_ERASEBKGND, TWMEraseBkgnd, WMEraseBkgnd
公开: 6、定义建构与析构方法 7、定义必要的其它方法以提供各种特性
发布: 8、以下继承来的属性 __property Alignment; __property Align; __property
DragCursor; __property DragMode; __property Enabled; __property
ParentFont; __property ParentShowHint; __property PopupMenu; __property
ShowHint; __property TabOrder; __property TabStop; __property
Visible; 9、以下继承来的方法 __property OnClick; __property
OnDblClick; __property OnDragDrop; __property OnDragOver; __property
OnEndDrag; __property OnEnter; __property OnExit; __property
OnMouseDown; __property OnMouseMove; __property OnMouseUp; __property
OnStartDrag; 10、加入以下事件 //初始化OpenGL状态 __property TNotifyEvent OnInit =
{read=FOnInit,write=FOnInit}; //专用于修改显示BPP模式 __property TNotifyEvent
OnPreInit = {read=FOnPreInit,write=FOnPreInit}; 11、重载以下事件 __property
TNotifyEvent OnResize = {read=FOnResize,write=FOnResize}; __property
TNotifyEvent OnPaint =
{read=FOnPaint,write=FOnPaint}; 12、将消息与其响应函数连接起来(Delphi中这一步是在定义函数时指定的)
源代码 unit GLPanel;
interface
uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls,OpenGL;
type TGLPanel = class(TCustomPanel) private { Private declarations
} DC: HDC; RC: HGLRC; procedure initDC; procedure
initGL; procedure PreparePixelFormat(var DC: HDC);
protected { Protected declarations
} FOnPaint:TNotifyEvent; FOnInit:TNotifyEvent; FOnPreInit:TNotifyEvent; FOnResize:TNotifyEvent;
procedure Paint;override; procedure Resize;override; procedure
WMDestroy(var Msg: TWMDestroy);message WM_DESTROY; procedure WMCreate(var
Msg:TWMCreate); message WM_CREATE;
public { Public declarations } constructor
Create(Owner:TComponent);override;
published { Published declarations }
property Alignment; property Align; property DragCursor; property
DragMode; property Enabled; property ParentFont; property
ParentShowHint; property PopupMenu; property ShowHint; property
TabOrder; property TabStop; property Visible;
property OnClick; property OnDblClick; property OnDragDrop; property
OnDragOver; property OnEndDrag; property OnEnter; property
OnExit; property OnMouseDown; property OnMouseMove; property
OnMouseUp; property OnStartDrag;
property OnInit:TNotifyEvent read FOnInit write FOnInit; property
OnPreInit:TNotifyEvent read FOnPreInit write FOnPreInit;
property OnResize:TNotifyEvent read FOnResize write FOnResize; property
OnPaint:TNotifyEvent read FOnPaint write FOnPaint;
end;
procedure Register;
implementation
procedure Register; begin RegisterComponents(’Samples’,
[TGLPanel]); end; //--------------------------------------------- constructor
TGLPanel.Create; begin inherited; end; //--------------------------------------------- procedure
TGLPanel.WMDestroy(var Msg: TWMDestroy); begin wglMakeCurrent(0,
0); wglDeleteContext(RC); ReleaseDC(Handle,
DC); end; //--------------------------------------------------- procedure
TGLPanel.initDC; begin DC :=
GetDC(Handle); PreparePixelFormat(DC); end; //--------------------------------------------------- procedure
TGLPanel.initGL; begin glClear(GL_COLOR_BUFFER_BIT or
GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_PROJECTION); glLoadIdentity; glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glOrtho(-1,
1, -1, 1, -1,
50); glMatrixMode(GL_MODELVIEW); glLoadIdentity; glEnable(GL_DEPTH_TEST); //注意下面这一行是为了做练习程序时可以直接用glColor指定材质而加的, //
可能使得光照或表面材质发生意想不到的变化, // 如果不需要可以去掉或在程序中用glDisable(GL_COLOR_MATERIAL);关闭
glEnable(GL_COLOR_MATERIAL); glShadeModel(GL_SMOOTH); gluLookAt(2, 4,
6, 0, 0, 0, 0, 1,
0); SwapBuffers(DC); end; //--------------------------------------------- procedure
TGLPanel.PreparePixelFormat(var DC: HDC); var PFD :
TPixelFormatDescriptor; ChosenPixelFormat :
Integer; begin FillChar(PFD, SizeOf(TPixelFormatDescriptor), 0);
with PFD do begin nSize :=
SizeOf(TPixelFormatDescriptor); nVersion := 1; dwFlags :=
PFD_DRAW_TO_WINDOW or PFD_SUPPORT_OPENGL
or PFD_DOUBLEBUFFER; iPixelType := PFD_TYPE_RGBA; cColorBits :=
16; // 16位颜色 cDepthBits := 32; // 32位深度缓冲 iLayerType :=
PFD_MAIN_PLANE; { Should be 24, but we must allow for the clunky WKU boxes
} end;
ChosenPixelFormat := ChoosePixelFormat(DC, @PFD); if ChosenPixelFormat = 0
then Raise Exception.Create(’ChoosePixelFormat
failed!’); SetPixelFormat(DC, ChosenPixelFormat, @PFD); end;
procedure TGLPanel.WMCreate(var
Msg:TWMCreate); begin //在这里做初始化工作 //修改DC的象素格式,使之支持OpenGL绘制 initDC; RC
:= wglCreateContext(DC); wglMakeCurrent(DC,
RC); //初始化GL绘制系统 initGL; if Assigned(FOnInit) then begin if
(wglMakeCurrent(DC,RC)=false) then ShowMessage(’wglMakeCurrent:’ +
IntToStr(GetLastError)); FOnInit(self); end; end; // procedure
TGLPanel.Paint; begin //TCustomPanel::Paint(); if Assigned(FOnPaint)
then begin wglMakeCurrent(DC,RC); FOnPaint(self); SwapBuffers(DC); end; end; // procedure
TGLPanel.Resize; begin inherited; if Assigned(FOnResize)
then begin wglMakeCurrent(DC,RC); glViewport(0,0,ClientWidth,ClientHeight); FOnResize(self); end; end; end.
以上代码仅用来说明原理及建立一个基本的练习环境,您可以自由使用,转载请注明出处。如果使用从本人主页下载的TGLPanel请遵守内附使用说明的版权申明。如果实际做东西,建议使用Mike
Lischke的GLScene控件组(http://www.lischke-online.de/)。
end
else
删除注册表项.......................
end;初始化扩展是通过IShellExtInit实现的,当外壳调用IShellExtInit.Initialize时,它传递一个数据对象包含来文件对应的目录的PIDL标识符。Initialize方法需要从数据对象中提取文件名,并把文件名和PIDL标识符保存起来为了以后使用。
function TCXPropSheet.SEIInitialize(pidlFolder: PItemIDList;
lpdobj: IDataObject; hKeyProgID: HKEY): HResult;
var
StgMedium: TStgMedium;
FormatEtc: TFormatEtc;
szFile: array[0..MAX_PATH+1]of Char;
filecount: integer;begin
Result:=E_FAIL;
if(lpdobj=nil)then
begin
Result:=E_INVALIDARG;
messagebox(0, ’1’, ’错误’, mb_ok);
Exit;
end;
with FormatEtc do
begin
cfFormat:=CF_HDROP;
ptd:=nil;
dwAspect:=DVASPECT_CONTENT;
lindex:=-1;
tymed:=TYMED_HGLOBAL;
end;
Result:=lpdobj.GetData(FormatEtc, StgMedium);
if Failed(Result)then
Exit;
//如果只有一个文件被选中,获得文件名并保存。
filecount:=DragQueryFile(stgmedium.hGlobal, $FFFFFFFF, nil, 0);
if filecount=1 then
begin
Result:=NOERROR;
DragQueryF [1] [2] 下一页 没有相关教程
|