Q&A

  • 포인터가 가르키는 주소가 접근가능한 부분인지 Free된 영역인지 검사하는 함수...
<!--CodeS-->
if not Assigned(Form1) then begin
  Form1 := TForm.Create(MainForm);
  Form1.WindowState := wsMaximized;
end
  else Form1.Show;
<!--CodeE-->

MDI 메인에 작성되어진 코드입니다.
그리고 Form1 은 MDI Child 입니다.
MDI Child는 닫으면 최소화가 되길래
OnClose 이벤트에

ActiveControl := Nil;
Self.Free;

를 해주어서 완전 날려버렸습니다.
그렇지만 MainForm 에 Form1 에는 그 할당받은 주소가 남아 있어서
Assigned 를 호출하면 True 를 반환하는데
Assigned 말고 포인터가 가르키는 주소가 유효한지 검사하는 함수는 없나요?
4  COMMENTS
  • Profile
    이중철 2005.07.29 01:31
    Assigned 함수는 해당 변수의 값이 nill인지 아닌지만 체크 합니다.
    Form1(MID Child 폼 가정시 지금은 TForm에서 생성되었기에 Normal form)이
    1회만 생성되기만을 원하신다면..
    MDIChildCount, MDIChildren을 사용해보세요
    참 그리고 예시된 문에서 TForm으로 생성되는 것이므로 MDIChild폼이 아닌것은 아시죠
    아래문장의 내용 그대로 사용할 생각 이시면 Controls 또는 Screen.Forms을 사용하세요

    그리고 Close시 Suicide 코드는 웬지 이상하지 않나요?
    Action := caFree;로 대체 하시는것이 좋을듯 합니다.


  • Profile
    채규봉 2005.07.29 01:57
    답변 감사합니다.
    먼저 예문에서 해당 폼 타입이 들어가는데
    혹시 뭣할까해서 걍 대충 수정했는데 그것까지 신경을 못 썼네요 ^^;

    <!--CodeS-->
        private
          CalA0B0C0D0: TCalA0B0C0D0;
          CalA0B0C0D1: TCalA0B0C0D1;
          CalA0B0C1D0: TCalA0B0C1D0;
    <!--CodeE-->
    일딴 메인폼에 위와 같이 선언이 되어 있습니다.
    위와 같은 폼이 수십개가 됩니다.

    <!--CodeS-->
            if FormName = 'CalA0B0C0D0' then begin
              if not Assigned(CalA0B0C0D0) then begin CalA0B0C0D0 := TcalA0B0C0D0.Create(MainForm); CalA0B0C0D0.WindowState := wsMaximized; end
              else CalA0B0C0D0.Show;
            end
            else if FormName = 'CalA0B0C0D0' then begin
              if not Assigned(CalA0B0C0D0) then begin CalA0B0C0D0 := TCalA0B0C0D0.Create(MainForm);  CalA0B0C0D0.WindowState := wsMaximized; end
              else CalA0B0C0D0.Show;
            end
    <!--CodeE-->
    그리고 이런식으로 수십번의 노가다를 했습니다. ㅎㅎ
    띄울 폼 이름은 DB에 들어있고 변수의 이름과 같긴하지만 어찌 접근을 해야 할지 몰라서..


    문제가 뭐냐면 폼의 구조가 트리라서 일딴 트리뷰를 DB에서 읽어서 구성했습니다.
    노드를 더블클릭하면 그 노드에 해당하는 폼의 이름을 DB에서 읽어 옵니다.
    그리고 그 이름의 폼이 생성 되었으면 보여주고 없으면 생성을 합니다.
    문제는 x박스를 누르면 그폼이 최소화 되면서 뒤에 숨어있던 수많은 -_-; 폼들이 너져분하게 보여집니다.
    그래서 x박스를 누르면 아예 사라지게 바꿨어요.
    (님께서 말씀하신 Action := caFree; 로 바꿨습니다. 제가 쓴 코드로도 되긴했는데 실은 뭔지모르고 여기저기서 따온거라 ㅎㅎ)
    그리고 나서 다시 그 폼을 띄우려고 하면 이미 생성이 되어 있으므로 접근을 하려고 하는데 접근하면
    Null pointer 오류가 발생하는것 같습니다.

    만약에 Action:=caFree; 로 사용하면 MDIChildCount가 줄어드나요?
    그러면 거기서 찾아서 띄우고 없으면 생성을 하면 될 듯한데..
    아.. 다시 질문을 드리려다가 문득 떠올라서 한번 해봐야겠습니다.

    ps 혹시 위와 같이 저렇게 삽질하는 방법 말고 문자열로 되어 있는 폼 이름을 이용하여
    해당 폼을 접근하는 좋은 방법이 있을까요??


  • Profile
    이중철 2005.07.29 22:03
    initialize 이나 메인폼 처음 시작 하는 부문에 다음과 같이 클래스를 등록 하여 주세요
    <!--CodeS-->
       RegisterClasses([TCalA0B0C0D0, TCalA0B0C0D1, TCalA0B0C1D0]);
    <!--CodeE-->


    아래의 함수는 클래스명칭으로만 설정했는데 만약 명칭 , 클래스명칭 이렇게 두개를 키로 할때는
    아래의 것을 약간 변형하여 사용하시면 될듯합니다.
    그리고 아래소스는 검증이 안된것입니다. 잔 실수가 있을수 있습니다.
    <!--CodeS-->
       Function TMainForm.ShowChildWnd( vFormClassNm : string) : TForm;
       var
          MyFormClass : TFormclass;
          i : integer;
       begin
          for i := 0 to MainForm.MDIChildCount - 1 do
              if Uppercase(MainForm.MDIChildren[i].classname) = Uppercase(vFormClassNm) then
              begin
                Result := MainForm.MDIChildren[i];
                break;
              end;

          if Result = nil then
          begin
             MyFormClass := TFormClass(GetClass(vFormClassNm));
             Result := MyFormClass.Create(MainForm);
            
          end;
       end;
    <!--CodeE-->

  • Profile
    채규봉 2005.08.18 13:13
    삽질로 끝내놓고 한참이 지난후에 봤습니다.
    답변 정말 감사합니다. ^^
    정말 좋은 방법이 있었는데 괜한 삽질만 했군요 ^^;