다음을 통해 공유


사용자 지정 탐색기 막대, 도구 밴드 및 데스크 밴드 만들기

탐색기 모음은 브라우저 창에 인접한 표시 영역을 제공하기 위해 Microsoft Internet Explorer 4.0과 함께 도입되었습니다. 기본적으로 Windows Internet Explorer 창 내의 자식 창이며 정보를 표시하고 거의 동일한 방식으로 사용자와 상호 작용하는 데 사용할 수 있습니다. 탐색기 막대는 브라우저 창의 왼쪽에 세로 창으로 가장 일반적으로 표시됩니다. 그러나 탐색기 모음은 브라우저 창 아래에 가로로 표시될 수도 있습니다.

Screenshot that shows the vertical and horizontal Explorer Bars.

탐색기 모음에는 다양한 용도로 사용할 수 있습니다. 사용자는 보기 메뉴의 탐색기 표시줄 하위 메뉴에서 선택하거나 도구 모음 단추를 클릭하는 등 여러 가지 방법으로 보려는 옵션을 선택할 수 있습니다. Internet Explorer는 즐겨찾기 및 검색을 비롯한 여러 표준 탐색기 막대를 제공합니다.

Internet Explorer를 사용자 지정할 수 있는 방법 중 하나는 사용자 지정 탐색기 모음을 추가하는 것입니다. 구현되고 등록되면 보기 메뉴의 탐색기 모음 하위 메뉴에 추가 됩니다. 사용자가 선택한 경우 탐색기 표시줄의 표시 영역을 사용하여 정보를 표시하고 일반 창과 거의 동일한 방식으로 사용자 입력을 수행할 수 있습니다.

screen shot of the explorer bars

사용자 지정 탐색기 모음을 만들려면 밴드 개체구현하고 등록해야 합니다. 밴드 개체는 셸 버전 4.71에서 도입되었으며 일반 창과 유사한 기능을 제공합니다. 그러나 COM(구성 요소 개체 모델) 개체이고 Internet Explorer 또는 셸에 의해 포함되기 때문에 약간 다르게 구현됩니다. 단순 밴드 개체는 첫 번째 그래픽에 표시되는 샘플 탐색기 막대를 만드는 데 사용되었습니다. 세로 탐색기 모음 샘플의 구현은 이후 섹션에서 자세히 설명합니다.

도구 밴드

도구 밴드는 Windows 라디오 도구 모음 기능을 지원하기 위해 Microsoft Internet Explorer 5에서 도입된 밴드 개체입니다. Internet Explorer 도구 모음은 실제로 여러 도구 모음 컨트롤을 포함하는 철근 컨트롤입니다. 도구 밴드를 만들어 해당 rebar 컨트롤에 밴드를 추가할 수 있습니다. 그러나 탐색기 막대와 마찬가지로 도구 밴드는 범용 창입니다.

screen shot of tool bands

사용자는 보기 메뉴의 도구 모음 하위 메뉴 또는 도구 모음 영역을 마우스 오른쪽 단추로 클릭하여 표시되는 바로 가기 메뉴에서 도구 모음을 선택하여 도구 모음을 표시합니다.

데스크 밴드

밴드 개체를 사용하여 책상 밴드를 만들 수도 있습니다. 기본 구현은 탐색기 막대와 유사하지만 책상 밴드는 Internet Explorer와 관련이 없습니다. 책상 밴드는 기본적으로 바탕 화면에 도킹 가능한 창을 만드는 방법입니다. 사용자가 작업 표시줄을 마우스 오른쪽 단추로 클릭하고 도구 모음 하위 메뉴에서 선택하여 선택합니다.

Screenshot that shows a sample desk band.

처음에는 책상 밴드가 작업 표시줄에 도킹됩니다.

Screenshot that shows desk bands docked on the task bar.

그러면 사용자는 책상 밴드를 바탕 화면으로 끌 수 있으며 일반 창으로 표시됩니다.

screen shot of desk bands

밴드 개체 구현

다음 항목을 다룹니다.

Band 개체 기본 사항

일반 창과 비슷하게 사용할 수 있지만 대역 개체는 컨테이너 내에 있는 COM 개체입니다. 탐색기 막대는 Internet Explorer에 포함되며, 책상 밴드는 셸에 포함되어 있습니다. 서로 다른 함수를 제공하지만 기본 구현은 매우 유사합니다. 주된 차이점은 대역 개체가 등록되는 방식이며, 개체의 형식과 해당 컨테이너를 제어합니다. 이 섹션에서는 모든 밴드 개체에 공통적인 구현의 이러한 측면에 대해 설명합니다. 추가 구현 세부 정보는 사용자 지정 탐색기 모음의 간단한 예제를 참조하세요.

IUnknown IClassFactory 외에도 모든 밴드 개체는 다음 인터페이스를 구현해야 합니다.

CLSID(클래스 식별자)를 등록하는 것 외에도 탐색기 표시줄 및 데스크 밴드 개체도 적절한 구성 요소 범주에 등록해야 합니다. 구성 요소 범주를 등록하면 개체 형식과 해당 컨테이너가 결정됩니다. 도구 밴드는 다른 등록 절차를 사용하며 CATID(범주 식별자)가 없습니다. 이러한 개체가 필요한 세 대역 개체의 CATID는 다음과 같습니다.

밴드 유형 구성 요소 범주
세로 탐색기 막대 CATID_InfoBand
가로 탐색기 표시줄 CATID_CommBand
데스크 밴드 CATID_DeskBand

 

밴드 개체를 등록하는 방법에 대한 자세한 내용은 밴드 등록을 참조하세요.

밴드 개체가 사용자 입력을 수락하는 경우 IInputObject도 구현해야 합니다. 탐색기 모음 또는 데스크 밴드에 대한 바로 가기 메뉴에 항목을 추가하려면 밴드 개체가 IContextMenu를 내보내야 합니다. 도구 밴드는 바로 가기 메뉴를 지원하지 않습니다.

밴드 개체는 자식 창을 구현하므로 Windows 메시징을 처리하는 창 프로시저도 구현해야 합니다.

밴드 개체는 컨테이너의 IOleCommandTarget 인터페이스를 통해 컨테이너에 명령을 보낼 수 있습니다. 인터페이스 포인터를 가져오려면 컨테이너의 IInputObjectSite::QueryInterface 메서드를 호출하고 IID_IOleCommandTarget 요청합니다. 그런 다음 IOleCommandTarget::Exec를 사용하여 컨테이너에 명령을 보냅니다. 명령 그룹이 CGID_DeskBand. 밴드 개체의 IDeskBand::GetBandInfo 메서드가 호출되면 컨테이너는 dwBandID 매개 변수를 사용하여 밴드 개체에 세 가지 명령에 사용되는 식별자를 할당합니다. 4개의 IOleCommandTarget::Exec 명령 ID가 지원됩니다.

  • DBID_BANDINFOCHANGED

    밴드의 정보가 변경되었습니다. pvaIn 매개 변수를 IDeskBand::GetBandInfo에 대한 최신 호출에서 수신된 밴드 식별자에 설정합니다. 컨테이너는 밴드 개체의 IDeskBand::GetBandInfo 메서드를 호출하여 업데이트된 정보를 요청합니다.

  • DBID_MAXIMIZEBAND

    밴드를 최대화합니다. pvaIn 매개 변수를 IDeskBand::GetBandInfo에 대한 최신 호출에서 수신된 밴드 식별자에 설정합니다.

  • DBID_SHOWONLY

    컨테이너의 다른 밴드를 켜거나 끕니다. 다음 값 중 하나를 사용하여 pvaIn 매개 변수를 VT_UNKNOWN 형식으로 설정합니다.

    설명
    pUnk 밴드 개체의 IUnknown 인터페이스에 대한 포인터입니다. 다른 모든 책상 밴드는 숨겨집니다.
    0 모든 책상 밴드를 숨깁니다.
    1 모든 책상 밴드를 표시합니다.

     

  • DBID_PUSHCHEVRON

    버전 5. 펼침 단추 메뉴를 표시합니다. 컨테이너는 RB_PUSHCHEVRON 메시지를 보내고 밴드 개체는 펼침 단추 메뉴를 표시하라는 메시지를 표시하는 RBN_CHEVRONPUSHED 알림을 받습니다. IOleCommandTarget::Exec 메서드의 nCmdExecOpt 매개 변수를 IDeskBand::GetBandInfo에 대한 가장 최근 호출에서 받은 대역 식별자에 설정합니다. IOleCommandTarget::Exec 메서드의 pvaIn 매개 변수를 애플리케이션 정의 값이 있는 VT_I4 형식으로 설정합니다. RBN_CHEVRONPUSHED 알림의 lAppValue 값으로 밴드 개체로 다시 전달됩니다.

밴드 등록

밴드 개체는 아파트 스레딩을 지원하는 OLE in-process 서버로 등록되어야 합니다. 서버의 기본값은 메뉴 텍스트 문자열입니다. 탐색기 막대의 경우 Internet Explorer 보기 메뉴의 탐색기 모음 하위 메뉴에 표시됩니다. 도구 대역의 경우 Internet Explorer 보기 메뉴의 도구 모음 하위 메뉴에 표시됩니다. 책상 대역의 경우 작업 표시줄 바로 가기 메뉴의 도구 모음 하위 메뉴에 표시됩니다. 메뉴 리소스와 마찬가지로 문자 앞에 앰퍼샌드(>)를 배치하면 밑줄이 그어져 바로 가기 키를 사용할 수 있습니다. 예를 들어 첫 번째 그래픽에 표시된 세로 탐색기 모음의 메뉴 문자열은 "샘플 및 세로 탐색기 막대"입니다.

처음에 Internet Explorer는 구성 요소 범주를 사용하여 레지스트리에서 등록된 탐색기 모음 개체의 열거형을 검색합니다. 성능을 높이기 위해 이 열거형을 캐시하여 이후에 추가된 탐색기 막대를 간과합니다. Windows Internet Explorer에서 캐시를 다시 빌드하고 새 탐색기 모음을 인식하도록 하려면 새 탐색기 모음을 등록하는 동안 다음 레지스트리 키를 삭제합니다.

\HKEY_CURRENT_USER Software\Microsoft\Windows\CurrentVersion\Explorer\Dis카드able\PostSetup\Component Categories\{00021493-0000-0000-C000-000000000046}\Enum

\HKEY_CURRENT_USER Software\Microsoft\Windows\CurrentVersion\Explorer\Dis카드able\PostSetup\Component Categories\{00021494-0000-0000-C000-000000000046}\Enum

참고 항목

각 사용자에 대해 탐색기 모음 캐시가 생성되므로 설치 애플리케이션은 모든 사용자 레지스트리 하이브를 열거하거나 사용자가 처음 로그온할 때 실행할 사용자별 스텁을 추가해야 할 수 있습니다.

 

일반적으로 밴드 개체에 대한 기본 레지스트리 항목은 다음과 같이 표시됩니다.

HKEY_CLASSES_ROOT
   CLSID
      {Your Band Object's CLSID GUID}
         (Default) = Menu Text String
         InProcServer32
            (Default) = DLL Path Name
            ThreadingModel = Apartment

또한 도구 밴드에는 해당 개체의 CLSID가 Internet Explorer에 등록되어 있어야 합니다. 이렇게 하려면 다음과 같이 도구 밴드 개체의 CLSID GUID로 명명된 HKEY_LOCAL_MACHINE\Software\Microsoft\Internet Explorer\도구 모음 아래에 값을 할당합니다. 해당 데이터 값은 무시되므로 값 형식은 중요하지 않습니다.

HKEY_LOCAL_MACHINE
   Software
      Microsoft
         Internet Explorer
            Toolbar
               {Your Band Object's CLSID GUID}

레지스트리에 추가할 수 있는 몇 가지 선택적 값이 있습니다. 예를 들어 탐색기 표시줄을 사용하여 HTML을 표시하려면 다음 값이 필요합니다. 표시된 값은 예제가 아니라 사용해야 하는 실제 값입니다.

HKEY_CLASSES_ROOT
   CLSID
      {Your Band Object's CLSID GUID}
         Instance
            CLSID
               (Default) = {4D5C8C2A-D075-11D0-B416-00C04FB90376}

위에 표시된 값과 함께 사용하면 탐색기 표시줄을 사용하여 HTML을 표시하려는 경우에도 다음 선택적 값이 필요합니다. 이 값은 탐색기 모음에 대한 HTML 콘텐츠가 포함된 파일의 위치로 설정해야 합니다.

HKEY_CLASSES_ROOT
   CLSID
      {Your Band Object's CLSID GUID}
         Instance
            InitPropertyBag
               Url

또 다른 선택적 값은 각각 세로 또는 가로인지에 따라 탐색기 막대의 기본 너비 또는 높이를 정의합니다.

HKEY_CURRENT_USER
   Software
      Microsoft
         Internet Explorer
            Explorer Bars
               {Your Band Object's CLSID GUID}
                  BarSize

BarSize 값은 막대의 너비 또는 높이로 설정해야 합니다. 이 값은 8바이트가 필요하며 레지스트리에 이진 값으로 배치됩니다. 처음 4바이트는 가장 왼쪽 바이트부터 시작하여 16진수 형식으로 픽셀 단위로 크기를 지정합니다. 마지막 4바이트는 예약되어 있으며 0으로 설정해야 합니다.

예를 들어 기본 너비가 291(0x123) 픽셀인 HTML 지원 탐색기 모음에 대한 전체 레지스트리 항목이 여기에 표시됩니다.

HKEY_CLASSES_ROOT
   CLSID
      {Your Band Object's CLSID GUID}
         (Default) = Menu Text String
         InProcServer32
            (Default) = DLL Path Name
            ThreadingModel = Apartment
         Instance
            CLSID
               (Default) = {4D5C8C2A-D075-11D0-B416-00C04FB90376}
            InitPropertyBag
               Url = Your HTML File
HKEY_CURRENT_USER
   Software
      Microsoft
         Internet Explorer
            Explorer Bars
               {Your Band Object's CLSID GUID}
                  BarSize = 23 01 00 00 00 00 00 00

프로그래밍 방식으로 밴드 개체의 CATID 등록을 처리할 수 있습니다. 구성 요소 범주 관리자 개체(CLSID_StdComponentCategoriesMgr)를 만들고 해당 ICatRegister 인터페이스에 대한 포인터를 요청합니다. 밴드 개체의 CLSID 및 CATID를 ICatRegister::RegisterClassImplCategories에 전달합니다.

사용자 지정 탐색기 모음의 간단한 예

이 예제에서는 소개에 표시된 샘플 세로 탐색기 모음의 구현을 안내합니다.

사용자 지정 탐색기 모음을 만들기 위한 기본 절차는 다음과 같습니다.

  1. DLL에 필요한 함수를 구현합니다.
  2. 필요한 COM 인터페이스를 구현합니다.
  3. 원하는 선택적 COM 인터페이스를 구현합니다.
  4. 개체의 CLSID 및 필요한 경우 구성 요소 범주를 등록합니다.
  5. 탐색기 표시줄의 표시 영역에 맞게 크기가 조정된 Internet Explorer의 자식 창을 만듭니다.
  6. 자식 창을 사용하여 정보를 표시하고 사용자와 상호 작용합니다.

탐색기 모음 샘플에서 사용되는 매우 간단한 구현은 적절한 구성 요소 범주에 등록하기만 하면 실제로 탐색기 모음 유형 또는 데스크 밴드에 사용할 수 있습니다. 각 개체 형식의 표시 영역 및 컨테이너에 대해 보다 정교한 구현을 사용자 지정해야 합니다. 그러나 이 사용자 지정의 대부분은 샘플 코드를 가져와서 친숙한 Windows 프로그래밍 기술을 자식 창에 적용하여 확장하여 수행할 수 있습니다. 예를 들어 사용자 상호 작용을 위한 컨트롤이나 더 풍부한 디스플레이를 위한 그래픽을 추가할 수 있습니다.

DLL 함수

세 개체는 모두 다음 함수를 노출하는 단일 DLL로 패키지됩니다.

처음 세 함수는 표준 구현이며 여기서는 설명하지 않습니다. 클래스 팩터리 구현도 표준입니다.

필수 인터페이스 구현

세로 탐색기 모음 샘플은 CExplorerBar 클래스의 일부로 IUnknown, IObjectWithSite, IPersistStreamIDeskBand의 네 가지 필수 인터페이스를 구현합니다. 생성자, 소멸자 및 IUnknown 구현은 간단하며 여기서는 설명하지 않습니다. 자세한 내용은 샘플 코드를 참조하세요.

다음 인터페이스에 대해 자세히 설명합니다.

IObjectWithSite

사용자가 탐색기 모음을 선택하면 컨테이너는 해당 밴드 개체의 IObjectWithSite::SetSite 메서드를 호출합니다. punkSite 매개 변수는 사이트의 IUnknown 포인터로 설정됩니다.

일반적으로 SetSite 구현은 다음 단계를 수행해야 합니다.

  1. 현재 보유 중인 사이트 포인터를 해제합니다.
  2. SetSite전달된 포인터가 NULL설정되면 밴드가 제거됩니다. SetSite 는 S_OK 반환할 수 있습니다.
  3. SetSite전달된 포인터가 NULL이 아닌 경우 새 사이트가 설정됩니다. SetSite 는 다음을 수행해야 합니다.
    1. IOleWindow 인터페이스에 대해 사이트에서 QueryInterface호출합니다.
    2. IOleWindow::GetWindow를 호출하여 부모 창의 핸들을 가져옵니다. 나중에 사용할 수 있는 핸들을 저장합니다. 더 이상 필요하지 않은 경우 IOleWindow를 릴리스합니다.
    3. 이전 단계에서 가져온 창의 자식으로 밴드 개체의 창을 만듭니다. 표시되는 창으로 만들지 마세요.
    4. 밴드 개체가 IInputObject 구현하는 경우 해당 IInputObjectSite 인터페이스에 대해 사이트에서 QueryInterface를 호출합니다. 나중에 사용할 수 있도록 이 인터페이스에 대한 포인터를 저장합니다.
    5. 모든 단계가 성공하면 S_OK 반환합니다. 그렇지 않은 경우 실패한 내용을 나타내는 OLE 정의 오류 코드를 반환합니다.

탐색기 모음 샘플은 다음과 같은 방법으로 SetSite를 구현합니다. 다음 코드에서 m_pSite IInputObjectSite 포인터를 보유하고 m_hwndParent 부모 창의 핸들을 보유하는 프라이빗 멤버 변수입니다. 이 샘플에서는 창 만들기도 처리됩니다. 창이 없으면 이 메서드는 SetSite에서 가져온 부모 창의 적절한 크기 자식으로 탐색기 모음의 창을 만듭니다. 자식 창의 핸들은 m_hwnd 저장됩니다.

STDMETHODIMP CDeskBand::SetSite(IUnknown *pUnkSite)
{
    HRESULT hr = S_OK;

    m_hwndParent = NULL;

    if (m_pSite)
    {
        m_pSite->Release();
    }

    if (pUnkSite)
    {
        IOleWindow *pow;
        hr = pUnkSite->QueryInterface(IID_IOleWindow, reinterpret_cast<void **>(&pow));
        if (SUCCEEDED(hr))
        {
            hr = pow->GetWindow(&m_hwndParent);
            if (SUCCEEDED(hr))
            {
                WNDCLASSW wc = { 0 };
                wc.style         = CS_HREDRAW | CS_VREDRAW;
                wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
                wc.hInstance     = g_hInst;
                wc.lpfnWndProc   = WndProc;
                wc.lpszClassName = g_szDeskBandSampleClass;
                wc.hbrBackground = CreateSolidBrush(RGB(255, 255, 0));

                RegisterClassW(&wc);

                CreateWindowExW(0,
                                g_szDeskBandSampleClass,
                                NULL,
                                WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
                                0,
                                0,
                                0,
                                0,
                                m_hwndParent,
                                NULL,
                                g_hInst,
                                this);

                if (!m_hwnd)
                {
                    hr = E_FAIL;
                }
            }

            pow->Release();
        }

        hr = pUnkSite->QueryInterface(IID_IInputObjectSite, reinterpret_cast<void **>(&m_pSite));
    }

    return hr;
}

샘플의 GetSite 구현은 SetSite에서 저장한 사이트 포인터를 사용하여 사이트의 QueryInterface 메서드에 대한 호출을 래핑합니다.

STDMETHODIMP CDeskBand::GetSite(REFIID riid, void **ppv)
{
    HRESULT hr = E_FAIL;

    if (m_pSite)
    {
        hr =  m_pSite->QueryInterface(riid, ppv);
    }
    else
    {
        *ppv = NULL;
    }

    return hr;
}

IPersistStream

Internet Explorer는 탐색기 모음의 IPersistStream 인터페이스를 호출하여 탐색기 표시줄이 영구 데이터를 로드하거나 저장할 수 있도록 합니다. 영구 데이터가 없으면 메서드는 여전히 성공 코드를 반환해야 합니다. IPersistStream 인터페이스는 IPersist에서 상속되므로 5개의 메서드를 구현해야 합니다.

탐색기 표시줄 샘플은 영구 데이터를 사용하지 않으며 IPersistStream최소 구현만 가지고 있습니다. IPersist::GetClassID는 개체의 CLSID(CLSID_SampleExplorerBar)를 반환하고 re기본der는 S_OK, S_FALSE 또는 E_NOTIMPL 반환합니다.

IDeskBand

IDeskBand 인터페이스는 밴드 개체와 관련이 있습니다. 하나의 메서드 외에도 IDockingWindow에서 상속되며, IOleWindow에서 상속됩니다.

GetWindowIOleWindow::ContextSensitiveHelp의 두 가지 IOleWindow 메서드가 있습니다. 탐색기 모음 샘플의 GetWindow 구현은 탐색기 모음의 자식 창 핸들 m_hwnd 반환합니다. 상황에 맞는 도움말은 구현되지 않으므로 ContextSensitiveHelp는 E_NOTIMPL 반환합니다.

IDockingWindow 인터페이스에는 세 가지 메서드가 있습니다.

ResizeBorderDW 메서드는 어떤 형식의 밴드 개체와도 함께 사용되지 않으며 항상 E_NOTIMPL 반환해야 합니다. ShowDW 메서드는 해당 매개 변수의 값에 따라 탐색기 모음의 창을 표시하거나 숨깁니다.

STDMETHODIMP CDeskBand::ShowDW(BOOL fShow)
{
    if (m_hwnd)
    {
        ShowWindow(m_hwnd, fShow ? SW_SHOW : SW_HIDE);
    }

    return S_OK;
}

CloseDW 메서드는 탐색기 모음의 창을 삭제합니다.

STDMETHODIMP CDeskBand::CloseDW(DWORD)
{
    if (m_hwnd)
    {
        ShowWindow(m_hwnd, SW_HIDE);
        DestroyWindow(m_hwnd);
        m_hwnd = NULL;
    }

    return S_OK;
}

re기본ing 메서드인 GetBandInfo는 IDeskBand와 관련이 있습니다. Internet Explorer는 이를 사용하여 탐색기 모음의 식별자 및 보기 모드를 지정합니다. Internet Explorer는 세 번째 매개 변수로 전달되는 DESKBANDINFO 구조체의 dwMask 멤버를 채워 탐색기 모음에서 하나 이상의 정보를 요청할 수도 있습니다. GetBandInfo는 식별자 및 보기 모드를 저장하고 DESKBANDINFO 구조를 요청된 데이터로 채워야 합니다. 탐색기 모음 샘플은 다음 코드 예제와 같이 GetBandInfo 를 구현합니다.

STDMETHODIMP CDeskBand::GetBandInfo(DWORD dwBandID, DWORD, DESKBANDINFO *pdbi)
{
    HRESULT hr = E_INVALIDARG;

    if (pdbi)
    {
        m_dwBandID = dwBandID;

        if (pdbi->dwMask & DBIM_MINSIZE)
        {
            pdbi->ptMinSize.x = 200;
            pdbi->ptMinSize.y = 30;
        }

        if (pdbi->dwMask & DBIM_MAXSIZE)
        {
            pdbi->ptMaxSize.y = -1;
        }

        if (pdbi->dwMask & DBIM_INTEGRAL)
        {
            pdbi->ptIntegral.y = 1;
        }

        if (pdbi->dwMask & DBIM_ACTUAL)
        {
            pdbi->ptActual.x = 200;
            pdbi->ptActual.y = 30;
        }

        if (pdbi->dwMask & DBIM_TITLE)
        {
            // Don't show title by removing this flag.
            pdbi->dwMask &= ~DBIM_TITLE;
        }

        if (pdbi->dwMask & DBIM_MODEFLAGS)
        {
            pdbi->dwModeFlags = DBIMF_NORMAL | DBIMF_VARIABLEHEIGHT;
        }

        if (pdbi->dwMask & DBIM_BKCOLOR)
        {
            // Use the default background color by removing this flag.
            pdbi->dwMask &= ~DBIM_BKCOLOR;
        }

        hr = S_OK;
    }

    return hr;
}

선택적 인터페이스 구현

필수는 아니지만 구현하는 데 유용할 수 있는 두 가지 인터페이스인 IInputObjectIContextMenu가 있습니다. 탐색기 모음 샘플은 IInputObject를 구현합니다. IContextMenu를 구현하는 방법에 대한 자세한 내용은 설명서를 참조하세요.

IInputObject

밴드 개체가 사용자 입력을 허용하는 경우 IInputObject 인터페이스를 구현해야 합니다. Internet Explorer는 IInputObjectSite를 구현하고 IInputObject를 사용하여 창이 둘 이상 포함된 경우 적절한 사용자 입력 포커스를 기본. 탐색기 모음에서 구현해야 하는 세 가지 메서드가 있습니다.

Internet Explorer는 UIActivateIO를 호출하여 탐색기 표시줄에 활성화 또는 비활성화 중임을 알릴 수 있습니다. 활성화되면 탐색기 모음 샘플은 SetFocus를 호출하여 포커스를 창으로 설정합니다.

Internet Explorer는 포커스가 있는 창을 확인하려고 할 때 HasFocusIO를 호출합니다. 탐색기 모음의 창 또는 하위 항목 중 하나에 포커스 가 있는 경우 HasFocusIO 는 S_OK 반환해야 합니다. 그렇지 않은 경우 S_FALSE 반환해야 합니다.

TranslateAcceleratorIO 를 사용하면 개체가 키보드 가속기를 처리할 수 있습니다. 탐색기 모음 샘플은 이 메서드를 구현하지 않으므로 S_FALSE 반환합니다.

샘플 막대의 IInputObjectSite 구현은 다음과 같습니다.

STDMETHODIMP CDeskBand::UIActivateIO(BOOL fActivate, MSG *)
{
    if (fActivate)
    {
        SetFocus(m_hwnd);
    }

    return S_OK;
}

STDMETHODIMP CDeskBand::HasFocusIO()
{
    return m_fHasFocus ? S_OK : S_FALSE;
}

STDMETHODIMP CDeskBand::TranslateAcceleratorIO(MSG *)
{
    return S_FALSE;
};

CLSID 등록

모든 COM 개체와 마찬가지로 탐색기 모음의 CLSID를 등록해야 합니다. Internet Explorer에서 개체가 제대로 작동하려면 적절한 구성 요소 범주(CATID_InfoBand)에도 등록해야 합니다. 탐색기 모음에 대한 관련 코드 섹션은 다음 코드 예제에 나와 있습니다.

HRESULT RegisterServer()
{
    WCHAR szCLSID[MAX_PATH];
    StringFromGUID2(CLSID_DeskBandSample, szCLSID, ARRAYSIZE(szCLSID));

    WCHAR szSubkey[MAX_PATH];
    HKEY hKey;

    HRESULT hr = StringCchPrintfW(szSubkey, ARRAYSIZE(szSubkey), L"CLSID\\%s", szCLSID);
    if (SUCCEEDED(hr))
    {
        hr = E_FAIL;
        if (ERROR_SUCCESS == RegCreateKeyExW(HKEY_CLASSES_ROOT,
                                             szSubkey,
                                             0,
                                             NULL,
                                             REG_OPTION_NON_VOLATILE,
                                             KEY_WRITE,
                                             NULL,
                                             &hKey,
                                             NULL))
        {
            WCHAR const szName[] = L"DeskBand Sample";
            if (ERROR_SUCCESS == RegSetValueExW(hKey,
                                                NULL,
                                                0,
                                                REG_SZ,
                                                (LPBYTE) szName,
                                                sizeof(szName)))
            {
                hr = S_OK;
            }

            RegCloseKey(hKey);
        }
    }

    if (SUCCEEDED(hr))
    {
        hr = StringCchPrintfW(szSubkey, ARRAYSIZE(szSubkey), L"CLSID\\%s\\InprocServer32", szCLSID);
        if (SUCCEEDED(hr))
        {
            hr = HRESULT_FROM_WIN32(RegCreateKeyExW(HKEY_CLASSES_ROOT, szSubkey,
                 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL));
            if (SUCCEEDED(hr))
            {
                WCHAR szModule[MAX_PATH];
                if (GetModuleFileNameW(g_hInst, szModule, ARRAYSIZE(szModule)))
                {
                    DWORD cch = lstrlen(szModule);
                    hr = HRESULT_FROM_WIN32(RegSetValueExW(hKey, NULL, 0, REG_SZ, (LPBYTE) szModule, cch * sizeof(szModule[0])));
                }

                if (SUCCEEDED(hr))
                {
                    WCHAR const szModel[] = L"Apartment";
                    hr = HRESULT_FROM_WIN32(RegSetValueExW(hKey, L"ThreadingModel", 0,  REG_SZ, (LPBYTE) szModel, sizeof(szModel)));
                }

                RegCloseKey(hKey);
            }
        }
    }

    return hr;
}

샘플에서 밴드 개체를 등록하면 일반적인 COM 프로시저가 사용됩니다.

CLSID 외에도 하나 이상의 구성 요소 범주에 대 한 대역 개체 서버를 등록 해야 합니다. 이는 실제로 세로 탐색기와 가로 탐색기 모음 샘플 간의 구현에서 기본 차이입니다. 이 프로세스는 구성 요소 범주 관리자 개체(CLSID_StdComponentCategoriesMgr)를 만들고 ICatRegister::RegisterClassImplCategories 메서드를 사용하여 밴드 개체 서버를 등록하여 처리됩니다. 이 예제에서는 다음 코드 예제와 같이 탐색기 모음 샘플의 CLSID 및 CATID를 Private 함수인 RegisterComCat에 전달하여 구성 요소 범주 등록을 처리합니다.

HRESULT RegisterComCat()
{
    ICatRegister *pcr;
    HRESULT hr = CoCreateInstance(CLSID_StdComponentCategoriesMgr, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pcr));
    if (SUCCEEDED(hr))
    {
        CATID catid = CATID_DeskBand;
        hr = pcr->RegisterClassImplCategories(CLSID_DeskBandSample, 1, &catid);
        pcr->Release();
    }
    return hr;
}

창 프로시저

밴드 개체는 자식 창을 표시에 사용하므로 Windows 메시징을 처리하는 창 프로시저를 구현해야 합니다. 밴드 샘플에는 최소한의 기능이 있으므로 창 프로시저는 5개의 메시지만 처리합니다.

더 많은 기능을 지원하기 위해 추가 메시지를 수용하도록 절차를 쉽게 확장할 수 있습니다.

LRESULT CALLBACK CDeskBand::WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    LRESULT lResult = 0;

    CDeskBand *pDeskBand = reinterpret_cast<CDeskBand *>(GetWindowLongPtr(hwnd, GWLP_USERDATA));

    switch (uMsg)
    {
    case WM_CREATE:
        pDeskBand = reinterpret_cast<CDeskBand *>(reinterpret_cast<CREATESTRUCT *>(lParam)->lpCreateParams);
        pDeskBand->m_hwnd = hwnd;
        SetWindowLongPtr(hwnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(pDeskBand));
        break;

    case WM_SETFOCUS:
        pDeskBand->OnFocus(TRUE);
        break;

    case WM_KILLFOCUS:
        pDeskBand->OnFocus(FALSE);
        break;

    case WM_PAINT:
        pDeskBand->OnPaint(NULL);
        break;

    case WM_PRINTCLIENT:
        pDeskBand->OnPaint(reinterpret_cast<HDC>(wParam));
        break;

    case WM_ERASEBKGND:
        if (pDeskBand->m_fCompositionEnabled)
        {
            lResult = 1;
        }
        break;
    }

    if (uMsg != WM_ERASEBKGND)
    {
        lResult = DefWindowProc(hwnd, uMsg, wParam, lParam);
    }

    return lResult;
}

WM_COMMAND 처리기는 단순히 0을 반환합니다. WM_PAINT 처리기는 소개의 탐색기 표시줄 예제에 표시된 간단한 텍스트 표시를 만듭니다.

void CDeskBand::OnPaint(const HDC hdcIn)
{
    HDC hdc = hdcIn;
    PAINTSTRUCT ps;
    static WCHAR szContent[] = L"DeskBand Sample";
    static WCHAR szContentGlass[] = L"DeskBand Sample (Glass)";

    if (!hdc)
    {
        hdc = BeginPaint(m_hwnd, &ps);
    }

    if (hdc)
    {
        RECT rc;
        GetClientRect(m_hwnd, &rc);

        SIZE size;

        if (m_fCompositionEnabled)
        {
            HTHEME hTheme = OpenThemeData(NULL, L"BUTTON");
            if (hTheme)
            {
                HDC hdcPaint = NULL;
                HPAINTBUFFER hBufferedPaint = BeginBufferedPaint(hdc, &rc, BPBF_TOPDOWNDIB, NULL, &hdcPaint);

                DrawThemeParentBackground(m_hwnd, hdcPaint, &rc);

                GetTextExtentPointW(hdc, szContentGlass, ARRAYSIZE(szContentGlass), &size);
                RECT rcText;
                rcText.left   = (RECTWIDTH(rc) - size.cx) / 2;
                rcText.top    = (RECTHEIGHT(rc) - size.cy) / 2;
                rcText.right  = rcText.left + size.cx;
                rcText.bottom = rcText.top + size.cy;

                DTTOPTS dttOpts = {sizeof(dttOpts)};
                dttOpts.dwFlags = DTT_COMPOSITED | DTT_TEXTCOLOR | DTT_GLOWSIZE;
                dttOpts.crText = RGB(255, 255, 0);
                dttOpts.iGlowSize = 10;
                DrawThemeTextEx(hTheme, hdcPaint, 0, 0, szContentGlass, -1, 0, &rcText, &dttOpts);

                EndBufferedPaint(hBufferedPaint, TRUE);

                CloseThemeData(hTheme);
            }
        }
        else
        {
            SetBkColor(hdc, RGB(255, 255, 0));
            GetTextExtentPointW(hdc, szContent, ARRAYSIZE(szContent), &size);
            TextOutW(hdc,
                     (RECTWIDTH(rc) - size.cx) / 2,
                     (RECTHEIGHT(rc) - size.cy) / 2,
                     szContent,
                     ARRAYSIZE(szContent));
        }
    }

    if (!hdcIn)
    {
        EndPaint(m_hwnd, &ps);
    }
}

WM_SETFOCUS 및 WM_KILLFOCUS 처리기는 사이트의 IInputObjectSite::OnFocusChangeIS 메서드를 호출하여 포커스 변경의 사이트에 알릴 수 있습니다.

void CDeskBand::OnFocus(const BOOL fFocus)
{
    m_fHasFocus = fFocus;

    if (m_pSite)
    {
        m_pSite->OnFocusChangeIS(static_cast<IOleWindow*>(this), m_fHasFocus);
    }
}

밴드 개체는 사용자 지정 탐색기 막대를 만들어 Internet Explorer의 기능을 확장하는 유연하고 강력한 방법을 제공합니다. 책상 밴드를 구현하면 일반 창의 기능을 확장할 수 있습니다. 일부 COM 프로그래밍이 필요하지만 궁극적으로 사용자 인터페이스에 대한 자식 창을 제공하는 역할을 합니다. 여기에서 구현의 대부분은 익숙한 Windows 프로그래밍 기술을 사용할 수 있습니다. 여기서 설명하는 예제에는 제한된 기능만 있지만 밴드 개체의 필요한 모든 기능을 보여 주며 고유하고 강력한 사용자 인터페이스를 만들기 위해 쉽게 확장할 수 있습니다.