在写ActiveForm的时候,遇到不少问题,下面是我对于这些问题做的一个总结:
一、DAX错误 DAX错误是DELPHI写ActiveX存在的一个老问题了,一直以来没有一个很好的解决办法,下面的方法只是说尽可能的避免DAX错误:
1、网上流传的修改AxCtrls单元 在AxCtrls单元中,找到ParkingWindow函数,修改如下:
1: function ParkingWindow: HWND;2: var3: TempClass: TWndClass;4: ParkingName : String;5: begin6: Result := xParkingWindow;7: //if Result <> 0 then Exit; //注意这里被注释掉8:9: ParkingName := 'DAXParkingWindow_' + Format('%p', [@ParkingWindowProc]);10: FillChar(TempClass, sizeof(TempClass), 0);11: if not GetClassInfo(HInstance, PChar(ParkingName), TempClass) then12: begin13: TempClass.hInstance := HInstance;14: TempClass.lpfnWndProc := @ParkingWindowProc;15: TempClass.lpszClassName := PChar(ParkingName);16: if Windows.RegisterClass(TempClass) = 0 then17: raise EOutOfResources.Create(SWindowClass);18: end;19:20: xParkingWindow := CreateWindowEx(WS_EX_TOOLWINDOW, TempClass.lpszClassName, nil,21: WS_POPUP, GetSystemMetrics(SM_CXSCREEN) div 2,22: GetSystemMetrics(SM_CYSCREEN) div 2, 0, 0, 0, 0, HInstance, nil);23: SetWindowPos(xParkingWindow, 0, 0, 0, 0, 0, SWP_NOACTIVATE or SWP_NOREDRAW24: or SWP_NOZORDER or SWP_SHOWWINDOW);25: Result := xParkingWindow;26: end;2、尽量避免使用全局变量。IE对于ActiveX是创建了之后,除非整个IE关闭,不然不会释放ActiveX。多次调用同一个ActiveX,其全部变量很可能会出现不可预料的错误。
二、释放问题 通常我们会在窗口的OnDestroy里面写释放代码,但在ActiveForm里面,窗口销毁确不会调用OnDestroy事件。通常的做法是重写ActiveForm的DoDestroy函数,如下:
1: procedure DoDestroy; override;//释放的代码写在这里面
三、使用GDI+的问题
我们使用的GDI+的代码,多半是由http://www.progdigy.com流传出来的,它在GDIOBJ单元的initialization和finalization节实现代码如下:
1: initialization2: begin3: // Initialize StartupInput structure4: StartupInput.DebugEventCallback := nil;5: StartupInput.SuppressBackgroundThread := False;6: StartupInput.SuppressExternalCodecs := False;7: StartupInput.GdiplusVersion := 1;8: // Initialize GDI+9: GdiplusStartup(gdiplusToken, @StartupInput, nil);10: end;11:12: finalization13: begin14: if assigned(GenericSansSerifFontFamily) then GenericSansSerifFontFamily.Free;15: if assigned(GenericSerifFontFamily) then GenericSerifFontFamily.Free;16: if assigned(GenericMonospaceFontFamily) then GenericMonospaceFontFamily.Free;17:18: if assigned(GenericTypographicStringFormatBuffer) then GenericTypographicStringFormatBuffer.free;19: if assigned(GenericDefaultStringFormatBuffer) then GenericDefaultStringFormatBuffer.Free;20:21: // Close GDI +22: GdiplusShutdown(gdiplusToken);23: end;24:
但是老的GDI+版本是存在BUG的,上面的代码在ActiveX释放的时候,会出现IE死掉的现象(此情况在VC编写的代码中同样存在)。因此我做了一些处理,注释掉上面的代码,然后在GDIOBJ单元中实现公共函数:
1: procedure GDIInit();2: begin3: // Initialize StartupInput structure4: StartupInput.DebugEventCallback := nil;5: StartupInput.SuppressBackgroundThread := False;6: StartupInput.SuppressExternalCodecs := False;7: StartupInput.GdiplusVersion := 1;8: // Initialize GDI+9: GdiplusStartup(gdiplusToken, @StartupInput, nil);10: end;11:12: procedure GDIFree();13: begin14: if assigned(GenericSansSerifFontFamily) then GenericSansSerifFontFamily.Free;15: if assigned(GenericSerifFontFamily) then GenericSerifFontFamily.Free;16: if assigned(GenericMonospaceFontFamily) then GenericMonospaceFontFamily.Free;17:18: if assigned(GenericTypographicStringFormatBuffer) then GenericTypographicStringFormatBuffer.free;19: if assigned(GenericDefaultStringFormatBuffer) then GenericDefaultStringFormatBuffer.Free;20:21: // Close GDI +22: GdiplusShutdown(gdiplusToken);23: end;24:
然后在ActiveForm的OnCreate和DoDestroy函数中进行创建和释放:
1: procedure TFrmMain.ActiveFormCreate(Sender: TObject);2: begin3: GDIInit();4: end;5:6: procedure TFrmMain.DoDestroy;7: begin8: inherited;9:10: GDIFree();11: end;
未完,待续...
本文总结了使用 Delphi 进行 ActiveX 开发时常见的问题及解决方案,包括如何避免 DAX 错误、正确处理 ActiveX 控件的生命周期管理以及使用 GDI+ 时的注意事项。
5604

被折叠的 条评论
为什么被折叠?



