질문1. 어떤 함수나 구조체나 클레스에 대해서 (예를 들면,IShellLink, SHGetPathFromIDList 등등)
그에 필요한 include시켜야 할 헤더파일이름은 어떻게 알아낼 수 있나요?
질문2. *.h 와 *.hpp 의 차이는 무엇인가요? C++Builder에서 어떤 API함수를 이용하는 예제 같은 걸 보면, *.hpp형태의 파일을 인쿠르드시키는데, 실제로 C++Builder Help 를 찾아보면, *.h 형태의 파일을 인쿠르드시키라고 나오거든요.
그리고 좀더 구체적인 질문들은 아래의 상황에 쓰여져 있습니다.
일단 New Application... 을 클릭해서 새로 프로젝트를 하나 만든 다음 Unit1.cpp에 다음과 같은 수정을 가했씁니다.
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
#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;
}
아래 어떤 분은 답변에서 위와 같이 shlobj.hpp를 include 시켰습니다.
그런데, 위의 코드를 위해서 shlobj.hpp를 인쿨르드해야한다는 사실은 어떻게 알아내는 것인지 모르겠어요.
어쨋든 이렇게 해서, 컴파일을 했더니,
Undefined Symbol 'IShellLink' , Undefined symbol 'LPITEMIDLIST'
Call To undefined symbol 'SHGetMalloc'
등등의 에러메시지가 나왔습니다.
그래서, 필요한 헤더파일을 조사해보려고, help를 이용했습니다.
IShellLink에다가 커서를 놓고 F1 키를 눌렀습니다.
그렇게 하면 IShellLink항목에 대한 도움말이 나타납니다.
여기서는 어떤 헤더파일을 인쿠르드해야 되는 지 알 수가 없었습니다.
직접 해보시면 아시겠지만, 그 항목에 나열되어 함수들 중에서 하나를 클릭했습니다.(예를 들면
GetArguments), 그래서 나오는 항목에서 Quick Info를 누르면,
IShellLink::GetArguments에 필요한 헤더파일이 shlobj.h 라고 나옵니다.
(shlobj.h와 shlobj.hpp의 차이가 뭘까요?)
그리고 그 외에 다른 함수들에서도 Quick info 에 보면 shlobj.h라고 나와서.
위의 소스에서
#include <shlobj.hpp>
를
#include <shlobj.h>
로 바꾸고 다시 컴파일해보았습니다.
그랬더니, 이번에는 Unit1.cpp 에서는 에러가 안나오고,
shlobj.h 에서 네 개의 에러가 나왔씁니다.
Multiple declaration for 'FVSHOWINFO' 등등의 에러메시지였습니다.
이 문제를 어떻게 해결해야 되는 걸까요?
|