[WPF] SplashScreen과 Window메세지 후킹

WPF 하면 할수록 어렵다.. 심지어 이건 거의 프로그램을 처음부터 다시 배운다는 느낌까지 갖을 정도다..
하긴 C# 이 약하긴 했으니 당연한건가..

주의깊게 볼것 : 윈도우메세지후킹(HwndSource, WndProc() )
                      Dispatcher.BeginInvoke()


1. 프로젝트에 Window를 추가하고 (여기서는 SplashScreen 이라고 이름지었다)
2. 윈도우 스타일을 None
3. Startup Position 을 Screen Center 로 설정
4. 적당한 이미지를 올려놓는다.
5. 생성된 SplashScreen.xaml.cs 파일을 아래와 같이 편집


using System.Windows.Threading;
using System.Windows.Interop;

public partial class SplashScreen
    {

        public SplashScreen()
        {
            InitializeComponent();
            this.Loaded += new RoutedEventHandler(Splash_Loaded);
        }

        void Splash_Loaded(object sender, RoutedEventArgs e)
        {
            HwndSource source = HwndSource.FromHwnd(new WindowInteropHelper(this).Handle);
            source.AddHook(new HwndSourceHook(WndProc));


            IAsyncResult result = null;

            // This is an anonymous delegate that will be called when the initialization has COMPLETED
            AsyncCallback initCompleted = delegate(IAsyncResult ar)
            {
                App.Current.ApplicationInitialize.EndInvoke(result);  // <<-- STA 관련한 문제 발생시 이 라인을 주석처리 해보라!!
                                                                                          // 솔직히 이 함수의 역할을 잘 모르겠다... 아시는분 댓글좀..
                // Ensure we call close on the UI Thread.

                Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal, (Invoker)delegate { Close(); });
            };

            // This starts the initialization process on the Application
            result = App.Current.ApplicationInitialize.BeginInvoke(this, initCompleted, null);

        }

        public void SetProgress(double progress)
        {
            // Ensure we update on the UI Thread.
            Dispatcher.BeginInvoke(DispatcherPriority.Normal, (Invoker)delegate { });
        }

        void cancelButton(object sender, RoutedEventArgs e)
        {
            this.DialogResult = false;
        }

        private static IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
        {
            const int WM_NCHITTEST = 0x0084;
            const int HTCAPTION = 0x0002;
            const int WM_NCLBUTTONDOWN = 0xA1;

            handled = false;

            switch (msg)
            {
                case WM_NCHITTEST:
                    {  
                        short x = (short)((lParam.ToInt32() & 0xFFFF));
                        short y = (short)((lParam.ToInt32() >> 16));

                        handled = true;

                        return new IntPtr(HTCAPTION);
                    }
                    break;
            }

            return IntPtr.Zero;
        }
    }

6. App.xaml.cs 를 아래와 같이 편집

internal delegate void Invoker();

    public partial class App : Application
    {
        internal delegate void ApplicationInitializeDelegate(SplashScreen splashWindow);
        internal ApplicationInitializeDelegate ApplicationInitialize;

        public App()
        {
            ApplicationInitialize = _applicationInitialize;
        }

        public static new App Current
        {
            get { return Application.Current as App; }
        }
       
        private void _applicationInitialize(SplashScreen splashWindow)
        {
            DbforIQ.LoadTableList();

            // Create the main window, but on the UI thread.
            Dispatcher.BeginInvoke(DispatcherPriority.Normal, (Invoker)delegate
            {
                ProtoType MainWindow = new ProtoType();

                MainWindow.Show();
            });
            
        }
    }

7. App.xaml 에서 StarupUri 를 아래와 같이 편집

StartupUri="SplashScreen.xaml"

8. 완료 ~_~


by MusaPanz | 2008/06/20 16:35 | WPF | 트랙백 | 덧글(0)

트랙백 주소 : http://mahapunch.egloos.com/tb/3792612
☞ 내 이글루에 이 글과 관련된 글 쓰기 (트랙백 보내기) [도움말]

:         :

:

비공개 덧글

◀ 이전 페이지          다음 페이지 ▶