1using System; 2using System.Collections.Generic; 3using System.Drawing; 4using System.Drawing.Drawing2D; 5using System.Windows.Forms; 6using WindowCapture.Integration; 7 8namespace WindowCapture.UI 9{ 10 /// <summary> 11 /// Dialog for exporting screenshot to Word with description and caption 12 /// </summary> 13 public class WordExportDialog : Form 14 { 15 private static readonly Color DarkBg = Color.FromArgb(30, 30, 34); 16 private static readonly Color DarkPanel = Color.FromArgb(40, 40, 45); 17 private static readonly Color DarkField = Color.FromArgb(50, 50, 55); 18 private static readonly Color AccentColor = Color.FromArgb(86, 156, 214); 19 private static readonly Color AccentHover = Color.FromArgb(100, 170, 230); 20 private static readonly Color TextColor = Color.FromArgb(230, 230, 230); 21 private static readonly Color DimTextColor = Color.FromArgb(140, 140, 140); 22 private static readonly Color BorderColor = Color.FromArgb(60, 60, 65); 23 private static readonly Color SuccessColor = Color.FromArgb(78, 154, 78); 24 private static readonly Color ErrorColor = Color.FromArgb(200, 85, 85); 25 26 private ComboBox cmbDocuments; 27 private Button btnRefresh; 28 private TextBox txtDescription; 29 private TextBox txtCaption; 30 private Button btnInsert; 31 private Button btnCancel; 32 private PictureBox previewBox; 33 private Label lblStatus; 34 private Label lblPreviewHint; 35 private Bitmap imageToInsert; 36 37 public bool Success { get; private set; } 38 39 public WordExportDialog(Bitmap image) 40 { 41 imageToInsert = image; 42 InitializeDialog(); 43 LoadDocuments(); 44 } 45 46 private void InitializeDialog() 47 { 48 Text = "Export to Word"; 49 FormBorderStyle = FormBorderStyle.None; 50 StartPosition = FormStartPosition.CenterScreen; 51 BackColor = DarkBg; 52 Size = new Size(650, 580); 53 DoubleBuffered = true; 54 55 // Title bar with gradient 56 var titlePanel = new Panel(); 57 titlePanel.Dock = DockStyle.Top; 58 titlePanel.Height = 48; 59 titlePanel.BackColor = DarkPanel; 60 titlePanel.Paint += (s, e) => 61 { 62 using (var brush = new LinearGradientBrush(titlePanel.ClientRectangle, 63 Color.FromArgb(45, 45, 50), Color.FromArgb(35, 35, 40), 90f)) 64 { 65 e.Graphics.FillRectangle(brush, titlePanel.ClientRectangle); 66 } 67 // Bottom border 68 using (var pen = new Pen(BorderColor)) 69 e.Graphics.DrawLine(pen, 0, titlePanel.Height - 1, titlePanel.Width, titlePanel.Height - 1); 70 }; 71 Controls.Add(titlePanel); 72 73 var titleIcon = new Label(); 74 titleIcon.Text = "📄"; 75 titleIcon.Font = new Font("Segoe UI", 16f); 76 titleIcon.ForeColor = AccentColor; 77 titleIcon.Location = new Point(16, 10); 78 titleIcon.AutoSize = true; 79 titlePanel.Controls.Add(titleIcon); 80 81 var titleLabel = new Label(); 82 titleLabel.Text = "Экспорт в Word"; 83 titleLabel.ForeColor = TextColor; 84 titleLabel.Font = new Font("Segoe UI Semibold", 12f); 85 titleLabel.Location = new Point(48, 13); 86 titleLabel.AutoSize = true; 87 titlePanel.Controls.Add(titleLabel); 88 89 var closeBtn = CreateCloseButton(); 90 closeBtn.Location = new Point(Width - 46, 4); 91 closeBtn.Click += (s, e) => { Success = false; Close(); }; 92 titlePanel.Controls.Add(closeBtn); 93 94 // Make title draggable 95 titlePanel.MouseDown += (s, e) => { if (e.Button == MouseButtons.Left) DragMove(); }; 96 titleLabel.MouseDown += (s, e) => { if (e.Button == MouseButtons.Left) DragMove(); }; 97 titleIcon.MouseDown += (s, e) => { if (e.Button == MouseButtons.Left) DragMove(); }; 98 99 int y = 65; 100 int margin = 24; 101 int fieldWidth = Width - margin * 2; 102 103 // Document selection section 104 var lblDoc = AddSectionLabel("Документ Word", margin, y); 105 y += 28; 106 107 cmbDocuments = new ComboBox(); 108 cmbDocuments.Location = new Point(margin, y); 109 cmbDocuments.Size = new Size(fieldWidth - 75, 32); 110 cmbDocuments.DropDownStyle = ComboBoxStyle.DropDownList; 111 cmbDocuments.BackColor = DarkField; 112 cmbDocuments.ForeColor = TextColor; 113 cmbDocuments.FlatStyle = FlatStyle.Flat; 114 cmbDocuments.Font = new Font("Segoe UI", 10f); 115 Controls.Add(cmbDocuments); 116 117 btnRefresh = CreateIconButton("⟳", cmbDocuments.Right + 8, y, 60, 32); 118 btnRefresh.Click += (s, e) => LoadDocuments(); 119 Controls.Add(btnRefresh); 120 y += 50; 121 122 // Preview section 123 AddSectionLabel("Предпросмотр", margin, y); 124 y += 28; 125 126 var previewPanel = new Panel(); 127 previewPanel.Location = new Point(margin, y); 128 previewPanel.Size = new Size(fieldWidth, 130); 129 previewPanel.BackColor = DarkField; 130 previewPanel.Paint += (s, e) => 131 { 132 using (var pen = new Pen(BorderColor)) 133 e.Graphics.DrawRectangle(pen, 0, 0, previewPanel.Width - 1, previewPanel.Height - 1); 134 }; 135 Controls.Add(previewPanel); 136 137 previewBox = new PictureBox(); 138 previewBox.Dock = DockStyle.Fill; 139 previewBox.SizeMode = PictureBoxSizeMode.Zoom; 140 previewBox.BackColor = Color.Transparent; 141 if (imageToInsert != null) 142 { 143 try { previewBox.Image = new Bitmap(imageToInsert); } catch { } 144 } 145 previewPanel.Controls.Add(previewBox); 146 147 lblPreviewHint = new Label(); 148 lblPreviewHint.Text = imageToInsert != null ? 149 string.Format("{0} × {1} px", imageToInsert.Width, imageToInsert.Height) : ""; 150 lblPreviewHint.ForeColor = DimTextColor; 151 lblPreviewHint.Font = new Font("Segoe UI", 8f); 152 lblPreviewHint.Location = new Point(margin, y + 132); 153 lblPreviewHint.AutoSize = true; 154 Controls.Add(lblPreviewHint); 155 y += 155; 156 157 // Description section 158 AddSectionLabel("Описание (перед рисунком)", margin, y); 159 var descHint = new Label(); 160 descHint.Text = "Times New Roman 14, интервал 1.5, отступ 1.25 см"; 161 descHint.ForeColor = DimTextColor; 162 descHint.Font = new Font("Segoe UI", 8f); 163 descHint.Location = new Point(margin + 195, y + 3); 164 descHint.AutoSize = true; 165 Controls.Add(descHint); 166 y += 28; 167 168 txtDescription = CreateTextBox(margin, y, fieldWidth, 85, true); 169 Controls.Add(txtDescription); 170 y += 100; 171 172 // Caption section 173 AddSectionLabel("Название рисунка", margin, y); 174 var captionHint = new Label(); 175 captionHint.Text = "Рисунок N — [ваш текст]"; 176 captionHint.ForeColor = DimTextColor; 177 captionHint.Font = new Font("Segoe UI", 8f); 178 captionHint.Location = new Point(margin + 140, y + 3); 179 captionHint.AutoSize = true; 180 Controls.Add(captionHint); 181 y += 28; 182 183 txtCaption = CreateTextBox(margin, y, fieldWidth, 32, false); 184 Controls.Add(txtCaption); 185 y += 50; 186 187 // Status bar 188 var statusPanel = new Panel(); 189 statusPanel.Location = new Point(0, Height - 60); 190 statusPanel.Size = new Size(Width, 60); 191 statusPanel.BackColor = DarkPanel; 192 statusPanel.Paint += (s, e) => 193 { 194 using (var pen = new Pen(BorderColor)) 195 e.Graphics.DrawLine(pen, 0, 0, statusPanel.Width, 0); 196 }; 197 Controls.Add(statusPanel); 198 199 lblStatus = new Label(); 200 lblStatus.Location = new Point(margin, 20); 201 lblStatus.Size = new Size(Width - margin * 2 - 200, 24); 202 lblStatus.ForeColor = DimTextColor; 203 lblStatus.Font = new Font("Segoe UI", 9f); 204 lblStatus.TextAlign = ContentAlignment.MiddleLeft; 205 statusPanel.Controls.Add(lblStatus); 206 207 // Buttons 208 btnCancel = CreateButton("Отмена", Width - margin - 190, 14, 90, 34, false); 209 btnCancel.Click += (s, e) => { Success = false; Close(); }; 210 statusPanel.Controls.Add(btnCancel); 211 212 btnInsert = CreateButton("Вставить", Width - margin - 90, 14, 90, 34, true); 213 btnInsert.Click += BtnInsert_Click; 214 statusPanel.Controls.Add(btnInsert); 215 216 // Paint outer border 217 Paint += (s, e) => 218 { 219 using (var pen = new Pen(BorderColor, 1)) 220 e.Graphics.DrawRectangle(pen, 0, 0, Width - 1, Height - 1); 221 }; 222 223 // Handle keys 224 KeyPreview = true; 225 KeyDown += (s, e) => 226 { 227 if (e.KeyCode == Keys.Escape) 228 { 229 Success = false; 230 Close(); 231 } 232 else if (e.KeyCode == Keys.Enter) 233 { 234 // Enter inserts (unless in multiline textbox without Ctrl) 235 if (e.Control || !txtDescription.Focused) 236 { 237 e.SuppressKeyPress = true; 238 BtnInsert_Click(null, null); 239 } 240 } 241 }; 242 243 // Set focus to description field on load 244 Shown += (s, e) => txtDescription.Focus(); 245 } 246 247 private void LoadDocuments() 248 { 249 cmbDocuments.Items.Clear(); 250 lblStatus.Text = "Поиск открытых документов Word..."; 251 lblStatus.ForeColor = DimTextColor; 252 253 var docs = WordIntegration.GetOpenDocuments(); 254 255 if (docs.Count == 0) 256 { 257 lblStatus.Text = "Документы не найдены. Откройте документ в Word."; 258 lblStatus.ForeColor = ErrorColor; 259 btnInsert.Enabled = false; 260 } 261 else 262 { 263 foreach (var doc in docs) 264 { 265 cmbDocuments.Items.Add(doc); 266 } 267 268 // Select previously selected document if still open 269 var prevSelected = WordIntegration.SelectedDocument; 270 if (prevSelected != null) 271 { 272 for (int i = 0; i < cmbDocuments.Items.Count; i++) 273 { 274 var item = cmbDocuments.Items[i] as WordDocumentInfo; 275 if (item != null && item.FullPath == prevSelected.FullPath) 276 { 277 cmbDocuments.SelectedIndex = i; 278 break; 279 } 280 } 281 } 282 283 if (cmbDocuments.SelectedIndex < 0 && cmbDocuments.Items.Count > 0) 284 cmbDocuments.SelectedIndex = 0; 285 286 lblStatus.Text = string.Format("Найдено: {0}. Ctrl+Enter для вставки.", docs.Count); 287 lblStatus.ForeColor = SuccessColor; 288 btnInsert.Enabled = true; 289 } 290 } 291 292 private void BtnInsert_Click(object sender, EventArgs e) 293 { 294 if (cmbDocuments.SelectedItem == null) 295 { 296 lblStatus.Text = "Выберите документ Word."; 297 lblStatus.ForeColor = ErrorColor; 298 return; 299 } 300 301 var doc = cmbDocuments.SelectedItem as WordDocumentInfo; 302 if (doc == null) return; 303 304 WordIntegration.SelectedDocument = doc; 305 306 lblStatus.Text = "Вставка изображения..."; 307 lblStatus.ForeColor = DimTextColor; 308 btnInsert.Enabled = false; 309 Application.DoEvents(); 310 311 bool result = WordIntegration.InsertImageWithCaption( 312 imageToInsert, 313 txtDescription.Text.Trim(), 314 txtCaption.Text.Trim()); 315 316 if (result) 317 { 318 Success = true; 319 Close(); 320 } 321 else 322 { 323 lblStatus.Text = "Ошибка вставки. Убедитесь, что Word запущен."; 324 lblStatus.ForeColor = ErrorColor; 325 btnInsert.Enabled = true; 326 } 327 } 328 329 private Label AddSectionLabel(string text, int x, int y) 330 { 331 var lbl = new Label(); 332 lbl.Text = text; 333 lbl.Location = new Point(x, y); 334 lbl.AutoSize = true; 335 lbl.ForeColor = TextColor; 336 lbl.Font = new Font("Segoe UI Semibold", 9.5f); 337 Controls.Add(lbl); 338 return lbl; 339 } 340 341 private TextBox CreateTextBox(int x, int y, int width, int height, bool multiline) 342 { 343 var txt = new TextBox(); 344 txt.Location = new Point(x, y); 345 txt.Size = new Size(width, height); 346 txt.Multiline = multiline; 347 txt.BackColor = DarkField; 348 txt.ForeColor = TextColor; 349 txt.BorderStyle = BorderStyle.FixedSingle; 350 txt.Font = new Font("Segoe UI", 10f); 351 if (multiline) txt.ScrollBars = ScrollBars.Vertical; 352 return txt; 353 } 354 355 private Button CreateButton(string text, int x, int y, int width, int height, bool isPrimary) 356 { 357 var btn = new Button(); 358 btn.Text = text; 359 btn.Location = new Point(x, y); 360 btn.Size = new Size(width, height); 361 btn.FlatStyle = FlatStyle.Flat; 362 btn.FlatAppearance.BorderSize = 1; 363 btn.FlatAppearance.BorderColor = isPrimary ? AccentColor : BorderColor; 364 btn.BackColor = isPrimary ? AccentColor : DarkField; 365 btn.ForeColor = TextColor; 366 btn.Font = new Font("Segoe UI", 9.5f); 367 btn.Cursor = Cursors.Hand; 368 369 if (isPrimary) 370 { 371 btn.MouseEnter += (s, e) => { btn.BackColor = AccentHover; }; 372 btn.MouseLeave += (s, e) => { btn.BackColor = AccentColor; }; 373 } 374 else 375 { 376 btn.MouseEnter += (s, e) => { btn.BackColor = Color.FromArgb(60, 60, 65); }; 377 btn.MouseLeave += (s, e) => { btn.BackColor = DarkField; }; 378 } 379 380 return btn; 381 } 382 383 private Button CreateIconButton(string icon, int x, int y, int width, int height) 384 { 385 var btn = new Button(); 386 btn.Text = icon; 387 btn.Location = new Point(x, y); 388 btn.Size = new Size(width, height); 389 btn.FlatStyle = FlatStyle.Flat; 390 btn.FlatAppearance.BorderSize = 1; 391 btn.FlatAppearance.BorderColor = BorderColor; 392 btn.BackColor = DarkField; 393 btn.ForeColor = TextColor; 394 btn.Font = new Font("Segoe UI", 12f); 395 btn.Cursor = Cursors.Hand; 396 btn.MouseEnter += (s, e) => { btn.BackColor = Color.FromArgb(60, 60, 65); }; 397 btn.MouseLeave += (s, e) => { btn.BackColor = DarkField; }; 398 return btn; 399 } 400 401 private Button CreateCloseButton() 402 { 403 var btn = new Button(); 404 btn.Text = "✕"; 405 btn.Size = new Size(40, 40); 406 btn.FlatStyle = FlatStyle.Flat; 407 btn.FlatAppearance.BorderSize = 0; 408 btn.ForeColor = DimTextColor; 409 btn.BackColor = Color.Transparent; 410 btn.Font = new Font("Segoe UI", 10f); 411 btn.Cursor = Cursors.Hand; 412 btn.MouseEnter += (s, e) => { btn.BackColor = Color.FromArgb(200, 50, 50); btn.ForeColor = TextColor; }; 413 btn.MouseLeave += (s, e) => { btn.BackColor = Color.Transparent; btn.ForeColor = DimTextColor; }; 414 return btn; 415 } 416 417 // P/Invoke for window dragging 418 [System.Runtime.InteropServices.DllImport("user32.dll")] 419 private static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam); 420 [System.Runtime.InteropServices.DllImport("user32.dll")] 421 private static extern bool ReleaseCapture(); 422 423 private void DragMove() 424 { 425 ReleaseCapture(); 426 SendMessage(Handle, 0xA1, 0x2, 0); 427 } 428 } 429}