|
간단하게 해결될줄 알았는데.. 생각보다 정말 복잡하군요.. -_-a
우선, OpenDialog의 버그 같습니다. 더블클릭으로 아이템을 선택하면 바로가기 폴더가 열리지 않지만, 아래의 Open 버튼을 눌러서 열면, 바로가기 폴더가 열립니다.
이걸 이용해서, 더블클릭이나 다른 방법을 써도, Open 한것처럼 속이는 방법을 사용했습니다.
IShellLink 를 이용하시면, 바로가기 정보를 얻어올 수 있는데, 이 정보로 바로가기의 원래 폴더가 폴더인지, 아니면 파일인지 비교한 후에 폴더이어야 들어갈 수 있도록 해야합니다. 그렇지 않으면 예상치 못한 이상한 결과가 나올 수 있지요.
또 안좋은 소식이지만, IShellLink 도 C++ Builder 5 에서 Multiple Define 버그가 있습니다. 우선 C++ Builder 5에서 사용하시려면 아래 작업을 거치셔야 합니다.
1. Project -> Option 에서 Directories/Conditionals 탭을 선택합니다.
2. Conditional defines 항목에 _DEBUG 라고 쓰여있는 항목을 _DEBUG;NO_WIN32_LEAN_AND_MEAN 이렇게 변경합니다.
3. #include <shlobj.h> 을 추가하여 컴파일해서 에러가 없으면 정상적으로 실행이 되는 것입니다.
파일을 선택하면 다이얼로그가 닫히기 전에 OnCanClose 이벤트가 발생하는데, 이 이벤트에서 처리를 모두 해주시면 됩니다.
순서는 다음과 같습니다.
1. 링크 파일 (확장자가 lnk) 이면, 그 링크파일이 지정된 곳을 알아냄
2. 그 지정된 곳이 파일이면 정상 종료, 폴더면 다음 과정을 실행
3. 파일 입력창을 모두 지우고, Open 버튼을 누른것처럼 메세지를 보냄
4. 종료를 하지 못하게함
이렇게 하시면, 자동으로 더블클릭시에도, 해당 폴더로 이동됩니다.
아래는 예제 코드 입니다.
//---------------------------------------------------------------------------
#include <vcl.h>
#include <shlobj.h> // IShellLink를 쓰기 위한 Include
#pragma hdrstop
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
OpenDialog1->Execute();
}
//---------------------------------------------------------------------------
String __fastcall TForm1::GetFullPath(String stLink)
{
IShellLink *psl;
String stFileName = "";
// ShellLink OLE를 이용한 GetFullPath, Resolve 에서 해당 바로가기를 분석합니다
CoInitialize(NULL);
if(SUCCEEDED(CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void **)&psl))) {
LPPERSISTFILE lppf;
if(SUCCEEDED(psl->QueryInterface(IID_IPersistFile, reinterpret_cast<void **>(&lppf)))) {
wchar_t wIconPath[MAX_PATH];
stLink.WideChar(wIconPath, MAX_PATH);
if(SUCCEEDED(lppf->Load(wIconPath, STGM_READ)))
if(SUCCEEDED(psl->Resolve(NULL, SLR_ANY_MATCH))) {
WIN32_FIND_DATA wfd;
char filename[MAX_PATH];
if(SUCCEEDED(psl->GetPath(filename, MAX_PATH, &wfd, SLGP_UNCPRIORITY)))
stFileName = filename;;
}
}
lppf->Release();
}
psl->Release();
return(stFileName);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::OpenDialog1CanClose(TObject *Sender, bool &CanClose)
{
WIN32_FIND_DATA fdFiles;
HANDLE hdHandle;
// 링크 파일이면...
if(ExtractFileExt(OpenDialog1->FileName).LowerCase() == ".lnk") {
// 파일 정보를 얻기 위해..
hdHandle = FindFirstFile(GetFullPath(OpenDialog1->FileName).c_str(), &fdFiles);
if(hdHandle) {
// 디렉토리면..
if(fdFiles.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
// 파일이름 입력 창을 모두 지우고 Open 버튼을 누른것처럼 속임
SendDlgItemMessage(GetForegroundWindow(), 1152, WM_SETTEXT, 0, LPARAM(PChar("")));
SendMessage(GetForegroundWindow(), WM_COMMAND, 1 + BN_CLICKED * 0x10000, LPARAM(GetDlgItem(GetForegroundWindow(), 1)));
CanClose = false;
}
FindClose(hdHandle);
}
}
}
//---------------------------------------------------------------------------
유지상 님이 쓰신 글 :
: 시빌더에서 폼에 OpenDialog를 올려놓고, 사용해보면, 그 오픈다이얼로그박스로 파일 하나 열려고 할 때에, 폴더의 바로가기를 클릭하면, 그 폴더 내로 가는 게 아니라, 그 바로가기 자체가 파일로 열립니다 아니 선택됩니다.
: 이거 막으려면 어떻게 해야 하나요?
|