在写ActiveForm的时候,遇到不少问题,下面是我对于这些问题做的一个总结:
一、DAX错误 DAX错误是DELPHI写ActiveX存在的一个老问题了,一直以来没有一个很好的解决办法,下面的方法只是说尽可能的避免DAX错误:
1、网上流传的修改AxCtrls单元 在AxCtrls单元中,找到ParkingWindow函数,修改如下:
1: function ParkingWindow: HWND;
2: var
3: TempClass: TWndClass;
4: ParkingName : String;
5: begin
6: 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: begin
13: 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_NOREDRAW
24: 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: initialization
2: begin
3: // 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: finalization
13: begin
14: 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: begin
3: // 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: begin
14: 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: begin
3: GDIInit();
4: end;
5:
6: procedure TFrmMain.DoDestroy;
7: begin
8: inherited;
9:
10: GDIFree();
11: end;
未完,待续...