서학수 tech2001@hitel.net|마이크로소프트 VB와 ASP.NET의 MVP였으며, 데브피아 ASP.NET과 WPF, Silverlight 시삽으로 활동 중이며, 현재 Silverlight와 WPF 기술과 관련하여 개발을 하고, 틈틈이 사진도 찍고 있다. 최근 Transfer Windows 7 모임과 함께 Windows7과 관련된 개발 기술을 알리고 있다.

 

 

 

Windows 7에는 이전까지 없었던 다양한 형태의 변화가 생겼다. 어떤 것은 혁신적이라고 생각되어질 만큼 눈에 띄는 것도 있다. 하지만 이 글에서는 가장 사용자의 피부에 와 닿는 부분을 살펴보게 될 것이다. 처음 Windows 7에 대한 여러 가지 정보를 접해 보면 대부분 멀티터치 라든지, 센서 기술 등의 화려한 것에 이끌릴 수 있지만 단 며칠만, 아니 단 몇 시간만 지속적으로 사용해 본 사람이라면 단 두 가지가 떠오를 것이다. ‘빠르다’, ‘테스크바(Task-bar) 정말 편하다’

 

 

정말 테스크바는 좋아졌다. 이렇게 영리하고 편리하며, 예쁘기까지 하다. 여기서 잠시 추억(?)을 떠 올려 보자.

 

 

 

 

 

Windows 7 이전까지 운영체제의 테스크바는 현재 실행되고 있는 응용프로그램을 표시하는 것이 주요 임무였고, Windows XP로 넘어오면서 응용프로그램을 빠르게 실행할 수 있는 바로가기 역할의 아이콘(Quick-Launch)이 생겼으며, 같은 응용프로그램이 실행되면 그룹화(Grouping)되는 정도의 역할을 담당했다. 그런 테스크바가 Windows 7에서는 스마트해진 것이다. 그러나 개발자에게 “무엇인가 스마트하게 변화되었다”라는 말은 또 하나를 배우고 익혀서 코드에 넣고 테스트해야 하는 골칫거리(?)가 생겨났다고 느낄 수도 있다. 하지만 걱정할 필요는 없다. 사용자를 위한 것 뿐 아닌, 개발자를 위한 것도 준비되어 있다. 이제 하나씩 그 베일을 벗겨보자.

 

 

테스크바(Taskbar)의 구성

 

 

Windows 7의 새로운 테스크바는 <화면 4>와 같이 빠른실행 부분과 현재 실행중인 응용프로그램을 따로 분리하여 나타내지 않고 하나로 표현한다. 실행 중이면 아이콘에 사각형 테두리가 생기고 현재 활성화되어 있다면 불투명한 배경이 보여 진다. 또한 <화면 4>처럼 여러 창이 겹쳐 보이기도 한다. 즉, 각각의 아이콘이 빠른실행이면서도 동시에 현재 실행 중인지도 함께 알려 주는 것이다. <화면 4>에서 보여지는 부분은 Windows 7에서 모두 처리되므로 굳이 개발자가 어떠한 코딩을 해야 하는 부분은 전혀 없다.

 

 

<화면 5-1>은 SQL Server Management Studio에서 마우스 오른쪽 버튼을 클릭했을 때이며, <화면 5-2>는 SQL Manage ment Studio가 실행 중일 동안 마우스 오른쪽 버튼을 클릭했을 때이다. <화면 5-3>은 실행 중인 SQL Management Studio에 마우스를 올려 놓으면 보여지는 작은 썸네일 화면이다. <화면 5>에서는 새로운 Windows 7 테스크바를 지원하지 않을 경우에 나타는 것을 확인할 수 있다.

반면 Windows 7에 있는 새로운 MS Media Player는 Windows 7 테스크바를 지원하기 때문에 마우스 오른쪽 버튼을 눌러서 보는 메뉴가 확연하게 다르다<화면 6-1>. 또한 실행중인 화면에서도 새로운 명령 버튼을 확인할 수가 있다<화면 6-2>.

이 중에서 <그림 6-1>에서 보는 실행 중이 아닌 상태에서도 기존에 열어보았던 파일에 바로 접근을 가능케 하는 목록을 점프리스트(Jump List)라고 부른다. 잘 생각해 보면 응용프로그램이 실행되고 있지 않은 상태에서 단 두 번의 클릭만으로 최근에 작업했던 또는 열어보았던 파일을 열어서 실행할 수 있다는 것이다. 당연히 이러한 기능을 구현하기 위해서는 개발자의 노력이 필요하다. SQL Management Studio처럼 개발자들은 별 다른 노력 없이 Windows 7에서 실행하는 것은 아무런 수고가 필요하지 않다. 하지만 이제 새로운 운영체제에 맞도록 추가 개발해야 하는 요건이 생겨난 것이다. 이 얼마나 귀찮고 힘든 일일까.

그러나 귀찮을지는 몰라도 적어도 어렵지는 않다. 그 이유는 개발을 준비하면서 알아보자.

테스크바 개발 준비
새로운 Windows 7 테스크바를 지원하는 응용프로그램을 개발하기 위해서는 다음과 같은 준비물이 필요하다. Windows 7는 물론 당연히 필요하다. 너무 당연한 말인가?

Microsoft Windows SDK for Windows 7 and .NET Framework 3.5 sp1
Windows 7과 관련된 기능을 사용하기 위해서 제공되는 SDK(SW Development Kit) 7
http://www.microsoft.com/downloads/details.aspx?FamilyID=c17ba869-9671-4330-a63e-1fd44e0e2505&displaylang=en

Visual Studio 2008 or 2010
최신 .NET을 포함하여 개발 하기 때문에 Visual Studio 2008 이상의 버전은 필수적이다. Visual Studio 2010에 대해서는 다음에서 정보를 얻을 수 있다.

http://www.microsoft.com/downloadS/details.aspx?familyid=75CBCBCD-B0E8-40EA-ADAE-85714E8984E3&displaylang=en

Windows API code pack

과거에는 Windows의 시스템과 그와 관련된 기능들을 이용하여 개발을 하기 위해서는 사실상 Visual C++과 같은 네이티브 개발 환경이 적합했고 .NET 개발자들은 쉽게 접근할 수가 없었다. 다행하게도 Windows 7이 발표되고 베타버전 때부터 이러한 개발자들의 고충을 알고 제공되는 것이 있었다. 그것은 Windows Code Pack이라 불리는 것으로 현재 Windows 7의 정식 버전에 맞추어 정식 1.0 버전이 공개되어 있다. Windows 7 기반의 기능들을 모두 .NET 버전으로 구현하는 오픈 소스 프로젝트로 관련된 소스뿐 아니라 샘플까지 모두 통째로 다운로드 받을 수 있다.

http://code.msdn.microsoft.com/WindowsAPICodePack

Windows API Code Pack (Ver 1.0)에서  지원하는 항목

● Windows 7 Taskbar Jump Lists, Icon Overlay, Progress Bar, Tabbed Thumbnails, and Thumbnail Toolbars.
● Windows 7 Libraries, Known Folders, non-file system containers.
● Windows Shell Search API support, a hierarchy of Shell Namespace entities, and Drag and Drop functionality for Shell Objects.
● Explorer Browser Control.
● Shell property system.
● Windows Vista and Windows 7 Common File Dialogs, including custom controls.
● Windows Vista and Windows 7 Task Dialogs.
● Direct3D 11.0, Direct3D 10.1/10.0, DXGI 1.0/1.1, Direct2D 1.0, DirectWrite, Windows Imaging Component (WIC) APIs. (DirectWrite and WIC have partial support)
● Sensor Platform APIs
● Extended Linguistic Services APIs
● Power Management APIs
● Application Restart and Recovery APIs
● Network List Manager APIs
● Command Link control and System defined Shell icons.

테스크바 지원 초간단 프로젝트

실제로 간단한 응용프로그램을 제작해 보자.

우선 Windows API Code Pack을 다운을 받고, 압축을 풀어 보면, 다음과 같은 폴더 구조가 있다.

 

 

앞서서 말했듯이 Windows API Code Pack은 전체 소스가 공개되어 있어 Visual Studio 솔루션 파일을 통째로 들어있음을 확인할 수 있다. 그 중에서 Core 부분과 Shell 부분이 기본적으로 사용해야 할 부분이다. 이름에서 보면 짐작할 수 있듯, 센서나 DirectX 등은 현재 사용할 필요가 없다. 사용하는 방법은 Core와 Shell을 컴파일하여 DLL을 직접 참조하는 방법과 이것 또한 Visual Studio Project의 전체 소스이므로 프로젝트 통째로 참조하는 방법이 있다. 공부도 하고 디버깅에 어떤 원리가 있는지 참고도 할 수 있으므로 여기서는 프로젝트 전체를 참조해 보도록 하겠다.

<화면 7>에서 박스가 되어 있는 Core 폴더와 Shell 폴더를 복사해 놓고, Visual Studio로 새로운 Windows 응용프로그램 프로젝트를 만들고 필요한 위치에 Core 폴더와 Shell 폴더를 복사한다.

(참고) Windows API Code Pack을 사용하기 위해서 무조건 참조해야 하는 것은 Core뿐이다. 하지만, Windows의 공통 기능이나, 대화상자, 라이브러리 등의 여러 가지 기본 기능을 Shell에서 포함하고 있기 때문에, 보통의 경우에는 Core부분과 Shell부분을 기본적으로 참조해 놓고 시작하는 경우가 대부분이다.

 

복사한 Core와 Shell을 솔루션에 추가하고, 초간단 프로젝트에 “프로젝트 참조”로 참조 추가를 하여 <화면 8>과 같은 구조가 되도록 한다. 정상적으로 추가되었는지 확인을 위해서 빌드해 보면 정상적으로 빌드 됨을 확인할 수 있다. 이것으로 Windows 7의 새로운 테스크바를 지원할 준비가 완료 되었다. 물론 기존에 이미 Windows 응용프로그램이나, WPF Windows 응용프로그램으로 만들어진 프로젝트가 있다면 위와 같이 Windows API Code Pack 중에서 Core와 Shell 부분을 참조할 수 있도록 프로젝트 참조 또는 완성된 DLL 참조를 통해서 참조만 추가해 주어도 .NET 프로젝트에서 손쉽게 Windows 7의 테스크바에 접근할 준비는 끝난 것이다. 이제 간단하게 테스크바에 메모장을 실행할 수 있는 작업(Task)을 하나 만들어 보자. 우선 다음과 같이 기본적으로 생겨진 Form1에서 이벤트중 Shown을 선택하고 <리스트 1>과 같이 코딩하자.

<리스트 1>

01:     public partial class Form1 : Form
02:     {
03:         private const string PROG_ID = "TestApplication001";
04:         private JumpList myList;
05:         private TaskbarManager winTaskbarManager = TaskbarManager.Instance;
06:
07:         public Form1()
08:         {
09:             InitializeComponent();
10:
11:             this.winTaskbarManager.ApplicationId = PROG_ID;
12:         }
13:
14:         private void Form1_Shown(object sender, System.EventArgs e)
15:         {
16:             myList = JumpList.CreateJumpList();
17:           
18:             string systemFolder = Environment.GetFolderPath(Environment.SpecialFolder.System);
19:             myList.AddUserTasks(new JumpListLink(Path.Combine(systemFolder,
20:                 "notepad.exe"), "메모장 열기")
21:                {
22:                    IconReference
23:                    = new IconReference(Path.Combine(systemFolder,
24:                        "notepad.exe"), 0)
25:                });
26:             myList.Refresh();
27:         }
28:     }

<리스트 1>에서 myList는 WindowsAPICodePack에서 제공하는 JumpList 타입이고, winTaskbarManager는 Windows APICodePack에서 제공하는 TaskbarManager 타입이다. 03번줄의 상수값은 테스크바가 아이콘을 식별하기 위한 ProgramID로 사용될 문자열 상수값이다. Windows 7의 테스크바는 응용프로그램의 실행파일로 같은 프로그램을 구별하는 것이 아니라 <리스트 1>의 11번줄에서 처럼 ApplicationId 값을 가지고 프로그램을 식별한다. 즉 실행파일이 달라도 ApplicationId가 같으면 테스크바에서는 겹쳐진 아이콘 형태로 표시된다.

<리스트 1>에서는 프로그램이 처음 실행할 때, 정해진 상수값으로 테스크바 매니저에게 ApplicationId 값을 알려놓은 다음, 프로그램이 화면에 보여지는 시점에 점프리스트를 가져오게 된다. 16번줄의 CreateJumgList() 메소드는 테스크바에서 현재 응용프로그램에 해당하는 점프리스트를 반환 받는다. 18번줄~25번줄은 시스템 폴더의 위치를 찾아서 메모장의 링크를 만들고 그 링크를 점프리스트의 사용자 작업줄로 추가하는 코드다. 이때 아이콘도 메모장의 아이콘을 얻어오도록 Shell의 도움을 받고 있다.

아직 화면에 아무런 작업을 하지 않았으나 이것을 실행하고, 테스크바에서 마우스 오른쪽 버튼을 클릭해 보면 <화면 9>와 같은 화면을 볼 수 있다.

 

 

실제로 ‘메모장 열기’를 클릭하면 메모장이 실행되는 것을 확인할 수 있다. 필자는 프로그램에 아이콘을 설정했기 때문에 파란색 원 모양의 아이콘이 표시되어 있다.

단, 몇 줄의 코드만으로 이런 작업이 가능한 것이다. 물론 Windows API Code Pack의 소스코드를 따라가다 보면 어떻게 이러한 동작이 가능한지 알아볼 수도 있고, 그 반대로 쉽게 사용만 할 수도 있다. 단, 위 소스코드는 위험천만하게도 이 응용프로그램이 Windows 7에서만 실행된다는 것을 전제로 한다. 만일 Windows Vista나 Windows XP와 같은 곳에서 이 프로그램을 실행했다면 당연히 프로그램은 오류를 나타내며 종료되고 말 것이다. 따라서 점프리스트와 같은 것은 현재 환경이 Windows 7 환경인지 검사할 필요가 있다. 물론 이 또한 Code Pack에서 제공한다. 다음 코드 한 줄이면 해결이다.

<리스트 2>
if (TaskbarManager.IsPlatformSupported == true)

위 <리스트 2>의 단 한 줄의 코드는 현재 TaskbarManager가 지원되는 환경인지 확인을 해주는 bool값을 가지고 있다. 조금 응용해 보자. <리스트 1>의 26번 줄 다음 라인에 <리스트 3>을 추가한다.

<리스트 3>
this.winTaskbarManager.SetProgressState(TaskbarProgressBarState.Normal);
TaskbarManager.Instance.SetProgressValue(50, 100);

소스코드만으로 짐작이 가능했겠지만 테스크바의 아이콘에 진행표시 배경을 추가하는 코드이다. <리스트 3>의 첫 번째 라인은 진행표시를 나타내도록 설정하는 것이며, 그 두 번째 라인은 0~100 중에서 50에 그 상태를 맞추는 것을 의미한다. 이렇게 <리스트 3>을 추가하여 실행하면 <화면 10>과 같은 화면을 얻을 수 있다.

 

 

진행률이 50%인 배경화면을 포함한 아이콘, 이것이 바로 Windows 7에서 탐색기로 파일을 복사하거나, Internet Explorer 8로 다운로드를 받는 동안 보이는 진행표시를 테스크바에서 볼 수 있었던 그 기능이다. 너무나도 쉽게 구현된다.

점프리스트 추가 프로젝트
상태표시를 하거나, 메모장을 링크로 연결하는 등은 별다른 수고 없이 개발할 수 있음을 알았다. 이제 워드나 엑셀처럼 파일을 열고 닫은 후 다시 파일을 빠르게 열 수 있도록 최근 작업했던 목록을 점프리스트로 표시해 보자.

이렇게 파일을 연결하는 것은 메모장의 링크를 거는 것과는 조금 다른 것이 있다. 그것은 파일을 현재 개발하고 있는 응용프로그램과 함께 등록 절차가 한 번 필요하다는 점이 있다는 것이다. 등록되지 않은 파일은 점프리스트의 최근목록에 나타나지 않거나, 사용자 정의 카테고리 등에 새롭게 등록하려 시도한다면 <화면 11>과 같은 오류가 나타날 것이다.

 

 

 

이런 파일을 등록하는 것은 Windows API Code Pack의 Sample에서 그 해결책 소스코드를 제공받을 수 있다. Windows APICodePack\Samples\Shell\TaskbarDemo 경로를 따라가면 RegistrationHelper 라는 콘솔응용프로그램이 있다. 이것을 사용하여 사용하고자 하는 파일과 현재의 응용프로그램을 등록하는 과정을 수행하면 된다. 등록하는 과정 자체가 중요한 것이므로 어떤 원리로 등록되는지는 생략하고 RegistrationHelper 프로젝트까지 현재 프로젝트에 포함시켜서 코드를 고쳐보자.

<리스트 4>
01:         public Form1()
02:         {
03:             InitializeComponent();
04:
05:             this.winTaskbarManager.ApplicationId = PROG_ID;
06:             executablePath = Assembly.GetEntryAssembly().Location;
07:             CheckFileRegistration();
08:         }
09:
10:         private void Form1_Shown(object sender, System.EventArgs e)
11:         {
12:             myList = JumpList.CreateJumpList();
13:
14:             myList.AddToRecent(@"C:\TEST1.txt");
15:             myList.Refresh();
16:         }

<리스트 2>를 <리스트 4>로 변경했다. 06번 라인과 07번 라인은 Windows API Code Pack의 Sample에서 자세한 내용을 살펴보면 되겠다. 확장자가 ‘.txt’로 된 파일을 사용하기 위해 등록되는 코드로 실행할 때에 단 한 번만 실행되는 부분이다. 중요한 점은 14번 라인이다. 이것을 실행한 다음 테스크바에서 마우스 오른쪽 버튼을 누르면 <화면 12>와 같은 화면을 볼 수 있다.

 

 

점프리스트에 단지 AddToRecent() 메소드의 호출만으로 최근에 작업했던 파일을 등록시킬 수 있다. 물론 다른 코드를 작성하지 않았기 때문에 실제로 <화면 12>에서 ‘TEST1’을 클릭하면 단지 응용프로그램이 하나 더 실행될 뿐 아무런 작동을 하지는 않는다. 이것은 등록할 때 사용했던 실행문의 파라미터의 해석을 통해서 처리될 수 있다. 지면 관계상 파라미터를 사용하여 최근 파일의 다시 로드를 살펴보지는 않겠다. 소스를 또 바꿔보자.

<리스트 5>

01:         private JumpListCustomCategory category1 = new JumpListCustomCategory("내맘대로 카테고리");
02:         private JumpListCustomCategory category2 = new JumpListCustomCategory("또하나의 카테고리");   
03:
04:         private void Form1_Shown(object sender, System.EventArgs e)
05:         {
06:             myList = JumpList.CreateJumpList();
07:
08:             myList.AddCustomCategories(category1, category2);
09:             category1.AddJumpListItems(new JumpListItem(@"C:\TEST1.txt"));
10:             category1.AddJumpListItems(new JumpListItem(@"C:\TEST2.txt"));
11:             category2.AddJumpListItems(new JumpListItem(@"C:\TEST1.txt"));
12:             category2.AddJumpListItems(new JumpListItem(@"C:\TEST2.txt"));
13:             myList.Refresh();
14:         }

위 <리스트 5>를 실행한 다음 테스크바에서 마우스 오른쪽 버튼을 누르면 <화면 13>과 같은 화면을 볼 수 있다.

 

 

 

다른 설명을 하지 않아도 사용자가 지정한 카테고리를 만들고 그 항목에 내용을 추가함을 알 수 있다. 08번 라인의 JumpList의 AddCustomCategories() 메소드는 여러 가지를 동시에 등록할 수 있기 때문에 이번 예제에서는 두 개의 카테고리를 동시에 파라미터로 넘겨서 등록했다. 각각의 카테고리에 해당하는 JumpListCustomCategory에는 JumpListItem을 만들어서 추가해 주는 것으로 항목을 하나씩 만들 수 있다. 주의해야 할 점은 중복을 스스로 체크해 주지 않기 때문에 개발자가 같은 항목이 추가되면 최근 것만 남기고 갱신할 수 있도록 신경 써 주어야 한다는 것이다.

 

 

썸네일 툴바 프로젝트

 

 

<화면 14>는 좌측에 이미지가 있는 폴더의 이미지들이 목록으로 나타나고 그 중에 선택된 이미지가 우측 영역에 확대되어 나타나는 간단한 WPF 응용프로그램이다. 이 응용프로그램을 Windows 7의 새로운 썸네일툴바 기능을 이용해서 <화면 15>처럼 보이도록 개발해 보자.

 

 

 

<화면 15>를 보면 썸네일로 나타나는 부분이 <화면 14>에서 보이는 좌측 목록은 보이지 않고, 큰 이미지만 보이고 있다. 또한 4개의 버튼이 있고, 각각 클릭했을 때, 이미지 목록 중 처음, 이전, 다음, 마지막 이미지를 선택할 수 있는 기능까지 구현되고 있다. 개발을 위해서 Windows API Code Pack에서 Core와 Shell을 DLL참조 또는 프로젝트 참조로 참조하는 WPF Windows 응용프로그램 프로젝트를 선택한다. Windows1.xaml에 다음과 같이 XAML을 코딩한다.

<리스트 6>

01: <Window x:Class="Microsoft.WindowsAPICodePack.Samples. ImageViewerDemo.Window1"
02:     xmlns="http://schemas.microsoft.com/winfx/2006/ xaml/presentation"
03:     xmlns:x="http://schemas.microsoft.com/winfx/ 2006/xaml"
04:     Title="Image Viewer WPF Demo (with Taskbar Thumbnail toolbar)" Height="600" Width="800" WindowStartupLocation="CenterScreen">
05:     <Window.Resources>
06:         <DataTemplate x:Key="MyImageTemplate">
07:             <StackPanel>
08:                 <Image Source="{Binding Path}" Width="100" Height="100"/>
09:                 <TextBlock Text="{Binding Name}" Width="100"/>
10:             </StackPanel>
11:         </DataTemplate>
12:     </Window.Resources>
13:     <DockPanel Name="dockPanel">
14:         <ListBox
15:       Name="ImageList"
16:       DockPanel.Dock="Left"
17:       ItemsSource="{Binding AllImages}"
18:       ItemTemplate="{StaticResource MyImageTemplate}"/>
19:         <Image DockPanel.Dock="Right" Name="pictureBox1" Source="{Binding ElementName=ImageList,Path=SelectedItem.Path}">
20:         </Image>
21:     </DockPanel>
22: </Window>

<리스트 6>에서 그림 목록을 채우기 위하여 17번 라인의 AllImages를 Windows1.xaml.cs 파일에 <리스트 7>처럼 작성한다.

<리스트 7>

01: private List<ShellFile> picturesList;
02:
03: public List<ShellFile> AllImages
04: {
05:     get
06:     {
07:         ShellContainer pics = (ShellContainer)KnownFolders.Pictures;
08:
09:         if (ShellLibrary.IsPlatformSupported)
10:             pics = (ShellContainer)KnownFolders.PicturesLibrary;
11:
12:         if (picturesList == null)
13:             picturesList = new List<ShellFile>();
14:         else
15:             picturesList.Clear();
16:
17:         GetPictures(pics);
18:         return picturesList;
19:     }
20: }
21:
22: private void GetPictures(ShellContainer folder)
23: {
24:     foreach (ShellFile sf in folder.OfType<ShellFile>())
25:     {
26:         string ext = Path.GetExtension(sf.Path).ToLower();
27:
28:         if (ext == ".jpg" || ext == ".jpeg" || ext == ".png" || ext == ".bmp")
29:             picturesList.Add(sf);
30:     }
31:
32:     foreach (ShellContainer subFolder in folder.OfType<ShellContainer>())
33:         GetPictures(subFolder);
34: }

<리스트 7>의 10번 라인에서 라이브러리에 이미지로 등록된 폴더들을 얻어오고 17번 라인에서 GetPictures를 호출하게 된다. 호출된 프로시저는 각각의 폴더에서 이미지들을 추출하여 picturesList에 추가하는 코드이다. <리스트 7>에서는 Windows 7의 라이브러리의 개념과 그것을 위하여 Windows API Code Pack을 활용하는 것을 알고 있어야 한다.

<리스트 8>01: pictureBox1.LayoutUpdated += new EventHandler(pictureBox1_LayoutUpdated);
02:
03: void pictureBox1_LayoutUpdated(object sender, EventArgs e)
04: {
05:     Vector v = VisualTreeHelper.GetOffset(pictureBox1);
06:
07:     TaskbarManager.Instance.TabbedThumbnail. SetThumbnailClip(
08:         (new WindowInteropHelper(this)).Handle,
09:         new System.Drawing.Rectangle((int)v.X,
10:                    (int)v.Y,
11:                    (int)pictureBox1.RenderSize.Width,
12:                                 (int)pictureBox1.RenderSize.Height));
13: }

<리스트 8>의 01번라인은 Window1() 생성자에서 이벤트 핸들러의 등록코드이며, 이미지의 레이아웃의 변화가 생길 때 picturBox1_LayoutUpdated가 실행 됨을 의미한다. 05번 라인에서 현재의 이미지가 되는 pictureBox1의 오프셋 값을 얻어오게 되고, 이것을 가지고 테스크바에서 리스트를 제외한 본 이미지만을 썸네일로 반영하는 것이 07번 라인부터 12번 라인까지이다. 길어 보이지만 실제로는 한 줄이다.

이제 Windows 7 테스크바의 썸네일 하단에 네 개의 아이콘으로 표시되는 버튼을 달아두어야 할 것이다. 이 썸네일 밑에 달려있는 버튼ThumbnailToolbarButton이라고 한다. 미리 아이콘파일(.ico)을 만들어 둔 다음, 프로젝트에 추가해 놓으면 준비는 끝났다.

<리스트 9>

01: private ThumbnailToolbarButton buttonPrevious;
02: private ThumbnailToolbarButton buttonNext;
03: private ThumbnailToolbarButton buttonFirst;
04: private ThumbnailToolbarButton buttonLast;
05:
06:  void Window1_Loaded(object sender, RoutedEventArgs e)
07: {
08:     buttonFirst = new ThumbnailToolbarButton(Properties.Resources.first, "First Image");
09:     buttonFirst.Enabled = false;
10:     buttonFirst.Click += new EventHandler<ThumbnailButtonClickedEventArgs>(buttonFirst_Click);
11:
12:     buttonPrevious = new ThumbnailToolbarButton(Properties.Resources.prevArrow, "Previous Image");
13:     buttonPrevious.Enabled = false;
14:     buttonPrevious.Click += new EventHandler<ThumbnailButtonClickedEventArgs>(buttonPrevious_Click);
15:
16:     buttonNext = new ThumbnailToolbarButton(Properties.Resources.nextArrow, "Next Image");
17:     buttonNext.Click += new EventHandler<ThumbnailButtonClickedEventArgs>(buttonNext_Click);
18:
19:     buttonLast = new ThumbnailToolbarButton(Properties.Resources.last, "Last Image");
20:     buttonLast.Click += new EventHandler<ThumbnailButtonClickedEventArgs>(buttonLast_Click);
21:
22:     TaskbarManager.Instance.ThumbnailToolbars.AddButtons(new WindowInteropHelper(this).Handle,
23:         buttonFirst, buttonPrevious, buttonNext, buttonLast);
24:
25:     // 이하 생략

 

<리스트 9>의 01번 라인부터 04번 라인까지 네 개의 버튼에 해당하는 객체를 정의하고, Window1이 Load될 때에 각각의 버튼을 생성하고 이벤트 핸들러를 등록한다. 필요에 따라서는 맨 처음 이미지를 보여줄 것이므로 09번 라인과 13번 라인처럼 버튼을 비활성화 시키기도 한다. 이렇게 만들어진 네 개의 썸네일버튼은 22번 라인에서처럼 한꺼번에 등록시킨다. 이렇게만 해도 <화면 15>처럼 네 개의 버튼이 제 기능을 갖도록 화면에 나타나게 되고, 각각의 이벤트 핸들러 프로시저에 이미지를 선택하는 코드를 넣어두게 되면, 마치 리모컨처럼 원격으로 테스크바에서 응용프로그램을 제어할 수가 있게 된다.

 

<리스트 10>

01: void ImageList_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
02: {
03:     if (ImageList.SelectedIndex == 0)
04:     {
05:         buttonFirst.Enabled = false;
06:         buttonPrevious.Enabled = false;
07:     }
08:     else if (ImageList.SelectedIndex > 0)
09:     {
10:         buttonFirst.Enabled = true;
11:         buttonPrevious.Enabled = true;
12:     }
13:     if (ImageList.SelectedIndex == ImageList.Items.Count - 1)
14:     {
15:         buttonLast.Enabled = false;
16:         buttonNext.Enabled = false;
17:     }
18:     else if (ImageList.SelectedIndex < ImageList.Items.Count - 1)
19:     {
20:         buttonLast.Enabled = true;
21:         buttonNext.Enabled = true;
22:     }
23: }

이미지 목록에서 선택된 이미지가 바뀔 때 마다 <리스트 10>의 코드가 실행되면, 각각의 썸네일버튼들은 상황에 맞추어 활성과 비활성 상태가 변화되어 적절히 버튼의 상태가 조절된다.

 

정리하며…
테스크바에는 지금까지 설명했던 것 이외에, Tab으로 구성된 윈도우들의 표현 방식이나 전환에 대한 부분도 있고, 메신저 프로그램처럼 현재 상태를 작은 아이콘으로 추가하여 덧붙이는 기능도 있다. 하지만 지면 관계상 많은 부분을 모두 설명할 수는 없었기에 가장 기본적인 것과 흥미 있을 것 같은 부분을 간략하게나마 살펴보았다. 아마도 Windows 7을 계속 사용하다 보면 테스크바가 모양만 좋아진 것이 아니라 얼마나 편리해졌는지 실감하게 될 것이다. 개발을 위해서 Windows XP와 2003 Server 그리고 Vista도 늘 함께 사용하고 있지만 Windows 7의 테스크바의 편리함은 더욱 더 빛을 발한다. 문제는 언제나 새로운 것을 활용하려면 개발자의 노력이 필요하게 되는데 지금껏 살펴보았듯이 기존 응용프로그램에 약간의 수고를 더해서 이제 막 날개를 펴고 비상하려는 Windows 7까지 완벽하게 지원되는 모습을 보여준다면 어떨까 싶다.

마지막으로 언제나 늦은 밤까지 일과 공부에 열중인 개발자들에게 박수를 보낸다.

 

출처 :  마이크로소프트웨어

+ Recent posts