올리기올려짐: 토 8월 12, 2006 12:28 am    주제: [쉘 #005] SHPathToPidl 함수 인용과 함께 답변 글 편집/삭제 글 삭제 글 올린이의 IP 주소 보기

이 함수는 일반 폴더 경로를 PIDL로 변환해준다.

HRESULT SHPathToPidl(LPCTSTR szPath, LPITEMIDLIST* ppidl)
{
LPSHELLFOLDER pShellFolder = NULL;
OLECHAR wszPath[MAX_PATH] = {0};
ULONG nCharParesd = 0;

HRESULT hr = SHGetDesktopFolder(&pShellFolder);
if(FAILED(hr))
return hr;

MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, szPath, -1, wszPath, MAX_PATH);
hr = pShellFolder->ParseDisplayName(NULL, NULL, wszPath, &nCharParesd, ppidl, NULL);
pShellFolder->Release();

return hr;
}
HRESULT SHGetDesktopFolder(IShellFolder **ppshf);

함수 설명
Retrieves the IShellFolder interface for the desktop folder, which is the root of the shell's namespace.

파라미터 ppshf
Address that receives an IShellFolder interface pointer for the desktop folder. The calling application is responsible for eventually freeing the interface by calling its Release method.

리턴값
Returns NOERROR if successful, or an OLE-defined error result otherwise.

위의 함수를 사용하여 우리가 얻을 수 있는 값은 바탕화면의
IShellFolder 인터페이스이다.

위의 함수를 이용하여 SHPathToPidl이라는 함수를 아래에 구현하였다.

이 함수를 이용하여 우리가 원하는 IShellFolder 인터페이스를 구하여 메서드인 ParseDisplayName() 함수를 이용하여 필요한 경로를 PIDL로 변경 가능하고..
또한 위에서 구해진 인터페이스를 통하여 앞으로 공부해나갈 네임스페이스 익스텐션들을 구현할 수 있다.
위의 함수는 원래 존재하는 함수가 아니고,
우리가 이러저러한 방법으로 시스템 이미지리스트의 인덱스를
알고 있다면 간단한 방법으로 그 아이콘을 찾을 수 있다.

HICON SHGetSystemIcon(int iIconIndex)
{
SHFILEINFO sfi;
ZeroMemory(&sfi, sizeof(SHFILEINFO));

HIMAGELIST himl = reinterpret_cast
(SHGetFileInfo("*.*", 0, &sfi, sizeof(SHFILEINFO),
SHGFI_ICON | SHGFI_SYSICONINDEX));

HICON hIcon = ImageList_ExtractIcon(0, himl, iIconIndex);

return hIcon;
}
#. 함수원형
LPITEMIDLIST WINAPI SHBrowseForFolder(LPBROWSEINFO lpbi);

#. BROWSEINFO 구조체
typedef struct _browseinfo
{
HWND hwndOwner; 윈도핸들
LPITEMIDLIST pidl; 나타낼 계층 구조상 루트
LPSTR pszDisplayName; 선택된 디스플레이네임 버퍼
LPCSTR lpszTitle; 트리위의 라벨의 문자열
UINT ulFlags; 윈도우 모양과 행동 설정
BFCALLBACK lpfn; 훅킹시 사용되는 콜밸
LPARAM lParam; 콜백에 전달될 파라미터
int iImage; 선택된 폴더나 파일의 아이콘 인덱스(시스템 이미지리스트)
} BROWSEINFO, *PBROWSEINFO, *LPBROWSEINFO;

#. 함수의 간단한 사용법
BROWSEINFO bi;
ZeroMemory(&bi, sizeof(BROWSEINFO));
bi.hwndOwner = hwnd;
LPITEMIDLIST pidl = SHBrowseForFolder(&bi);

TCHAR szPath[MAX_PATH] = {0};
SHGetPAthFromIDList(pidl, szPath);

#. 함수에 사용되는 플래그
BIF_RETURNONLYFSDIRS 디렉토리만 선택할 수 있다.
네트워크는 보여주기는 하되 선택할 수 없다.
BIF_DONTGOBELOWDOMAIN 해당도메인만 보이고 네트워크는 보이지 않는다.
BIF_STATUSTEXT 다이알로그 템플릿에 라벨이 들어있으며 임의의 텍스트 출력이 가능하다.
BIF_EDITBOX 폴더를 수동으로 선택하는 에디트 박스를 가진다. (쉘 버전 4.71이상에서 지원)
BIF_VALIDATE 잘못된 경로를 에디트했을 경우 경고 표시
BIF_BROWSEFORCOMPUTER 사용자 컴퓨터 이름만 선택가능
BIF_BROWSEFORPRINTER 프린터 이름만 선택가능
BIF_BROWSEINCLUDEFILES 파일이름도 보여준다. 이를 선택가능 (보통 폰트경로나 프린트 경로를 설정할 경우)

#. CALLBACK의 사용
int CALLBACK BrowseCallbackProc(
HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM dwData);

hwnd는 훅킹할 윈도핸들이고, uMsg는 전달되는 메시지이다.
lParam은 uMsg에 따라 다른 의미를 가지게 된다. dwData는 사용자 정의 데이터로 여러분이 VROWSEINFO 구조체의 lParam 멤버를 통해 지정한 것과 동일한 데이터이다.

우리가 감지할 수 있는 이벤트로는
1. BFFM_INITIALIZED - 대화상자가 초기화 완료
2. BFFM_SELCHANGED - 선택이 변경됨
3. BFFM_VALIDATEFAILED - 에디트박스에 부적절할값 입력

우리가 보낼 수 있는 메시지
1. BFFM_ENABLEOK - 확인 버튼 인에이블
2. BFFM_SETSELECTION - 지정된 파일이나 폴더를 선택
lParam에 PIDL이나 해당 경로가 들어가고
wParam에는 해석법이 들어있다. FALSE면 PIDL TRUE면 경로
BFFM_SETSTATUSTEXT 상태바에 텍스트를 임의로 넣는다.

#. 컨텍스트 메뉴버튼 없애기

BFFM_INITIALIZED 메시지에 대한 응답으로
DWORD dwStyle = GetWindowLong(hwnd, GET_EXSTYLE);
SetWindowLong(hwnd, GWL_EXSTYLE, dwStyle & ~WS_EX_CONTEXTHELP);

#. 대화 캡션 변경

BFFM_INITIALIZED 메시지에 대한 응답으로
SetWindowTExt(hwnd, 원하는 캡션);

#. 초기화 위치 바꾸기

BFFM_INITIALIZED 메시지에 대한 응답으로
RECT rc;
GetClientRect(hwnd, &rc);
SetWindowPos(hwnd, NULL, (GetSystemMetrics(SM_CXSCREEN)-(rc.right-rc.left))/2,
(GetSystemMetrics(SM_CYSCREEN)-(rc.bottom-rc.top))/2,
0, 0, SWP_NOZORDER | SWP_NOSIZE);

#. 상태 라벨에 경로명 넣기

BFFM_SELCHANGED 메시지에 대한 응답으로
TCHAR szText[MAX_PATH] = {0};
SHGetPathFromIDList(reinterpret_cast(lParam), szText);
SendMessage(hwnd, BFFM_SETSTATUSTEXT, 0, reinterpret_cast(szText));

첨부파일에는 두가지의 예제가 들어있다.
첫번째 파일은 Printers라는 가상 폴더를 루트로 하는
예제이고,
두번째는 일반적인 결로를 루트로하는 예제이다.
#. SHGetFileInfo()로 무엇을 할 수 있을까?
1.실행파일의 플팻폼을 Win32, Win16, MS-DOS 알아내기
2.파일아이콘의 특성들
3.디스플레이 속성
4.그파일만의 다른 특수 속성들..

#. SHGetFileInfo 함수의 구조
DWORD SHGetFileInfo(
LPCTSTR pszPath, 경로 버퍼
DWORD dwAttrib, 파일 속성의 조합
SHFILEINFO FAR* psfi, SHFILEINFO 구조체의 주소(반환값)
UINT cbFileInfo, 위 구조체의 크기
UINT uFlags) 이 플래그에 의해서 함수의 행동과 정보가 결정됨.

#. SHFILEINFO 구조체
typedef struct_SHFILEINFO
{
HICON hIcon;
int iIcon;
DWORD dwAttributes;
char szDisplayName[MAX_PATH];
char szTypeName[80];
} SHFILEINFO;


#. 간단한 예제 (www.wrox.com)
SHFILEINFO sfi;
ZeroMemory(&sfi, sizeof(SHFILEINFO));
DWORD dwRC = SHGetFileInfo(파일경로, 속성, &sfi, 크기, 플래그들);

#. 각종 플래그값
SHGFI_ICON - 파일 아이콘의 핸들
SHGFI_DISPLAYNAME - 파일 디스플레이 이름
SHGFI_TYPENAME - 파일 종류 문자열
SHGFI_ATTRIBUTES - 파일 속성
SHGFI_ICONLOCATION - 아이콘이 들어있는 파일 이름에 대한 포인터
이 플래그는 SHGFI_DISPLAYNAME과 함께 사용할 수 없다.
경로가 폴더일때만 정상 작동한다.
SHGFI_EXETYPE - 대상 플랫폼을 반환한다.
SHGFI_SYSICONINDEX 주어진 아이콘의 시스템 이미지 리스트의 핸들 반환.
인덱스는 구조체의 iIcon에 저장된다.

SHGFI_LARGEICON 큰아이콘을 찾아낸다.
SHGFI_SMALLICON 작은 아이콘
SHGFI_OPENICON 폴더의 경우 열렸을 때의 아이콘.
SHGFI_SHELLICONSIZE 아이콘의 크기를 알아낸다.
SHGFI_SELECTED 구한 아이콘이 선택되었을때 화면에 나타나는 아이콘(하이라이트된 형태)
SHGFI_LINKOVERLAY 바로가기 아이콘

#. 간단한 예제들...

EX 1) 아이콘 읽기

HICON GetFileTypeIcon(LPCTSTR szFileType, LPCTSTR szTypeName)
{
SHFILEINFO sfi;
ZeroMemory(&sfi, sizeof(SHFILEINFO));
SHGetFileInfo(szFileType, 0, &sfi, sizeof(SHFILEINFO),
SHGFI_USEFILEATTRIBUTES | SHGFI_ICON | SHGFI_TYPENAME);

lstrcpy(szTypeName, sfi.szTypeName);
return sfi.hIcon);
}

EX 2) PIDL의 사용

SHGFI_PIDL은 파일 이름인 것처럼 전달되고 아이템이 실제로는 PIDL임을 시스템에게 알린다.

LPITEMIDLIST pidl;
SHGetSpecialFolderLocation(NULL, CSIDL_DRIVES, &pidl);
DWORD dwRC = SHGetFileInfo(
reinterpret_cast(pidl), 속성, &sfi,
sizeof(SHFILEINFO), 플래그 | SHGFI_PIDL);

EX 3) 공유폴더인가?

BOOL IsDirectoryShared(LPCTSTR dirname)
{
SHFILEINFO sfi;
ZeroMemory(&sfi, sizeof(SHFILEINFO));
SHGetFileInfo(dirname, 0, &sfi, sizeof(SHFILEINFO),
SHGFI_ATTRIBUTES);

return (sfi.dwAttributes & SFGAO_SHARE);
}


EX 4) 공유폴더 아이콘 구하기

HICON GetSharedFolderIcon(HICON hiFolder)
{
HICON hiShared;
HICON hiHand;

ExtractIcon("shell32.dll", 28, &hiand, NULL, 1);

HIMAGELIST himl = ImageList_Create(32,32,ILC_MASK,1,0);

ImageList_AddIcon(himl, hiFolder);
ImageList_AddIcon(himl, hiHand);

HIMAGELIST himlNew = ImageList_Create(himl,0,himl,1,0,0);

hiShared = ImageList_ExtractIcon(0, himlNew, 0);

DestroyIcon(hiHand);

ImageList_Destroy(himl);
ImageList_Destyoy(himlNew);

return hiFolder;
}
#. 정의
int WINAPI SHFileOperation(LPSHFILEOPSTRUCT lpFileOp);

#. LPSHFILEOPSTRUCT 구조
typedef struct _LPSHFILEOPSTRUCT
{
HWND hwnd;
UINT wFunc;
LPCSTR pFrom;
LPCSTR pTo;
FILEOP_FLAGS fFlags;
BOOL fAnyOpsrationAborted;
LPVOID hNameMappings;
LPCSTR lpszProgressTitle;
} SHFILEOPSTRUCT, FAR* LPSHFILEOPSTRUCT;

#. 특징
1. 하나 이상의 파일을 원본경로에서 대상경로로 복사가능
2. 하나 이상을 삭제하여 휴지통으로 보내기
3. 파일 이름 변경
4. 하나 이상의 파일을 원본경로에서 대상경로로 이동가능

#. 구조체 멤버의 의미
hwnd 대화상자의 부모 핸들
wFunc 수행할 작업
pFrom 원본파일 이름을 가진 버퍼
pTo 대상 파일 이름을 가진 버퍼(삭제시 무시)
fFlags 작업에 영향을 주는 플래그들
fAnyOpsrationAborted 반환값:강제종료 or 정상종료
hNameMappings 파일매핑에 관한 객체 핸들
lpszProgressTitle 대화상자의 제목 타이틀

#. 세부 사항
1.wFunc - FO_MOVE / FO_COPY / FO_DELETE / FO_RENAME
2.pFrom - pTo 각각의 파일은 \0으로 구분하고 종료는 \0\0으로 한다.
위에서 pFrom은 와일드 카드를 사용할 수 있다.
3. 파일의 이동과 복사
FOF_MULTIDESFILES - pTo에는 여러개의 파일, 각각 원본과 대응
FOF_SILENT - 피드백 메시지를 없앤다.
FOF_RENAMEONCOLLISION - 같은 경로/이름 이면 자동으로 업데이트
FOR_NOCIONFIRMATION - 혹시 나타나는 메시지박스가 있으면 사용자가 모두 '예'를 선택한 것으로 간주. 예외로 빠진 디렉토리를 생성할 것인지를 묻는데 이는 FOF_NOCONFIRMMKDIR과 조합한다.
FOF_FILESONLY - 서브디렉토리가 있을 경우 파일만 처리핟고 하부는 신경끝.
FOF_SIMPLEPROGRESS - 단순한 화면, 애니메이션만 보이고 파일명 등은 나타나지 않는다.
FOF_NOCONFIRMMKDIR - 대상 디렉토리가 없을 경우 조용히 생성한다.
FOF_NOERRORUI - 어떠한 에러메시지에 대한 대화상자도 생기지 않는다.
FOF_NOCOPYSECURITYATTRIBS - Windows NT 4.0 이상 액티브 데스크 톱을 갖춘 오에스에서 보안속성은 복사되지 않도록 한다

+ Recent posts