이벤트 : OnCustomDrawCell


if not ( AViewInfo.Selected ) then

  begin

    if ( Odd( AViewInfo.GridRecord.Index ) ) then

      ACanvas.Brush.Color := $00F4F4F4

    else

      ACanvas.Brush.Color := clWhite;

  end;

원도우 OS에서는 폼관리가 SDI폼와 MDI폼와 MSDI폼으로 나누어진다.

 

SDI(Single Document Interface)폼

 

한창에 하나의 문서만 열어 놓고 작업 할 수 있는 형태의 프로그램입니다.

메모장,그림판,웹브라우저등에서 사용됩니다.

 

MDI(Multiple Document Interface)폼

 

한창안에서 여러 문서창을 열어 놓고 작업 할 수 있는 형태의 프로그램 방식입니다.
포토샵에 사용됩니다.

 

MSDI(Multiple Single Document Interface)폼

 

최근에 한글2002 , 워드2003 같은 프로그램에서 사용되며 한창에서 여러창을 열수 있으며 그 열린창의 구조는 MDI구조를 가지고 있게 된다.

 

※ MDI 구조에서 자식창을 최대화하면 최소화, 최대화, 닫기창이 안보인다.

 

보통 자식창이 최대화 되면 최소화, 최대화, 닫기 창이 안보인다.

이유는 부모창에 메뉴컴포넌트가 없기 때문이다. 부모창에 메뉴 컴포넌트를 생성하면 문제가 해결되지만 그게 힘들다면 최대화, 아이콘화, 창배열등의 함수가 있으므로 이것들을 불러내 부모창의 툴바나 팝업메뉴에 사용하면 됩니다.

(ArrangeIcons, Cascade, Next, Previous, Tile, WindowState)

 

델파이 서브폼(메인폼에서 호출되는 폼)의 종류

 

모달폼

 

서브폼을 종료해야만 메인폼으로 이동, 선택할수 있는 폼스타일

 

모달리스폼

 

메인폼과 서브폼을 자유자재로 이동, 선택할수 있는 폼스타일

 

델파이 서브폼생성시 초기 과정

 

1) File/New/Form에서 새로운 폼을 추가합니다.

 

2) 새로운폼을 출력한후 File/Save을 이용하여 유닛을 저장합니다.

 

3) 메인폼에서 서브폼을 호출하기 위해 메인폼을 선택한후 File/Use Unit으로 서브폼의 유닛명을 선택합니다.

 

4) Project/Options을 선택하여 auto create forms에 메인폼만 빼고 서브폼을 전부 우측으로 이동시킨다. auto create forms은 프로그램 시작시 자동으로 생성되기 필요없는 메모리를 사용하게 됩니다. 서브폼들은 프로그램 시작시 자동생성할 필요가 없습니다.

 

델파이 서브폼출력 예제

 

※폼 생성시 구문은 다음과 같다.

form_name:=T+form_name.create(application);

 

procedure TForm1.XiButton3Click(Sender: TObject);
var
  i:byte;

  Form2:TForm2:
begin
if RadioGroup1.ItemIndex = 0 then//모달창 출력
  begin
    Form2:=TForm2.Create(application);
    //application이면 application객체에 포함
    //self이면 form객체에 포함
    //form이면 form객체에 포함
    Form2.ShowModal;
    Form2.Free;
  end
else if RadioGroup1.ItemIndex = 1 then//모달리스창 출력
  begin
    //이미 폼이 출력되었으면 출력을 안합니다.
    for i := 0 to application.ComponentCount -1 do
    begin
      if application.Components[i] is TForm2 then
        begin
          (application.Components[i] as TForm).show;
          exit;
        end;
    end;
    form2:=TForm2.Create(application);
    form2.show;
  end
else//메세지 출력
  begin
    ShowMessage(‘폼 종류를 선택하시오’);
  end
end;

 

※ 모달창을 닫을때는 폼객체을 소멸하기위한 키워드인 free메소드를 사용해야 합니다.

※ 모달리스창은 해당 서브폼의 onClose이벤트에 "action:=cafree;" 이소스를 넣어서 종료해야 시스템에 메모리를 정상적으로 반납합니다.

 

서브폼과 버튼컴포넌트의 ModalResult속성 이용하기

 

모달창은 호출한품에서 결과값을 리턴받아 제어가 가능하다.

다음의 소스는 메인폼에 기입한다.

procedure TForm1.XiButton3Click(Sender: TObject);
begin
  Form3:=TForm3.Create(application);
  if Form3.ShowModal = mrAbort then
    ShowMessage(‘신기하다’);
  Form3.Free;
end;

서브폼의 버튼 컴포넌트에서 ModalResult속성에 mrAbort를 선택한후 프로그램 실행하면

메세지가 출력된다.

 

모달창에서의 modalresult을 이용해 창생성시 나쁜점

 

1.modalresult에서 help빼고는 모든 창이 닫힌다.

2.modalresult을 사용한  폼에서 엔터키 제어시 무조건 modalresult을 사용한 버튼이 눌러진다.

3.부모창에서 제어하지 않는 modalresult을 사용한 버튼은 무조건 창을 닫게 한다.

 

[MDI] SDI으로 폼생성이 아닌 MDI방식으로 폼생성시 종료시 처리

 

MDI방식에서는 SHOW메소드로 생성이 가능하며 종료시에는 해당 폼의 CLOSE이벤트에

Action := caFree;을 넣어주어여 메모리 반납이 됩니다.

 

[MDI] MDI 방식의 프로그램 주의사항

 

fsMDIForm이 화면에 모두 로딩되기 전에 fsMDIChild를 모달리스폼으로 호출하게되면

"Can create form. No MDI forms are currently active"라는에러 메시지가 출력되고 폼생성이

안된다.

 

fsMDIForm이 화면에 로딩되기 전이라고 하면 onActivate, onCreate, onShow등과 같은 이벤트

에서 실행되는 시점을 말한다.

 

이때는 화면에 로딩되기 맨마지막 부분의 onCreate나 onShow에 타이머를 작동시키는 소스

를 넣고 해당 타미머에 fsMDIChild를 호출하는 소스를 넣어주면 된다.

 

※ MDIChild폼을 showmodal메소드로 생성하면 "Cannot make a visible window modal"

에러메시지를 출력후 모달리스폼으로 생성되어진다.

 

[MDI] 예제 타이머 컴포넌트의 onTimer 이벤트 핸들러 내용

 

procedure TFMain.FirstWorkTimer(Sender: TObject);
begin

  FirstWork.Enabled := false;

  ShowNotice; //# 공지사항창
  ShowMinWon_Check;
  //ShowDocSeviceNotice;

  //20051109 edscom 마우스 휠 움직임 좋게 할려구..
  Application.onMessage:= MusMessage;

end;

 

[MDI] 필요한 상황

 

1. MDI 프로그램을 실행시키면 자동으로 MDIChild 폼이 생성돼야 할때


프로그램의 중복실행을 방지하는 방법으로는 CreateMutex가 많이 쓰이는 것 같습니다.
저는 조금 고전적이지만 이해하기 쉬운 Global Atom Table을 이용한 방법을 소개합니다.
실은 10년전쯤에 컴포넌트로 만든 것을 컴포넌트 설치과정 없이 바로 이용할 수 있도록 단순한 유니트로
바꾼 것입니다. 
이용법은 프로그램 소스 내용 중 상수로 정의된 Author와 RunProgram 값을 올바르게 고친 후 프로젝트가 위치한 
폴더에 복사해 두고, 아래와 같이 프로젝트 소스화일(*.dpr)의 uses절에 제일 먼저 RunOne을 등록만 하면 됩니다. 
  uses RunOne, 
            Forms, . . .  .

그리고 RunOne은 실행하고자 하는 프로그램이 이미 실행중일 경우 최소화 상태이면 원래 크기로, 최상위
윈도우가 아니면 최상위 윈도우로 변경하여 사용자가 이전에 이미 실행 중이었다는 것을 바로 인식할 수 
있도록 해 줍니다.
아래는 RunOne.pas 소스입니다.

unit RunOne;

interface

uses WinTypes, SysUtils, Forms;

const
  Author = 'Silhwan Hyun';  // 저자명 : 실행여부를 검사하기 위한 검색어를 구성함.
  RunProgram = 'TClock';    // 프로그램명 :             "

implementation

var
  AtomText: array[0..63] of Char;
  AtomSaved : boolean = false;

  MyClassName    : array[0..255] of Char;
  FoundPrevInst  : boolean = false;
  PrevInstHandle : HWnd = 0;
  FoundAtom      : TAtom;

  NewAtom : TAtom;
  MyPopup : HWnd;

function LookAtAllWindows(Handle: HWnd; Temp: Longint): BOOL; stdcall;
var
  ClassName : array[0..255] of Char;
begin
  LookAtAllWindows := true;

  if GetClassName(Handle, ClassName, SizeOf(ClassName)) > 0 then
  begin
    if StrComp(ClassName, MyClassName) = 0 then // 동일 window class ?
    begin
    // 중복실행여부를 조사하기 위한 검색어 생성
       StrPCopy(AtomText, Author + RunProgram + IntToStr(Handle));
    // 검색어가 Global Atom Table에 등록되어 있는지 확인
       FoundAtom := GlobalFindAtom(AtomText);
       if FoundAtom <> 0 then  // Global Atom Table에 등록되어 있으면
       begin
          FoundPrevInst  := true;    // 이미 실행 중인 것으로 표시
          PrevInstHandle := Handle;  // 실행 중인 어플리케이션 윈도우 핸들
          LookAtAllWindows := false; // enumeration 함수를 종료시킨다
       end;
    end;
  end;
end;

initialization
 // 프로그램의 클래스명을 알아낸다.   
  GetClassName(Application.Handle, MyClassName, SizeOf(MyClassName));
 // 윈도우를 검색하여 중복실행이 아닌지 확인한다
  EnumWindows(@LookAtAllWindows, 0);
  if FoundPrevInst then   // 이미 실행 중이면
  begin
     MyPopup := GetLastActivePopup(PrevInstHandle);
     BringWindowToTop(PrevInstHandle);
     if IsIconic(MyPopup) then
     begin
        ShowWindow(MyPopup, SW_RESTORE);  // 최소화 상태이면 원래 크기로
     end else
        BringWindowToTop(MyPopup);        // 최상위 윈도우로
     SetForegroundWindow(MyPopup);      // 포커스를 준다.    *** Added ***

     Halt(0);  // 새로 실행한 프로그램은 강제로 종료시킨다
  end else
  begin
   // 실행중이 아니면 검색어를 Global Atom Table에 등록한다
     StrPCopy(AtomText, Author + RunProgram + IntToStr(Application.Handle));
     NewAtom := GlobalAddAtom(AtomText);
     if NewAtom <> 0 then   // Global Atom Table에 등록성공이면
        AtomSaved := true;
  end;

finalization
  // 프로그램 종료시는 Global Atom Table에 등록해 둔 검색어를 해제한다.
  if AtomSaved then
  begin
     FoundAtom := GlobalFindAtom(AtomText);
     if FoundAtom <> 0 then
        GlobalDeleteAtom(FoundAtom);
  end;

end.



댓글 중~ 


단지...
BringWindowToTop 다음에

     SetForegroundWindow(MyPopup);

이것을 추가하는것이 더 편할것 같습니다.
어차피 실행할려고 한것이니 최상위 및 원복 후 포커스를 주는것이 좋을듯 합니다. ^^  



원본 링크 : http://www.delmadang.com/community/bbs_print.asp?bbsNo=3&bbsCat=0&indx=412497

+ Recent posts