|
유지상 님이 쓰신 글 :
: 저는 간단한 노트형태의 윈도우들을 데스크탑에 돌아다니게 하는 프로그램을 제작하고 있습니다.
: 이 프로그램은 윈도우즈가 돌아가고 있을 때는 항상 켜져 있어야 합니다.
: 즉, 윈도우즈가 부팅되면, 이 노트프로그램도 자동으로 실행됩니다.(시작프로그램 디렉토리에 링크파일을 올려주면 이렇게 되지요.)
: 그리고, 사용자가 직접 노트프로그램을 종료하지 않는한은 윈도우즈가 종료될 때 까지 계속 running 하게 됩니다.
: 저는 이 노트프로그램의 메인폼의 OnClose()루틴 속에 노트정리된 정보들을 모두 저장하는 루틴이 포함되어있씁니다.
: 즉, 이 노트프로그램이 종료되면서 자신의 정보를 설정파일에 저장합니다.
: 그리고 윈도우즈가 다시 부팅되어서 노트프로그램이 다시 실행되게 되면, 설정파일에서 정보를 복구하게 되는 것입니다.
: 그런데 제가 테스트로 메인폼의 OnClose()함수 내에 ShowMessage("OnClose"); 를 삽입해봤습니다.
: 이때, 윈도우즈가 종료되면서 (제가 사용하는 것은 windows XP) 그 윈도우즈는 이 때 켜져 있는 프로그램들이 무엇이 있나를 찾아본 후, 켜져 있는 프로그램들을 강제종료하게 됩니다.
: 제 노트프로그램이 강제종료될 때, ShowMessage("OnClose"); 는 실행되지 않았습니다.
: 즉, 메인폼의 OnClose()함수는 실행되지 않은 것입니다. 따라서 설정파일에 정보저장하는 루틴도 실행되지 않은 체 강제종료되는 것이었씁니다.
: 이 문제를 어떻게 해결하면 좋을까요?
:
: (질문1) 윈도우즈종료될때, 윈도우즈가 강제종료를 시행하기 전에, 제 노트프로그램이 알아서, 그 전에 정상적으로 종료를 하게 하려면 어떻게 해야 하나요?
:
: (질문2) 이 노트프로그램의 링크를 사용자가 원하는 대로 시작프로그램디렉토리에 생성했다가 지웠다가 해야 하는데, 이를 위해서 링크를 생성해주는 함수는 무엇인가요?
:
:
Windows 운영체제 종료 시 작업을 해야 한다면 아래와같이 하시면 됩니다.
참고로, 응용 프로그램에서 Windows를 종료시키려면 ExitWindowsEx() API 함수를 사용합니다.
//헤더 파일
class TForm1 : public TForm
{
//중략
void __fastcall WMQueryEndSession(Messages::TMessage &Msg);
void __fastcall WMEndSession(Messages::TMessage &Msg);
BEGIN_MESSAGE_MAP
MESSAGE_HANDLER(WM_QUERYENDSESSION,TMessage,WMQueryEndSession);
MESSAGE_HANDLER(WM_ENDSESSION,TMessage,WMEndSession);
END_MESSAGE_MAP(TForm);
};
//유닛 파일
//---------------------------------------------------------------------------
//Windows 운영체제가 종료하려할 때 현재 실행 중인 각 프로그램에게
//종료 가능여부를 물음
void __fastcall TForm1::WMQueryEndSession(TMessage &Msg)
{
Msg.Result=1; //종료 가능 ,
//종료하지 못하게 하려면 Msg.Result=0;
}
//---------------------------------------------------------------------------
//Windows 운영체제가 종료
void __fastcall TForm1::WMEndSession(TMessage &Msg)
{
if(Msg.WParam==true)
{
//Windows 운영체제 종료 시 처리할 작업 수행
}
Msg.Result=0;
}
//아래 예제는 어디에선가 가져온 것인데 잘 기억이 나질 않는군요.
//단축 아이콘
#include <shlobj.hpp>
//----------------------------------------------------------------------
//바탕화면에 단축 아이콘 만들기
bool CreateShortCut(const AnsiString &file, const AnsiString &linkName)
{
IShellLink* pLink;
IPersistFile* pPersistFile;
LPMALLOC ShellMalloc;
LPITEMIDLIST DesktopPidl;
char DesktopDir[MAX_PATH];
// pidl 을 하나 만들 때, 이것은 쉘의 mallocator에 의해
// 해제 되어야 한다. 쉘의 mallocator 객체는
// API SHGetMalloc 함수를 통해서 얻을 수 있다.
if(FAILED(SHGetMalloc(&ShellMalloc)))
return false;
// 데스크탑 디렉토리에 대한 pidl 을 얻기 위해 다음과 같이 작성한다.
// 함수가 실패하면 아무런 처리도 하지 않게 된다.
if(FAILED(SHGetSpecialFolderLocation(NULL,
CSIDL_DESKTOPDIRECTORY,
&DesktopPidl)))
return false;
// pidl을 문자열로 바꾼다.
if(!SHGetPathFromIDList(DesktopPidl, DesktopDir))
{
ShellMalloc->Free(DesktopPidl);
ShellMalloc->Release();
return false;
}
// pidl 을 해제한다.
ShellMalloc->Free(DesktopPidl);
ShellMalloc->Release();
// 제일 먼저, COM 라이브러리를 초기화한다.
if(SUCCEEDED(CoInitialize(NULL)))
{
// CoInitialize 가 성공하면 CoCreateInstance를 호출해
// 인스턴스를 생성한다.
if(SUCCEEDED(CoCreateInstance(CLSID_ShellLink, NULL,
CLSCTX_INPROC_SERVER,
IID_IShellLink, (void **) &pLink)))
{
// 인스턴스가 생성되면, 그 안에 필요한 속성을 채운다.
pLink->SetPath(file.c_str());
pLink->SetDescription("단축 아이콘 생성");
pLink->SetShowCmd(SW_SHOW);
// 이제 필요한 과정은 하드 드라이브에 대한 단축키 지정이다.
// IShellLink 객체는 IPersistFile 인터페이스도 생성해준다.
// QueryInterface 를 사용해 이 객체의 IPersistFile 부분을 얻는다.
if(SUCCEEDED(pLink->QueryInterface(IID_IPersistFile,
(void **)&pPersistFile)))
{
// 성공하면, 단축키를 작성하기 위해
// IPersistFile 를 저장한다.
WideString strShortCutLocation((String(DesktopDir)+"\\" + linkName).c_str());
pPersistFile->Save(strShortCutLocation.c_bstr(), TRUE);
pPersistFile->Release();
pLink->Release();
CoUninitialize();
return true;
}
pLink->Release();
}
// 마지막으로 인스턴스에 대한 메모리로부터의 해제를 위해 CoUninitialize
// 를 호출한다.
CoUninitialize();
}
return false;
}
:
:
|