ShowMessage로 메세지박스를 보여주려고 하면
아주 가끔 
원치않게 다른폼뒤에 메세지 박스가 뜬다던가?
또는 Top폼이 바뀌면서 메세지 박스가 뜬다던가 하는 현상이 있습니다.
얼마전 델마당에도 질문이 올라왔었구
어제 포럼에도 올라왔네요
http://www.delmadang.com/community/bbs_view.asp?bbsNo=17&bbsCat=0&st=&keyword=&indx=408159&keyword1=&keyword2=&page=18
http://cbuilder.borlandforum.com/impboard/impboard.dll?action=read&db=bcb_qna&no=55272
개인적인 경험으로 저런 현상이 나타나는 원인을 집어보면..
[원인s]
원인1. ShowMessage로 뜬 메세지박스보다 일반폼이 나중에 Show되는 경우
  
   무엇인가 설정하면서 메세지박스가 떴는데...
   그상태에서 무슨 이벤트가 발생하여 ( 네트워크로 무슨 정보가 온다던가 , timer에 이벤트가 있다던가) 
   Form을 Show해주면 
   나중에 Show한 폼이 메세지박스보다 앞에 뜹니다.
 
void __fastcall TForm1::Button2Click(TObject *Sender)
{
    Timer1->Enabled=true;
    ShowMessage("Form2가 앞에 뜰까 ShowMessage가 앞에 뜰까?");
}
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
    Timer1->Enabled=false;
    Form2->Show();
}
 
  위와같은 경우 메세지박스가 뜬후 메세지박스위에 Form이 뜨게 됩니다.
  위 코드는 억지로 그런 현상을 만든것인데 저런현상이 생각보다 종종 있더군요
   
원인2.   WndParent가 Application->Handle이 아닌경우에..
  
  VCL에서 모든 폼은 윈도우핸들 생성시에 설정하는 
  CreateParams의 WndParent 가 기본적으로는 Application->Handle 이 됩니다.
  (MDI Child폼 빼구)
  그런데 메신져처럼 대화창을 작업표시줄에 표시하고 싶다면
  Form의 CreateParams에서 
  WndParent를 GetDesktopWindow() 로 바꿔주면 되죠
   그런데 문제는 WndParent를 DesktopWindow로 바꾼 Form에서 
   ShowMessage를 호출하면
   
  WndParent가 Application->Handle인 폼이 앞으로 나오고 그 앞에 메세지박스가 뜹니다.
 
void __fastcall TForm1::Button2Click(TObject *Sender)
{
    Form2->ShowModal();
}
//=================================================================
void __fastcall TForm2::CreateParams(TCreateParams &Params)
{
    TForm::CreateParams(Params);
    Params.WndParent= GetDesktopWindow();
}
void __fastcall TForm2::Button2Click(TObject *Sender)
{
    ShowMessage("이 메세지박스는 어디에 뜰까?");
}
  이 경우에는 Form2에서 띄운 메세지 박스는 Form1위에 뜨고
  메세지박스가 Form2에 가려져 보이지 않게될수도 있습니다.
  Form2가 Modal로 뜬 상황이니..
  메세지박스을 앞으로 가져올수도 없는 상황이되죠..
 
기타 원인..
   
   그밖에도 잘모르지만 여러가지 원인이 있을수 있을것 입니다.
 
[문제해결을 위해 알아야 할것]
먼저 알아야 할 사실을   사실은
1. ShowMessage로 띄우는 메세지박스는 Win32 api  MessageBox로 띄우는 윈도우와 다른놈입니다.
    그냥 다른놈이 아니라 TForm을 상속받은 TMessageForm을 ShowModal로 띄워주는것 뿐이라는 사실입니다.
   Dialogs 유닛에 보면  다음과 같이 선언되어있죠!
   TMessageForm = class(TForm)
   그러니 TForm1  , TForm2 같이 TForm을 상속받은폼이나 TMessageForm이나 비슷한놈인게죠
2. 두번째 CreateParams 에 정해주는 WndParent 가 뭐냐는 것입니다.
   //
   이놈은  실제 Form의 윈도우핸들을 생성할때 사용하는 API인 CreateWindowEx 함수의
   9번째 들어가는 파라메터로 부모윈도우를 나타내는 것입니다.   
   
http://www.winapi.co.kr/reference/Function/CreateWindowEx.htm
   VCL( C++빌더 또는 Delphi) 에서는 기본적으로 
    Applicaiton->Handle의 부모윈도우는  Desktop윈도우이구
    다른 모든 Form의 부모윈도우(hWndParent)는 Applicaiton->Handle 이 됩니다.
    참조 
http://serious-code.net/moin.cgi/Scrap_2fInsideTheVcl_2fPart3
    SetPaent로 정해주는 부모윈도우와는 좀 개념이 다르죠
    SetParent로 정해주는 parent는  -  보여주는 영역과 관련있다고 생각할수 있구요
    CreateWindowEx 에서 정해주는 wndParent는 -  보여주는 위치(Z-Order)와 관련있다고 할수 있습니다.
결론적으로 메세지박스및 폼이 뜨는 위치는 모두 Z-Order와 관련된 문제입니다.
     Form의 Style을 StayOnTop으로 설정해주는것도 Z-Order 문제이구요
     Z-Order 때문에 ShowMessage, MessagBox,Form등 모든윈도우가 원하는 위치(z-order)에 뜨지 않고
     엉뚱한 위치(Z-Order)에 뜰수 있는것이죠
[해결방법]
원인을 이해 했으니 해결방법도 Z-Order를 어떻게 조절해줄수 있을까 하는 관점에서 찾아나가시면 될것입니다.
해결방법1. 
먼저 위에 원인2번과 같은 경우에 
개인적으로 ShowMessage를 새로 만들어서 사용하기도 합니다. (ShowMessageEx)
Dialog 유닛에 있는 소스를 참조하여 TMessageFormEx 를 만들어 사용하는데
TMessageFormEx 에서 CreateParams의  WndParent를 Application->Handle로 하지 않고
Screen->ActiveForm->Handle로 하도록 만들어 사용합니다.
이렇게 하면 항상 현재 ActiveForm 이 WndParnet 가 되기때문에 
Active된 폼에서 ShowMessageEx를 호출할때 메세지박스가 현재폼보다는 항상 앞에뜨게 되죠
또는 그냥 win32api  MessageBox를 씁니다.
MessageBox 함수의 첫번째 인자가 WndParent 가 되므로
MessageBox(this->Handle , ******) ; 
이런식으로 사용하죠
해결방법2.
   원인1과 같은 경우는 
   Screen객체의 OnActiveFormChange 이벤트 핸들러를 이용합니다.
   OnActiveFormChange이벤트는 말그대로  Active된 폼이 바뀔때 발생합니다.
   ShowMessage로 메세지박스를 띄우면 TMessageForm이 뜨게 되는데 
   이때 Screen의 OnActiveFormChange 이벤트가 발생하게 되죠
   이 이벤트에서 TMessageForm의 Z-Order를 TopMost로 설정해주면 
   어떤 폼보다 앞에 뜨게 됩니다.
   (단점 다른프로그램이 Active되어도 그 앞에 뜰수가 있습니다. StayOnTop처럼)
 
//c++builder
void __fastcall TForm1::FormCreate(TObject *Sender)   
{    
    Screen->OnActiveControlChange=OnScreenActiveFormChange;   
}   
//---------------------------------------------------------------------------   
void __fastcall TForm1::OnScreenActiveFormChange(TObject *Sender)   
{   
    if( Screen->ActiveForm!=NULL)   
    {   
        String sClsName=Screen->ActiveForm->ClassName();   
        if(sClsName=="TMessageForm")   
            SetWindowPos(Screen->ActiveForm->Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);   
    }   
}   
//---------------------------------------------  
void __fastcall TForm1::Button1Click(TObject *Sender)   
{   
    ShowMessage("이 메세지 항상 Top으로 뜨나?");   
}   
 
//delphi
procedure TForm1.FormCreate(Sender: TObject);    
begin    
  Screen.OnActiveFormChange:=OnScreenActiveFormChange;    
end;    
  
procedure TForm1.OnScreenActiveFormChange(Sender: TObject);    
begin    
  if Assigned(Screen.ActiveForm) and (Screen.ActiveForm.ClassName='TMessageForm') then    
      SetWindowPos(Screen.ActiveForm.Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE);    
end;   
   
   
이상입니다.
그럼..
RAD2007까지는 TMessageForm을 이용하는데..
RAD2010에서는 전혀 다른 방식으로 동작하는듯 하네요(rad2009는 확인해 보지 못함)
rad2010에서는 위와같은 현상이 잘 나지 않을듯 합니다.(아직 격어보지 못해서..)