public GlowEdgeDrawingContext(/*int width, int height*/) { _screenDC = ApiUser32.GetDC(IntPtr.Zero); if (ScreenDC == IntPtr.Zero) { throw new Exception(nameof(ScreenDC)); } _windowDC = ApiGdi32.CreateCompatibleDC(ScreenDC); if (WindowDC == IntPtr.Zero) { throw new Exception(nameof(WindowDC)); } _backgroundDC = ApiGdi32.CreateCompatibleDC(ScreenDC); if (BackgroundDC == IntPtr.Zero) { throw new Exception(nameof(BackgroundDC)); } _blend.BlendOp = (byte)AlphaBlendControl.AC_SRC_OVER; // 唯一值 _blend.BlendFlags = 0; // 必须 0 _blend.SourceConstantAlpha = 0xFF; // 不增加额外的 Alpha 值,一切以源为主 _blend.AlphaFormat = (byte)AlphaBlendControl.AC_SRC_ALPHA; // 使用源的 Alpha 通道 //_windowBitmap = new GlowWindowBitmap(ScreenDC, width, height); //ApiGdi32.SelectObject(_windowDC, _windowBitmap.Handle); }
/// <summary> /// 重新设置窗口的窗口过程,保证窗口过程是 <see cref="WndProc(IntPtr, uint, IntPtr, IntPtr)"/> /// </summary> /// <remarks> /// 该函数并非无意义,我们定义 <see cref="WndProc(IntPtr, uint, IntPtr, IntPtr)"/> 为窗口过程,子类通过重写该过程实现 /// 窗口消息的处理。但是,如果子类要自己定义窗口类,那么必然存在将窗口过程设置为其他的情况,为了保证正常,所有才会有这个方法; /// 另外,窗口过程是switch,如果switch的判断内容过多,会造成性能的下降,该方法也可以将创建将创建时的窗口过程和实际执行的窗口 /// 过程进行分离,从而实现减少实际窗口过程的switch判断的目的。 /// </remarks> private void SubclassWndProc() { _wndProc = new WndProc(WndProc); ApiUser32.SetWindowLong( _handle, GWLIndex.GWLP_WNDPROC, Marshal.GetFunctionPointerForDelegate(_wndProc)); }
/// <summary> /// 取消窗口类的注册,删除内存 /// </summary> protected virtual void DestroyWindowClassCore() { if (_wndClassAtom != 0) { var moduleHandle = ApiKernel32.GetModuleHandle(null); ApiUser32.UnregisterClass(new IntPtr(_wndClassAtom), moduleHandle); _wndClassAtom = 0; } }
protected override void DisposeNativeResources() { if (BackgroundDC != IntPtr.Zero) { ApiGdi32.DeleteDC(BackgroundDC); } if (WindowDC != IntPtr.Zero) { ApiGdi32.DeleteDC(WindowDC); } if (ScreenDC != IntPtr.Zero) { ApiUser32.ReleaseDC(IntPtr.Zero, ScreenDC); } }
/// <summary> /// 销毁窗口,删除内存。 /// </summary> protected virtual void DestroyWindowCore() { if (_handle != IntPtr.Zero) { bool result = false; /* * if (Application.Current != null) * Application.Current.Dispatcher.Invoke( * new Action(() => { * result = ApiUser32.DestroyWindow(_handle); })); */ result = ApiUser32.DestroyWindow(_handle); _handle = IntPtr.Zero; } }
/// <summary> /// 注册窗口类。默认的。 /// </summary> /// <param name="className"></param> /// <returns></returns> /// <remarks> /// 抽象的记录提供的默认的窗口注册方法。在我们的项目中,我们需要注册的是窗口是分层窗口,用来实现边框的 /// </remarks> protected ushort RegisterClass(string className) { var wndClassEx = default(WNDCLASSEX); wndClassEx.cbSize = (uint)Marshal.SizeOf(typeof(WNDCLASSEX)); wndClassEx.style = (uint)WndClassStyle.CS_DEFAULT; // 原来是 0u wndClassEx.cbClsExtra = 0; // 默认0就行 wndClassEx.cbWndExtra = 0; // 同上 wndClassEx.hInstance = ApiKernel32.GetModuleHandle(null); // 程序的句柄 wndClassEx.hIcon = IntPtr.Zero; // 默认 0 就行 wndClassEx.hCursor = IntPtr.Zero; // 默认 0 就行 wndClassEx.hbrBackground = IntPtr.Zero; // 默认 0 就行 wndClassEx.lpfnWndProc = Marshal.GetFunctionPointerForDelegate(_wndProc = new WndProc(WndProc)); wndClassEx.lpszClassName = className; wndClassEx.lpszMenuName = null; return(ApiUser32.RegisterClassEx(ref wndClassEx)); }
/// <summary> /// 窗口过程。默认。 /// </summary> protected virtual IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam) => ApiUser32.DefWindowProc(hwnd, msg, wParam, lParam);