windowcapture
исходный код / UI/WordExportDialog.cs

WordExportDialog.cs

429 строк · 16,974 байт · модуль UI
  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}