질문의 설명이 잘 이해가 가지 않네요
" 임의로 handle 과 real 을 a,b 로 표현하겠습니다" 라는 문장에서
"handle"은 뭐고 "real"은 뭔가요?
==================================================================
질문에 대한 이해를 떠나서 Main폼의 WndParent를 GesktopWindow로 설정해서 사용할때
지난번에 얘기하지 못한 중요한 사실이 있네요..
[VCL 어플리케이션의 메인윈도우 핸들은?]
BDS2005 이상 버젼에서는 설정에 따라서 다르지만
기본적으로 VCL(Delphi , CBuilder)에서 메인윈도우는 MainForm->Handle이 아닙니다.
Application->Handle이 VCL 어플리케이션의 메인윈도우핸들 입니다.
확인하는 쉬운 방법은 작업표시줄에서 어플리케이션 버튼에서 마우스 우클릭하여
System메뉴를 띄워보세요
보통 System메뉴는 (이전크기,이동,최대화,최소화,닫기) 이렇게 여섯가지 입니다.
그런데 메인폼의 캡션에서 메뉴를 띄우면 6개의 메뉴가 나오지만
작업표시줄에서 메뉴를 띄우면 (이전크기,최소화,닫기) 이렇게 3가지만 나옵니다.
왜냐하면 Application->Handle 윈도우를 CreateWindow한후에
MAXIMIZE , SIZE , MOVE 세개의 시스템 메뉴를 삭제하기때문이죠
[Application->MainForm은 어떻게 결정되나?]
Application->MainForm은 프로그램에서 Form을 생성하는 순서에 따라
Form1이 될수도 있구 Form2도 될수 있습니다.
일반적으로 먼저 생성되는 폼이 Application->MainForm이 되지만
좀더 정확하게 표현하면
Application->CreateForm 함수로 생성된 첫번째 폼이 Application->MainForm 이 됩니다.
[Application->MainForm과 Application->Hanlde은 무슨 관계?]
대부분의 경우 VCL로 어플리케이션 개발할때
Application->Hanlde이 메인윈도우핸들이라는것을 인식하지 못합니다.
왜냐하면
Application->MainForm에서 발생하는 System-Message중 일부를 Application->Hadle 로 보내구요
작업표시줄의 Application->Handle의 버튼에서 발생하는 System-Message중 일부를
Application->MainForm->Handle로 보내기때문입니다.
[Application->MainForm과 Application->Hanlde의 연결고리 끊기]
여기가 가장 중요한데요
다음과 같이 Application->Handle을 hide시키면
ShowWindow(Application->Handle,SW_HIDE);
Application->Handle에서 발생하는 system-message를 필터링 하는 기능은
별로 신경쓰지 않아도 될것입니다.
하지만 Application->MainForm->Handle에서 발생하는 system-message(WM_SYSCOMMAND)는
Application->Handle의 WindowProc로 가지 않도록 필터링 해줘야 합니다.
아래는 TCustomForm의 WM_SYSCOMMAND 메세지에 대한 처리 코드 입니다.
procedure TCustomForm.WMSysCommand(var Message: TWMSysCommand);
begin
with Message do
begin
if (CmdType and $FFF0 = SC_MINIMIZE) and (Application.MainForm = Self) then
Application.WndProc(TMessage(Message)) //여기가 중요
else if (CmdType and $FFF0 <> SC_MOVE) or (csDesigning in ComponentState) or
(Align = alNone) or (WindowState = wsMinimized) then
inherited;
if ((CmdType and $FFF0 = SC_MINIMIZE) or (CmdType and $FFF0 = SC_RESTORE)) and
not (csDesigning in ComponentState) and (Align <> alNone) then
RequestAlign;
end;
end;
위 코드를 보면 WM_SYSCOMMAND 에서
CommandType즉 WParam이 SC_MINIMIZE 이구 현재 폼이 Application->MainForm이면
해당 Application.WndProc 로 보내서 처리하도록 하고 있습니다.
코드
다음과 같이 코딩하면 메인폼의 minimize command가 Application->Handle 의 WindowProc로 가는것을
막을수 있습니다.
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::CreateParams(Controls::TCreateParams &Params)
{
TCustomForm::CreateParams(Params);
//Form1의 Wndparent를 Gesktopwindow로 설정
Params.WndParent=0;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::WndProc(TMessage &Msg)
{
if(Msg.Msg==WM_SYSCOMMAND && Msg.WParam==SC_MINIMIZE)
{
//Form1의minimize 시스템 메세지를 필터링
this->WindowState=wsMinimized;
return;
}
TCustomForm::WndProc(Msg);
}
void __fastcall TForm1::FormShow(TObject *Sender)
{
//Form1이 Show될때 Application->Handle을 hide시킴
ShowWindow(Application->Handle,SW_HIDE);
}
//---------------------------------------------------------------------------
그럼...
조안 님이 쓰신 글 :
: 안녕하세요. 저번에 ShowMessage 최상위에 뜨는 내용 질문드렸는데요
:
http://cbuilder.borlandforum.com/impboard/impboard.dll?action=read&db=bcb_qna&no=57217
:
: 그때 말씀해주신대로
:
: 메인폼의 WndParent도 Application->Handle이 아니라 GetDesktopWindow로 설정하구
: 메인폼이 Show될때 Application->Handle을 Hide시켜 버립니다.
:
: 를 사용한뒤,
:
: String sClsName=Screen->ActiveForm->ClassName();
: if(sClsName=="TMessageForm")
: SetWindowPos(Screen->ActiveForm->Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
:
: 를 사용하여 메시지박스를 항상 최상위로 띄웠습니다.
:
: 이게 잘 통한다고 생각했는데..
:
: 문제는, 메인폼에 최소화 버튼이 있습니다
:
: 임의로 handle 과 real 을 a,b 로 표현하겠습니다
:
: 최소화 버튼을 누르기 전까지는. a가 hide 상태로 잘되있어서. 작업표시줄에 b만 뜨고, b만 보여집니다
:
: 근데 최소화 버튼을 누르면 b 가 작업표시줄로 숨어들어가면서, a 가 나타나고, 화면에도 a가 뜨게됩니다
:
: 이게 어떻게 된건지 ㅜㅜ
:
: 어떻게 하면 이문제를 해결 할 수 있을까요?