http://cbuilder.borlandforum.com/impboard/impboard.dll?action=read&db=bcb_tip&no=883
장성호님의 글입니다.
Design-time때 Form의 FormStyle을 fsStayOnTop으로 설정하고
해당Form을 Show또는 ShowModal해보면
실제로 StayOnTop이 적용이 안된다는 질문이 커뮤니티에 심심찮게 올라옵니다.
비슷한 팁들이 여러가지 있던데... 정확한 원인과 증상에 대한 설명은 잘 없더군요
제가 올린 답변글에서도 마찬가지구...
오늘 일때문에 간단히 테스트 해보았는데...
정확한 이유에 대해서는 설명을 못하겠지만.
증상과 해결방안에 대해서 좀 기술해 보겠습니다.
Form의 FormStyle을 fsStayOnTop으로 설정하면
Form이 생성될때 TCustomForm의 CreateWnd함수에서 다음과 같은 코드가 실행됩니다.
stayontop관련 팁들을 보면 대게
SetWindowPos( Handle , HWND_TOPMOST, ...) 를 하라고 되어있죠
그런데 이렇게 한후에 Form을 Show 하면
Application(프로그램)내에서는 해당폼이 top으로 뜹니다.
그런데 전체 desktop에는 적용이 안되죠
제가 이해한 것은 Form이 Visible=true일때랑 false일때
SetWindowPos(Handle, HWND_TOPMOST ... 이 다르게 먹는다는것입니다.
그럼
Form을 데스크탑 전체에 topmost로 항상띄우려면 어떻게 해야할까요?
Form의 OnShow이벤트에서
SetWindowPos(Handle, HWND_TOPMOST...해주면 됩니다.
FormStyle을 그냥 fsNormal로 둬도 상관없구요
Form이 만약 hide되었다가 다시 Show할때 topmost가 해제 되기때문에
매번 Form이 show될때마다 SetWindowPos(Handle, HWND_TOPMOST...를 해줘야 합니다.
그런데...
Form을 Show했을때랑 ShowModal했을때 TopMost가 다르게 동작하는 부분도 있더군요
ShowModal로 했을경우엔 위와같이 Form의 OnShow에서
한번 SetWindowPos(..HWND_TOPMOST...)해주면 되는데..
그냥 Show로 할경우 현재프로그램의 다른 Form으로 포커스를 이동할경우엔 문제없지만
다른프로그램으로 이동하면 topmost가 풀려버립니다.
이경우 현재프로그램이 Deactivate 될때 TopMost폼을 다시 ToopMost로 Set해주면 되더군요
다음과 같이...
참 그리고 만약 top속성을 변경하고 싶다고
그리고 run-time에 FormStyle을 변경하는 경우가 있는데...
이것도 별로 바람직하지는 않습니다.
임프님이 작성한 팁에 나와있듯이 Form이 한번 껌벅거릴것입니다.
http://cbuilder.borlandforum.com/impboard/impboard.dll?action=read&db=bcb_tip&no=32
FormStyle을 변경할때 CreateWindow를 다시 하기때문이죠
윈도우 핸들을 따로 저장해뒀다 .. 뭐시기 하는경우 문제가 발생할수 있겠죠
그리고 Form위의 다른 window-control도 모두 CreateWindow를 다시 하기때문에 매우 좋지 않습니다.
간만에 팁을 올렸네요
요즘 회사일이 바쁘기도 하구...
개인적으로 운영하는 카페도 신경쓴다구... 볼포에는 Q&A만 주로 하네요..
그럼..
장성호님의 글입니다.
Design-time때 Form의 FormStyle을 fsStayOnTop으로 설정하고
해당Form을 Show또는 ShowModal해보면
실제로 StayOnTop이 적용이 안된다는 질문이 커뮤니티에 심심찮게 올라옵니다.
비슷한 팁들이 여러가지 있던데... 정확한 원인과 증상에 대한 설명은 잘 없더군요
제가 올린 답변글에서도 마찬가지구...
오늘 일때문에 간단히 테스트 해보았는데...
정확한 이유에 대해서는 설명을 못하겠지만.
증상과 해결방안에 대해서 좀 기술해 보겠습니다.
Form의 FormStyle을 fsStayOnTop으로 설정하면
Form이 생성될때 TCustomForm의 CreateWnd함수에서 다음과 같은 코드가 실행됩니다.
- procedure TCustomForm.CreateWnd;
- var
- ClientCreateStruct: TClientCreateStruct;
- begin
- inherited CreateWnd;
- if NewStyleControls then
- if BorderStyle <> bsDialog then
- SendMessage(Handle, WM_SETICON, 1, GetIconHandle) else
- SendMessage(Handle, WM_SETICON, 1, 0);
- if not (csDesigning in ComponentState) then
- case FormStyle of
- fsMDIForm:
- ...
- fsStayOnTop:
- SetWindowPos(Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE or
- SWP_NOSIZE or SWP_NOACTIVATE); // 팁과 똑같은 방식으로 설정함
- end;
- end;
procedure TCustomForm.CreateWnd; var ClientCreateStruct: TClientCreateStruct; begin inherited CreateWnd; if NewStyleControls then if BorderStyle <> bsDialog then SendMessage(Handle, WM_SETICON, 1, GetIconHandle) else SendMessage(Handle, WM_SETICON, 1, 0); if not (csDesigning in ComponentState) then case FormStyle of fsMDIForm: ... fsStayOnTop: SetWindowPos(Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE or SWP_NOACTIVATE); // 팁과 똑같은 방식으로 설정함 end; end;
stayontop관련 팁들을 보면 대게
SetWindowPos( Handle , HWND_TOPMOST, ...) 를 하라고 되어있죠
그런데 이렇게 한후에 Form을 Show 하면
Application(프로그램)내에서는 해당폼이 top으로 뜹니다.
그런데 전체 desktop에는 적용이 안되죠
제가 이해한 것은 Form이 Visible=true일때랑 false일때
SetWindowPos(Handle, HWND_TOPMOST ... 이 다르게 먹는다는것입니다.
그럼
Form을 데스크탑 전체에 topmost로 항상띄우려면 어떻게 해야할까요?
Form의 OnShow이벤트에서
SetWindowPos(Handle, HWND_TOPMOST...해주면 됩니다.
- procedure TForm2.FormShow(Sender: TObject);
- begin
- SetWindowPos(Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE or
- SWP_NOSIZE or SWP_NOACTIVATE);
- end;
procedure TForm2.FormShow(Sender: TObject); begin SetWindowPos(Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE or SWP_NOACTIVATE); end;
FormStyle을 그냥 fsNormal로 둬도 상관없구요
Form이 만약 hide되었다가 다시 Show할때 topmost가 해제 되기때문에
매번 Form이 show될때마다 SetWindowPos(Handle, HWND_TOPMOST...를 해줘야 합니다.
그런데...
Form을 Show했을때랑 ShowModal했을때 TopMost가 다르게 동작하는 부분도 있더군요
ShowModal로 했을경우엔 위와같이 Form의 OnShow에서
한번 SetWindowPos(..HWND_TOPMOST...)해주면 되는데..
그냥 Show로 할경우 현재프로그램의 다른 Form으로 포커스를 이동할경우엔 문제없지만
다른프로그램으로 이동하면 topmost가 풀려버립니다.
이경우 현재프로그램이 Deactivate 될때 TopMost폼을 다시 ToopMost로 Set해주면 되더군요
다음과 같이...
- procedure TForm1.FormCreate(Sender: TObject);
- begin
- Application.OnDeactivate:=AppDeactivate;
- end;
- procedure TForm1.AppDeactivate(Sender: TObject);
- begin
- if Form2.Visible then
- begin
- SetWindowPos(Form2.Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE or
- SWP_NOSIZE or SWP_NOACTIVATE );
- end;
- end;
procedure TForm1.FormCreate(Sender: TObject); begin Application.OnDeactivate:=AppDeactivate; end; procedure TForm1.AppDeactivate(Sender: TObject); begin if Form2.Visible then begin SetWindowPos(Form2.Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE or SWP_NOACTIVATE ); end; end;
참 그리고 만약 top속성을 변경하고 싶다고
그리고 run-time에 FormStyle을 변경하는 경우가 있는데...
이것도 별로 바람직하지는 않습니다.
임프님이 작성한 팁에 나와있듯이 Form이 한번 껌벅거릴것입니다.
http://cbuilder.borlandforum.com/impboard/impboard.dll?action=read&db=bcb_tip&no=32
FormStyle을 변경할때 CreateWindow를 다시 하기때문이죠
윈도우 핸들을 따로 저장해뒀다 .. 뭐시기 하는경우 문제가 발생할수 있겠죠
그리고 Form위의 다른 window-control도 모두 CreateWindow를 다시 하기때문에 매우 좋지 않습니다.
간만에 팁을 올렸네요
요즘 회사일이 바쁘기도 하구...
개인적으로 운영하는 카페도 신경쓴다구... 볼포에는 Q&A만 주로 하네요..
그럼..