|
답변이 아닙니다.
요건 좀 어려운 문제네요
네이트온 같은 메신져의 경우 대화창이 메임폼과 따고 작업표시줄에 나타나는데
이것도 대화창은 작업관리자(Task Manager)에서 작업끝내기를 클릭하면 프로그램이 전체 종료해버리네요
작업관리자 응용프로그램 탭에서 "작업 끝내기"(End Task)를 클릭하는경우
1. 먼저 WM_CLOSE 메세지를 해당 윈도우에 SendMessage(or Post) 하는것 같습니다.
2. 그리고 한 2초정도 있다가 TeminateProcess 를 호출해서 프로세서를 완전히 죽여버리는듯 합니다.
WM_QUIT 메세지도 안나라 오더라구요
결론적으로
방안1. TaskManager를 Hook 하는 방법
방안2. Terminateprocess 같은 API를 HOOK 하는 방안
등과 같이 Hook을 이용한 방법으로 할수는 있을것 같은데...
hook이 그렇게 쉽지는 않으니까...
방안3. sub폼을 모두 process를 분리합니다.
구글에서 얼마전에 발표한 웹브라우져 크롬이 멀티 프로세서로 되어있죠
프로세서간 통신은 NamedPipe를 이용한다고 어디서 본것 같습니다.
요 구조로 하면 작업관리자 hook하지 않고 , 작업관리자에서 "End Task" 클릭할때 해당 폼만
종료되게 할수 있을것입니다.
그런데 멀티프로세서로 하면 .. 또 신경써야 할것이 한두가지가 아니니
배보다 배꼽이 커질듯....
방안4. TaskManager를 다른 놈으로 바꿔버리는 방법도 있을것 같습니다.
별로 도움은 안될것 같은데 ..
아뭍은 좋은 해결책 찾으면 공유해 주십시요
그럼..
저도 SUB폼을
공윤경 님이 쓰신 글 :
: 답변 감사합니다.
: 메인 프로그램이 아닌 생성한 폼이 다섯개면 프로세스쪽말고 Application탭에 다섯개의 폼이 나와있는데
: 그걸 클릭해서 폼을 하나씩 죽일수는 없는건가요?
:
:
: Lyn 님이 쓰신 글 :
: : 프로세스(태스크) 가 죽으면 당연히 거기에 속해있던 폼들은 다 닫히고 해제되는게 당연합니다.
: :
: : 폼 여러개 띄웠다고 그게 따로도는게 아닙니다.
: :
: : 메인프로그램이 죽어도 나머지가 안죽게 하시려면 멀티프로세스구조(여러개의 exe) 로 가셔야합니다.
: : 공윤경 님이 쓰신 글 :
: : : //---------------------------------------------------------------------------
: : : //MAIN.CPP
: : : #include <vcl.h>
: : : #pragma hdrstop
: : :
: : : #include "main.h"
: : : #include "Sub.h"
: : : //---------------------------------------------------------------------------
: : : #pragma package(smart_init)
: : : #pragma resource "*.dfm"
: : : TSDIMainForm *SDIMainForm;
: : : //---------------------------------------------------------------------------
: : : __fastcall TSDIMainForm::TSDIMainForm(TComponent* Owner)
: : : : TForm(Owner)
: : : {
: : : }
: : : void __fastcall TSDIMainForm::WMUserMessage(TMessage &msg)
: : : {
: : : CreateSubForm();
: : : }
: : : //---------------------------------------------------------------------------
: : : void __fastcall TSDIMainForm::CreateSubForm(void)
: : : {
: : : m_FormNumber++;
: : : AnsiString str = "SDIアプリサンプル["+IntToStr(m_FormNumber)+"]";
: : : TSDISubForm *sForm;
: : : sForm = new TSDISubForm(this);
: : : sForm->Show();
: : : sForm->Caption = str;
: : : }
: : : //---------------------------------------------------------------------------
: : : void __fastcall TSDIMainForm::FormCreate(TObject *Sender)
: : : {
: : : m_FormNumber = 0;
: : : CreateSubForm();
: : : }
: : : //---------------------------------------------------------------------------
: : : //---------------------------------------------------------------
: : : //MAIN.H
: : :
: : : #ifndef mainH
: : : #define mainH
: : : //---------------------------------------------------------------------------
: : : #include <Classes.hpp>
: : : #include <Controls.hpp>
: : : #include <StdCtrls.hpp>
: : : #include <Forms.hpp>
: : : #define message WM_USER + 50
: : : //---------------------------------------------------------------------------
: : : class TSDIMainForm : public TForm
: : : {
: : : __published: // IDE 管理のコンポーネント
: : : void __fastcall FormCreate(TObject *Sender);
: : : private: // ユーザー宣言
: : : void __fastcall WMUserMessage(TMessage &msg);
: : : BEGIN_MESSAGE_MAP
: : : MESSAGE_HANDLER(message, TMessage, WMUserMessage)
: : : END_MESSAGE_MAP(TForm);
: : : public: // ユーザー宣言
: : : __fastcall TSDIMainForm(TComponent* Owner);
: : :
: : : int m_FormNumber;
: : : void __fastcall CreateSubForm(void);
: : :
: : : };
: : : //---------------------------------------------------------------------------
: : : extern PACKAGE TSDIMainForm *SDIMainForm;
: : : //---------------------------------------------------------------------------
: : : #endif
: : :
: : :
: : :
: : :
: : : //---------------------------------------------------------------------------
: : : //SUB.CPP
: : : #include <vcl.h>
: : : #pragma hdrstop
: : :
: : : #include "Sub.h"
: : : #include "main.h"
: : : #include <Windows.hpp>
: : : //---------------------------------------------------------------------------
: : : #pragma package(smart_init)
: : : #pragma resource "*.dfm"
: : : TSDISubForm *SDISubForm;
: : : //---------------------------------------------------------------------------
: : : __fastcall TSDISubForm::TSDISubForm(TComponent* Owner)
: : : : TForm(Owner)
: : : {
: : : }
: : : //---------------------------------------------------------------------------
: : : bool __fastcall TSDISubForm::IsLastForm(TForm* form)
: : : {
: : : bool bRst = true;
: : : TForm *sForm;
: : : for(int idx = 0; idx < Screen->FormCount ; idx++)
: : : {
: : : sForm = Screen->Forms[idx];
: : : if((sForm != form)&&(sForm->Visible == true)&&
: : : (sForm->ParentWindow == 0 || sForm->HandleAllocated() || (IsChild(sForm->Handle,sForm->ParentWindow)==false))) {
: : : bRst = false;
: : : break;
: : : }
: : : }
: : : return bRst;
: : : }
: : :
: : : void __fastcall TSDISubForm::subNewClick(TObject *Sender)
: : : {
: : : SDIMainForm->CreateSubForm();
: : : }
: : : //---------------------------------------------------------------------------
: : :
: : : void __fastcall TSDISubForm::subCloseClick(TObject *Sender)
: : : {
: : : Close();
: : : }
: : : //---------------------------------------------------------------------------
: : :
: : : void __fastcall TSDISubForm::subAllCloseClick(TObject *Sender)
: : : {
: : : Application->Terminate();
: : : }
: : : //---------------------------------------------------------------------------
: : : // ウィンドウ復帰
: : : //---------------------------------------------------------------------------
: : : void __fastcall TSDISubForm::RestoreWind(void)
: : : {
: : : int nWin = Screen->FormCount;
: : : HWND hWnd;
: : : for(int idx = 0; idx < Screen->FormCount; idx++)
: : : {
: : : hWnd = Screen->Forms[idx]->Handle;
: : : //WindowがNormalではない場合
: : : if(Screen->Forms[idx]->WindowState != wsNormal) {
: : : if(GetClassNameStr(hWnd) == this->ClassName()) {
: : :
: : : DefWindowProc(hWnd,WM_SYSCOMMAND,SC_RESTORE,0);
: : : }
: : : }
: : : }
: : : }
: : : //---------------------------------------------------------------------------
: : : void __fastcall TSDISubForm::subCascadeClick(TObject *Sender)
: : : {
: : : RestoreWind();
: : : int nWin = Screen->FormCount;
: : : HWND *WndHandleList;
: : : WndHandleList = new HWND[nWin];
: : : for(int idx = 0; idx < Screen->FormCount; idx++)
: : : {
: : : WndHandleList[idx] = Screen->Forms[idx]->Handle;
: : : SetForegroundWindow(WndHandleList[idx]);
: : : }
: : :
: : : CascadeWindows(0,
: : : NULL,//MDITILE_SKIPDISABLED
: : : NULL,
: : : Screen->FormCount,
: : : WndHandleList);
: : : SetForegroundWindow(Handle);
: : : delete [] WndHandleList;
: : : }
: : : //---------------------------------------------------------------------------
: : :
: : : void __fastcall TSDISubForm::subTileVerticalClick(TObject *Sender)
: : : {
: : : RestoreWind();
: : : int nWin = Screen->FormCount;
: : : HWND *WndHandleList;
: : : WndHandleList = new HWND[nWin];
: : : for(int idx = 0; idx < Screen->FormCount; idx++)
: : : {
: : : WndHandleList[idx] = Screen->Forms[idx]->Handle;
: : : SetForegroundWindow(WndHandleList[idx]);
: : : }
: : :
: : : TileWindows( 0,
: : : MDITILE_VERTICAL,//MDITILE_SKIPDISABLED
: : : NULL,
: : : Screen->FormCount,
: : : WndHandleList
: : : );
: : : delete [] WndHandleList;
: : : SetForegroundWindow(Handle);
: : : }
: : : //---------------------------------------------------------------------------
: : :
: : : void __fastcall TSDISubForm::subTileHorizontalClick(TObject *Sender)
: : : {
: : : RestoreWind();
: : : int nWin = Screen->FormCount;
: : : HWND *WndHandleList;
: : : WndHandleList = new HWND[nWin];
: : : for(int idx = 0; idx < Screen->FormCount; idx++)
: : : {
: : : WndHandleList[idx] = Screen->Forms[idx]->Handle;
: : : SetForegroundWindow(WndHandleList[idx]);
: : :
: : : }
: : : TileWindows(0,
: : : MDITILE_HORIZONTAL,//MDITILE_SKIPDISABLED
: : : NULL,
: : : Screen->FormCount,
: : : WndHandleList
: : : );
: : : delete [] WndHandleList;
: : : SetForegroundWindow(Handle);
: : : }
: : : //---------------------------------------------------------------------------
: : :
: : : void __fastcall TSDISubForm::subAllMinClick(TObject *Sender)
: : : {
: : : HWND hWindow;
: : : for(int idx = 0; idx < Screen->FormCount; idx++)
: : : {
: : : hWindow = Screen->Forms[idx]->Handle;
: : : if(GetClassNameStr(hWindow) == this->ClassName()) {
: : : PostMessage(hWindow,WM_SYSCOMMAND,SC_MINIMIZE,0);
: : : }
: : : }
: : : }
: : : //---------------------------------------------------------------------------
: : : String __fastcall TSDISubForm::GetClassNameStr(HWND hWindow)
: : : {
: : : int Len;
: : :
: : : char *Buffer;
: : : String Result;
: : : Buffer = StrAlloc(MAX_PATH);
: : : try {
: : : Len = GetClassName(hWindow,Buffer,StrBufSize(Buffer));
: : : Result = Buffer;
: : :
: : : }__finally{
: : : StrDispose(Buffer);
: : : return Result;
: : : }
: : : }
: : :
: : : void __fastcall TSDISubForm::FormClose(TObject *Sender,
: : : TCloseAction &Action)
: : : {
: : : if(IsLastForm(this)) {
: : : Application->Terminate();
: : : }
: : : }
: : : //---------------------------------------------------------------------------
: : :
: : : void __fastcall TSDISubForm::FormShow(TObject *Sender)
: : : {
: : : ShowWindow(Application->Handle,SW_HIDE);
: : : if(!NotFirstForm) {
: : : NotFirstForm = true;
: : : switch(CmdShow)
: : : {
: : : case SW_SHOWMINNOACTIVE:
: : : WindowState = wsMinimized;
: : : break;
: : : case SW_SHOWMAXIMIZED:
: : : WindowState = wsMaximized;
: : : break;
: : : }
: : : }
: : : }
: : : //---------------------------------------------------------------------------
: : : void __fastcall TSDISubForm::CreateParams(TCreateParams &Params)
: : : {
: : : TForm::CreateParams(Params);
: : : if(FormStyle == fsNormal || FormStyle == fsStayOnTop) {
: : : if(BorderStyle == bsSingle || BorderStyle == bsSizeable) {
: : : Params.ExStyle = Params.ExStyle |WS_EX_APPWINDOW;
: : : Params.WndParent = 0;
: : : }
: : : }
: : : }
: : :
: : : //SUB.h
: : : //---------------------------------------------------------------------------
: : :
: : : #ifndef SubH
: : : #define SubH
: : : //---------------------------------------------------------------------------
: : : #include <Classes.hpp>
: : : #include <Controls.hpp>
: : : #include <StdCtrls.hpp>
: : : #include <Forms.hpp>
: : : #include <Menus.hpp>
: : : //---------------------------------------------------------------------------
: : : class TSDISubForm : public TForm
: : : {
: : : __published: // IDE 管理のコンポーネント
: : : TMainMenu *MainMenu1;
: : : TMenuItem *MenuFile;
: : : TMenuItem *subNew;
: : : TMenuItem *subClose;
: : : TMenuItem *subAllClose;
: : : TMenuItem *N3;
: : : TMenuItem *Show1;
: : : TMenuItem *subCascade;
: : : TMenuItem *subTileVertical;
: : : TMenuItem *subTileHorizontal;
: : : TMenuItem *subAllMin;
: : : void __fastcall subNewClick(TObject *Sender);
: : : void __fastcall subCloseClick(TObject *Sender);
: : : void __fastcall subAllCloseClick(TObject *Sender);
: : : void __fastcall subCascadeClick(TObject *Sender);
: : : void __fastcall subTileVerticalClick(TObject *Sender);
: : : void __fastcall subTileHorizontalClick(TObject *Sender);
: : : void __fastcall subAllMinClick(TObject *Sender);
: : : void __fastcall FormClose(TObject *Sender, TCloseAction &Action);
: : : void __fastcall FormShow(TObject *Sender);
: : : private: // ユーザー宣言
: : : bool __fastcall TSDISubForm::IsLastForm(TForm *form);
: : : void __fastcall TSDISubForm::RestoreWind(void);
: : : protected:
: : : String __fastcall GetClassNameStr(HWND hWindow);
: : : void __fastcall CreateParams(TCreateParams ¶ms);
: : : public: // ユーザー宣言
: : : __fastcall TSDISubForm(TComponent* Owner);
: : : bool NotFirstForm;
: : : };
: : : //---------------------------------------------------------------------------
: : : extern PACKAGE TSDISubForm *SDISubForm;
: : : //---------------------------------------------------------------------------
: : : #endif
: : :
: : :
: : : //PROJ
: : : //---------------------------------------------------------------------------
: : :
: : : #include <vcl.h>
: : : #pragma hdrstop
: : : USERES("prjSdi.res");
: : : USEFORM("main.cpp", SDIMainForm);
: : : USEFORM("Sub.cpp", SDISubForm);
: : : //---------------------------------------------------------------------------
: : : BOOL IsPrevAppExist(const char * mutextname)
: : : {
: : : bool bRst = false;
: : : CreateMutex(NULL, true, mutextname);
: : : if (GetLastError() == ERROR_ALREADY_EXISTS) {
: : : bRst = true;
: : : }
: : : return bRst;
: : : }
: : : WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
: : : {
: : : HANDLE mutex;
: : : HWND hWindow;
: : : try
: : : {
: : : const char * mutexname= "SDIFORM";
: : : if(IsPrevAppExist(mutexname)) {
: : : hWindow = FindWindow("TSDIMainForm",NULL);
: : : SetForegroundWindow(hWindow);
: : : SendMessage(hWindow, WM_USER+50,0,0);
: : : }
: : : else {
: : : SetProp(Application->Handle,PChar(mutexname),mutex);
: : : Application->Initialize();
: : : Application->CreateForm(__classid(TSDIMainForm), &SDIMainForm);
: : : Application->ShowMainForm = false;
: : : Application->Run();
: : : RemoveProp(Application->Handle, PCHAR(mutexname));
: : : }
: : : }
: : : catch (Exception &exception)
: : : {
: : : Application->ShowException(&exception);
: : : }
: : : ReleaseMutex(mutex);
: : : return 0;
: : : }
: : : //---------------------------------------------------------------------------
: : : 안녕하세요? 공윤경이라고 합니다.
: : : 프로그램의 테스크메니져로부터의 종료시 문제
: : :
: : : 테스크메니져서에 프로세스에서는 하나의 EXE화일이 보이고
: : : 어플리케이션에서 동적으로 생성한 폼의 이름이 보여서.
: : : 어플리케이션부에서 하나씩 클릭해서 종료가능한 프로그램을 작성중입니다.
: : : 코드에 이상이 있나요? 실행 + 종료등 아무에러가 없는데
: : : 테스트매니져서에서 프로그램을 종료시키면 에러가 발생하고 프로그램이 전부 종료됩니다.
: : : 메인폼과 서브폼으로 이루어져서 실행시 메인폼은 보이지않고
: : : 서브폼이 뜹니다. 그이후에도 서브폼으로부터 서브폼을 추가하는 형태의 프로그램입니다.
: : :
: : : 뭔가 제가 잘못생각한 부분이 있는지...
: : :
: : : 잘부탁드립니다 ^^
|