2008년 06월 20일
[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. 완료 ~_~

하긴 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 | 2008/06/20 16:35 | WPF | 트랙백 | 덧글(0)





☞ 내 이글루에 이 글과 관련된 글 쓰기 (트랙백 보내기) [도움말]