해당 윈도우 클래서 내에서 this.Handle 을 날리면 윈도우 핸들을 불러올 수 있다 -_- ...
접기
필자가 C# 개발자는 아니지만 아무래도 이 프로그램은 C# 이 편하겠다 싶어서
C# 을 한번 사용해봤는데, 코딩 도중 . . .
아니, C# 은 윈도우 핸들을 제공해주지 않는건가 . . . ?
구글링으로 검색해보면 죄다
1. FindWindow 로 자신의 윈도우를 검색해보세요.
- 이럴 일은 극히 드믈지만 같은 윈도우 이름이 나올시 문제가 발생할 수 있음.
2. WindowInteropHelper.handle 을 사용해보세요 !
- .Net Framework 2.0 은 존중받을 수 없나욧 !
( 호환을 고려해서 현재 2.0 으로 제작중 )
3. 그렇다면, System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle 은요 ?
- 윈도우 핸들값을 리턴하는건지, C# 전용 윈도우 핸들 오브젝트 값을 리턴하는건지
감이 안잡히는데, 적어도 Debug.Print 로 값을 확인해보니 정상적인 값은 나오지 않더군요...
찾던 중, 마음에 드는 답이 찾아왔는데
4. GetWindowThreadProcessId Api 를 이용해보세요 !
- !?
GetWindowThreadProcessId 를 사용하면 확실하게 윈도우 핸들을 잡아낼 수 있다.
여기다, 얻어오는 윈도우 핸들에서 이름을 추출해 비교까지 하면 더더욱 만족스러운 결과를 얻을 수 있다.
if ( process_id == current_process_id
&& get_window_name(hwnd) == "WindowName" )
이와 같은 식으로 . . .
다만, 필자가 만들고 있는 프로그램은 메인 윈도우가 하나라 구지 이름비교까지 확인할 필요도 없어서
대충 발로 만들어봤다.
[ GetCurrentProcess().MainWindowHandle 의 잘못된 값 리턴 ]
[ Spy++ 을 통해 윈도우 핸들 확인 ]
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace WindowsFormsApplication1 { public partial class Form1 : Form { public Form1() { InitializeComponent(); }
private void Form1_Load(object sender, EventArgs e) { System.Diagnostics.Debug.Print(System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle.ToString("X8")); System.Diagnostics.Debug.Print(CFindWindow.FindMainWindowFromProcessId(System.Diagnostics.Process.GetCurrentProcess().Id).ToString("X8")); System.Diagnostics.Debug.Print(CFindWindow.FindMainWindowFromCurrentProcessId().ToString("X8")); System.Diagnostics.Debug.Print(CFindWindow.FindWindow(null, "Form1").ToString("X8")); System.Diagnostics.Debug.Print(CFindWindow.FindWindowEx(IntPtr.Zero, IntPtr.Zero, null, "Form1").ToString("X8")); } } public static class CFindWindow { private delegate bool EnumWindowsProc(IntPtr hWnd,IntPtr lParam); [DllImport("user32.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Winapi)] private extern static bool EnumWindows(EnumWindowsProc EnumProc,IntPtr lParam); [DllImport("user32.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Winapi)] private extern static IntPtr GetAncestor(IntPtr hWnd, int gaFlags); [DllImport("user32.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Winapi)] private extern static int GetWindowThreadProcessId(IntPtr hWnd, ref int lpdwProcessId); [DllImport("user32.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Winapi)] public extern static IntPtr FindWindow(string lpszClass, string lpszWindow); [DllImport("user32.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Winapi)] public extern static IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter,string lpszClass, string lpszWindow);
// GetAncestor Flags private const int GA_PARENT = 1; private const int GA_ROOT = 2; private const int GA_ROOTOWNER = 3;
private static IntPtr m_Wnd;
private static bool _EnumWindowsProc(IntPtr hWnd, IntPtr lParam) { int dwProcessId = 0; GetWindowThreadProcessId(hWnd,ref dwProcessId); if (dwProcessId == (int)lParam) { m_Wnd = GetAncestor(hWnd, GA_ROOTOWNER); return false; } return true; }
public static IntPtr FindMainWindowFromProcessId(int nProcess) { m_Wnd = IntPtr.Zero; EnumWindows(_EnumWindowsProc, (IntPtr)nProcess); return m_Wnd; }
public static IntPtr FindMainWindowFromCurrentProcessId() { return FindMainWindowFromProcessId(System.Diagnostics.Process.GetCurrentProcess().Id); } } }
이와 같은 식으로 구현하였다.
확실히 C#을 사용하면 다양한 라이브러리를 사용할 수 있어 이득이 큰데
자잘한 핸들 컨트롤 + 디버깅이 생각보다 귀찮게 하는거 같아
C# 개발자분들의 노고가 눈에 보이기 시작했다...
접기