Silverlight 5에서는 많은 사람들의 의견을 수용하여 여러 가지 기능들이 추가되었습니다.

이 중에서 P/Invoke 기능은 상당히 중요한 의미를 가집니다.

 

그래서, 이번 강좌에서는 Silverlight 5의 P/Invoke 기능에 대해서 살펴봅니다.

 

중요! P/Invoke 기능은 Silverlight 5 Beta에서는 지원되지 않고 Silverlight 5 RC 이후에서만 지원됩니다.

 

 

P/Invoke란?

P/Invoke는 Platform Invocation Services의 약자로서 쉽게 말하면 .NET 어셈블리가 아닌 윈도우의 표준 DLL 파일에 있는 기능을 가져다 쓸 수 있게 해주는 기능입니다. P/Invoke는 윈도우 개발자에게는 매우 익숙한 기능으로 아마도 윈폼이나 WPF, VB6로 개발해보신 분들은 아마 잘 알고 계실 겁니다.

 

P/Invoke를 이용하면 다음과 같은 것들을 할 수 있습니다.

- Silverlight 내에서 Win32 API를 직접 호출

- VC++ 등으로 만들어진 윈도우 표준 DLL의 함수 호출

 

Silverlight에서 P/Invoke를 사용할 수 있다는 것은 Silverlight OOB의 기능을 무한대로 확장할 수 있다는 것을 의미합니다.

Silverlight 3에서 OOB가 처음 도입되었고, Silverlight 4에서 COM Automation 지원, Silverlight 5에서는 P/Invoke 지원이 추가되었죠. 이제 Silverlight에서 COM Automation에 이어 P/Invoke까지 지원됨으로써 Silverlight로 웬만한 윈도우 응용 프로그램을 만들 수 있게 되었습니다. 무거운 WPF대신 말이죠!

 

지금까지 경험으로 보건대 전반적으로 Siverlight가 WPF에 비해 가볍고 민첩하게 작동합니다. 따라서 멋진 UI가 필요한 윈도우 응용 프로그램을 만들 때 WPF 대신 Silverlight를 사용하는 것을 적극적으로 고려해보세요. 특히, 넷북과 같은 저사양 PC에서도 빠르게 돌아갈 겁니다.

 

Silverlight에서 P/Invoke 지원은 중요한 의미가 있습니다. 실버라이트가 처음 나왔을 때에는 멀티 플랫폼/멀티 브라우저를 표방했었지요. 그런데 P/Invoke는 윈도우 전용 기능입니다. 물론 OOB에서만 사용할 수 있긴 하지만 Mac에서는 사용할 수 가 없는 기능입니다. 개인적인 생각입니다만 아마 앞으로 웹에서 Silverlight나 Flash 같은 브라우저 플러그인 기술들이 점차적으로 지양되는 추세이며, Silverlight가 이러한 흐름에 맞게 브라우저 플러그인에서 데스크탑/모바일 UI 프레임웍으로 진화하고 있는 것이 아닌가 싶습니다.

 

여하튼, Silverlight 5만으로도 꽤 쓸만하게 윈도우 응용 프로그램을 만들 수 있게 되었습니다.

 

 

 

P/Invoke 사용하기

 

P/Invoke 사용법은 간단합니다. 데스크탑용 .NET Framework에서 하던 그대로 하시면 됩니다.

단, 다음과 같이 OOB 기능을 활성화하고, 권한 상승 역시 체크해야 합니다.

 

image_4.png

 

image_6.png

 

 

 

간단한 샘플을 하나 만들어보죠.

이 샘플에서는 다음과 같은 Win32 API를 사용하고 있습니다.

  • GetWindowsDirectory – 윈도우 폴더 경로를 반환합니다.
  • FindWindow – 특정 윈도우의 핸들을 가져옵니다.
  • MoveWindow – 특정 윈도우의 위치와 크기를 변경합니다.

 

using System;

using System.Collections.Generic;

using System.Linq;

using System.Windows;

using System.Windows.Controls;

using System.Runtime.InteropServices;

using System.Text;

 

namespace PInokeSample

{

    public partial class MainPage : UserControl

    {

 

        [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]

        static extern uint GetWindowsDirectory(StringBuilder lpBuffer, uint uSize);

 

        [DllImport("user32.dll", SetLastError = true)]

        internal static extern bool MoveWindow(IntPtr hWnd, int X, int Y,

                                int nWidth, int nHeight, bool bRepaint);

 

        [DllImport("user32.dll", SetLastError = true)]

        static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

 

        const int MaxPathLength = 255;

 

        public MainPage()

        {

            InitializeComponent();

            btnGetWindowsPath.Click += new RoutedEventHandler(btnGetWindowsPath_Click);

            btnMoveNotePad.Click += new RoutedEventHandler(btnMoveNotePad_Click);

        }

 

        void btnGetWindowsPath_Click(object sender, RoutedEventArgs e)

        {

            StringBuilder sb = new StringBuilder(MaxPathLength);

            int len = (int)GetWindowsDirectory(sb, MaxPathLength);

           

            string _windowsDirectory = sb.ToString(0, len);

            MessageBox.Show(_windowsDirectory);

        }

 

        void btnMoveNotePad_Click(object sender, RoutedEventArgs e)

        {

            IntPtr hwnd = FindWindow(null, "제목 없음 - 메모장");

 

            if ((int)hwnd == 0)

            {

                MessageBox.Show("해당 윈도우를 찾지 못했습니다.");

                return;

            }

            else

            {

                MoveWindow(hwnd, 20,20,400,400, true);

            }

 

        }

 

    }

}

 

 

P/Invoke는 [DllImport]라는 특성을 이용하여 정의하며, 데스크탑 .NET Framework와 똑같은 방법으로 사용하면 됩니다.

 

프로젝트를 실행해보면 다음과 같이 됩니다.

image_8.png

 

 

 

Get Windows Path 버튼을 누르면 윈도우 경로를 보여줍니다. Silverlight 기본 함수로는 이런 거 안됩니다. ^^

 

image_10.png

 

 

 

 

메모장을 띄워놓은 후 Move NotePad 버튼을 클릭하면 메모장이 400*400의 정사각형 모양으로 바뀌죠. 즉 Silverlight 바깥에 있는 다른 윈도우 응용 프로그램을 제어할 수 있는 겁니다!

 

image_12.png

 

 

 

이 예에서는 간단한 Win32 API를 호출해봤는데, P/Invoke 기능을 이용하면 Silverlight에서는 안되는 많은 기능들을 구현할 수 있습니다. 게다가 C++로 만든 DLL등과도 연계할 수 있으므로 안되는 것이 없다라고 말할 수 있을 정도이지요.

 

이제 남은 것은 어떤 API를 호출할 수 있느냐는 것인데… http://www.pinvoke.net 에 가보시면 P/Invoke로 호출할 수 있는 Windows API들을 쉽게 검색하실 수 있습니다. 게다가 C#과 VB샘플까지도 보여주죠^^





profile