2011년 8월 3일 수요일

WPF에서 타이머개체 사용하기

1. WPF자체의 타이머가 이닌 Windows.Form의 타이머를 사용하는 방법
using System.Windows.Forms;


// Timer개체를 생성, 속성, 이벤트 정의
timer = new Timer();
timer.Interval = 200;
timer.Tick += new EventHandler(timer_Tick);
timer.Enabled = true;


// 타이머의 Tick 이벤트
private void timer_Tick(object sender, EventArgs e)
{
            DrawClock();
}
/// 이코드는 Shape로 만들어진 시계의 시, 분, 초 침을 현재 시간에 맞추어
/// 각도를 조정하는 코드이다.
///   첨부한 샘플을 참고하라.


/// <summary>
/// 시침, 분침, 초침 그리기
/// </summary>
private void DrawClock()
{
            DateTime now = DateTime.Now;
            txtTime.Text = now.ToLongTimeString();
            int hour = now.Hour;
            int minute = now.Minute;
            int second = now.Second;
            double hourAngle = hour * 30 + minute * 0.5;
            double minuteAngle = minute * 6 + second * 0.1;
            double secondAngle = second * 6;
            rotateHour.Angle = hourAngle;
            rtHour.RenderTransform = rotateHour;
            rotateMinute.Angle = minuteAngle;
            rtMinute.RenderTransform = rotateMinute;
            rotateSecond.Angle = secondAngle;
            rtSecond.RenderTransform = rotateSecond;
}

2. WPF자체의 타이머를 사용하는 방법
이것은 윈폼용과 동일하게 동작합니다.
이벤트도 같구요. 다만, Enabled가 이니라 Start(), Stop()이네요.

public DispatcherTimer Timer = new DispatcherTimer();
void Window1_Loaded(object sender, RoutedEventArgs e)
{
    Timer.Interval = TimeSpan.FromSeconds(3);
    Timer.Tick += new EventHandler(Timer_Tick);
    Timer.Start();
}


3. 별도의 쓰레드를 만들어 동작하는 타이머를 사용하는 방법
Thread로 동작하는 것 같더군요. 따라서, 폼 개체에 접근할 수 없습니다.
this 라던가.. 폼 개체에 접근하려면 에러가 발생합니다.


사용방법은 using System.Timers; 를 추가하고 그냥 사용하시면 됩니다.
다만, Tick 이벤트가 아니라
aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
Elapsed 이벤트를 사용합니다. 이벤트 핸들러도 다릅니다.
참고하세요.

System.Timers.Timer Class는 TestWindow와 다른 새로운 Thread를 생성해서 동작을 합니다.
System.Windows.Threading.DispatcherTimer는 TestWindow와 같은 Thread에서 동작을 합니다.


WPF용으로는 두가지의 타이머가 있습니다.
이 두가지 타이머간에는 다음과 같은 차이점이 존재합니다..


Dispatcher Class
 - 같은 Thread에서 동작하기 때문에 동기화 작업이 필요없고, TestWindow의 멤버도
   자유롭게 접근 가능합니다.

Timer Class
 - 서로 다른 Thread에서 동작하기 때문에 TestWindow의 멤버변수에 직접 접근을 할수 없습니다.
    (직접 접근을 하기 위해서는 Invoke나 BeginInvoke를 사용하여야 합니다)
 - 서로 다른 Thread에서 동작하기 때문에 List를 추가/삭제 하기 위해서는 추가적으로 Thread간
   동기화 작업을 해줘야 합니다.

현재 작업경로 가져오기

현재 작업 디렉토리의 졍규화된 경로를 가져옵니다.

System.Environment.CurrentDirectory

결과값에는 "\"는 포함되지 않습니다.
따라서, System.Environment.CurrentDirectory + "\\" + txtFileName.Text; 와 같이 사용해야 합니다.

아무데나 눌러서 창을 이동할때

타이틀이 없는 창을 이동하는 방법

Win32나 MFC등에서는 보통 이러한 경우 창 이동과 관련된 부분을 직접 구현 해야 하지만 WPF에서는 이러한 상황 에서 개발자의 부담을 덜어드리고자 간단한 메서드 호출 한번으로 마우스를 사용한 창 이동 기능을 구현 할 수 있습니다. 

Window Class에서 DragMove 메서드를 제공하는데요, 이 는 마우스 왼쪽 단추를 누른 상태로 창 클라이언트 영역의 노출된 영역에서 창을 끌 수 있도록 돕습니다. 사용방법이 매우 간단합니다. 

마우스를 사용해서 창을 끌 수 있도록 하고 싶은 객체의 MouseLeftButtonDown이벤트에 DragMove()메서드를 호출해주기만 하면 됩니다. 

void Window1_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)     this.DragMove();}

외부의 프로세스(앱)을 호출(실행)하고 태스크를 관리할때

외부의 프로그램을 실행하는 코드입니다.
System.Diagnostics.Process.Start("Shutdown.exe", "-s -f -t 00");         // 시스템 종료
System.Diagnostics.Process.Start("Shutdown.exe", "-r -f -t 00");          // 시스템 다시 시작

System.Diagnostics의 Process 개체로 노트패드 프로세스를 생성하여 실행합니다.
Process myProcess = new Process();
myProcess.StartInfo.FileName = "Notepad";
myProcess.StartInfo.WindowStyle = ProcessWindowStyle.Maximized;
myProcess.Start();

나중에 강제로 중지시키거나 정보를 검색할 수 있습니다.
myProcess.CloseMainWindow();

응답의 유무를 검사하여 정상종료와 강제종료를 할 수 있습니다.
If myProcess.Responding Then
    myProcess.CloseMainWindow()
Else
    ' Forces the process to close if the Responding value is False.
    myProcess.Kill()
End If

실행중인 모든 프로세스를 검색할 수 있습니다.
Process[] myProcesses = Process.GetProcesses();
foreach (Process myProcess in myProcesses)
{
      Console.WriteLine(myProcess.ProcessName);
}

프로세스 이름으로 현재 실행중인 프로세스를 가져올 수 있습니다.
myProcesses = Process.GetProcessesByName("Notepad");

아이콘파일, 실행파일에서 아이콘 가져오기

파일관리자 같은 앱을 만들다보면 꼭 필요하지요...


/// System.Drawing.Icon을 이용하여 아이콘을 추출하는 함수
public System.Windows.Media.ImageSource getIcon(string filename)
{
            System.Windows.Media.ImageSource icon;
            using (System.Drawing.Icon sysicon = System.Drawing.Icon.ExtractAssociatedIcon(filename))
            {
                icon = System.Windows.Interop.Imaging.CreateBitmapSourceFromHIcon(
                            sysicon.Handle,
                            System.Windows.Int32Rect.Empty,
                            System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());
            }
            return icon;
}

// 이렇게 사용하세요. 아이콘파일의 기본 크기는 32이니깐...
private void button5_Click(object sender, RoutedEventArgs e)
{
            image1.Source = getIcon(textBox1.Text);
            image1.Width = 32;
            image1.Height = 32;
}

당연하겠지만, 이코드를 사용하려면 System.Drawing을 참조추가해야만 하겠죠?


getIcon(textBox1.Text) 에서 textBox1.Text는 추출하고자 하는 파일의 실제경로(FullPath)이어야 합니다.
경로가 틀리면 에러가 발생하겠죠?

using (System.Drawing.Icon sysicon = System.Drawing.Icon.ExtractAssociatedIcon(filename))
이 줄에서 에러가 발생합니다. 

실제 사용하려면 에러 핸들러를 달거나, 파일유무를 검사하면 되겠죠...