프로그래밍/델파이

ActiveForm의 DAX 오류 해결하기.

채윤아빠 2009. 6. 18. 16:16
728x90
반응형
Delphi7을 이용한 ActiveForm을 제작하였더니, 다음과 같은 오류가 발생하였습니다.
TActiveForm의 OnDestroy가 호출되지 않는 문제가 있었고, ActiveForm을 오랫동안 사용하게 되면, 알 수 없는 오류들이 발생하는 것이었습니다.

구글링을 하여 보면, 여러 자료들이 나오고 아래 참고자료를 참고해 보시면 되고, 저는 다음과 같이 해결하였습니다.
먼저 델파이 VCL의 axctrls.pas 소스의 ParkingWindow 윈도우 부분을 아래와 같이 수정합니다. 수정 전에 원본 axctrls.pas 파일과 axctrls.dcu 파일을 백업해 둡니다.

function ParkingWindow: HWND;
var
  TempClass: TWndClass;
  ParkingName : String; 
begin
//  2009-06-23 : 각 컨트롤별로 ParkingWindow를 갖도록 함
//  Result := xParkingWindow;
//  if Result <> 0 then Exit;

  ParkingName := 'DAXParkingWindow_' +   Format('%p', [@ParkingWindowProc]);
  FillChar(TempClass, sizeof(TempClass), 0);
//  if not GetClassInfo(HInstance, 'DAXParkingWindow', TempClass) then
  if not GetClassInfo(HInstance, PChar(ParkingName), TempClass) then
  begin
    TempClass.hInstance := HInstance;
    TempClass.lpfnWndProc := @ParkingWindowProc;
//    TempClass.lpszClassName := 'DAXParkingWindow';
    TempClass.lpszClassName := PChar(ParkingName);
    if Windows.RegisterClass(TempClass) = 0 then
      raise EOutOfResources.Create(SWindowClass);
  end;
  xParkingWindow := CreateWindowEx(WS_EX_TOOLWINDOW, TempClass.lpszClassName, nil,
    WS_POPUP, GetSystemMetrics(SM_CXSCREEN) div 2,
    GetSystemMetrics(SM_CYSCREEN) div 2, 0, 0, 0, 0, HInstance, nil);
  SetWindowPos(xParkingWindow, 0, 0, 0, 0, 0, SWP_NOACTIVATE or SWP_NOREDRAW
    or SWP_NOZORDER or SWP_SHOWWINDOW);
  Result := xParkingWindow;
end;

프로젝트에 axctrls.pas 소스를 첨가하여 컴파일하여 axctrls.dcu 파일을 생성하고, axctrls.dcu 파일을 델파이가 설치된 디렉토리의 Lib 및 Lib\Debug 디렉토리에 복사합니다.

아래 참고자료의 첫번째 URL 정보를 참고하여 패치를 작성하였으나, XP에서 문제가 해결되지 않고 여전히 발생하였습니다. 다각도로 디버깅을 하여본 결과, 첫 번째 창이 사라질 때, 파킹 윈도우(ParkingWindow)도 함께 사라져버리는 것이었습니다. 그래서 첫 번째 창을 닫아버리면 세 번째 창을 띄울때부터는 DAX나 System Error 1400이나, Access Violation이 발생하는 것이었습니다.

그래서 위와 같이 처음 두 줄을 주석 처리하여 각 ActiveForm마다 새로운 파킹 윈도우(ParkingWindow가 생성되도록 하였너니, DAX 등과 같은 오류가 발생하지는 않았습니다.

그러나, 위와 같이 패치한 이후에도 사용자들에게서 몇 가지 문제점이 나타났습니다.
리소스를 더 이상 할당 할 수 없는 문제가 발생하는 경우가 있었고, 그래도 여전히 System. Error 1400 오류가 발생하는 경우가 나타났었습니다.
특이한 EurekaLog에 메모리 누수가 상당히 많이 잡한다는 점이었는데, VCL문제인지, 패치한 소스에 문제인지는 좀더 분석을 해봐야 겠습니다.

OnDestroy가 호출되지 않는 문제는 BeforeDestruction 메소드를 override 하여 OnDestroy 이벤트 핸들러를 재할당하는 방식으로 해결하였습니다.

procedure TActiveFormX1.BeforeDestruction;
begin
  OnDestroy := ActiveFormDestroy;

  inherited;
end;




참고자료