private void CalibrationAdjusterManualForm_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e) { int s = ScreenPixelHelper.ConvertMmToPixels(1); //step size of keyboard arrow input to control the gaze point adjustment offset switch (e.KeyCode) { case Keys.Enter: currentCircle++; this.Invalidate(); // This forces the form to repaint break; case Keys.Up: ca.adjGridOffset[currentCircle].Offset(0, -1 * s); break; case Keys.Down: ca.adjGridOffset[currentCircle].Offset(0, s); break; case Keys.Left: ca.adjGridOffset[currentCircle].Offset(-1 * s, 0); break; case Keys.Right: ca.adjGridOffset[currentCircle].Offset(s, 0); break; case Keys.Alt: //no break stmt case Keys.Escape: ca.writeCalibrationAdjustmentCsv(); this.Close(); //prevent altf4 crash break; case Keys.Space: //record adjustment Point wp = controller.WarpPointer.GetWarpPoint(); Point calpoint = ca.adjGrid[currentCircle]; ca.adjGridOffset[currentCircle] = new Point((calpoint.X - wp.X), (calpoint.Y - wp.Y)); this.Invalidate(); // This forces the form to repaint break; default: break; } //see if done all adjustment points if (currentCircle == 9) { ca.writeCalibrationAdjustmentCsv(); currentCircle = 0; this.Close(); } }
public bool BoxLargeEnough(Box b) { if (b == null) { return(false); } int threshold = ScreenPixelHelper.ConvertMmToPixels(ConfigManager.cursorMagnetClippingMinBoxWidthMm); return(b.width() >= threshold && b.height() >= threshold); }
//Calculates target circle radius based on number of iterations completed, max number of iterations, min and max circle radiuses private int GetTargetCircleRadius(int iter) { int maxIterations = ConfigManager.calibrationIterationCountMax; int minRadius = ScreenPixelHelper.ConvertMmToPixels(1); int maxRadius = ScreenPixelHelper.ConvertMmToPixels(ConfigManager.calibrationCircleSizeMm); int rDiff = maxRadius - minRadius; double rStep = (double)rDiff / (double)(maxIterations - 1); int iterBounded = Math.Min(iter, maxIterations - 1); //note: deliberately capping at maxIterations -1 and therefore never reaches 0.2% screen return((int)(maxRadius - iterBounded * rStep)); }
public bool NearLastIbeamPoint(Point p) { if (lastIbeamPoint == null) { return(false); } int nearbyMm = 7; //mm int nearbyPixels = ScreenPixelHelper.ConvertMmToPixels(nearbyMm); return(PointHelper.GetPointDistance(p, lastIbeamPoint) <= nearbyPixels); }
//whenever this method is called, it paints from scratch and does not append to what's already on the screen //this method is typically called whenever RefreshScreen is called (60 fps) protected override void OnPaint(PaintEventArgs e) { int radius = ScreenPixelHelper.ConvertMmToPixels(1.25); //radius Point p = ca.adjGrid[currentCircle]; Rectangle rec = new Rectangle(p.X - radius, p.Y - radius, radius * 2, radius * 2); e.Graphics.DrawEllipse(Pens.White, rec); //draw gray gaze point p = controller.WarpPointer.GetNextPoint(controller.WarpPointer.GetGazePoint()); p.Offset(ca.adjGridOffset[currentCircle]); rec = new Rectangle(p.X - radius, p.Y - radius, radius * 2, radius * 2); e.Graphics.FillEllipse(Brushes.Gray, rec); }
//TODO: refactor these methods to same one and use enums /* * Returns true if: * All gazepoints for the past minMs duration are within radiusMm of the first gaze point in the observed set. * * This function should be called when you want to limit the fixation region to a certain millimeters within the * gazepoint at minMs milliseconds ago. */ public static bool IsStationaryFixation(int minMs, int radiusMm) { if (warpPointer == null) { return(false); } List <Point> rawGazePoints = warpPointer.GetGazeHistory(); if (rawGazePoints == null || rawGazePoints.Count == 0) { return(false); } int sampleRate = warpPointer.GetSampleRate(); //total number of samples that should be meet the fixation width criteria int lookbackSampleCount = (int)Math.Max(1, sampleRate * minMs / 1000); if (lookbackSampleCount > rawGazePoints.Count) { return(false); } //Find the average of all the lookbackSamples ... int startIndex = Math.Max(0, rawGazePoints.Count - lookbackSampleCount); Point runningSum = new Point(0, 0); Point runningAvg = new Point(0, 0); for (int i = startIndex; i < rawGazePoints.Count; i++) { runningSum.X += rawGazePoints[i].X; runningSum.Y += rawGazePoints[i].Y; } runningAvg.X = runningSum.X / lookbackSampleCount; runningAvg.Y = runningSum.Y / lookbackSampleCount; //Check if distances between all points are within radius for (int i = startIndex + 1; i < rawGazePoints.Count; i++) { if (PointHelper.GetPointDistance(runningAvg, rawGazePoints[i]) > ScreenPixelHelper.ConvertMmToPixels(radiusMm)) { return(false); //this point is too far from the first point } } return(true); }
public List <Box> getNearBoxes(Point gp) { List <Box> nearby = new List <Box>(); int nearThreshold = ScreenPixelHelper.ConvertMmToPixels(ConfigManager.cursorMagnetClippingThresholdMm); foreach (Box b in boxes) { //should only work if the box have height and width //if box is valid and the point is near a box defined by threshold, then we add it to the working set if ((isNearBox(gp, b, nearThreshold)) && (b.top != b.bottom && b.left != b.right)) { nearby.Add(b); // Debug.WriteLine("Found Box nearby" + currentBox[0] + "," + currentBox[1] + " " + Cursor.Position); } } return(nearby); }
private void AddGazeButtons() { //int buttonHeight = ScreenPixelHelper.ConvertMmToPixels(ConfigManager.dockButtonHeightMm); int buttonHeightOffsetPx = ScreenPixelHelper.ConvertMmToPixels(5); int buttonHeight = (this.Height / gazeButtonTextStrings.Length) - buttonHeightOffsetPx; //Calculate vertical spacing between each of the buttons int heightStep = (this.Height - buttonHeight) / (gazeButtonTextStrings.Length - 1); for (int i = 0; i < gazeButtonTextStrings.Length; i++) { //create a new button Button b = new Button(); b.AutoSize = false; b.Width = this.Width; //TODO: replace with just height b.Height = buttonHeight; //Location of the button is relative to the form b.Location = new Point(this.Width - b.Width, i * heightStep); b.Text = gazeButtonTextStrings[i]; b.Font = new Font(FontFamily.GenericSansSerif, 14); b.TextAlign = ContentAlignment.MiddleRight; b.ForeColor = Color.White; b.BackColor = Color.Black; //remove border b.TabStop = false; b.FlatStyle = FlatStyle.Flat; b.FlatAppearance.BorderSize = 0; //Apply padding to enlarge the "gazeable/clickable" area of the button //b.Padding = new Padding(buttonLeftPadding, buttonVerticalPadding, 0, buttonVerticalPadding); //b.Margin = new Padding(buttonLeftPadding, buttonVerticalPadding, 0, buttonVerticalPadding); b.Click += gazeButton_Click; //b.Paint += new System.Windows.Forms.PaintEventHandler(this.gazeButton_Paint); b.MouseEnter += gazeButton_MouseEnter; b.MouseLeave += gazeButton_MouseLeave; //TODO: ButtonBorderStyle.None gazeButtonsList.Add(b); this.Controls.Add(b); } }
public void setMode(Mode mode) { if (warp != null) { warp.Dispose(); } if (prec != null) { prec.Dispose(); } this.mode = mode; switch (mode) { case Mode.EYEX_AND_TRACKIR: warp = new EyeXWarpPointer(ScreenPixelHelper.ConvertMmToPixels(25)); prec = new TrackIRPrecisionPointer(ScreenPixelHelper.ConvertMmToPixels(25), 0.3); break; case Mode.EYEX_AND_SMARTNAV: warp = new EyeXWarpPointer(ScreenPixelHelper.ConvertMmToPixels(1)); prec = new NoPrecisionPointer(); state = TrackingState.RUNNING; break; case Mode.EYEX_ONLY: warp = new EyeXWarpPointer(ScreenPixelHelper.ConvertMmToPixels(5)); prec = new NoPrecisionPointer(); break; } Logger.WriteVar(nameof(mode), mode); if (!warp.IsStarted()) { state = TrackingState.ERROR; } if (!prec.IsStarted()) { state = TrackingState.ERROR; } }
public Point StayOrExitBox(Point gp) { //iterate through all the most recent raw gaze points and check that they all are at least thresholdPixels away int threshold = ScreenPixelHelper.ConvertMmToPixels(ConfigManager.cursorMagnetClippingExitThresholdMm); List <Point> rawGazePoints = mc.WarpPointer.GetGazeHistory(); if (rawGazePoints == null || rawGazePoints.Count == 0 || ClippedBox == null) { winzoomAvailable = true; return(gp); //todo: out of bound? } int sampleRate = mc.WarpPointer.GetSampleRate(); int recentDurationMs = ConfigManager.cursorMagnetClippingExitDurationMs; //todo: config int lookbackSampleCount = sampleRate * recentDurationMs / 1000; int startIndex = Math.Max(0, rawGazePoints.Count - lookbackSampleCount); //all points have to leave the box by at least exitThreshold amount in order to consider exit //equivalent to having 1 point not leave the box by exitThreshold to continue staying for (int i = startIndex; i < rawGazePoints.Count; i++) { //use the calibration adjusted value for the raw data Point adjustedGp = new Point(rawGazePoints[i].X, rawGazePoints[i].Y); adjustedGp.Offset(calibrationAdjuster.GetCalibrationAdjustment(adjustedGp)); if (isNearBox(adjustedGp, ClippedBox, ScreenPixelHelper.ConvertMmToPixels(ConfigManager.cursorMagnetClippingExitThresholdMm))) { //stay in box, since 1 point is still threshold/2 near the perimeter of the currently clipped box return(ClippedBox.center()); } } //We went through the most recent gaze points and all of them are more than threshold away //Exit this box ClippedBox = null; winzoomAvailable = true; return(gp); //todo: out of bound }
private void DockForm_Load(object sender, EventArgs e) { //1. Setup dock so that form window takes calculated user-amount of space on right side int dockWidth = ScreenPixelHelper.ConvertMmToPixels(ConfigManager.dockFormMaxWidthMm); //Calculate dock height Rectangle wa = ScreenPixelHelper.GetScreenWorkingArea(); int dockHeight = wa.Height; //calculate dock location Point dockLocation = new Point(wa.Right - dockWidth, wa.Top); this.Location = dockLocation; this.Size = new Size(dockWidth, dockHeight); this.BackColor = Color.Black; //Add all the buttons for the dock AddGazeButtons(); SetActiveGazeButton(GAZE_BUTTON_TYPE.NONE); Logger.WriteMsg("About to register dockbar."); //Now let's dock the window RegisterDockbar(); }
/* * Returns true if: * The speed of eye movement does not exceed (radiusMM / ConfigManager.fixationMinDurationMs) millimeters/seconds * measured over a total duration of minMs. * * This function should be called when it's acceptable for the eyes to continue moving slowly and still count it as fixation. */ public static bool IsMovingFixation(int minMs, int radiusMm) { if (warpPointer == null) { return(false); } List <Point> rawGazePoints = warpPointer.GetGazeHistory(); if (rawGazePoints == null || rawGazePoints.Count == 0) { return(false); } int sampleRate = warpPointer.GetSampleRate(); //total number of samples that should be meet the fixation width criteria int lookbackSampleCount = (int)Math.Max(1, sampleRate * minMs / 1000); if (lookbackSampleCount > rawGazePoints.Count) { return(false); } //moving window samples amount int windowSampleCount = Math.Max(sampleRate * ConfigManager.fixationMinDurationMs / 1000, 1); int stopIndex = Math.Max(0, rawGazePoints.Count - windowSampleCount); //Get average of the first window //We start at the most recent point in history Point runningSum = new Point(0, 0); Point runningAvg = new Point(0, 0); for (int i = rawGazePoints.Count - 1; i >= stopIndex; i--) { runningSum.X += rawGazePoints[i].X; runningSum.Y += rawGazePoints[i].Y; } runningAvg.X = runningSum.X / windowSampleCount; runningAvg.Y = runningSum.Y / windowSampleCount; //Check that each point in the current window meets the fixation width criteria for (int i = rawGazePoints.Count - 1; i >= stopIndex; i--) { if (PointHelper.GetPointDistance(runningAvg, rawGazePoints[i]) > ScreenPixelHelper.ConvertMmToPixels(radiusMm)) { return(false); //this point is too far from the avg } } //slide window until we complete lookbackSampleCount many stopIndex = Math.Max(0, rawGazePoints.Count - lookbackSampleCount); int lowerIndex = rawGazePoints.Count - 1 - windowSampleCount; while (lowerIndex >= stopIndex) { int upperIndex = lowerIndex + windowSampleCount; //Remove one point from window runningSum.X -= rawGazePoints[upperIndex].X; runningSum.Y -= rawGazePoints[upperIndex].Y; //Add another point to the window runningSum.X += rawGazePoints[lowerIndex].X; runningSum.Y += rawGazePoints[lowerIndex].Y; //Recalculate avg runningAvg.X = runningSum.X / windowSampleCount; runningAvg.Y = runningSum.Y / windowSampleCount; //See if newest point is within the average if (PointHelper.GetPointDistance(runningAvg, rawGazePoints[lowerIndex]) > ScreenPixelHelper.ConvertMmToPixels(radiusMm)) { return(false); //this point is too far from the avg } lowerIndex--; } //Been through lookbackSampleCount and all of them according to the moving window are within fixation width requirement return(true); }
//NOTE: it doesn't really matter if user's taskbar is arranged elsewhere since we are using this hider form public static Point GetStartMenuLocation() { return(new Point(ScreenPixelHelper.ConvertMmToPixels(3), ScreenPixelHelper.GetScreenSize().Height - ScreenPixelHelper.ConvertMmToPixels(4))); }
public Point ConvertToScreenPoint(Point p) { Rectangle screenSize = ScreenPixelHelper.GetScreenSize(); p = BoundPointToRect(p, screenSize, 5); int delta = ScreenPixelHelper.ConvertMmToPixels(1); //We want to find the "center" which is the focal point of where magnified and system cursor intersect //on the winzoom box. It is different whether edge or corner, or if winzoom box is in middle of screen int x = 0; if (Math.Abs(activeRect.Left - activeRectSrc.Left) < delta) { x = 0; } else if (Math.Abs(activeRect.Right - activeRectSrc.Right) < delta) { x = screenSize.Width; } else if (activeRect.Left < delta) //only activeRect is left aligned { //Experimentally and analytically determined this formula x = Convert.ToInt32((Convert.ToDouble(activeRectSrc.Left) * zoomPct / (zoomPct - 100))); } else if (Math.Abs(activeRect.Right - screenSize.Width) < delta) //only activeRect is right aligned { int xdiff = (activeRect.Right - activeRectSrc.Right); //this will be a positive number int xDiffScaled = Convert.ToInt32((Convert.ToDouble(xdiff) * zoomPct / (zoomPct - 100))); x = activeRect.Right - xDiffScaled; } else { x = activeRectSrcCenter.X; } int y = 0; if (Math.Abs(activeRect.Top - activeRectSrc.Top) < delta) { y = 0; } else if (Math.Abs(activeRect.Bottom - activeRectSrc.Bottom) < delta) { y = screenSize.Height; } else if (activeRect.Top < delta) //only activeRect is left aligned { y = Convert.ToInt32((activeRectSrc.Top * zoomPct / (zoomPct - 100))); } else if (Math.Abs(activeRect.Bottom - screenSize.Width) < delta) //only activeRect is right aligned { int ydiff = (activeRect.Bottom - activeRectSrc.Bottom); //this will be a positive number int yDiffScaled = Convert.ToInt32((ydiff * zoomPct / (zoomPct - 100))); y = activeRect.Bottom - yDiffScaled; } else { y = activeRectSrcCenter.Y; } //This center is essentially the focal point of the magnified cursor and system cursor Point center = new Point(x, y); Point diff = new Point(p.X - center.X, p.Y - center.Y); //The magnified cursor and the actively controlled cursor are the same point in top left corner of activeRectSrc //As main cursor moves, magnified cursor moves away twice as fast if we return p and do no adjustments //Therefore we need to divide the distance of gaze point from top left corner by zoomFactor to get magnified and gaze point to be same return(new Point(center.X + Convert.ToInt32((float)diff.X / ((float)zoomPct / (float)100)), center.Y + Convert.ToInt32((float)diff.Y / ((float)zoomPct / (float)100))));; }
public Point ClipToBox(Point gp) { //Check if LinkDict is not populated if (ClippedBox == null) { if (!boxesInitComplete || boxes.Count < 1) { return(gp); } //We also want to make sure that the gp is not near the Windows Taskbar, otherwise have difficulty using start menu or switching applications Rectangle workingArea = ScreenPixelHelper.GetScreenWorkingArea(); //We also want to make sure browser navigation buttons can be clicked comfortably int topBar = 105; if (gp.X < workingArea.Left || gp.X > workingArea.Right || gp.X < (workingArea.Top + topBar - 15) || gp.Y > workingArea.Bottom) { winzoomAvailable = true; return(gp); } List <Box> nearby = new List <Box>(); nearby.AddRange(getNearBoxes(gp)); if (nearby.Count == 0) { winzoomAvailable = true; return(gp); } if (nearby.Count == 1)//if no box around, we keep the cursor where it is { //We clip to the center of the clickable element winzoomAvailable = false; ClippedBox = nearby[0]; return(ClippedBox.center()); } else { if (!CheckAllBoxesLargeEnough(nearby)) { winzoomAvailable = true; ClippedBox = null; return(gp); } ClippedBox = findClosestBox(gp, nearby);//closest Box winzoomAvailable = false; return(ClippedBox.center()); } } else //box was previously clipped { /* * if(no box around) * ruturn ClippedBox.center or (-100,-100)either exit or stay * else * if GP is in direction of anotherBox * return changeBox() * else * either exit or stay */ //no other box around, //exit List <Box> otherNearby = getNearBoxes(gp); if (otherNearby.Contains(ClippedBox)) { otherNearby.Remove(ClippedBox); } //remove the clipped box as it is itself if (otherNearby.Count == 0) { return(StayOrExitBox(gp)); } else { if (!CheckAllBoxesLargeEnough(otherNearby)) { //must use winzoom and exit since we've approached a really small box, force exit from box winzoomAvailable = true; ClippedBox = null; return(gp); } if (ClippedBox.ContainsPoint(gp)) { return(ClippedBox.center()); } //Check if gp is contained by any of the otherNearby boxes, and if so is it at least changeBoxPercThresh into it foreach (Box b in otherNearby) { //If it's a large box then a few pixels should be enough to enter it... and for a small box use a small percentage of it if (b.ContainsPointPercentageWithin(ClippedBox, gp, ConfigManager.cursorMagnetClippingChangeBoxIntoPerc) || b.ContainsPointPixelsWithin(ClippedBox, gp, ScreenPixelHelper.ConvertMmToPixels(ConfigManager.cursorMagnetClippingExitThresholdMm)) ) { winzoomAvailable = false; ClippedBox = b; return(b.center()); } } //the gazepoint has not met the criteria for changing to a different box, see if it should stay or exit return(StayOrExitBox(gp)); } } }
//whenever this method is called, it paints from scratch and does not append to what's already on the screen //this method is typically called whenever RefreshScreen is called (60 fps) protected override void OnPaint(PaintEventArgs e) { //Draw overall target circle (which shrinks with duration) int radius = GetTargetCircleRadius(iteration); Point calpoint = ca.adjGrid[currentCircle]; Rectangle rec = new Rectangle(calpoint.X - radius, calpoint.Y - radius, radius * 2, radius * 2); if (iteration == 0) { e.Graphics.DrawEllipse(Pens.White, rec); } else if (iteration < ConfigManager.calibrationIterationCountMax - 1) { e.Graphics.DrawEllipse(Pens.DarkCyan, rec); //also draw inner circles to guide radius = GetTargetCircleRadius(iteration + 1); rec = new Rectangle(calpoint.X - radius, calpoint.Y - radius, radius * 2, radius * 2); e.Graphics.DrawEllipse(Pens.DarkMagenta, rec); } else { e.Graphics.FillEllipse(Brushes.DarkMagenta, rec); e.Graphics.DrawEllipse(Pens.DarkCyan, rec); } //Reset the iterations and calibrating this point if user has already been trying longer than expected if (iteration > ConfigManager.calibrationIterationCountMax + 1) { calstate = CalState.WAITING_FOCUS; iteration = 0; } Point gp = controller.WarpPointer.GetNextPoint(controller.WarpPointer.GetGazePoint()); //detect whether gaze point is close to the calibration circle (at most 7cm of screen away) if (PointHelper.GetPointDistance(gp, calpoint) < ScreenPixelHelper.ConvertMmToPixels(70)) { //draw gray gaze point as long as it's not the final iteration(s) int gazeRadius = ScreenPixelHelper.ConvertMmToPixels(1) / 2; Point p = controller.WarpPointer.GetNextPoint(controller.WarpPointer.GetGazePoint()); p.Offset(ca.adjGridOffset[currentCircle]); rec = new Rectangle(p.X - gazeRadius, p.Y - gazeRadius, gazeRadius * 2, gazeRadius * 2); if (iteration < ConfigManager.calibrationIterationCountMax) { e.Graphics.FillEllipse(Brushes.Gray, rec); if (iteration > 0) { //Get antipoint, which is basically located on other cide of currentCircle int xDiff = p.X - ca.adjGrid[currentCircle].X; int yDiff = p.Y - ca.adjGrid[currentCircle].Y; Point ap = new Point(p.X - xDiff * 2, p.Y - yDiff * 2); rec = new Rectangle(ap.X - gazeRadius, ap.Y - gazeRadius, gazeRadius * 2, gazeRadius * 2); e.Graphics.FillEllipse(Brushes.Gray, rec); } } if (calstate == CalState.WAITING_FOCUS) { StartTimer(); calstate = CalState.FOCUS_IN_PROGRESS; return; } else if (calstate == CalState.FOCUS_IN_PROGRESS) { if (DoneWaitingTime(150)) { calstate = CalState.FOCUSED; } else { return; } } else if (calstate == CalState.FOCUSED) { //Done waiting the focus time and eyes are focussed UpdateCalibrationAdjustmentWithCurrentGaze(); StartTimer(); sampleCollectionStartTime = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond; calstate = CalState.COLLECTING_SAMPLES; iteration = 0; return; } else if (calstate == CalState.COLLECTING_SAMPLES) { //Done waiting time to start collecting samples //We don't want the gaze to lag across the screen so we trick the user thinking it's centered already if (iteration == 0 || iteration == 1) { UpdateCalibrationAdjustmentWithCurrentGaze(); } if (DoneWaitingTime(ConfigManager.calibrationIterationTimeMs)) { //Check if current gaze point is close to the center of the target circle iteration++; Point wp = controller.WarpPointer.GetWarpPoint(); double pointDistance = PointHelper.GetPointDistance(calpoint, wp); int pointDistanceThreshold = ScreenPixelHelper.ConvertMmToPixels(ConfigManager.calibrationCompletedThresholdMm); UpdateCalibrationAdjustmentWithCurrentGaze(); if (iteration >= ConfigManager.calibrationIterationCountMax && pointDistance < pointDistanceThreshold) { //calibration for this point is successful currentCircle++; if (currentCircle == 9) { ca.writeCalibrationAdjustmentCsv(); currentCircle = 0; Cursor.Show(); this.Close(); } } else { StartTimer(); } this.Invalidate();// This forces the form to repaint } } } else { iteration = 0; calstate = CalState.WAITING_FOCUS; } }
//This function gets called pretty much every precision gaze mouse form refresh public void ShowCursorOverlay(Point p) { if (activeGazeButton == GAZE_BUTTON_TYPE.DOWN || activeGazeButton == GAZE_BUTTON_TYPE.UP) { if (cursorOverlayForm == null || cursorOverlayForm.IsDisposed) { Logger.WriteMsg("New Cursor Overlay Form being created."); cursorOverlayForm = new CursorOverlayForm(); } //Only update the overlay location if there is a change by more than 5 mm if (PointHelper.GetPointDistance(p, cursorOverlayForm.currentPoint) > ScreenPixelHelper.ConvertMmToPixels(5)) { cursorOverlayForm.currentPoint = p; if (activeGazeButton == GAZE_BUTTON_TYPE.DOWN) { cursorOverlayForm.UpdateOverlayType(CursorOverlayForm.OVERLAY_TYPE.DOWNARROW); } else if (activeGazeButton == GAZE_BUTTON_TYPE.UP) { cursorOverlayForm.UpdateOverlayType(CursorOverlayForm.OVERLAY_TYPE.UPARROW); } if (!cursorOverlayForm.Visible) { Logger.WriteMsg("Cursor OverlyForm about to be shown."); cursorOverlayForm.Show(); } else { cursorOverlayForm.Invalidate(); } } } else { HideCursorOverlayForm(); } }