public PenHandle(HPEN handle, bool ownsHandle = true) { Debug.Assert(handle.IsInvalid || Imports.GetObjectType(handle) == ObjectType.Pen || Imports.GetObjectType(handle) == ObjectType.ExtendedPen); Handle = handle; _ownsHandle = ownsHandle; }
/// <summary> /// Creates a solid pen based on the <paramref name="color"/> and <paramref name="width"/>. /// </summary> public CreatePenScope(Color color, int width = 1) { // From MSDN: if width > 1, the style must be PS_NULL, PS_SOLID, or PS_INSIDEFRAME. HPen = CreatePen( width > 1 ? PS.GEOMETRIC | PS.SOLID : default,
internal bool MessageHandler(int nMsg, IntPtr wParam, IntPtr lParam, ref int nRes) { if (m_hWndPaint == IntPtr.Zero) { return(false); } //TODO::消息队列处理 #region 处理监听 for (int i = 0; i < m_aMessageFilters.Count; i++) { bool bHandled = false; var nResult = m_aMessageFilters[i].MessageHandler(nMsg, wParam, lParam, ref bHandled); if (bHandled) { nRes = nResult; return(true); } } #endregion switch (nMsg) { case WindowMessages.WM_APP: break; case WindowMessages.WM_CLOSE: break; case WindowMessages.WM_ERASEBKGND: { nRes = 1; return(true); } case WindowMessages.WM_PAINT: #region 处理WM_PAINT RECT rcPaint = new RECT(); if (!NativeMethods.GetUpdateRect(m_hWndPaint, ref rcPaint, false)) { return(true); } if (m_RootControl == null) { PAINTSTRUCT ps = new PAINTSTRUCT(); NativeMethods.BeginPaint(m_hWndPaint, ref ps); NativeMethods.EndPaint(m_hWndPaint, ref ps); return(true); } if (m_bAlphaBackground) { var dwExStyle = NativeMethods.GetWindowLong(m_hWndPaint, SetWindowLongOffsets.GWL_EXSTYLE); if ((dwExStyle.ToInt32() & WindowStyles.WS_EX_LAYERED) != 0x80000) { NativeMethods.SetWindowLong(m_hWndPaint, (int)SetWindowLongOffsets.GWL_EXSTYLE, dwExStyle.ToInt32() ^ WindowStyles.WS_EX_LAYERED); } RECT rcClient = new RECT(); NativeMethods.GetClientRect(m_hWndPaint, ref rcClient); PAINTSTRUCT ps = new PAINTSTRUCT(); NativeMethods.BeginPaint(m_hWndPaint, ref ps); if (m_bUpdateNeeded) { m_bUpdateNeeded = false; if (NativeMethods.IsRectEmpty(ref rcClient) == 0) { } } } if (m_bUpdateNeeded) { m_bUpdateNeeded = false; RECT rcClient = new RECT(); NativeMethods.GetClientRect(m_hWndPaint, ref rcClient); if (NativeMethods.IsRectEmpty(ref rcClient) == 0) { } } if (m_bFocusNeeded) { } //TODO::Animating #region Render screen if (m_bOffscreenPaint && m_hbmpOffscreen == IntPtr.Zero) { RECT rcClient = new RECT(); NativeMethods.GetClientRect(m_hWndPaint, ref rcClient); m_hDcOffscreen = NativeMethods.CreateCompatibleDC(m_hDcPaint); m_hbmpOffscreen = NativeMethods.CreateCompatibleBitmap(m_hDcPaint, rcClient.right - rcClient.left, rcClient.bottom - rcClient.top); Debug.Assert(m_hDcOffscreen != IntPtr.Zero); Debug.Assert(m_hbmpOffscreen != IntPtr.Zero); } { PAINTSTRUCT ps = new PAINTSTRUCT(); NativeMethods.BeginPaint(m_hWndPaint, ref ps); if (m_bOffscreenPaint) { HBITMAP hOldBitmap = NativeMethods.SelectObject(m_hDcOffscreen, m_hbmpOffscreen); int nSaveDC = NativeMethods.SaveDC(hOldBitmap); //TODO::Paint NativeMethods.RestoreDC(m_hDcOffscreen, nSaveDC); NativeMethods.BitBlt(ps.hdc, ps.rcPaint.Left, ps.rcPaint.Top, ps.rcPaint.Width, ps.rcPaint.Height, m_hDcOffscreen, ps.rcPaint.Left, ps.rcPaint.Top, TernaryRasterOperations.SRCCOPY); NativeMethods.SelectObject(m_hDcOffscreen, hOldBitmap); if (m_bShowUpdateRect) { HPEN hOldPen = NativeMethods.SelectObject(ps.hdc, m_hUpdateRectPen); NativeMethods.SelectObject(ps.hdc, NativeMethods.GetStockObject(HOLLOW_BRUSH)); NativeMethods.Rectangle(ps.hdc, rcPaint.left, rcPaint.top, rcPaint.right, rcPaint.bottom); NativeMethods.SelectObject(ps.hdc, hOldPen); } } else { int nSaveDC = NativeMethods.SaveDC(ps.hdc); //TODO::Paint NativeMethods.RestoreDC(ps.hdc, nSaveDC); } NativeMethods.EndPaint(m_hWndPaint, ref ps); } #endregion // If any of the painting requested a resize again, we'll need // to invalidate the entire window once more. if (m_bUpdateNeeded) { NativeMethods.InvalidateRect(m_hWndPaint, IntPtr.Zero, 0); } #endregion return(true); case WindowMessages.WM_PRINTCLIENT: { #region 处理WM_PRINTCLIENT RECT rcClient = new RECT(); NativeMethods.GetClientRect(m_hWndPaint, ref rcClient); HDC hDC = (HDC)wParam; int save = NativeMethods.SaveDC(hDC); //TODO::Paint // Check for traversing children. The crux is that WM_PRINT will assume // that the DC is positioned at frame coordinates and will paint the child // control at the wrong position. We'll simulate the entire thing instead. if ((lParam.ToInt64() & WM_PRINT_Flags.PRF_NONCLIENT) != 0) { HWND hWndChild = NativeMethods.GetWindow(m_hWndPaint, GetWindowFlags.GW_CHILD); while (hWndChild != NativeMethods.NULL) { RECT rcPos = new RECT(); NativeMethods.GetWindowRect(hWndChild, ref rcPos); POINT pt = new POINT() { x = rcPos.left, y = rcPos.top }; NativeMethods.MapWindowPoints(NativeMethods.HWND_DESKTOP, m_hWndPaint, pt, 2); POINT tmpPt = new POINT(); NativeMethods.SetWindowOrgEx(hDC, -rcPos.left, -rcPos.top, out tmpPt); // NOTE: We use WM_PRINT here rather than the expected WM_PRINTCLIENT // since the latter will not print the nonclient correctly for // EDIT controls. var newlParam = new IntPtr(lParam.ToInt64() | WM_PRINT_Flags.PRF_NONCLIENT); NativeMethods.SendMessage(hWndChild, WindowMessages.WM_PRINT, wParam, newlParam); hWndChild = NativeMethods.GetWindow(hWndChild, GetWindowFlags.GW_HWNDNEXT); } } NativeMethods.RestoreDC(hDC, save); #endregion } break; case WindowMessages.WM_GETMINMAXINFO: break; case WindowMessages.WM_SIZE: break; case WindowMessages.WM_TIMER: break; case WindowMessages.WM_MOUSEHOVER: break; case WindowMessages.WM_MOUSELEAVE: break; case WindowMessages.WM_MOUSEMOVE: break; case WindowMessages.WM_LBUTTONDOWN: break; case WindowMessages.WM_LBUTTONDBLCLK: break; case WindowMessages.WM_LBUTTONUP: break; case WindowMessages.WM_RBUTTONDOWN: break; case WindowMessages.WM_CONTEXTMENU: break; case WindowMessages.WM_MOUSEWHEEL: break; case WindowMessages.WM_CHAR: break; case WindowMessages.WM_KEYDOWN: break; case WindowMessages.WM_KEYUP: break; case WindowMessages.WM_SETCURSOR: break; case WindowMessages.WM_NOTIFY: break; case WindowMessages.WM_COMMAND: break; case WindowMessages.WM_CTLCOLOREDIT: case WindowMessages.WM_CTLCOLORSTATIC: break; case WM_EFFECTS: break; case WM_RELOADSTYLE: break; default: break; } //TODO::处理消息队列 return(false); }