예제 #1
0
 private static extern bool ClientToScreen(IntPtr window, out Point2D coords);
예제 #2
0
        private static void AAEdgeCopy(byte* addr, int width, int stride, double x1, double x2, int y, byte* srcAddr, int srcWidth, int srcStride, Point2D offset, bool left, int clipMin = int.MinValue, int clipMax = int.MaxValue)
        {
            if(x1 > x2) Util.Swap(ref x1, ref x2);

            addr += (y * width * stride);
            srcAddr += ((y + offset.Y) * srcWidth * stride);
            double xmin;
            double xmax = x1;
            double ymin;
            double ymax = 1;
            double dydx = -1 / (x2 - x1);
            if(x2 == x1) dydx = 0;
            double alpha;
            do
            {
                xmin = xmax;
                xmax = Min((int)xmin + 1, x2);
                ymin = ymax;
                ymax = ymin + (xmax - xmin) * dydx;
                if(xmin < clipMin) continue;
                if(xmin > clipMax) break;
                alpha = (xmin - (int)xmin) * ymin;
                alpha += (ymax + ymin) * (xmax - xmin) / 2;
                ARGB color = *(ARGB*)(srcAddr + (((int)xmin + offset.X) * srcStride));
                *(ARGB*)(addr + ((int)xmin * stride)) &= new ARGB((byte)(color.A * (left ? (1 - alpha) : alpha)), color.RGB);
            }while(xmax != x2);
        }
예제 #3
0
        protected override void WndProc(ref Message m)
        {
            try
            {
                int code = m.Msg;
                DualParameter wParam = (DualParameter)m.WParam;
                DualParameter lParam = (DualParameter)m.LParam;
                switch (m.Msg)
                {
                    case WM_CLOSE:
                    {
                        if(OnClose != null) OnClose();
                        return;
                    }
                    case WM_SIZE:
                    {
                        Size = new Point2D(lParam.LowWord, lParam.HighWord);
                        if(OnResize != null) OnResize(Size);
                        break;
                    }
                    case WM_PAINT:
                    {
                        PaintData data;
                        IntPtr screenDC = BeginPaint(Handle, out data);
                        WinAPIUtils.Assert(screenDC != IntPtr.Zero);

                        //blit display buffer to screen
                        Image buffer = BufferStrategy.GetDisplayBuffer().Image;
                        bool success = BitBlt(screenDC, 0, 0, buffer.Width, buffer.Height, buffer.GetDeviceContext(), 0, 0, SRCCOPY);
                        WinAPIUtils.Assert(success);

                        EndPaint(Handle, ref data);
                        return;
                    }
                    case WM_SETFOCUS:
                    {
                        IsFocused = true;
                        break;
                    }
                    case WM_KILLFOCUS:
                    {
                        IsFocused = false;
                        break;
                    }
                    case WM_MOUSEMOVE:
                    {
                        //get move info
                        Point2D mouseCoords = (Point2D)lParam;
                        Point2D delta = mouseCoords - PrevMouseCoords;
                        //if mouse was previously outside window
                        if(!IsMouseInWindow)
                        {
                            IsMouseInWindow = true;
                            if(OnMouseEnter != null) OnMouseEnter();
                            //suppress inaccurate delta value
                            delta = new Point2D(0, 0);
                            //start tracking mouse so we recieve WM_MOUSELEAVE
                            TRACKMOUSEEVENT eventTrack = new TRACKMOUSEEVENT(Handle);
                            bool success = TrackMouseEvent(ref eventTrack);
                            WinAPIUtils.Assert(success);
                        }

                        //call event
                        if(OnMouseMove != null)
                        {
                            OnMouseMove(mouseCoords, delta);
                            PrevMouseCoords = mouseCoords;
                            //consume
                            return;
                        }else
                        {
                            PrevMouseCoords = mouseCoords;
                        }
                        break;
                    }
                    case WM_MOUSELEAVE:
                    {
                        IsMouseInWindow = false;
                        if(OnMouseExit != null) OnMouseExit();
                        break;
                    }
                    case WM_LBUTTONDOWN:
                    {
                        if(OnMousePress != null)
                        {
                            OnMousePress(MouseButton.LEFT);
                            //consume
                            return;
                        }
                        break;
                    }
                    case WM_LBUTTONUP:
                    {
                        if(OnMouseRelease != null)
                        {
                            OnMouseRelease(MouseButton.LEFT);
                            //consume
                            return;
                        }
                        break;
                    }
                    case WM_RBUTTONDOWN:
                    {
                        if(OnMousePress != null)
                        {
                            OnMousePress(MouseButton.RIGHT);
                            //consume
                            return;
                        }
                        break;
                    }
                    case WM_RBUTTONUP:
                    {
                        if(OnMouseRelease != null)
                        {
                            OnMouseRelease(MouseButton.RIGHT);
                            //consume
                            return;
                        }
                        break;
                    }
                    case WM_MBUTTONDOWN:
                    {
                        if(OnMousePress != null)
                        {
                            OnMousePress(MouseButton.MIDDLE);
                            //consume
                            return;
                        }
                        break;
                    }
                    case WM_MBUTTONUP:
                    {
                        if(OnMouseRelease != null)
                        {
                            OnMouseRelease(MouseButton.MIDDLE);
                            //consume
                            return;
                        }
                        break;
                    }
                    case WM_XBUTTONDOWN:
                    {
                        if(OnMousePress != null)
                        {
                            MouseButton button = (wParam.HighWord == 0x0001 ? MouseButton.EXTRA_1 : MouseButton.EXTRA_2);
                            OnMousePress(button);
                            //consume
                            return;
                        }
                        break;
                    }
                    case WM_XBUTTONUP:
                    {
                        if(OnMouseRelease != null)
                        {
                            MouseButton button = (wParam.HighWord == 0x0001 ? MouseButton.EXTRA_1 : MouseButton.EXTRA_2);
                            OnMouseRelease(button);
                            //consume
                            return;
                        }
                        break;
                    }
                    case WM_MOUSEWHEEL:
                    {
                        if(OnMouseWheel != null)
                        {
                            int delta = (wParam.HighWord / WHEEL_DELTA);
                            OnMouseWheel(delta);
                            //consume
                            return;
                        }
                        break;
                    }
                    case WM_KEYDOWN:
                    case WM_SYSKEYDOWN:
                    {
                        if(OnKeyPress != null)
                        {
                            //only post event if not a repeat
                            //aka previous state up
                            if((lParam.Number & 0x40000000) == 0)
                            {
                                KeyboardButton button = (KeyboardButton)wParam.Number;
                                OnKeyPress(button);
                                //consume
                                return;
                            }
                        }
                        break;
                    }
                    case WM_KEYUP:
                    case WM_SYSKEYUP:
                    {
                        if(OnKeyRelease != null)
                        {
                            //only post event if not a repeat
                            //aka previous state down
                            if((lParam.Number & 0x40000000) != 0)
                            {
                                KeyboardButton button = (KeyboardButton)wParam.Number;
                                OnKeyRelease(button);
                                //consume
                                return;
                            }
                        }
                        break;
                    }
                    case WM_CHAR:
                    {
                        if(OnCharTyped != null)
                        {
                            char c = (char)wParam.Number;
                            bool repeat = ((lParam.Number & 0x40000000) != 0);
                            //ok if char events are repeats
                            OnCharTyped(c, repeat);
                            //consume
                            return;
                        }
                        break;
                    }
                }
            }catch(System.Threading.ThreadAbortException)
            {
                //do nothing, simply means we called Stop on the message thread
            }catch(Exception ex)
            {
                Console.WriteLine(ex);
            }
            base.WndProc(ref m);
        }
예제 #4
0
        protected void Render(Image image, bool useMarker, int markerLoc = -1)
        {
            image.Fill(BackColor.Value);

            string text = Text.Value;
            if(text == null) text = "null";
            int length = text.Length;
            if(length == 0)
            {
                return;
            }
            if(!LockFont)
            {
                Point2D idealSize = new Point2D(image.Width / (Math.Max(length, lengthOverride) - Margin.Value.X * 2), image.Height - Margin.Value.Y * 2);
                if(CurrentFont == null || CurrentFont.Size != idealSize)
                {
                    CurrentFont = Font.GetFont(idealSize, Style);
                }
            }
            int x = 0;
            int y = 0;
            switch(HorizontalJustify)
            {
                case Justify.MIN: x = Margin.Value.X; break;
                case Justify.MIDDLE: x = (image.Width / 2) - (CurrentFont.Width * length / 2); break;
                case Justify.MAX: x = image.Width - (CurrentFont.Width * length) - Margin.Value.X; break;
            }
            switch(VerticalJustify)
            {
                case Justify.MIN: y = Margin.Value.Y; break;
                case Justify.MIDDLE: y = (image.Height / 2) - (CurrentFont.Height / 2); break;
                case Justify.MAX: y = image.Height - CurrentFont.Height - Margin.Value.Y; break;
            }
            CurrentFont.Draw(image, x, y, text, TextColor.Value);
            if(useMarker)
            {
                CurrentFont.Draw(image, x + (int)((markerLoc - .5) * CurrentFont.Width), y, '|', TextColor.Value);
            }
        }
예제 #5
0
        /// <summary>
        /// Basic implementation of a map src solid filling renderer.
        /// </summary>
        /// <param name="clip">The clipping rectangle.</param>
        /// <param name="scanner">The scans to render.</param>
        /// <param name="dest">The map to render to.</param>
        /// <param name="src">The source map.</param>
        /// <param name="offset">The offset of the source map.</param>
        /// <param name="mode">The color blending mode to use.</param>
        /// <param name="isAA">True if anti-aliasing is enabled.</param>
        public static void SolidCopyRender(Rectangle clip, Scanner scanner, DataMap<ARGB> dest, DataMap<ARGB> src, Point2D offset, ColorMode mode = ColorMode.NORMAL, bool isAA = true)
        {
            IUnsafeMap uDest = dest as IUnsafeMap;
            IUnsafeMap uSrc = src as IUnsafeMap;
            if(uDest == null)
            {
                throw new InvalidOperationException("Destination image does not support advanced color rendering!");
            }
            if(uSrc == null)
            {
                throw new InvalidOperationException("Source image does not support advanced color rendering!");
            }
            byte* addr = uDest.BeginUnsafeOperation();
            int width = dest.Width;
            int stride = uDest.GetStride();
            byte* srcAddr = uSrc.BeginUnsafeOperation();
            int srcWidth = src.Width;
            int srcStride = uSrc.GetStride();

            for(int y = scanner.yMin; y <= scanner.yMax; y++)
            {
                double x1 = Max(scanner[y].min, clip.Min.X);
                double x2 = Min(scanner[y].max, clip.Max.X);
                //Anti-Aliasing variables
                //x1 vars are x min side
                //x2 vars are x max side
                //xb vars are y min side
                //xa vars are y max side
                double x1b = 0, x1a = 0;
                double x2b = 0, x2a = 0;
                int left;
                int right;
                if(isAA)
                {
                    bool hasMin = false, hasMax = false;
                    //if not at ymin or ymin is a clipped min (aka we have another "ghost" scan)
                    if(y > scanner.yMin || scanner.isYMinClipped)
                    {
                        x1b = Max(scanner[y - 1].min, clip.Min.X);
                        x2b = Min(scanner[y - 1].max, clip.Max.X);
                        x1b = (x1b + x1) / 2;
                        x2b = (x2b + x2) / 2;
                        hasMin = true;
                    }
                    //if not at ymax or ymax is a clipped max (aka we have another "ghost" scan)
                    if(y < scanner.yMax || scanner.isYMaxClipped)
                    {
                        x1a = Max(scanner[y + 1].min, clip.Min.X);
                        x2a = Min(scanner[y + 1].max, clip.Max.X);
                        x1a = (x1a + x1) / 2;
                        x2a = (x2a + x2) / 2;
                        hasMax = true;
                    }

                    if(!hasMin)
                    {
                        //if single line shape, just make everything literal
                        if(!hasMax)
                        {
                            x1b = x1a = x1;
                            x2b = x2a = x2;
                        }else//if at ymin, extrapolate max->current into current->min
                        {
                            x1b = x1 - (x1a - x1);
                            x2b = x2 - (x2a - x2);
                        }
                    }else//if at ymax, extrapolate min->current into current->max
                    if(!hasMax)
                    {
                        x1a = x1 + (x1 - x1b);
                        x2a = x2 + (x2 - x2b);
                    }

                    //if aa, round toward center, otherwise round away to match default renderer
                    left = (int)Math.Ceiling(Max(x1b, x1a));
                    right = (int)Math.Floor(Min(x2b, x2a));
                }else
                {
                    //if not aa, round away to match default renderer
                    left = (int)Math.Floor(x1);
                    right = (int)Math.Ceiling(x2);
                }

                //if valid center
                if(left <= right)
                {
                    //solid fill with blend modes
                    byte* ptr = addr + (left + (y * width)) * stride;
                    byte* srcPtr = srcAddr + ((left + offset.X) + ((y + offset.Y) * srcWidth)) * srcStride;
                    byte* endPtr = ptr + (right - left + 1) * stride;
                    switch(mode)
                    {
                        case ColorMode.BLEND:
                        {
                            while(ptr != endPtr)
                            {
                                //*((ARGB*)ptr) &= *((ARGB*)srcPtr);
                                //manually inline blending
                                ARGB srcColor = *(ARGB*)srcPtr;
                                ARGB color = *(ARGB*)ptr;
                                int aComp = 255 - srcColor.A;
                                color = new ARGB{A = (byte)(srcColor.A + color.A),
                                                 R = (byte)(((srcColor.R * srcColor.A) + (color.R * aComp)) >> 8),
                                                 G = (byte)(((srcColor.G * srcColor.A) + (color.G * aComp)) >> 8),
                                                 B = (byte)(((srcColor.B * srcColor.A) + (color.B * aComp)) >> 8)};
                                *(ARGB*)ptr = color;
                                ptr += stride;
                                srcPtr += srcStride;
                            }
                            break;
                        }
                        case ColorMode.NORMAL:
                        {
                            while(ptr != endPtr)
                            {
                                *((ARGB*)ptr) = *((ARGB*)srcPtr);
                                ptr += stride;
                                srcPtr += srcStride;
                            }
                            break;
                        }
                        case ColorMode.MASK:
                        {
                            while(ptr != endPtr)
                            {
                                if((*((ARGB*)srcPtr)).A != 0)
                                    *((ARGB*)ptr) = *((ARGB*)srcPtr);
                                ptr += stride;
                                srcPtr += srcStride;
                            }
                            break;
                        }
                    }
                }
                //if aa, add smoothing to edges
                if(isAA)
                {
                    int center = (left + right) / 2;
                    if(Min(x1b, x1a) != left)
                        AAEdgeCopy(addr, width, stride, x1b, x1a, y, srcAddr, srcWidth, srcStride, offset, true, clipMax: Min(center, clip.Max.X));
                    if(Max(x2b, x2a) != right)
                        AAEdgeCopy(addr, width, stride, x2b + 1, x2a + 1, y, srcAddr, srcWidth, srcStride, offset, false, clipMin: Max(center + 1, clip.Min.X));
                }
            }

            uDest.EndUnsafeOperation();
            uSrc.EndUnsafeOperation();
        }
예제 #6
0
 public MouseWheelEventArgs(MouseWheelEventArgs args)
     : base(args)
 {
     Coords = args.Coords;
     Delta = args.Delta;
 }
예제 #7
0
 private void OnMove(Point2D coords, Point2D delta)
 {
     mouseCoords.Value = coords;
 }
예제 #8
0
 public MouseMoveEventArgs(Point2D coords, Point2D delta)
 {
     Coords = coords;
     Delta = delta;
 }
예제 #9
0
 public MouseWheelEventArgs(Point2D coords, int delta)
 {
     Coords = coords;
     Delta = delta;
 }
예제 #10
0
 public MouseButtonEventArgs(MouseButtonEventArgs args)
     : base(args)
 {
     Coords = args.Coords;
     Button = args.Button;
     Pressed = args.Pressed;
 }
예제 #11
0
 public MouseButtonEventArgs(Point2D coords, MouseButton button, bool pressed)
 {
     Coords = coords;
     Button = button;
     Pressed = pressed;
 }
예제 #12
0
파일: Root.cs 프로젝트: jonhartnett/IROM-UI
 /// <summary>
 /// Resizes this <see cref="Root"/> to ensure it always matches its <see cref="Window"/>
 /// </summary>
 /// <param name="size">The new size.</param>
 private void OnResize(Point2D size)
 {
     Size.Value = size;
 }
예제 #13
0
파일: Root.cs 프로젝트: jonhartnett/IROM-UI
 /// <summary>
 /// Finds every visible, non-hidden component in the given location in decreasing z order.
 /// </summary>
 /// <param name="location">The location.</param>
 /// <param name="findInvisible">If true, the search will include invisible and hidden components.</param>
 /// <param name="inputMode">If true, uses input visible and hidden.</param>
 /// <returns>The components in z order.</returns>
 public Component[] FindAll(Point2D location, bool findInvisible = false, bool inputMode = false)
 {
     return FindAll(new Rectangle{Min = location, Max = location}, findInvisible, inputMode);
 }
예제 #14
0
        internal void MouseMoveEvent(Point2D mouseCoords, Point2D delta)
        {
            if(Parent != null)
            {
                Point2D oldCoords = mouseCoords - delta;

                //store all components that are guaranteed a call
                ActiveComponents.Clear();
                foreach(MouseButton button in Enum.GetValues(typeof(MouseButton)))
                {
                    ActiveComponents.UnionWith(MouseActiveComponents.GetValues(button));
                }

                //add all entered components to exited
                //if they don't get removed, then we schedule an exit
                ExitedComponents.Clear();
                ExitedComponents.UnionWith(EnteredComponents);

                CheckZone();

                //prepare event list
                Component[] eventList = Parent.FindAll(new Rectangle{Min = VectorUtil.Min(mouseCoords, oldCoords), Max = VectorUtil.Max(mouseCoords, oldCoords)}, false, true);

                //true if the cursor was set to a special value
                bool cursorSet = false;
                //true if the drop zone was updated
                bool zoneSet = false;

                //perform normal event passing
                foreach(Component comp in eventList)
                {
                    //if not set yet and special cursor
                    if(!cursorSet &&
                       comp.HoverCursor.Value != Cursor.UNSPECIFIED)
                    {
                        cursorSet = true;
                        if(previousCursor == Cursor.UNSPECIFIED) previousCursor = Parent.WindowObj.CurrentCursor;
                        Parent.WindowObj.CurrentCursor = comp.HoverCursor.Value;
                    }
                    //if haven't entered yet
                    if(!EnteredComponents.Contains(comp))
                    {
                        //call enter
                        comp.InvokeMouseEnter();
                        EnteredComponents.Add(comp);
                    }else //else prevent automatic exit
                    {
                        ExitedComponents.Remove(comp);
                    }
                    if(grabbedComponent != null && !zoneSet && comp is IDropZone && comp.Bounds.Contains(mouseCoords) && CurrentZone != comp)
                    {
                        IDropZone zone = (IDropZone)comp;
                        if(zone.Handles(grabbedComponent))
                        {
                            CurrentZone = zone;
                            zoneSet = true;
                        }
                    }
                    //call event with local mouse coords
                    comp.InvokeMouseMove(mouseCoords - (Point2D)comp.Position.Value, delta);
                    //remove from active components (we don't care if it doesn't contain the element, it'll just do nothing)
                    ActiveComponents.Remove(comp);
                    //consume if opaque
                    if(comp.InputOpaque.Value)
                    {
                        break;
                    }
                }

                //if cursor was not
                if(!cursorSet && previousCursor != Cursor.UNSPECIFIED)
                {
                    Parent.WindowObj.CurrentCursor = previousCursor;
                }

                //satisfy all waiting components
                foreach(Component comp in ActiveComponents)
                {
                    //call event with local mouse coords
                    comp.InvokeMouseMove(mouseCoords - (Point2D)comp.Position.Value, delta);
                }

                //remove all exited from entered
                EnteredComponents.ExceptWith(ExitedComponents);
                //exit all exited
                foreach(Component comp in ExitedComponents)
                {
                    //call exit
                    comp.InvokeMouseExit();
                }
            }
        }