학습자료(~2017)/C,C++

icon overlay 아이콘 오버레이 [펌 정리]

단세포소년 2011. 11. 10. 15:21
반응형

드랍박스나 기타 동기화 프로그램 실행시키면
아이콘에 체크표시가 된것을 볼수 있다. 이를 어떻게 구현할까..
구글에서 검색만 6시간 넘게 하여 찾아낸 내용들이다. 후.. 영어도 딸리는데 찾느라 죽는지 알았다...


기본 지식은 ATL, 레지스트.. 나는 아직 관련 지식이 미미하여 샘플 코드를 수정하여 쓰고 있다.
"ATL" 너를 정복해주겠어.. 나중에.. 


아래의 두 압축파일이 아이콘 오버레이를 구현한 샘플파일이다.
실행 아주 잘된다.
첫번째 샘플코드는 탐색기에 나타나는 아이콘에 오버레이를 주는 방식이고
두번째 샘플코드는 윈도우7 에서 보면 바탕화면 맨 아래에 실행시킨 프로그램 목록 아이콘으로 나오는 그곳에 오버레이를
주는 방법이다.
드랍박스같은 아이콘 오버레이를 구현하고 싶은 분들은 첫번째 샘플코드를 활용하도록...





아래의 내용으로 기본 구조만 알아보고 위의 샘플파일을 받아서 수정하여 사용하면 좋다.
위의 샘플 파일을 컴파일하고 생성된 dll 파일을 레지스트에 등록한다.(등록 방법은 아래에 있다.)
위의 샘플 파일을 실행했는데도 변화가 없다면 레지스트의 순서를 바꾸어 보도록한다. 아이콘 오버레이는 최대 갯수가 11개고 우선순위에 따라 나타나지 않을수도 있다.
아이콘 오버레이 레지스트 순서변경 : http://kkamagui.tistory.com/771 



코드 프로젝트에 있는 lallous의 강좌에 기초합니다. VC6을 기준으로 설명합니다.

http://www.codeproject.com/shell/overlayicon.asp

간단한 구현을 통해 위와 같이 자신이 만든 아이콘을 원래 아이콘에 덧붙일 수 있습니다.

아이콘 오버레이 라고 하는데요 세 단계를 통해 구현합니다.

1. 아이콘과 함께 기본 COM 객체 구현

2. IShellIconOverlayIdentifier 인터페이스 구현

3. 인터페이스 registering

단계를 설명하기 전에 원리를 설명하도록 하겠습니다.

윈도우의 탐색기는 단순한 어플리케이션이 아닙니다.

윈도우 쉘을 보여주고 구동하는 어플리케이션으로써 작업관리자에 explorer.exe로 나옵니다.

이 프로세스를 종료하면 바탕화면도 작업표시줄도 다 없어집니다. 그럼 다름 프로그램을 시작할 방법이 없어진답니다.

쉘에는 탐색기, 작업표시줄, 바탕 화면 등으로 구성되어 있다고 합니다.

쉘은 윈도우 구동시에 올라오는데 이 쉘에 영향을 주는 프로그램을 쉘 프로그램이라고 합니다.

아이콘 오버레이도 이 기술에 속합니다. 그 중에서도 쉘 익스텐션이라고 하죠.

쉘 익스텐션을 통해 마우스 오른쪽버튼 누르면 나타나는 등록정보창, 아이콘, 트레이 아이콘 등의 조작을 할 수 있습니다.

윈도우 시작과 함께 쉘이 올라올 때 특정 위치의 레지스트리에 등록된 dll(COM 서버)를 로드합니다.

COM 서버에서 어떤 인터페이스를 구현하느냐에 따라 기능이 결정됩니다.

우리는 아이콘 오버레이를 지원하는 인터페이스를 구현할 것입니다.

1 단계

- 프로젝트 생성 시 ATL Project를 선택합니다.

- 프로젝트 이름은 IconOveray라고 하겠습니다.

- Application Settings에서 Dynamic-Link Library(dll) 을 선택합니다. (default입니다)

- MFC를 지원하고 싶으시면 MFC support를 선택합니다.

- 아이콘 리소스를 추가합니다.

2 단계

- 클래스 뷰에서 IconOverlay를 마우스 오른쪽버튼 클릭한 후 New ATL Object... 를 선택합니다

- Objects-> Simple Object를 선택하고 Add버튼을 누른 후에 Short Name 에 MyIconOverlay를 적습니다.

- Option은 그대로 두시고 finish 버튼 누릅니다.

// MyIconOverlay.h : Declaration of the CMyIconOverlay

#pragma once

#include "resource.h" // main symbols

#include "IconOverlay.h"

#if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)

#error "Sin.........atforms."

#endif

#include <shlobj.h>

#include <comdef.h>

// CMyIconOverlay

class ATL_NO_VTABLE CMyIconOverlay :

public CComObjectRootEx<CComSingleThreadModel>,

public CComCoClass<CMyIconOverlay, &CLSID_MyIconOverlay>,

public IDispatchImpl<IMyIconOverlay, &IID_IMyIconOverlay, &LIBID_IconOverlayLib, /*wMajor =*/ 1, /*wMinor =*/ 0>,

public IShellIconOverlayIdentifier

{

public:

CMyIconOverlay()

{

}

// IShellIconOverlayIdentifier 메소드

STDMETHOD(GetOverlayInfo)(LPWSTR pwszIconFile,

int cchMax,int *pIndex,DWORD* pdwFlags);

STDMETHOD(GetPriority)(int* pPriority);

STDMETHOD(IsMemberOf)(LPCWSTR pwszPath,DWORD dwAttrib);

DECLARE_REGISTRY_RESOURCEID(IDR_MYICONOVERLAY)

BEGIN_COM_MAP(CMyIconOverlay)

COM_INTERFACE_ENTRY(IMyIconOverlay)

COM_INTERFACE_ENTRY(IDispatch)

COM_INTERFACE_ENTRY(IShellIconOverlayIdentifier)

END_COM_MAP()

DECLARE_PROTECT_FINAL_CONSTRUCT()

HRESULT FinalConstruct()

{

return S_OK;

}

void FinalRelease()

{

}

public:

};

OBJECT_ENTRY_AUTO(__uuidof(MyIconOverlay), CMyIconOverlay)

- IShellIconOverlayIdentifier의 메소드는 세 개입니다.

◎ GetOverlayInfo 에서는 모듈의 아이콘을 직접 등록합니다.

◎ GetPriority는 아이콘 오버레이가 나타날 순서를 정합니다. 오버레이가 두개 이상 적용될 시 쓰일 거 같습니다.

◎ IsMemberOf 는 파일마다 오버레이가 적용될지 여부를 결정해 줍니다. 파일 이름이나 속성 등으로 결정할 수 있습니다.

예제를 보겠습니다.

// MyIconOverlay.cpp : Implementation of CMyIconOverlay

#include "stdafx.h"

#include "MyIconOverlay.h"

// CMyIconOverlay

// IShellIconOverlayIdentifier::GetOverlayInfo

STDMETHODIMP CCOverlayProvider::GetOverlayInfo(

LPWSTR pwszIconFile,

int cchMax,

int* pIndex,

DWORD* pdwFlags)

{

// 모듈의 위치를 얻어옴

GetModuleFileNameW(_AtlBaseModule.GetModuleInstance(), pwszIconFile, cchMax);

// 리소스에서의 인덱스 설정, 아이콘이 여러개 등록되어 있을 경우 인덱스로 구분함

*pIndex=0;

*pdwFlags = ISIOI_ICONFILE | ISIOI_ICONINDEX;

return S_OK;

}

// IShellIconOverlayIdentifier::GetPriority

STDMETHODIMP CCOverlayProvider::GetPriority(int* pPriority)

{

// 0부터 priority를 설정함

*pPriority=0;

return S_OK;

}

// IShellIconOverlayIdentifier::IsMemberOf (이 부분에 원하는 파일을 추출하여 오버레이하는것이 가능하죠)

STDMETHODIMP CCOverlayProvider::IsMemberOf(LPCWSTR pwszPath, DWORD dwAttrib)

{

// 유니코드를 LPCSTR로 변환

USE_CONVERSION;

LPCSTR pszPath = W2CA(pwsPath);

/*

파일 경로 : pwszPath (유니코드), pszPath (LPCSTR)

파일 경로를 이용해 파일 이름의 특징이나, 속성등을 알아낸 후에 오버레이 여부 결정

오버레이 : S_OK 반환

그냥 그대로 : S_FALSE; 반환

*/

//doc 파일일 경우 S_OK 반환

if ( strstr(pszPath, ".doc") != 0 )

return S_OK;

else

return S_FALSE;

}

- 간단하죠? 이제 레지스트리에 잘 등록되도록 해주면 됩니다.

단계 3

- IconOverlay.rgs 파일을 엽니다.

- 레지스터 등록하는 코드가 있습니다. 아래에 다음과 같은 코드를 추가하여 줍니다.

//IconOverlay.rgs

HKCR

{

NoRemove AppID

{

'%APPID%' = s 'IconOverlay'

'IconOverlay.DLL'

{

val AppID = s '%APPID%'

}

}

}

//아래에 추가

HKLM

{

NoRemove SOFTWARE

{

NoRemove Microsoft

{

NoRemove Windows

{

NoRemove CurrentVersion

{

NoRemove Explorer

{

NoRemove ShellIconOverlayIdentifiers

{

ForceRemove MyOverlayIcon = s '%APPID%'

{

}

}

}

}

}

}

}

}

- VS 2005에서는 APPID를 변수화 하여서 위와 같이 씁니다만.. VS 6.0 버전에서는 위의 코드에 나와있는 GUID를 복사해서 넣어줘야 합니다.

ex ) ForceRemove MyOverlayIcon = s '{81539FE6-33C7-4CE7-90C7-1C7B8F2F2D40}' //이런 식으로요

자 이제 3단계까지 하셨다면, 컴파일 하여 dll을 등록할 수 있습니다.

컴파일만 해도 등록이 되며, Debug폴더 등에 dll 파일이 생성된걸 확인하실 수 있습니다.

그런데 오버레이가 되지 않는다구요?

당연하죠~ 윈도우 쉘은 이미 실행 되어있고 이 dll은 쉘이 실행될 때 같이 로드됩니다.

로그오프 하신 후 다시 켜시면 오버레이된 아이콘을 볼 수 있습니다.

Tip. 프로그램을 작성하다보면 디버깅은 필수가 됩니다. 그런데 그럴때 마다 로그오프와 온을 하여야하나 -_-;;;

그게 얼마나 귀찮은지는 잘알고 있죠 그래서 한가지 Tip은....

윈도우 작업관리자(Ctrl + Alt + Del)를 호출합니다.

프로세스텝에서 explorer.exe 를 종료 시키면... 그럼 아주 재미있는 현상(?)이 발생하죠..ㅎㅎㅎ

작업관리자의 메뉴중 파일항목에 새 작업(실행)메뉴를 실행하면 익숙한 창이 하나 뜨죠 거기서 explorer.exe를 실행시키면 됩니다.

쉘 프로그래밍의 경우 쉘에서 동작됨의로 본의 아니게 위의 경우를 자주 쓰게 되더라구요...ㅎ

레지스트리 등록하는 방법은 블로그 http://blog.naver.com/shin5341/80026999483 에 참조





DLL파일 레지스트리에 등록 또는 삭제 하기

1. 일반적인 방법

등록 : regsvr32 xxxxx.dll

삭제 : regsvr32 -u xxxxx.dll

2. Contextmenu 등록해서 사용하는 방법

a. 탐색기를 열고 "폴더옵션" 메뉴에서 "파일형식" 탭을 선택합니다.
b. "새로 만들기" 버튼을 눌러 파일 확장명을 "DLL"이라고 친 다음 확인

그러면 "DLL" 항목이 등록된 파일형식 리스트에 나타납니다.

c. 해당 항목을 선택하고 "고급" 버튼을 누릅니다.
d. "새로 만들기" 버튼을 누릅니다.
e. 명령어란에 "레지등록하기"라고 입력합니다.
f. 명령을 실행할 프로그램 명에 아래와 같이 입력 후 "확인" 버튼을 누릅니다.(찾아보기 이용해서 위치지정)

c:windows\system32\regsvr32.exe "%1"

g. 또 다시 "새로 만들기" 버튼을 누릅니다.
h. 명령어란에 "레지제거하기"라고 입력합니다.
i. 명령을 실행할 프로그램 명에 아래와 같이 입력 후 "확인" 버튼을 누릅니다.(찾아보기 이용해서 위치지정)

c:windows\system32\regsvr32.exe -u "%1"

j. 이제 모든 작업을 마칩니다.
k. 탐색기에서 님이 등록하고자 하는 DLL을 선택하여 오른쪽 마우스를 눌러 확인합니다.




참고 : http://blog.naver.com/PostView.nhn?blogId=shin5341&logNo=80036292162  아이콘 오버레이
참고 : http://blog.naver.com/shin5341/80026999483  레지스트 등록

반응형