1using System; 2using System.Collections.Generic; 3using System.Drawing; 4using System.Drawing.Drawing2D; 5using System.Drawing.Imaging; 6using System.Drawing.Text; 7using System.IO; 8using System.Linq; 9using System.Runtime.InteropServices; 10using System.Windows.Forms; 11using WindowCapture.App; 12using WindowCapture.Detection; 13using WindowCapture.Effects; 14using WindowCapture.Helpers; 15using WindowCapture.Integration; 16using WindowCapture.Models; 17using WindowCapture.Native; 18 19namespace WindowCapture.UI 20{ 21 public partial class EditorForm 22 { 23 // ===== Keyboard input ===== 24 25 private void EditorForm_KeyDown(object sender, KeyEventArgs e) 26 { 27 // Video playback shortcuts 28 if (isVideoFile && (videoBrowser != null || dsMedia != null)) 29 { 30 if (e.KeyCode == Keys.Space && !e.Control) 31 { 32 VideoJS("vToggle"); 33 e.SuppressKeyPress = true; 34 e.Handled = true; 35 return; 36 } 37 if (e.KeyCode == Keys.Left && !e.Control) 38 { 39 // Seek back 5 seconds 40 double t = Math.Max(0, videoCurrentTime - 5); 41 VideoJS("vSeek", t.ToString(System.Globalization.CultureInfo.InvariantCulture)); 42 e.Handled = true; 43 return; 44 } 45 if (e.KeyCode == Keys.Right && !e.Control) 46 { 47 // Seek forward 5 seconds 48 double t = Math.Min(videoDuration, videoCurrentTime + 5); 49 VideoJS("vSeek", t.ToString(System.Globalization.CultureInfo.InvariantCulture)); 50 e.Handled = true; 51 return; 52 } 53 if (e.KeyCode == Keys.M) 54 { 55 VideoJS("vMute"); 56 e.Handled = true; 57 return; 58 } 59 } 60 61 // Ctrl+Space when Word panel is open - insert 62 if (e.KeyCode == Keys.Space && e.Control && wordSidePanel != null && wordSidePanel.IsExpanded) 63 { 64 e.SuppressKeyPress = true; 65 e.Handled = true; 66 wordSidePanel.DoInsert(); 67 return; 68 } 69 70 // Ctrl+Space when Word panel is NOT open - quick AI insert 71 if (e.KeyCode == Keys.Space && e.Control && (wordSidePanel == null || !wordSidePanel.IsExpanded)) 72 { 73 e.SuppressKeyPress = true; 74 e.Handled = true; 75 QuickAIInsert(); 76 return; 77 } 78 79 // Ignore hotkeys when text input is active (let TextBox handle them) 80 if (canvas != null && canvas.IsTextInputActive) 81 { 82 return; 83 } 84 85 // Space - short press: copy and close, long press (250ms): export to Word 86 if (e.KeyCode == Keys.Space && !spaceHeld) 87 { 88 spaceHeld = true; 89 spaceDownTime = DateTime.Now; 90 91 // Start timer to check for long press 92 if (spaceHoldTimer == null) 93 { 94 spaceHoldTimer = new System.Windows.Forms.Timer(); 95 spaceHoldTimer.Interval = SpaceHoldThreshold; 96 spaceHoldTimer.Tick += SpaceHoldTimer_Tick; 97 } 98 spaceHoldTimer.Start(); 99 e.Handled = true; 100 return; 101 } 102 103 // Ctrl+Z - undo 104 if (e.Control && e.KeyCode == Keys.Z) 105 { 106 Undo(); 107 e.Handled = true; 108 return; 109 } 110 111 // Escape - close 112 if (e.KeyCode == Keys.Escape) 113 { 114 Close(); 115 e.Handled = true; 116 return; 117 } 118 119 // Ctrl+S - save 120 if (e.Control && e.KeyCode == Keys.S) 121 { 122 SaveImage(); 123 e.Handled = true; 124 return; 125 } 126 127 // Ctrl+O - open file (viewer mode) 128 if (e.Control && e.KeyCode == Keys.O) 129 { 130 OpenFileDialog(); 131 e.Handled = true; 132 return; 133 } 134 135 // Ctrl+T - grab text from image (OCR) -> clipboard 136 if (e.Control && e.KeyCode == Keys.T) 137 { 138 GrabText(); 139 e.Handled = true; 140 return; 141 } 142 143 // Viewer mode shortcuts 144 if (viewerMode) 145 { 146 // Left/Right arrow: browse images 147 if (e.KeyCode == Keys.Left && !e.Control) 148 { 149 BrowseFile(-1); 150 e.Handled = true; 151 return; 152 } 153 if (e.KeyCode == Keys.Right && !e.Control) 154 { 155 BrowseFile(1); 156 e.Handled = true; 157 return; 158 } 159 if (e.KeyCode == Keys.R) 160 { 161 FitToWindow(); 162 e.Handled = true; 163 return; 164 } 165 if (e.KeyCode == Keys.F) 166 { 167 SetZoom(1.0f); 168 e.Handled = true; 169 return; 170 } 171 // F11 or double-click: toggle maximize 172 if (e.KeyCode == Keys.F11) 173 { 174 WindowState = WindowState == FormWindowState.Maximized 175 ? FormWindowState.Normal : FormWindowState.Maximized; 176 e.Handled = true; 177 return; 178 } 179 } 180 181 // Plus/Minus for zoom 182 if (e.KeyCode == Keys.Oemplus || e.KeyCode == Keys.Add) 183 { 184 ApplyZoom(1f); 185 e.Handled = true; 186 return; 187 } 188 if (e.KeyCode == Keys.OemMinus || e.KeyCode == Keys.Subtract) 189 { 190 ApplyZoom(-1f); 191 e.Handled = true; 192 return; 193 } 194 195 // Alt - enable auto-detect mode (only after Alt was released once) 196 if (e.Alt && !altPressed && altWasReleasedOnce) 197 { 198 altPressed = true; 199 canvas.Cursor = Cursors.Cross; 200 var mousePos = canvas.PointToClient(Cursor.Position); 201 var imgPt = new Point((int)(mousePos.X / zoomLevel), (int)(mousePos.Y / zoomLevel)); 202 UpdateAutoDetect(imgPt); 203 canvas.Invalidate(); 204 } 205 } 206 207 private void EditorForm_KeyUp(object sender, KeyEventArgs e) 208 { 209 // Handle space key release for Word panel - must be processed even when wordDialogOpen 210 if (e.KeyCode == Keys.Space) 211 { 212 // Notify side panel that space was released (for focus handling) 213 if (wordSidePanel != null && wordSidePanel.IsExpanded) 214 { 215 wordSidePanel.OnSpaceReleased(); 216 } 217 218 // If space was held (short press detection) 219 if (spaceHeld) 220 { 221 spaceHeld = false; 222 if (spaceHoldTimer != null) 223 { 224 spaceHoldTimer.Stop(); 225 } 226 227 // Check if it was a short press (timer didn't fire yet) 228 var elapsed = (DateTime.Now - spaceDownTime).TotalMilliseconds; 229 if (elapsed < SpaceHoldThreshold && !wordDialogOpen) 230 { 231 CopyToClipboard(); 232 Close(); 233 return; 234 } 235 } 236 return; 237 } 238 239 // Ignore other KeyUp events if Word dialog is open 240 if (wordDialogOpen) return; 241 242 if (e.KeyCode == Keys.LMenu || e.KeyCode == Keys.RMenu || e.KeyCode == Keys.Menu) 243 { 244 if (!altWasReleasedOnce) 245 { 246 altWasReleasedOnce = true; 247 return; 248 } 249 250 if (altPressed && autoDetectedRect.Width > 5 && autoDetectedRect.Height > 5) 251 { 252 var hl = new HighlightRect(autoDetectedRect); 253 canvas.Highlights.Add(hl); 254 canvas.UndoStack.Add(new UndoAction("highlight", hl)); 255 } 256 altPressed = false; 257 autoDetectedRect = Rectangle.Empty; 258 canvas.Cursor = Cursors.Default; 259 canvas.Invalidate(); 260 } 261 } 262 263 private void SpaceHoldTimer_Tick(object sender, EventArgs e) 264 { 265 spaceHoldTimer.Stop(); 266 267 if (!spaceHeld) return; 268 spaceHeld = false; 269 270 // Long press detected - open Word export dialog 271 ExportToWord(); 272 } 273 } 274}