2009-04-06 3 views
2

내가 일하고있는 응용 프로그램의 한 부분에서, 정확히 어떻게 델파이 문서가 그것을 말하는지 (이 코드 샘플은 델파이 도움말 파일에서 나온 것입니다) CMExit 메시지 수신시 유효성 검사를 수행하는 폼 컨트롤이 있습니다) :모달 대화 상자가 닫힐 때 Delphi CMExit 메시지가 전송되지 않습니까?

procedure TDBCalendar.CMExit(var Message: TWMNoParams); 
begin 
try 
    FDataLink.UpdateRecord;       { tell data link to update database } 
except 
    on Exception do SetFocus;      { if it failed, don't let focus leave } 
end; 
inherited; 
end; 

컨트롤의 초점이 사라지 자마자 유효성 검사를 수행하기위한 것입니다. 예를 들어, OK 버튼을 클릭하면 폼 컨트롤에 포커스가 사라지고이 메서드는 실행되고 예외가 발생하면 해당 폼 컨트롤로 다시 포커스가 설정됩니다. (따라서 "확인"버튼의 "클릭"이벤트는 절대 통과하지 못하고 대화 상자는 절대로 닫히지 않을 것입니다).

문제는이 양식 컨트롤이 모달 대화 상자 창 안에 있다는 것입니다. 확인을 클릭하면 실제로 CMExit 메시지가 전송되고 레코드가 업데이트되고 유효성 검사가 수행됩니다. 그러나 양식 컨트롤에서 Enter 키를 누르면 CMExit 메시지를 보내지 않고 모달 대화 상자가 을 닫습니다. 폼 컨트롤이 결코 "포커스를 잃지 않는 것"입니다. 즉, 양식이 실제로 데이터의 유효성을 검사하지 않고 닫힐뿐만 아니라 데이터 세트도 업데이트되지 않습니다.

이 문제가 발생하면 내 데이터 집합 업데이트/유효성 검사 코드를 배치하기 가장 좋은 곳은 어디입니까? OnCoseQuery 핸들러에서 대화 상자 양식으로 옮기고이를 구현할 수는 있지만 양식 자체에서 양식 컨트롤 모두에 논리가 복제된다는 것을 의미합니다. (폼 컨트롤은 다른 장소에서 사용되며, 동작을 변경하지 않도록하고 싶습니다.)

는 (나는 양식이 닫힙니다. 컨트롤이 결코 실제로 잃게 초점을 않기 때문에 CMExit가 트리거되지 않는다는 것을 추측하지만, 폼 컨트롤은 여전히 ​​폐쇄 된 형태의 "집중하고있다".)

+0

Cm_Exit는 포커스 변경 이벤트입니다. 그것으로부터 SetFocus를 호출하지 마라. 초점이 이미 변경되는 동안 초점을 변경하지 마십시오. 대신 메시지를 게시하고 이에 대한 응답으로 포커스를 변경하십시오. OS는 포커스를 변경하는 동안 중단되는 것을 좋아하지 않습니다. 실제로 초점이 무엇인지 혼란 스럽습니다. –

답변

7

닫는 양식이 반드시 TControl의 퇴장 이벤트를 시작하는 것은 아닙니다. 사용자는 Alt-F4를 누를 수 있습니다.

유효성 검사를 별도의 proc으로 옮기고 해당 종료 프로 시저를 종료시 닫기 이벤트에서 호출하는 것이 좋습니다.

아래의 코드는 너무 많은 수정없이 작동합니다 :

function TDBCalendar.UpdateSuccessful: boolean; 
begin 
    { tell data link to update database } 
    { if successful, return True, else return False } 
    { this function must be Public if a form is gonna check this value } 
    Result := True; 
    try 
    FDataLink.UpdateRecord; 
    except on Exception do 
    Result := False; 
    end; 
    inherited; 
end; 

procedure TDBCalendar.CMExit(var Message: TWMNoParams); 
begin 
    //if not valid, then don't let them leave 
    if not(UpdateSuccessful) then begin 
    SetFocus; 
    end; 
end; 

/////////////////////////////////////////// 
//on the form that contains your control... 
/////////////////////////////////////////// 

procedure TMyForm.FormClose(Sender: TObject; var Action: TCloseAction); 
begin 
    //if not valid, then don't let them close the form 
    if not(dbcal.ControlIsValid) then begin 
    Action := caNone; 
    end 
    else begin 
    inherited; 
    end; 
end; 
관련 문제