Добавьте файлы проекта.

This commit is contained in:
Professional 2025-04-21 21:14:48 +07:00
parent 74cf6d2453
commit 438a7c85cc
17 changed files with 1808 additions and 0 deletions

18
App.config Normal file
View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
<section name="SKLADm.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
</sectionGroup>
</configSections>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2" />
</startup>
<userSettings>
<SKLADm.Properties.Settings>
<setting name="SavedStoresJson" serializeAs="String">
<value />
</setting>
</SKLADm.Properties.Settings>
</userSettings>
</configuration>

223
Form1.Designer.cs generated Normal file
View File

@ -0,0 +1,223 @@
//------------------------------------------------------------------------------
// <auto-generated>
// Этот код создан программой.
// Исполняемая версия:4.0.30319.42000
//
// Изменения в этом файле могут привести к неправильной работе и будут потеряны в случае
// повторной генерации кода.
// </auto-generated>
//------------------------------------------------------------------------------
namespace OzonInternalLabelPrinter // Убедитесь, что это ваше пространство имен
{
partial class Form1
{
/// <summary>
/// Обязательная переменная конструктора.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Освободить все используемые ресурсы.
/// </summary>
/// <param name="disposing">истинно, если управляемый ресурс должен быть удален; иначе ложно.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
// Освобождаем ресурсы, созданные в коде Form1.cs
_httpClient?.Dispose();
_printDocForSetup?.Dispose(); // Добавлено освобождение PrintDocument
}
base.Dispose(disposing);
}
#region Код, автоматически созданный конструктором форм Windows
/// <summary>
/// Требуемый метод для поддержки конструктора — не изменяйте
/// содержимое этого метода с помощью редактора кода.
/// </summary>
private void InitializeComponent()
{
this.label3 = new System.Windows.Forms.Label();
this.txtOfferId = new System.Windows.Forms.TextBox();
this.btnGetData = new System.Windows.Forms.Button();
this.lblProductName = new System.Windows.Forms.Label();
this.lblProductSku = new System.Windows.Forms.Label();
this.lblProductBarcode = new System.Windows.Forms.Label();
this.btnPrintLabel = new System.Windows.Forms.Button();
this.lblStatus = new System.Windows.Forms.Label();
this.cmbStores = new System.Windows.Forms.ComboBox();
this.btnManageStores = new System.Windows.Forms.Button();
this.labelStore = new System.Windows.Forms.Label();
this.btnPageSetup = new System.Windows.Forms.Button(); // Объявление кнопки Настройки
this.pageSetupDialog1 = new System.Windows.Forms.PageSetupDialog(); // Объявление диалога Настройки
this.SuspendLayout();
//
// label3
//
this.label3.AutoSize = true;
this.label3.Location = new System.Drawing.Point(12, 94); // Скорректировано
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(51, 13);
this.label3.TabIndex = 4;
this.label3.Text = "Артикул:";
//
// txtOfferId
//
this.txtOfferId.Enabled = false;
this.txtOfferId.Location = new System.Drawing.Point(88, 91); // Скорректировано
this.txtOfferId.Name = "txtOfferId";
this.txtOfferId.Size = new System.Drawing.Size(176, 20);
this.txtOfferId.TabIndex = 3; // TabIndex изменен
this.txtOfferId.TextChanged += new System.EventHandler(this.txtOfferId_TextChanged);
//
// btnGetData
//
this.btnGetData.Enabled = false;
this.btnGetData.Location = new System.Drawing.Point(270, 89); // Скорректировано
this.btnGetData.Name = "btnGetData";
this.btnGetData.Size = new System.Drawing.Size(118, 23);
this.btnGetData.TabIndex = 4; // TabIndex изменен
this.btnGetData.Text = "Получить данные";
this.btnGetData.UseVisualStyleBackColor = true;
this.btnGetData.Click += new System.EventHandler(this.btnGetData_Click);
//
// lblProductName
//
this.lblProductName.AutoSize = true;
this.lblProductName.Location = new System.Drawing.Point(12, 133); // Скорректировано
this.lblProductName.Name = "lblProductName";
this.lblProductName.Size = new System.Drawing.Size(60, 13);
this.lblProductName.TabIndex = 5;
this.lblProductName.Text = "Название:";
//
// lblProductSku
//
this.lblProductSku.AutoSize = true;
this.lblProductSku.Location = new System.Drawing.Point(12, 156); // Скорректировано
this.lblProductSku.Name = "lblProductSku";
this.lblProductSku.Size = new System.Drawing.Size(51, 13);
this.lblProductSku.TabIndex = 6;
this.lblProductSku.Text = "Артикул:";
//
// lblProductBarcode
//
this.lblProductBarcode.AutoSize = true;
this.lblProductBarcode.Location = new System.Drawing.Point(12, 179); // Скорректировано
this.lblProductBarcode.Name = "lblProductBarcode";
this.lblProductBarcode.Size = new System.Drawing.Size(59, 13);
this.lblProductBarcode.TabIndex = 7;
this.lblProductBarcode.Text = "Штрихкод:";
//
// btnPrintLabel
//
this.btnPrintLabel.Enabled = false;
this.btnPrintLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(204)));
this.btnPrintLabel.Location = new System.Drawing.Point(16, 214); // Скорректировано
this.btnPrintLabel.Name = "btnPrintLabel";
this.btnPrintLabel.Size = new System.Drawing.Size(373, 33);
this.btnPrintLabel.TabIndex = 8; // TabIndex изменен
this.btnPrintLabel.Text = "Печать этикетки";
this.btnPrintLabel.UseVisualStyleBackColor = true;
this.btnPrintLabel.Click += new System.EventHandler(this.btnPrintLabel_Click);
//
// lblStatus
//
this.lblStatus.AutoSize = true;
this.lblStatus.Location = new System.Drawing.Point(13, 260); // Скорректировано
this.lblStatus.Name = "lblStatus";
this.lblStatus.Size = new System.Drawing.Size(44, 13);
this.lblStatus.TabIndex = 9;
this.lblStatus.Text = "Статус:";
//
// cmbStores
//
this.cmbStores.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.cmbStores.FormattingEnabled = true;
this.cmbStores.Location = new System.Drawing.Point(88, 24);
this.cmbStores.Name = "cmbStores";
this.cmbStores.Size = new System.Drawing.Size(176, 21);
this.cmbStores.TabIndex = 0;
this.cmbStores.SelectedIndexChanged += new System.EventHandler(this.cmbStores_SelectedIndexChanged);
//
// btnManageStores
//
this.btnManageStores.Location = new System.Drawing.Point(270, 23);
this.btnManageStores.Name = "btnManageStores";
this.btnManageStores.Size = new System.Drawing.Size(118, 23);
this.btnManageStores.TabIndex = 1;
this.btnManageStores.Text = "Упр. магазинами...";
this.btnManageStores.UseVisualStyleBackColor = true;
this.btnManageStores.Click += new System.EventHandler(this.btnManageStores_Click);
//
// labelStore
//
this.labelStore.AutoSize = true;
this.labelStore.Location = new System.Drawing.Point(12, 27);
this.labelStore.Name = "labelStore";
this.labelStore.Size = new System.Drawing.Size(54, 13);
this.labelStore.TabIndex = 15;
this.labelStore.Text = "Магазин:";
//
// btnPageSetup
// *** Новая кнопка Настройки принтера ***
this.btnPageSetup.Location = new System.Drawing.Point(270, 53);
this.btnPageSetup.Name = "btnPageSetup";
this.btnPageSetup.Size = new System.Drawing.Size(118, 23);
this.btnPageSetup.TabIndex = 2; // Изменен TabIndex
this.btnPageSetup.Text = "Настройка принтера";
this.btnPageSetup.UseVisualStyleBackColor = true;
this.btnPageSetup.Click += new System.EventHandler(this.btnPageSetup_Click);
//
// pageSetupDialog1
// *** Диалог настройки страницы ***
this.pageSetupDialog1 = new System.Windows.Forms.PageSetupDialog();
this.pageSetupDialog1.EnableMetric = true;
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(404, 288); // Скорректирован размер
this.Controls.Add(this.btnPageSetup); // Добавлена кнопка
this.Controls.Add(this.labelStore);
this.Controls.Add(this.btnManageStores);
this.Controls.Add(this.cmbStores);
this.Controls.Add(this.lblStatus);
this.Controls.Add(this.btnPrintLabel);
this.Controls.Add(this.lblProductBarcode);
this.Controls.Add(this.lblProductSku);
this.Controls.Add(this.lblProductName);
this.Controls.Add(this.btnGetData);
this.Controls.Add(this.txtOfferId);
this.Controls.Add(this.label3);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
this.MaximizeBox = false;
this.Name = "Form1";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "Генератор внутренних этикеток Ozon";
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Label label3;
private System.Windows.Forms.TextBox txtOfferId;
private System.Windows.Forms.Button btnGetData;
private System.Windows.Forms.Label lblProductName;
private System.Windows.Forms.Label lblProductSku;
private System.Windows.Forms.Label lblProductBarcode;
private System.Windows.Forms.Button btnPrintLabel;
private System.Windows.Forms.Label lblStatus;
private System.Windows.Forms.ComboBox cmbStores;
private System.Windows.Forms.Button btnManageStores;
private System.Windows.Forms.Label labelStore;
private System.Windows.Forms.Button btnPageSetup; // Добавлено
private System.Windows.Forms.PageSetupDialog pageSetupDialog1; // Добавлено
}
}

500
Form1.cs Normal file
View File

@ -0,0 +1,500 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Printing;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Cryptography; // Для шифрования/дешифрования
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows.Forms;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using SKLADm.Properties; // Для доступа к Settings.Default
using SKLADm;
using ZXing;
using ZXing.Common;
using ZXing.Windows.Compatibility;
namespace OzonInternalLabelPrinter // Убедитесь, что это ваше пространство имен
{
public partial class Form1 : Form
{
private HttpClient _httpClient;
// Bitmap больше не нужен как поле класса
// private Bitmap _labelBitmap;
private string _currentProductName;
private string _currentSku;
private string _currentBarcode;
private List<OzonStore> _availableStores;
// Поле для хранения экземпляра документа между настройкой и печатью
private PrintDocument _printDocForSetup; // Используем для PageSetup и Print
// Конструктор формы
public Form1()
{
InitializeComponent(); // Инициализирует компоненты из ДИЗАЙНЕРА
InitializeHttpClient();
// Инициализируем PrintDocument один раз
_printDocForSetup = new PrintDocument();
// Устанавливаем обработчик печати один раз
_printDocForSetup.PrintPage += new PrintPageEventHandler(pd_PrintPage);
// Загружаем магазины при запуске ПОСЛЕ инициализации _printDocForSetup
LoadStoresToComboBox();
}
// Инициализация HTTP клиента
private void InitializeHttpClient()
{
_httpClient = new HttpClient
{
BaseAddress = new Uri("https://api-seller.ozon.ru/")
};
_httpClient.DefaultRequestHeaders.Accept.Clear();
_httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
}
// --- Логика работы с магазинами и ключами ---
private static readonly byte[] s_entropy = null; // Энтропия для шифрования
// Дешифрование Api-Key
private string DecryptApiKey(string encryptedKeyBase64)
{
if (string.IsNullOrEmpty(encryptedKeyBase64)) return string.Empty;
try
{
byte[] encryptedBytes = Convert.FromBase64String(encryptedKeyBase64);
byte[] decryptedBytes = ProtectedData.Unprotect(encryptedBytes, s_entropy, DataProtectionScope.CurrentUser);
return Encoding.UTF8.GetString(decryptedBytes);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"Ошибка дешифрования ключа: {ex.Message}");
MessageBox.Show($"Не удалось дешифровать Api-Key для магазина '{cmbStores.Text}'. Возможно, настройки повреждены или созданы под другим пользователем.\n\nОшибка: {ex.Message}",
"Ошибка ключа", MessageBoxButtons.OK, MessageBoxIcon.Error);
return null;
}
}
// Загрузка магазинов из настроек в ComboBox
private void LoadStoresToComboBox()
{
string json = Settings.Default.SavedStoresJson;
_availableStores = new List<OzonStore>();
if (!string.IsNullOrEmpty(json))
{
try
{
_availableStores = JsonConvert.DeserializeObject<List<OzonStore>>(json) ?? new List<OzonStore>();
}
catch (Exception ex)
{
MessageBox.Show($"Ошибка загрузки списка магазинов: {ex.Message}", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Warning);
_availableStores = new List<OzonStore>();
}
}
cmbStores.DataSource = null;
cmbStores.DataSource = _availableStores;
cmbStores.DisplayMember = "StoreName";
bool storesExist = _availableStores.Any();
cmbStores.Enabled = storesExist;
txtOfferId.Enabled = storesExist;
btnPageSetup.Enabled = storesExist; // Включаем настройку, если есть магазины
// Кнопка GetData включится при вводе артикула
if (storesExist)
{
cmbStores.SelectedIndex = 0;
// Установим принтер по умолчанию для _printDocForSetup, если возможно
TrySetDefaultPrinterForDocument();
}
else
{
cmbStores.SelectedIndex = -1;
// Показываем сообщение, если нужно
// MessageBox.Show("Нет сохраненных магазинов...", "Внимание", MessageBoxButtons.OK, Information);
}
ResetProductData();
// Обновляем состояние кнопки GetData после загрузки
txtOfferId_TextChanged(txtOfferId, EventArgs.Empty);
}
// Попытка установить принтер по умолчанию для PrintDocument
private void TrySetDefaultPrinterForDocument()
{
string thermalPrinterName = "Xprinter XP-365B"; // Или другое имя по умолчанию
foreach (string printerName in PrinterSettings.InstalledPrinters)
{
if (printerName.Equals(thermalPrinterName, StringComparison.OrdinalIgnoreCase))
{
try
{
_printDocForSetup.PrinterSettings.PrinterName = printerName;
System.Diagnostics.Debug.WriteLine($"Принтер по умолчанию '{printerName}' установлен для PrintDocument.");
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"Ошибка установки принтера по умолчанию '{printerName}': {ex.Message}");
}
return; // Выходим после нахождения
}
}
System.Diagnostics.Debug.WriteLine($"Принтер по умолчанию '{thermalPrinterName}' не найден.");
}
// --- Обработчики событий UI ---
private void btnManageStores_Click(object sender, EventArgs e)
{
using (FormManageStores manageForm = new FormManageStores())
{
manageForm.ShowDialog(this);
LoadStoresToComboBox(); // Перезагружаем список
}
}
private void cmbStores_SelectedIndexChanged(object sender, EventArgs e)
{
ResetProductData();
txtOfferId_TextChanged(txtOfferId, EventArgs.Empty); // Обновляем состояние кнопки GetData
// Можно попробовать обновить принтер по умолчанию для _printDocForSetup,
// если у разных магазинов могут быть разные принтеры (но это усложнит логику)
}
private void txtOfferId_TextChanged(object sender, EventArgs e)
{
btnGetData.Enabled = cmbStores.SelectedItem != null && !string.IsNullOrEmpty(txtOfferId.Text.Trim());
if (string.IsNullOrEmpty(txtOfferId.Text.Trim()))
{
ResetProductData();
}
}
// --- Кнопка "Настройка принтера" ---
private void btnPageSetup_Click(object sender, EventArgs e)
{
// Убедимся, что принтер в _printDocForSetup актуален (если не нашли Xprinter при запуске,
// или если у пользователя несколько принтеров)
if (!PrinterSettings.InstalledPrinters.Cast<string>().Contains(_printDocForSetup.PrinterSettings.PrinterName))
{
// Если текущий принтер недоступен, сбрасываем на принтер по умолчанию Windows
try
{
_printDocForSetup.PrinterSettings = new PrinterSettings(); // Сброс на настройки по умолчанию
System.Diagnostics.Debug.WriteLine("Текущий принтер в PrintDocument был недоступен, сброшен на принтер по умолчанию Windows.");
}
catch { }
}
pageSetupDialog1.Document = _printDocForSetup; // Связываем диалог с нашим PrintDocument
pageSetupDialog1.MinMargins = new Margins(0, 0, 0, 0); // Минимальные поля
pageSetupDialog1.AllowMargins = true; // Разрешаем менять поля
pageSetupDialog1.AllowOrientation = false; // Запрещаем менять ориентацию
pageSetupDialog1.AllowPaper = true; // Разрешаем менять размер бумаги
pageSetupDialog1.AllowPrinter = true; // Разрешаем выбирать другой принтер
if (pageSetupDialog1.ShowDialog(this) == DialogResult.OK)
{
// Настройки применились к _printDocForSetup
lblStatus.Text = "Настройки принтера применены.";
System.Diagnostics.Debug.WriteLine($"PageSetupDialog OK: New PaperSize={_printDocForSetup.DefaultPageSettings.PaperSize.PaperName}, Printer={_printDocForSetup.PrinterSettings.PrinterName}");
}
else
{
lblStatus.Text = "Настройка принтера отменена.";
}
}
// --- Получение данных из API ---
private async void btnGetData_Click(object sender, EventArgs e)
{
OzonStore selectedStore = cmbStores.SelectedItem as OzonStore;
if (selectedStore == null) { MessageBox.Show("Выберите магазин.", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; }
string clientId = selectedStore.ClientId;
string apiKey = DecryptApiKey(selectedStore.EncryptedApiKey);
if (apiKey == null) { lblStatus.Text = "Ошибка ключа API."; return; }
string rawOfferId = txtOfferId.Text.Trim();
if (string.IsNullOrEmpty(rawOfferId)) { MessageBox.Show("Введите Артикул.", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; }
string offerId = Regex.Replace(rawOfferId, @"[^a-zA-Zа-яА-Я0-9_-]", "");
if (string.IsNullOrEmpty(offerId)) { MessageBox.Show("Артикул некорректен.", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; }
if (offerId != rawOfferId) { txtOfferId.Text = offerId; }
ResetProductData();
lblStatus.Text = "Запрос данных...";
Application.DoEvents();
_httpClient.DefaultRequestHeaders.Remove("Client-Id");
_httpClient.DefaultRequestHeaders.Remove("Api-Key");
_httpClient.DefaultRequestHeaders.Add("Client-Id", clientId);
_httpClient.DefaultRequestHeaders.Add("Api-Key", apiKey);
string responseBody = string.Empty;
try
{
var requestData = new { offer_id = new[] { offerId } };
var jsonRequest = JsonConvert.SerializeObject(requestData);
var content = new StringContent(jsonRequest, Encoding.UTF8, "application/json");
HttpResponseMessage response = await _httpClient.PostAsync("/v3/product/info/list", content);
responseBody = await response.Content.ReadAsStringAsync();
System.Diagnostics.Debug.WriteLine($"API Response ({response.StatusCode}): {responseBody}");
if (response.IsSuccessStatusCode)
{
JObject jsonResponse = JObject.Parse(responseBody);
JToken itemsArray = jsonResponse["items"];
if (itemsArray != null && itemsArray.Type == JTokenType.Array && itemsArray.HasValues)
{
JToken firstItem = itemsArray[0];
if (firstItem != null)
{
_currentProductName = firstItem["name"]?.ToString() ?? "N/A";
_currentSku = firstItem["offer_id"]?.ToString() ?? offerId;
_currentBarcode = firstItem["barcode"]?.ToString();
if (string.IsNullOrEmpty(_currentBarcode))
{
JToken barcodesToken = firstItem["barcodes"];
if (barcodesToken != null && barcodesToken.Type == JTokenType.Array && barcodesToken.HasValues)
{ _currentBarcode = barcodesToken.First?.ToString(); }
}
_currentBarcode = _currentBarcode ?? "N/A";
GenerateLabelPreview(); // Обновляем UI и включаем кнопку печати
}
else { HandleApiError("Нет данных о товаре в ответе.", responseBody); }
}
else { HandleApiError("Ответ API не содержит списка товаров.", responseBody); }
}
else { HandleApiError($"Ошибка API: {response.StatusCode}", responseBody); }
}
catch (JsonReaderException jsonEx) { MessageBox.Show($"Ошибка JSON: {jsonEx.Message}\n{responseBody}", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error); ResetProductData(); }
catch (HttpRequestException httpEx) { MessageBox.Show($"Ошибка сети: {httpEx.Message}", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error); ResetProductData(); }
catch (Exception ex) { MessageBox.Show($"Ошибка: {ex.Message}", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error); ResetProductData(); }
finally { apiKey = null; }
}
// Обработка ошибок API
private void HandleApiError(string messagePrefix, string responseBody)
{
string errorMessage = $"{messagePrefix}";
try
{
JObject errorJson = JObject.Parse(responseBody);
string ozonError = errorJson["message"]?.ToString() ?? errorJson["error"]?["message"]?.ToString();
errorMessage = string.IsNullOrEmpty(ozonError) ? $"{messagePrefix}\n{responseBody}" : $"{messagePrefix}\n{ozonError}";
}
catch { errorMessage = $"{messagePrefix}\n{responseBody}"; }
MessageBox.Show(errorMessage, "Ошибка API Ozon", MessageBoxButtons.OK, MessageBoxIcon.Error);
lblStatus.Text = "Ошибка API.";
ResetProductData();
}
// Сброс данных о товаре и состояния UI
private void ResetProductData()
{
_currentProductName = null;
_currentSku = null;
_currentBarcode = null;
lblProductName.Text = "Название:";
lblProductSku.Text = "Артикул:";
lblProductBarcode.Text = "Штрихкод:";
// Очищаем превью, если оно есть
if (this.Controls.ContainsKey("picLabelPreview"))
(this.Controls["picLabelPreview"] as PictureBox).Image = null;
btnPrintLabel.Enabled = false;
// lblStatus.Text = "Статус:";
}
// Генерация (только обновление UI)
private void GenerateLabelPreview()
{
bool dataAvailable = !string.IsNullOrEmpty(_currentSku) &&
!string.IsNullOrEmpty(_currentProductName) &&
!string.IsNullOrEmpty(_currentBarcode) &&
_currentBarcode != "N/A";
if (!dataAvailable) { ResetProductData(); return; }
lblProductName.Text = $"Название: {_currentProductName}";
lblProductSku.Text = $"Артикул: {_currentSku}";
lblProductBarcode.Text = $"Штрихкод: {_currentBarcode}";
// Очистка превью, если оно есть
if (this.Controls.ContainsKey("picLabelPreview"))
(this.Controls["picLabelPreview"] as PictureBox).Image = null;
btnPrintLabel.Enabled = true;
lblStatus.Text = "Данные получены, готово к печати.";
}
// --- Печать ---
// Кнопка "Печать этикетки"
private void btnPrintLabel_Click(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(_currentSku) || string.IsNullOrEmpty(_currentProductName) || string.IsNullOrEmpty(_currentBarcode) || _currentBarcode == "N/A")
{
MessageBox.Show("Нет данных для печати.", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return;
}
PrintDialog printDialog = new PrintDialog();
printDialog.Document = _printDocForSetup; // Используем настроенный документ
printDialog.AllowSomePages = false;
printDialog.AllowSelection = false;
printDialog.UseEXDialog = true;
if (printDialog.ShowDialog(this) == DialogResult.OK)
{
// _printDocForSetup уже содержит принтер и настройки страницы, выбранные в PrintDialog или PageSetupDialog
// Переустанавливаем поля на случай, если PrintDialog их сбросил
_printDocForSetup.DefaultPageSettings.Margins = new Margins(0, 0, 0, 0);
_printDocForSetup.OriginAtMargins = false;
try
{
lblStatus.Text = $"Печать на {_printDocForSetup.PrinterSettings.PrinterName}...";
_printDocForSetup.Print(); // Печатаем с текущими настройками
lblStatus.Text = "Отправлено на печать.";
}
catch (InvalidPrinterException)
{
MessageBox.Show($"Ошибка: Принтер '{_printDocForSetup.PrinterSettings.PrinterName}' недоступен или не найден.\nПроверьте подключение или выберите другой принтер в настройках.", "Ошибка принтера", MessageBoxButtons.OK, MessageBoxIcon.Error);
lblStatus.Text = "Ошибка принтера.";
}
catch (Exception ex)
{
MessageBox.Show($"Ошибка печати: {ex.Message}", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
lblStatus.Text = "Ошибка печати.";
}
}
else { lblStatus.Text = "Печать отменена."; }
printDialog.Dispose();
}
// Метод отрисовки страницы для печати (динамический)
private void pd_PrintPage(object sender, PrintPageEventArgs e)
{
// Проверка данных
if (string.IsNullOrEmpty(_currentSku) || string.IsNullOrEmpty(_currentProductName) || string.IsNullOrEmpty(_currentBarcode) || _currentBarcode == "N/A")
{ System.Diagnostics.Debug.WriteLine("PrintPage ABORTED - Missing data!"); e.Cancel = true; return; }
Graphics g = e.Graphics;
// Получаем РЕАЛЬНЫЕ границы печатаемой области в единицах Graphics (обычно сотые дюйма)
// Не PageBounds, а PrintableArea! PageBounds - это физический размер листа.
RectangleF printArea = e.PageSettings.PrintableArea;
// Отступы от КРАЕВ ПЕЧАТАЕМОЙ ОБЛАСТИ (в единицах Graphics)
// Подбирайте эти значения, чтобы получить рамку внутри печатаемой зоны
float marginX = 5 * g.DpiX / 100f; // Пример: 5/100 дюйма -> в единицах Graphics
float marginY = 3 * g.DpiY / 100f; // Пример: 3/100 дюйма -> в единицах Graphics
// Область для рисования контента внутри отступов
float drawableX = printArea.Left + marginX;
float drawableY = printArea.Top + marginY;
float drawableWidth = printArea.Width - (marginX * 2);
float drawableHeight = printArea.Height - (marginY * 2);
float currentY = drawableY; // Текущая позиция по Y
// Проверка на валидность области
if (drawableWidth <= 0 || drawableHeight <= 0) { System.Diagnostics.Debug.WriteLine("PrintPage ABORTED - Invalid drawable area!"); e.Cancel = true; return; }
System.Diagnostics.Debug.WriteLine("--- Printing Page (Dynamic) ---");
System.Diagnostics.Debug.WriteLine($"Paper: {e.PageSettings.PaperSize.PaperName} ({e.PageSettings.PaperSize.Width}x{e.PageSettings.PaperSize.Height}) hund.inch");
System.Diagnostics.Debug.WriteLine($"PrintableArea ({g.PageUnit}): X={printArea.X:F2}, Y={printArea.Y:F2}, W={printArea.Width:F2}, H={printArea.Height:F2}");
System.Diagnostics.Debug.WriteLine($"Drawable Area ({g.PageUnit}): X={drawableX:F2}, Y={drawableY:F2}, W={drawableWidth:F2}, H={drawableHeight:F2}");
// Шрифты (размер в пунктах)
float baseFontSizePoints = 6f; // Базовый размер, можно менять
Font titleFont = new Font("Arial", baseFontSizePoints + 1, FontStyle.Bold);
Font regularFont = new Font("Arial", baseFontSizePoints);
Font barcodeTextFont = new Font("Arial", baseFontSizePoints - 1);
try
{
// --- Рисуем Название ---
string productName = _currentProductName ?? "N/A";
SizeF titleSize = g.MeasureString(productName, titleFont, (int)drawableWidth);
// Ограничиваем высоту, чтобы поместилось остальное
float maxTitleHeight = drawableHeight * 0.3f;
float actualTitleHeight = Math.Min(titleSize.Height, maxTitleHeight);
g.DrawString(productName, titleFont, Brushes.Black, new RectangleF(drawableX, currentY, drawableWidth, actualTitleHeight));
currentY += actualTitleHeight + (2 * g.DpiY / 72f); // Отступ 2 пункта
// --- Рисуем Артикул ---
string skuText = $"Артикул: {_currentSku ?? "N/A"}";
SizeF skuSize = g.MeasureString(skuText, regularFont, (int)drawableWidth);
if (currentY + skuSize.Height < printArea.Bottom - marginY - 15 * 100f / g.DpiY) // Оставляем ~15px под ШК + текст
{
g.DrawString(skuText, regularFont, Brushes.Black, drawableX, currentY);
currentY += skuSize.Height + (3 * g.DpiY / 72f); // Отступ 3 пункта
}
// --- Рисуем Штрихкод ---
float remainingHeight = (printArea.Bottom - marginY) - currentY; // Оставшаяся высота
if (remainingHeight > 15 * 100f / g.DpiY) // Если осталось хотя бы ~15px
{
try
{
// --- Расчет размеров ШК ---
float barcodeTextHeight = g.MeasureString(_currentBarcode, barcodeTextFont).Height;
float barcodePrintHeight = Math.Max(10 * 100f / g.DpiY, remainingHeight - barcodeTextHeight - (2 * g.DpiY / 72f)); // Вычитаем текст и отступ
float barcodePrintWidth = drawableWidth * 0.98f;
int barcodePixelHeight = (int)(barcodePrintHeight * g.DpiY / 100f);
int barcodePixelWidth = (int)(barcodePrintWidth * g.DpiX / 100f);
if (barcodePixelHeight < 10 || barcodePixelWidth < 40) throw new Exception("Слишком мало места для ШК.");
BarcodeFormat barcodeFormat = BarcodeFormat.CODE_128;
// ... (определение barcodeFormat) ...
if (_currentBarcode.Length == 13 && long.TryParse(_currentBarcode, out _)) barcodeFormat = BarcodeFormat.EAN_13;
else if (_currentBarcode.Length == 8 && long.TryParse(_currentBarcode, out _)) barcodeFormat = BarcodeFormat.EAN_8;
var barcodeWriter = new ZXing.Windows.Compatibility.BarcodeWriter { Format = barcodeFormat, Options = new EncodingOptions { Height = barcodePixelHeight, Width = barcodePixelWidth, PureBarcode = true, Margin = 1 } };
using (var barcodeBitmap = barcodeWriter.Write(_currentBarcode))
{
float barcodeX = drawableX + (drawableWidth - barcodePrintWidth) / 2.0f; // Центрируем
g.DrawImage(barcodeBitmap, barcodeX, currentY, barcodePrintWidth, barcodePrintHeight);
currentY += barcodePrintHeight + (1 * g.DpiY / 72f); // Отступ 1 пункт
}
// --- Рисуем текст ШК ---
SizeF barcodeTextSize = g.MeasureString(_currentBarcode, barcodeTextFont);
if (currentY + barcodeTextSize.Height <= printArea.Bottom - marginY)
{
float textX = drawableX + (drawableWidth - barcodeTextSize.Width) / 2.0f; // Центрируем
g.DrawString(_currentBarcode, barcodeTextFont, Brushes.Black, textX, currentY);
}
else { System.Diagnostics.Debug.WriteLine("SKIPPING Barcode text - no space"); }
}
catch (Exception exBarcode)
{
System.Diagnostics.Debug.WriteLine($"Error drawing barcode: {exBarcode.Message}");
g.DrawString("Ошибка ШК", regularFont, Brushes.Red, drawableX, currentY); // Рисуем ошибку вместо ШК
}
}
else { System.Diagnostics.Debug.WriteLine("SKIPPING Barcode - not enough vertical space"); }
}
catch (Exception exDraw) { System.Diagnostics.Debug.WriteLine($"Error drawing page: {exDraw}"); }
finally { titleFont.Dispose(); regularFont.Dispose(); barcodeTextFont.Dispose(); }
e.HasMorePages = false;
}
} // Конец класса Form1
} // Конец namespace

120
Form1.resx Normal file
View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

201
FormManageStores.Designer.cs generated Normal file
View File

@ -0,0 +1,201 @@
namespace SKLADm
{
partial class FormManageStores
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.lstStores = new System.Windows.Forms.ListBox();
this.label1 = new System.Windows.Forms.Label();
this.groupBox1 = new System.Windows.Forms.GroupBox();
this.btnAddStore = new System.Windows.Forms.Button();
this.txtEditApiKey = new System.Windows.Forms.TextBox();
this.label4 = new System.Windows.Forms.Label();
this.txtEditClientId = new System.Windows.Forms.TextBox();
this.label3 = new System.Windows.Forms.Label();
this.txtStoreName = new System.Windows.Forms.TextBox();
this.label2 = new System.Windows.Forms.Label();
this.btnDeleteStore = new System.Windows.Forms.Button();
this.btnClose = new System.Windows.Forms.Button();
this.groupBox1.SuspendLayout();
this.SuspendLayout();
//
// lstStores
//
this.lstStores.FormattingEnabled = true;
this.lstStores.Location = new System.Drawing.Point(12, 25);
this.lstStores.Name = "lstStores";
this.lstStores.Size = new System.Drawing.Size(188, 199); // Adjust height as needed
this.lstStores.TabIndex = 0;
// Add event handler if you want to display details on selection:
// this.lstStores.SelectedIndexChanged += new System.EventHandler(this.lstStores_SelectedIndexChanged);
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(12, 9);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(121, 13);
this.label1.TabIndex = 1;
this.label1.Text = "Сохраненные магазины:";
//
// groupBox1
//
this.groupBox1.Controls.Add(this.btnAddStore);
this.groupBox1.Controls.Add(this.txtEditApiKey);
this.groupBox1.Controls.Add(this.label4);
this.groupBox1.Controls.Add(this.txtEditClientId);
this.groupBox1.Controls.Add(this.label3);
this.groupBox1.Controls.Add(this.txtStoreName);
this.groupBox1.Controls.Add(this.label2);
this.groupBox1.Location = new System.Drawing.Point(219, 25);
this.groupBox1.Name = "groupBox1";
this.groupBox1.Size = new System.Drawing.Size(303, 155); // Adjust size as needed
this.groupBox1.TabIndex = 2;
this.groupBox1.TabStop = false;
this.groupBox1.Text = "Добавить новый магазин";
//
// btnAddStore
//
this.btnAddStore.Location = new System.Drawing.Point(196, 118);
this.btnAddStore.Name = "btnAddStore";
this.btnAddStore.Size = new System.Drawing.Size(97, 23);
this.btnAddStore.TabIndex = 6;
this.btnAddStore.Text = "Добавить";
this.btnAddStore.UseVisualStyleBackColor = true;
this.btnAddStore.Click += new System.EventHandler(this.btnAddStore_Click);
//
// txtEditApiKey
//
this.txtEditApiKey.Location = new System.Drawing.Point(74, 86);
this.txtEditApiKey.Name = "txtEditApiKey";
this.txtEditApiKey.PasswordChar = '*';
this.txtEditApiKey.Size = new System.Drawing.Size(219, 20);
this.txtEditApiKey.TabIndex = 5;
//
// label4
//
this.label4.AutoSize = true;
this.label4.Location = new System.Drawing.Point(16, 89);
this.label4.Name = "label4";
this.label4.Size = new System.Drawing.Size(48, 13);
this.label4.TabIndex = 4;
this.label4.Text = "Api-Key:";
//
// txtEditClientId
//
this.txtEditClientId.Location = new System.Drawing.Point(74, 57);
this.txtEditClientId.Name = "txtEditClientId";
this.txtEditClientId.Size = new System.Drawing.Size(219, 20);
this.txtEditClientId.TabIndex = 3;
//
// label3
//
this.label3.AutoSize = true;
this.label3.Location = new System.Drawing.Point(16, 60);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(50, 13);
this.label3.TabIndex = 2;
this.label3.Text = "Client ID:";
//
// txtStoreName
//
this.txtStoreName.Location = new System.Drawing.Point(74, 28);
this.txtStoreName.Name = "txtStoreName";
this.txtStoreName.Size = new System.Drawing.Size(219, 20);
this.txtStoreName.TabIndex = 1;
//
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(16, 31);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(60, 13);
this.label2.TabIndex = 0;
this.label2.Text = "Название:";
//
// btnDeleteStore
//
this.btnDeleteStore.Location = new System.Drawing.Point(12, 230); // Position below listbox
this.btnDeleteStore.Name = "btnDeleteStore";
this.btnDeleteStore.Size = new System.Drawing.Size(188, 23);
this.btnDeleteStore.TabIndex = 3;
this.btnDeleteStore.Text = "Удалить выбранный";
this.btnDeleteStore.UseVisualStyleBackColor = true;
this.btnDeleteStore.Click += new System.EventHandler(this.btnDeleteStore_Click);
//
// btnClose
//
this.btnClose.DialogResult = System.Windows.Forms.DialogResult.Cancel; // Makes Esc close the form
this.btnClose.Location = new System.Drawing.Point(447, 230); // Position bottom right
this.btnClose.Name = "btnClose";
this.btnClose.Size = new System.Drawing.Size(75, 23);
this.btnClose.TabIndex = 4;
this.btnClose.Text = "Закрыть";
this.btnClose.UseVisualStyleBackColor = true;
this.btnClose.Click += new System.EventHandler(this.btnClose_Click);
//
// FormManageStores
//
this.AcceptButton = this.btnAddStore; // Enter in groupbox adds store
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.CancelButton = this.btnClose; // Esc closes form
this.ClientSize = new System.Drawing.Size(534, 267); // Adjust size as needed
this.Controls.Add(this.btnClose);
this.Controls.Add(this.btnDeleteStore);
this.Controls.Add(this.groupBox1);
this.Controls.Add(this.label1);
this.Controls.Add(this.lstStores);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; // Prevent resizing
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "FormManageStores";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; // Center over Form1
this.Text = "Управление магазинами Ozon";
this.groupBox1.ResumeLayout(false);
this.groupBox1.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.ListBox lstStores;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.GroupBox groupBox1;
private System.Windows.Forms.Button btnAddStore;
private System.Windows.Forms.TextBox txtEditApiKey;
private System.Windows.Forms.Label label4;
private System.Windows.Forms.TextBox txtEditClientId;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.TextBox txtStoreName;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Button btnDeleteStore;
private System.Windows.Forms.Button btnClose;
}
}

150
FormManageStores.cs Normal file
View File

@ -0,0 +1,150 @@
using Newtonsoft.Json;
using OzonInternalLabelPrinter; // Добавляем пространство имен для OzonStore
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography; // Для ProtectedData
using System.Text;
using System.Windows.Forms;
namespace SKLADm
{
public partial class FormManageStores : Form
{
private List<OzonStore> _stores;
// Энтропия для шифрования (можно оставить null или использовать свой секрет)
private static readonly byte[] s_entropy = null; // Или Encoding.UTF8.GetBytes("MyOptionalEntropy");
public FormManageStores()
{
InitializeComponent();
LoadStoresToListBox();
}
// --- Шифрование Api-Key ---
private string EncryptApiKey(string apiKey)
{
if (string.IsNullOrEmpty(apiKey)) return string.Empty;
try
{
byte[] apiKeyBytes = Encoding.UTF8.GetBytes(apiKey);
byte[] encryptedBytes = ProtectedData.Protect(apiKeyBytes, s_entropy, DataProtectionScope.CurrentUser);
return Convert.ToBase64String(encryptedBytes);
}
catch (Exception ex)
{
MessageBox.Show($"Ошибка шифрования ключа: {ex.Message}", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
return null; // Возвращаем null при ошибке
}
}
// --- Загрузка магазинов из настроек ---
private void LoadStoresToListBox()
{
string json = Properties.Settings.Default.SavedStoresJson;
_stores = new List<OzonStore>();
if (!string.IsNullOrEmpty(json))
{
try
{
_stores = JsonConvert.DeserializeObject<List<OzonStore>>(json) ?? new List<OzonStore>();
}
catch (Exception ex)
{
MessageBox.Show($"Ошибка загрузки списка магазинов: {ex.Message}", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Warning);
_stores = new List<OzonStore>(); // Создаем пустой список при ошибке
}
}
UpdateListBox();
}
// --- Сохранение магазинов в настройки ---
private void SaveStores()
{
try
{
string json = JsonConvert.SerializeObject(_stores, Formatting.Indented);
Properties.Settings.Default.SavedStoresJson = json;
Properties.Settings.Default.Save();
}
catch (Exception ex)
{
MessageBox.Show($"Ошибка сохранения списка магазинов: {ex.Message}", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
// --- Обновление ListBox ---
private void UpdateListBox()
{
lstStores.DataSource = null; // Сначала отвязываем источник
lstStores.DataSource = _stores; // Привязываем обновленный список
lstStores.DisplayMember = "StoreName"; // Отображаем имя
}
// --- Кнопка "Добавить магазин" ---
private void btnAddStore_Click(object sender, EventArgs e)
{
string storeName = txtStoreName.Text.Trim();
string clientId = txtEditClientId.Text.Trim();
string apiKey = txtEditApiKey.Text.Trim(); // Берем ключ как есть
if (string.IsNullOrEmpty(storeName) || string.IsNullOrEmpty(clientId) || string.IsNullOrEmpty(apiKey))
{
MessageBox.Show("Пожалуйста, заполните все поля: Название, Client ID, Api-Key.", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return;
}
// Проверяем, нет ли уже магазина с таким именем
if (_stores.Any(s => s.StoreName.Equals(storeName, StringComparison.OrdinalIgnoreCase)))
{
MessageBox.Show("Магазин с таким названием уже существует.", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return;
}
// Шифруем ключ
string encryptedKey = EncryptApiKey(apiKey);
if (encryptedKey == null) // Если шифрование не удалось
{
return;
}
// Создаем и добавляем магазин
OzonStore newStore = new OzonStore(storeName, clientId, encryptedKey);
_stores.Add(newStore);
// Сохраняем и обновляем список
SaveStores();
UpdateListBox();
// Очищаем поля ввода
txtStoreName.Clear();
txtEditClientId.Clear();
txtEditApiKey.Clear();
}
// --- Кнопка "Удалить выбранный" (Опционально) ---
private void btnDeleteStore_Click(object sender, EventArgs e)
{
if (lstStores.SelectedItem is OzonStore selectedStore)
{
if (MessageBox.Show($"Вы уверены, что хотите удалить магазин '{selectedStore.StoreName}'?", "Подтверждение", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
{
_stores.Remove(selectedStore);
SaveStores();
UpdateListBox();
}
}
else
{
MessageBox.Show("Выберите магазин для удаления.", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
// --- Кнопка "Закрыть" ---
private void btnClose_Click(object sender, EventArgs e)
{
this.DialogResult = DialogResult.OK; // Указываем, что форма закрыта штатно
this.Close();
}
}
}

120
FormManageStores.resx Normal file
View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

28
OzonStore.cs Normal file
View File

@ -0,0 +1,28 @@
using System;
namespace OzonInternalLabelPrinter
{
[Serializable] // Важно для возможной сериализации в будущем, хотя с JSON необязательно
public class OzonStore
{
public string StoreName { get; set; } // Имя, которое видит пользователь
public string ClientId { get; set; }
public string EncryptedApiKey { get; set; } // Храним ЗАШИФРОВАННЫЙ ключ
// Конструктор для удобства
public OzonStore(string name, string clientId, string encryptedKey)
{
StoreName = name;
ClientId = clientId;
EncryptedApiKey = encryptedKey;
}
public OzonStore() { } // Пустой конструктор для сериализации
// Переопределяем ToString, чтобы в ComboBox отображалось имя
public override string ToString()
{
return StoreName ?? "Без имени";
}
}
}

23
Program.cs Normal file
View File

@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
using OzonInternalLabelPrinter; // Добавляем директиву using для пространства имен с Form1
namespace SKLADm
{
internal static class Program
{
/// <summary>
/// Главная точка входа для приложения.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
}

View File

@ -0,0 +1,33 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// Общие сведения об этой сборке предоставляются следующим набором
// набора атрибутов. Измените значения этих атрибутов для изменения сведений,
// связанных со сборкой.
[assembly: AssemblyTitle("SKLADm")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("SKLADm")]
[assembly: AssemblyCopyright("Copyright © 2025")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Установка значения False для параметра ComVisible делает типы в этой сборке невидимыми
// для компонентов COM. Если необходимо обратиться к типу в этой сборке через
// COM, следует установить атрибут ComVisible в TRUE для этого типа.
[assembly: ComVisible(false)]
// Следующий GUID служит для идентификации библиотеки типов, если этот проект будет видимым для COM
[assembly: Guid("17f6818e-f645-43c4-a25a-eab41e5e1be6")]
// Сведения о версии сборки состоят из указанных ниже четырех значений:
//
// Основной номер версии
// Дополнительный номер версии
// Номер сборки
// Редакция
//
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

71
Properties/Resources.Designer.cs generated Normal file
View File

@ -0,0 +1,71 @@
//------------------------------------------------------------------------------
// <auto-generated>
// Этот код создан программным средством.
// Версия среды выполнения: 4.0.30319.42000
//
// Изменения в этом файле могут привести к неправильному поведению и будут утрачены, если
// код создан повторно.
// </auto-generated>
//------------------------------------------------------------------------------
namespace SKLADm.Properties
{
/// <summary>
/// Класс ресурсов со строгим типом для поиска локализованных строк и пр.
/// </summary>
// Этот класс был автоматически создан при помощи StronglyTypedResourceBuilder
// класс с помощью таких средств, как ResGen или Visual Studio.
// Для добавления или удаления члена измените файл .ResX, а затем перезапустите ResGen
// с параметром /str или заново постройте свой VS-проект.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources
{
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources()
{
}
/// <summary>
/// Возврат кэшированного экземпляра ResourceManager, используемого этим классом.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager
{
get
{
if ((resourceMan == null))
{
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SKLADm.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Переопределяет свойство CurrentUICulture текущего потока для всех
/// подстановки ресурсов с помощью этого класса ресурсов со строгим типом.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture
{
get
{
return resourceCulture;
}
set
{
resourceCulture = value;
}
}
}
}

117
Properties/Resources.resx Normal file
View File

@ -0,0 +1,117 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

38
Properties/Settings.Designer.cs generated Normal file
View File

@ -0,0 +1,38 @@
//------------------------------------------------------------------------------
// <auto-generated>
// Этот код создан программой.
// Исполняемая версия:4.0.30319.42000
//
// Изменения в этом файле могут привести к неправильной работе и будут потеряны в случае
// повторной генерации кода.
// </auto-generated>
//------------------------------------------------------------------------------
namespace SKLADm.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.13.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default {
get {
return defaultInstance;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("")]
public string SavedStoresJson {
get {
return ((string)(this["SavedStoresJson"]));
}
set {
this["SavedStoresJson"] = value;
}
}
}
}

View File

@ -0,0 +1,9 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" GeneratedClassNamespace="SKLADm.Properties" GeneratedClassName="Settings">
<Profiles />
<Settings>
<Setting Name="SavedStoresJson" Type="System.String" Scope="User">
<Value Profile="(Default)" />
</Setting>
</Settings>
</SettingsFile>

122
SKLADm.csproj Normal file
View File

@ -0,0 +1,122 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{17F6818E-F645-43C4-A25A-EAB41E5E1BE6}</ProjectGuid>
<OutputType>WinExe</OutputType>
<RootNamespace>SKLADm</RootNamespace>
<AssemblyName>SKLADm</AssemblyName>
<TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<Deterministic>true</Deterministic>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Drawing.Common, Version=8.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>packages\System.Drawing.Common.8.0.12\lib\net462\System.Drawing.Common.dll</HintPath>
</Reference>
<Reference Include="System.Security" />
<Reference Include="System.Security.Cryptography.ProtectedData, Version=9.0.0.4, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\System.Security.Cryptography.ProtectedData.9.0.4\lib\net462\System.Security.Cryptography.ProtectedData.dll</HintPath>
</Reference>
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Deployment" />
<Reference Include="System.Drawing" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
<Reference Include="zxing, Version=0.16.10.0, Culture=neutral, PublicKeyToken=4e88037ac681fe60, processorArchitecture=MSIL">
<HintPath>packages\ZXing.Net.0.16.10\lib\net461\zxing.dll</HintPath>
</Reference>
<Reference Include="zxing.presentation, Version=0.16.10.0, Culture=neutral, PublicKeyToken=4e88037ac681fe60, processorArchitecture=MSIL">
<HintPath>packages\ZXing.Net.0.16.10\lib\net461\zxing.presentation.dll</HintPath>
</Reference>
<Reference Include="ZXing.Windows.Compatibility, Version=0.16.13.0, Culture=neutral, PublicKeyToken=4e88037ac681fe60, processorArchitecture=MSIL">
<HintPath>packages\ZXing.Net.Bindings.Windows.Compatibility.0.16.13\lib\netstandard2.0\ZXing.Windows.Compatibility.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="Form1.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Form1.Designer.cs">
<DependentUpon>Form1.cs</DependentUpon>
</Compile>
<Compile Include="FormManageStores.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="FormManageStores.Designer.cs">
<DependentUpon>FormManageStores.cs</DependentUpon>
</Compile>
<Compile Include="OzonStore.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<EmbeddedResource Include="Form1.resx">
<DependentUpon>Form1.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="FormManageStores.resx">
<DependentUpon>FormManageStores.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</EmbeddedResource>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<None Include="packages.config" />
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="packages\NETStandard.Library.2.0.3\build\netstandard2.0\NETStandard.Library.targets" Condition="Exists('packages\NETStandard.Library.2.0.3\build\netstandard2.0\NETStandard.Library.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>Данный проект ссылается на пакеты NuGet, отсутствующие на этом компьютере. Используйте восстановление пакетов NuGet, чтобы скачать их. Дополнительную информацию см. по адресу: http://go.microsoft.com/fwlink/?LinkID=322105. Отсутствует следующий файл: {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('packages\NETStandard.Library.2.0.3\build\netstandard2.0\NETStandard.Library.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\NETStandard.Library.2.0.3\build\netstandard2.0\NETStandard.Library.targets'))" />
</Target>
</Project>

25
SKLADm.sln Normal file
View File

@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.13.35913.81 d17.13
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SKLADm", "SKLADm.csproj", "{17F6818E-F645-43C4-A25A-EAB41E5E1BE6}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{17F6818E-F645-43C4-A25A-EAB41E5E1BE6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{17F6818E-F645-43C4-A25A-EAB41E5E1BE6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{17F6818E-F645-43C4-A25A-EAB41E5E1BE6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{17F6818E-F645-43C4-A25A-EAB41E5E1BE6}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {58FC063D-E3B8-421B-BCB0-0349A0C4DCDB}
EndGlobalSection
EndGlobal

10
packages.config Normal file
View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.NETCore.Platforms" version="1.1.0" targetFramework="net462" />
<package id="NETStandard.Library" version="2.0.3" targetFramework="net462" />
<package id="Newtonsoft.Json" version="13.0.3" targetFramework="net462" />
<package id="System.Drawing.Common" version="8.0.12" targetFramework="net462" />
<package id="System.Security.Cryptography.ProtectedData" version="9.0.4" targetFramework="net462" />
<package id="ZXing.Net" version="0.16.10" targetFramework="net462" />
<package id="ZXing.Net.Bindings.Windows.Compatibility" version="0.16.13" targetFramework="net462" />
</packages>