Продолжаем работать со временем.
В прошлом примере, был получен список 'lstTemp' с временем.
Список выглядит так:
23 часов 58 минут,
23 часов 53 минут,
19 часов 9 минут,
23 часов 57 минут,
и т.д.
Наша цель преобразовать время, которое сейчас является типом данных "string" в тип данных "DateTime".
В C# существуют 2 метода(самые популярные), которые пытаются конвертировать "string" => "DateTime". Рассмотрим их более подробно.
1. DateTime.ParseExact(string s, string format, IFormatProvider? provider) - этот метод в качестве аргументов, кроме строки с датой, принимает еще строку в которой указан формат представления даты, а так же строку с указанием культуры, в которой принято такое представление.
Пример:
Пример:
Поэтому будет разбивать на определённые этапы:
1. Создаёт список с типом данных 'DateTime':
3. Конвертируем и сохраняем полученное время в ранее созданный список 'listTimeTemp':
#Csharp, #Дата
В прошлом примере, был получен список 'lstTemp' с временем.
Список выглядит так:
23 часов 58 минут,
23 часов 53 минут,
19 часов 9 минут,
23 часов 57 минут,
и т.д.
Наша цель преобразовать время, которое сейчас является типом данных "string" в тип данных "DateTime".
В C# существуют 2 метода(самые популярные), которые пытаются конвертировать "string" => "DateTime". Рассмотрим их более подробно.
1. DateTime.ParseExact(string s, string format, IFormatProvider? provider) - этот метод в качестве аргументов, кроме строки с датой, принимает еще строку в которой указан формат представления даты, а так же строку с указанием культуры, в которой принято такое представление.
Пример:
string time = "2021 Четверг октябрь 28 16:01";
System.Globalization.CultureInfo culture = System.Globalization.CultureInfo.CreateSpecificCulture("ru-RU");
DateTime dt = DateTime.ParseExact(time, "yyyy dddd MMMM dd HH:mm", culture);
Результат: 23.06.2020 14:35:00
2.DateTime.Parse(string s) - этот метод в качестве аргумента принимает строку с датой.Пример:
string time = "23:58";
DateTime dt = = DateTime.Parse(time);
Результат: 28.10.2021 23:58:00
Методы существуют, но в нашем случае они не подходят т.к. не смогут распознать формат такого времени: "23 часов 58 минут".Поэтому будет разбивать на определённые этапы:
1. Создаёт список с типом данных 'DateTime':
var listTimeTemp = new List<DateTime>();
2. Подготовим время в нормальный формат с помощью регулярного выражения, который поймёт метод: DateTime.Parse(string s):tmpData = Regex.Replace(tmpData, @"ча.*?\s", ":");
tmpData = Regex.Replace(tmpData, @"мин.*", "");
после чистки, время уже будет иметь вот такой формат: "23:58"3. Конвертируем и сохраняем полученное время в ранее созданный список 'listTimeTemp':
listTimeTemp.Add(DateTime.Parse(tmpData));
4. Сортируем полученное время в порядке возрастания с помощью 'Linq':listTimeTemp.Sort((a, b) => a.CompareTo(b));
5. Создаёт список с типом данных 'double':var totalMinutes = new List<double>();
6. Создаём цикл для списка 'listTimeTemp'( для того, чтобы получить минуты из часов и минуты из минут, соответственно. Формат времени из которого берутся эти данные:'28.10.2021 23:58:00'(пример)): foreach (var hours in listTimeTemp)
{
int minutesFromHours = hours.Hour * 60;
int minutesFromMinutes = hours.Minute;
totalMinutes.Add(minutesFromHours + minutesFromMinutes);
}
7. Получаем среднюю сумму значения всех полученных минут из списка 'totalMinutes'.var sum = totalMinutes.Sum() / listTimeTemp.Count;
8. Создаём объект 'TimeSpan', для того, чтобы из средней суммы, которую получили выше, получить часы и минуты:TimeSpan ts = TimeSpan.FromMinutes(sum);
int midHours = ts.Hours;
int midMinutes = ts.Minutes;
9. Пример результата:string res = ts.Hours.Tostring() + ":" + ts.Minutes.Tostring();
"22:52" - наше полученное искомое среднее время.
10. Пример всего кода:var tmpData = string.Empty;
var listTimeTemp = new List<DateTime>();
for (x = 0; x < lstTemp.Count; x++)
{
tmpData = lstTemp[x].Trim();
tmpData = Regex.Replace(tmpData, @"ча.*?\s", ":");
tmpData = Regex.Replace(tmpData, @"мин.*", "");
listTimeTemp.Add(DateTime.Parse(tmpData));
}
listTimeTemp.Sort((a, b) => a.CompareTo(b));
var totalMinutes = new List<double>();
foreach (var hours in listTimeTemp)
{
int minutesFromHours = hours.Hour * 60;
int minutesFromMinutes = hours.Minute;
totalMinutes.Add(minutesFromHours +
minutesFromMinutes);
}
var sum = totalMinutes.Sum() / listTimeTemp.Count;
TimeSpan ts = TimeSpan.FromMinutes(sum);
int midHours = ts.Hours;
int midMinutes = ts.Minutes;
string res = ts.Hours.Tostring() + ":" + ts.Minutes.Tostring();
В этом примере рассмотрел те вещи, которые можно делать используя 'DateTime' и 'TimeSpan'.#Csharp, #Дата
Сегодня буду говорить о База Данных и СУБД, в дальнейшем буду рассматривать конкретные примеры.
Для меня База Данных - это то место, где хранятся необходимые сведения, которые необходимо использовать в проектах(делаю то разделение, которое использую в своей специализации).
Это могут быть:
1. Текстовые файлы - просто огромное кол-во проектов и заказчиков, обожают хранить информацию в *.txt файлах.
2. Excel таблицы - различные форматы таблиц, самые популярные: csv, xls,xlsx и т.д.
3. Json - это подвид текстового формата с расширением *json, он очень удобен из-за своей структуры. При работе с сайтами, этот формат очень популярен. К примеру многие сайты, которые имеют API - выводят информацию в этом формате.
4. Xml - ещё один формат напоминающий json, но есть отличия и очень серьёзные, имеет расширение *.xml. Очень часто используются при загрузки на сайты, каких либо товаров, продуктов, также используются сайтами недвижимости(Yandex,Cian,Avito и др.)
5. MySQL - система управления базами данных. В современном мире без элементарного понимания работы с MySql, могут начаться большие трудности. Многие скрипты, проекты, веб-приложения используют эту систему. Один жирный минус - для неё нужен сервер.
6. SQLite - компактная встраиваемая система управления базами данных. Очень удобно её использовать т.к. не требует "лишних телодвижений". Создал файл(к примеру: *.db), в нём таблицу и подключился к ней, просто указав путь, "красота".
7. Microsoft SQL Server - парадоксально, но не смотря на то, что мною проекты созданы в основном на C#, эту СУБД использую крайне редко т.к. многим надо "выход в мир" и быть более свободными и не зависеть от привязки к Windows. Хотя эта СУБД, также очень популярна.
8. Firebase.google.com - это облачный сервис, в котором также можно создать свою Б.Д. В чём её преимущество: просто подключиться, доступность из любой точки мира, бесплатно(платный вариант также есть, но в основном он не нужен), в какой-то степени замена MySQL(но, очень условно т.к. есть отличия при работе с ней).
Перечислил то, что использую в своих проектах в 90% случаях. Понятно, что это только часть из того, что есть, но этого вполне мне хватает.
Много из всего этого, я буду рассматривать с своих примерах т.к. работа с ними имеет свой подход.
Для меня База Данных - это то место, где хранятся необходимые сведения, которые необходимо использовать в проектах(делаю то разделение, которое использую в своей специализации).
Это могут быть:
1. Текстовые файлы - просто огромное кол-во проектов и заказчиков, обожают хранить информацию в *.txt файлах.
2. Excel таблицы - различные форматы таблиц, самые популярные: csv, xls,xlsx и т.д.
3. Json - это подвид текстового формата с расширением *json, он очень удобен из-за своей структуры. При работе с сайтами, этот формат очень популярен. К примеру многие сайты, которые имеют API - выводят информацию в этом формате.
4. Xml - ещё один формат напоминающий json, но есть отличия и очень серьёзные, имеет расширение *.xml. Очень часто используются при загрузки на сайты, каких либо товаров, продуктов, также используются сайтами недвижимости(Yandex,Cian,Avito и др.)
5. MySQL - система управления базами данных. В современном мире без элементарного понимания работы с MySql, могут начаться большие трудности. Многие скрипты, проекты, веб-приложения используют эту систему. Один жирный минус - для неё нужен сервер.
6. SQLite - компактная встраиваемая система управления базами данных. Очень удобно её использовать т.к. не требует "лишних телодвижений". Создал файл(к примеру: *.db), в нём таблицу и подключился к ней, просто указав путь, "красота".
7. Microsoft SQL Server - парадоксально, но не смотря на то, что мною проекты созданы в основном на C#, эту СУБД использую крайне редко т.к. многим надо "выход в мир" и быть более свободными и не зависеть от привязки к Windows. Хотя эта СУБД, также очень популярна.
8. Firebase.google.com - это облачный сервис, в котором также можно создать свою Б.Д. В чём её преимущество: просто подключиться, доступность из любой точки мира, бесплатно(платный вариант также есть, но в основном он не нужен), в какой-то степени замена MySQL(но, очень условно т.к. есть отличия при работе с ней).
Перечислил то, что использую в своих проектах в 90% случаях. Понятно, что это только часть из того, что есть, но этого вполне мне хватает.
Много из всего этого, я буду рассматривать с своих примерах т.к. работа с ними имеет свой подход.
This media is not supported in your browser
VIEW IN TELEGRAM
Вот пример одного из скриптов, который помогает анализировать группы из ТГ и сокращает большое кол-во ручного труда.
Преимущества:
- Многопоточность.
- Работа с СУБД - SQLite(как писал выше, один файл, путь к Б.Д. и всё).
- Выборка групп(из сервиса и нашей Б.Д.), согласно критериям, которые были заданы в настройках программы.
- Сохранения данных в docs.google.com
- Подсчёт средней величины размещения рекламных постов в днях и по времени на площадке.
- Создание скриншотов, тех постов, которые принесли больше всего кол-во подписчиков, согласно выбранной тематике.
- Кол-во новых подписчиков(минимум, максимум, среднее) от тех рекламных постов, которые были размещены на площадке раньше.
- и др. фишки, которые помогают делать анализ площадки.
Недостатки:
- Плата за использования программного комплекса ZennoPoster.
- Плата за использование сервиса с которого берутся данные.
- Ограниченное кол-во потоков.
Часть вещей, которые реализовал в этом скрипте, буду описывать в дальнейших постах.
#ZennoPoster
Преимущества:
- Многопоточность.
- Работа с СУБД - SQLite(как писал выше, один файл, путь к Б.Д. и всё).
- Выборка групп(из сервиса и нашей Б.Д.), согласно критериям, которые были заданы в настройках программы.
- Сохранения данных в docs.google.com
- Подсчёт средней величины размещения рекламных постов в днях и по времени на площадке.
- Создание скриншотов, тех постов, которые принесли больше всего кол-во подписчиков, согласно выбранной тематике.
- Кол-во новых подписчиков(минимум, максимум, среднее) от тех рекламных постов, которые были размещены на площадке раньше.
- и др. фишки, которые помогают делать анализ площадки.
Недостатки:
- Плата за использования программного комплекса ZennoPoster.
- Плата за использование сервиса с которого берутся данные.
- Ограниченное кол-во потоков.
Часть вещей, которые реализовал в этом скрипте, буду описывать в дальнейших постах.
#ZennoPoster
В прошлых постах публиковал о тех СУБД(MySql в частности), которые использую в своей практике и тут-же подвернулся интересный пример, который показывает 'МОЩЬ' языка программирования Sql.
Похожий запрос в практике встречается в 99% случаях.
Цель:
Сделать запрос, который укажет кол-во звонков с определенных площадок.
Дано:
Две разных таблицы в одной Б.Д.
1. ads_phones (первая таблица)
2. ads_calls (вторая таблица)
Решение:
Интересные моменты, на которые стоит обратить внимание.
а) Запрос формирует одну общую таблицу из двух(нескольких), где оператор ON - условие для сравнения(т.е. "номера телефонов" в табл. должны совпадать).
б) Запрос делает выборку данных, за прошлый месяц.
в) Запрос делает группировку данных согласно минимальному кол-ву, которые нам интересны(т.е. > 1).
Рекомендую сохранить пример этого запроса т.к. "Узнавать Кол-во" чего либо, приходиться очень часто.
#Sql, #MySql
Похожий запрос в практике встречается в 99% случаях.
Цель:
Сделать запрос, который укажет кол-во звонков с определенных площадок.
Дано:
Две разных таблицы в одной Б.Д.
1. ads_phones (первая таблица)
2. ads_calls (вторая таблица)
Решение:
SELECT ads_phones.note, ads_phones.phone, COUNT(ads_calls.call_to) AS count_call FROM ads_phones INNER JOIN ads_calls ON ads_calls.call_to = ads_phones.phone AND MONTH(ads_calls.created) = MONTH(NOW() - INTERVAL 1 MONTH) GROUP BY ads_calls.call_to HAVING COUNT(ads_calls.call_to) > 1 ORDER BY count_call DESC
Интересные моменты, на которые стоит обратить внимание.
а) Запрос формирует одну общую таблицу из двух(нескольких), где оператор ON - условие для сравнения(т.е. "номера телефонов" в табл. должны совпадать).
INNER JOIN ads_calls ON ads_calls.call_to = ads_phones.phone
б) Запрос делает выборку данных, за прошлый месяц.
MONTH(ads_calls.created) = MONTH(NOW() - INTERVAL 1 MONTH)
в) Запрос делает группировку данных согласно минимальному кол-ву, которые нам интересны(т.е. > 1).
GROUP BY ads_calls.call_to HAVING COUNT(ads_calls.call_to) > 1
Рекомендую сохранить пример этого запроса т.к. "Узнавать Кол-во" чего либо, приходиться очень часто.
#Sql, #MySql
Хочу сделать опрос. Интересны ли вам статьи связанные с такой виртуальной системой как Proxmox. Это выгодно только в том случае, если есть окупаемость(аренда сервера).
Да - 2
👍👍 13%
Нет - 11
👍👍👍👍👍👍👍👍 69%
Без разницы - 3
👍👍👍 19%
👥 16 человек уже проголосовало.
Да - 2
👍👍 13%
Нет - 11
👍👍👍👍👍👍👍👍 69%
Без разницы - 3
👍👍👍 19%
👥 16 человек уже проголосовало.
Proxmox
Proxmox Server Solutions
Proxmox develops powerful and efficient open-source server solutions like the Proxmox VE platform, Proxmox Backup Server, and Proxmox Mail Gateway.
Необходимо передавать картинку Post/Get запросами. Подумав, а почему не передавать с помощью кодировки base64?
Пример: №1 (картинку в base64):
1. Путь к нашей картинке и переменную для нашей кодировки base64(тип данных string).
2. Создаём кодировку base64 из нашей картинки, как строку(тип данных string).
2.1. Рекомендую использовать оператор "using" - для того, чтобы правильно освобождать,сбрасывать,удалять неуправляемые ресурсы(аналог метода Dispose)
2.2. Получаем нашу картинку из файла.
{
2.3. Для чтения/записи данных в память, в виде массива, используя класс MemoryStream.
{
2.4. Сохраняем нашу картинку в экземпляр класса MemoryStream.
}
}
3. Полученную строку base64String, уже можем передавать, сохранять и делать с ней что угодно.
3.1. Сервис для просмотра полученной картинки из кодировки base64(тип данных string)
Продолжение следует....
#Csharp, #base64
Пример кодировки.
Пример: №1 (картинку в base64):
1. Путь к нашей картинке и переменную для нашей кодировки base64(тип данных string).
string pathFile = "D:\1_picture.jpeg";
string base64String = null;
2. Создаём кодировку base64 из нашей картинки, как строку(тип данных string).
2.1. Рекомендую использовать оператор "using" - для того, чтобы правильно освобождать,сбрасывать,удалять неуправляемые ресурсы(аналог метода Dispose)
2.2. Получаем нашу картинку из файла.
using (Image image = Image.FromFile(pathFile)
{
2.3. Для чтения/записи данных в память, в виде массива, используя класс MemoryStream.
using (MemoryStream m = new MemoryStream())
{
2.4. Сохраняем нашу картинку в экземпляр класса MemoryStream.
image.Save(m, image.RawFormat);
2.5. Получаем массив для дальнейшей конвертации.byte[] imageBytes = m.ToArray();
2.6. Получаем кодировку картинки в base64. base64String = Convert.ToBase64String(imageBytes);
}
}
3. Полученную строку base64String, уже можем передавать, сохранять и делать с ней что угодно.
3.1. Сервис для просмотра полученной картинки из кодировки base64(тип данных string)
Продолжение следует....
#Csharp, #base64
Пример кодировки.
В предыдущем примере рассмотрел случай кодирования картинку в base64.
Теперь рассмотрим обратный случай.
Пример: №2 (base64 в картинку):
1. Инициализируем новые переменные: путь к нашей картинке и кодировку base64.
2. Получаем массив из переменной base64StringNew.
3. Используем оператор "using"(рекомендую) для работы с картинкой.
3.1. Создаём картинку из полученного массива и сохраняем её, согласно нашего пути (pathFileNew).
Все эти случаи в практике используются довольно часто: сервисы для решения каптч, создание сайтов, работа с Б.Д.
Кодирование и декодирование в base64 - это очень полезная вещь.
#Csharp, #base64
Результаты кодирования и декодирования.
Теперь рассмотрим обратный случай.
Пример: №2 (base64 в картинку):
1. Инициализируем новые переменные: путь к нашей картинке и кодировку base64.
string pathFileNew = "D:\1_pictureCopy.jpeg";
string base64StringNew = base64String
(полученная кодировка base64 из пред. примера);2. Получаем массив из переменной base64StringNew.
byte[] imgBytes = Convert.FromBase64String(base64StringNew);
3. Используем оператор "using"(рекомендую) для работы с картинкой.
using (var imageFile = new FileStream(pathFileNew, FileMode.Create))
{
3.1. Создаём картинку из полученного массива и сохраняем её, согласно нашего пути (pathFileNew).
imageFile.Write(imgBytes, 0, imgBytes.Length);
imageFile.Flush();
}
Все эти случаи в практике используются довольно часто: сервисы для решения каптч, создание сайтов, работа с Б.Д.
Кодирование и декодирование в base64 - это очень полезная вещь.
#Csharp, #base64
Результаты кодирования и декодирования.
Как и обещал ранее, буду рассматривать некоторые примеры, которые были реализованы мною в этом скрипте (если будет интересна одноразовая услуга по сбору площадок, используя этот скрипт, пишите).
Очень часто при вёрстки макетов сайта, похожая информация находится в в одинаковых тегах(div,tr,td,span и т.д.), которые для удобства отображения находятся в отдельных классах. Для того, чтобы получить всю эту информацию, необходимо это учесть.
Поэтому в данном примере это учту и покажу xPath запрос, который помог справится с этим.
Работаю с программным комплексом ZennoPoster
1. Обращаемся к свойству('ActiveTab') объекта('instance') и передаём полученную информацию в класс('Tab') (более подробнее писал выше).
2. С помощью XPath запроса передаём найденные элементы в класс 'HtmlElementCollection'.
Интересный момент, на который стоит обратить внимание.
а) Тело самого запроса использует логический оператор "или (|)", это позволяет нам собирать информацию с одинаковых тегов, но у которых разное оформление( "class")
3. Основную информацию об элементах получил, дальше необходимо её обрабатывать.
#ZennoPoster, #Xpath
Очень часто при вёрстки макетов сайта, похожая информация находится в в одинаковых тегах(div,tr,td,span и т.д.), которые для удобства отображения находятся в отдельных классах. Для того, чтобы получить всю эту информацию, необходимо это учесть.
Поэтому в данном примере это учту и покажу xPath запрос, который помог справится с этим.
Работаю с программным комплексом ZennoPoster
1. Обращаемся к свойству('ActiveTab') объекта('instance') и передаём полученную информацию в класс('Tab') (более подробнее писал выше).
Tab tab = instance.ActiveTab;
2. С помощью XPath запроса передаём найденные элементы в класс 'HtmlElementCollection'.
HtmlElementCollection entries = tab.FindElementsByXPath("//tr[starts-with(@class,'tr_even')] | //tr[starts-with(@class,'tr_odd')]");
Интересный момент, на который стоит обратить внимание.
а) Тело самого запроса использует логический оператор "или (|)", это позволяет нам собирать информацию с одинаковых тегов, но у которых разное оформление( "class")
"//tr[starts-with(@class,'tr_even')] | //tr[starts-with(@class,'tr_odd')]"
3. Основную информацию об элементах получил, дальше необходимо её обрабатывать.
#ZennoPoster, #Xpath
Сегодня отойдём слегка от программирования и займёмся реестром Windows(и да, её также можно использовать как своеобразную Б.Д., где есть свои таблицы).
Очень часто возникает ситуация, когда есть у нас файл, который хотим использовать как "шаблон" для всех своих последующих проектов, чтобы он был под рукой.Поэтому, проще всего создавать его из "контекстного меню Windows".
Шаги, которые необходимо предпринять:
1. Переходим в директорию:
"C:\Windows\ShellNew" и сохраняем(копируем) необходимый файл, который будет нашим шаблоном.
2. Открываем "редактор реестра". Запустить его можно, нажатием клавиши "Windows + R", вбиваем "regedit" в окно "Выполнить" и нажать "Ок".
3. Переходим в раздел "HKEY_CLASSES_ROOT" и находим в нём другой раздел, название которого совпадает с расширением нашего файла(в данном случае .zp) и в ней должен быть след.-ий раздел "ShellNew" (если его нет, то необходимо создать).
4. В текущем разделе "ShellNew" - необходимо создать "Строковый параметр" со значением "STARTZENNOFILE.zp" (это мой пример шаблона, который создал ранее) и названием "FileName".
5. На этом всё, получаем удовольствия от создания новых проектов, используя готовый "Шаблон".
Также в дальнейшем планирую показать пару примеров, в которых показана работа с реестром, но как программист т.к. обычно там хранятся настройки программ.
#РеестрWindows
Очень часто возникает ситуация, когда есть у нас файл, который хотим использовать как "шаблон" для всех своих последующих проектов, чтобы он был под рукой.Поэтому, проще всего создавать его из "контекстного меню Windows".
Шаги, которые необходимо предпринять:
1. Переходим в директорию:
"C:\Windows\ShellNew" и сохраняем(копируем) необходимый файл, который будет нашим шаблоном.
2. Открываем "редактор реестра". Запустить его можно, нажатием клавиши "Windows + R", вбиваем "regedit" в окно "Выполнить" и нажать "Ок".
3. Переходим в раздел "HKEY_CLASSES_ROOT" и находим в нём другой раздел, название которого совпадает с расширением нашего файла(в данном случае .zp) и в ней должен быть след.-ий раздел "ShellNew" (если его нет, то необходимо создать).
4. В текущем разделе "ShellNew" - необходимо создать "Строковый параметр" со значением "STARTZENNOFILE.zp" (это мой пример шаблона, который создал ранее) и названием "FileName".
5. На этом всё, получаем удовольствия от создания новых проектов, используя готовый "Шаблон".
Также в дальнейшем планирую показать пару примеров, в которых показана работа с реестром, но как программист т.к. обычно там хранятся настройки программ.
#РеестрWindows
Продолжаю писать статьи связанные с созданием приложения используя WPF. Даю ссылку на свой прошлый пост, где касался слегка этой темы.
Планирую написать ряд статей по созданию приложения, которое отсылает текстовые сообщения в ТГ(телеграм), используя его API.
Почему? Потому что, написания приложений используя API ТГ в "тренде" и полагаю он ещё будет долгое время.
В этой части статьи покажу весь код XAML файла, который реализовал т.е. интерфейс самой программы.
Основной код:
В дальнейшем опишу, почему использовал эти блоки и некоторую логику самого приложения.
В результате создания приложения этот код будет корректироваться.
#WPF, #Csharp
Планирую написать ряд статей по созданию приложения, которое отсылает текстовые сообщения в ТГ(телеграм), используя его API.
Почему? Потому что, написания приложений используя API ТГ в "тренде" и полагаю он ещё будет долгое время.
В этой части статьи покажу весь код XAML файла, который реализовал т.е. интерфейс самой программы.
Основной код:
<Window x:Class="TelegramBot.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:TelegramBot"
mc:Ignorable="d"
Title="MainWindow" Height="150" Width="800">
<DockPanel LastChildFill="True">
<Menu DockPanel.Dock="Top">
<MenuItem Header="Данные">
<MenuItem Header="Сохранить"
Command=""/>
<Separator/>
<MenuItem Header="Выход"
Click="MenuItem_Click"/>
</MenuItem>
</Menu>
<ListView DockPanel.Dock="Left"
Background="MidnightBlue"
Width="140">
<TextBlock Text="Новое сообщение:" Foreground="White"/>
</ListView>
<StatusBar DockPanel.Dock="Bottom">
<StatusBar.ItemsPanel>
<ItemsPanelTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="100" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
</Grid>
</ItemsPanelTemplate>
</StatusBar.ItemsPanel>
<StatusBarItem>
<TextBlock Text="Статус:" />
</StatusBarItem>
<Separator Grid.Column="1" />
<StatusBarItem Grid.Column="2">
<TextBlock Text="Не отправлено" />
</StatusBarItem>
<Separator Grid.Column="3" />
<StatusBarItem Grid.Column="4">
<TextBlock Text="Кол-во знаков:" />
</StatusBarItem>
<Separator Grid.Column="5" />
<StatusBarItem Grid.Column="6">
<TextBlock Text="259" />
</StatusBarItem>
</StatusBar>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="5*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBox Grid.Column="0" AcceptsReturn="True" VerticalScrollBarVisibility="Auto"
HorizontalScrollBarVisibility="Auto"/>
<Button Grid.Column="1" x:Name="buttonSentMessage" Width="60" Height="30" Content="Нажать" Click="Button_Click" />
</Grid>
</DockPanel>
</Window>
В дальнейшем опишу, почему использовал эти блоки и некоторую логику самого приложения.
В результате создания приложения этот код будет корректироваться.
#WPF, #Csharp
Рассматриваю более детальнее код, который опубликовал в прошлой статье.
1. Это часть кода генерируется автоматически в которой объявляются пространства имён.
Мне интересна, в данном случае, вот эта строка, где указываем размеры формы приложения:
2. Контейнер DockPanel - его очень удобно использовать для создания стандартных интерфейсов.
Верхнюю и левую часть - можно использовать для меню.
Нижнюю часть - для отображение какой-то доп информации(чаще строка состояния, в сайтостроении называют также эту часть "подвал").
Правую часть - для отображения дополнительной части.
Центр - здесь находится основное содержание.
Свойство
3. Элемент управления Menu (выделяю его специально, т.к. в него входят другие элементы) - который расположен в верхней части нашей DockPanel панели.
3.1.
3.2. Свойство
3.3. Элемент
3.4. Событие
Продолжение следует....
#WPF, #Csharp
1. Это часть кода генерируется автоматически в которой объявляются пространства имён.
<Window x:Class="TelegramBot.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:TelegramBot"
mc:Ignorable="d"
Title="MainWindow" Height="150" Width="800">
Мне интересна, в данном случае, вот эта строка, где указываем размеры формы приложения:
" Title="MainWindow" Height="150" Width="800"
2. Контейнер DockPanel - его очень удобно использовать для создания стандартных интерфейсов.
Верхнюю и левую часть - можно использовать для меню.
Нижнюю часть - для отображение какой-то доп информации(чаще строка состояния, в сайтостроении называют также эту часть "подвал").
Правую часть - для отображения дополнительной части.
Центр - здесь находится основное содержание.
<DockPanel LastChildFill="True">
..................
..................
..................
</DockPanel>
Свойство
LastChildFill="True"
означает, что последний элемент(в нашем случае, это текстовое поле "TextBox" и кнопка "Button") заполняет всё оставшееся пространство. 3. Элемент управления Menu (выделяю его специально, т.к. в него входят другие элементы) - который расположен в верхней части нашей DockPanel панели.
<Menu DockPanel.Dock="Top">
<MenuItem Header="Данные">
<MenuItem Header="Сохранить"
Command=""/>
<Separator/>
<MenuItem Header="Выход"
Click="MenuItem_Click"/>
</MenuItem>
</Menu>
3.1.
<MenuItem Header="Данные">
- это название меню. Оно может состоять из нескольких т.е. :<MenuItem Header="Данные">
<MenuItem Header="Сохранить">
<MenuItem Header="Выход"">
3.2. Свойство
"Command"
используется для паттерна MVVM(Model-View-ViewModel). О нём буду говорить, в других постах, если будет необходимо.3.3. Элемент
<Separator/>
- это понятно, "разделитель". 3.4. Событие
Click="MenuItem_Click"
с присвоенным ему именем. Оно будет обрабатываться в коде.Продолжение следует....
#WPF, #Csharp
Продолжаю знакомить с WPF.
В предыдущем посте остановился на рассмотрении элемента управления "Menu".
В этом рассмотрю сразу несколько элементов управления(кратко) "ListView", "TextBlock", "StatusBar" и "Grid"
1. Часть кода, который буду рассматривать.
2. Элемент управления ListView(главный элемент в нашем интерфейсе), расположен в левой части интерфейса
2.1. Короткий пример(добавление "Заголовков " столбцов т.е. "Headers"):
2.2. Элемент управления TextBlock - служит для вывода текстовой информации и имеет свойство
3. Переходим к след. элементу управления StatusBar (главный элемент в нашем интерфейсе), располагается в нижней части интерфейса
Интересный момент: Многие элементы управления имеют ограничения в оформлении и для того, чтобы убрать их необходимо использовать другие элементы, которые будут вложены в текущие.
3.1. Обратимся к свойству ItemsPanel у элемента StatusBar т.е.
3.2. Далее обратимся к элементу ItemsPanelTemplate, который будет в какой-то степени отвечать за оформления нашего StatusBar.
Элемент ItemsPanelTemplate, необходимо будет использовать довольно часто при работе с WPF.
3.3. В ItemsPanelTemplate добавляем такой элемент управления, как Grid
Grid - ЭТО мощный и часто используемый контейнер, напоминающий обычную таблицу. Прошу запомнить это т.к. без него интерфейс напоминал "беспорядочность".
3.3.1. Элемент Grid имеет два интересных свойств:
а)
б)
На этом всё.
Продолжение следует.....
#WPF, #Csharp
В предыдущем посте остановился на рассмотрении элемента управления "Menu".
В этом рассмотрю сразу несколько элементов управления(кратко) "ListView", "TextBlock", "StatusBar" и "Grid"
1. Часть кода, который буду рассматривать.
<ListView DockPanel.Dock="Left"
Background="MidnightBlue"
Width="140">
<TextBlock Text="Новое сообщение:" Foreground="White"/>
</ListView>
<StatusBar DockPanel.Dock="Bottom">
<StatusBar.ItemsPanel>
<ItemsPanelTemplate>
<Grid>
<Grid.ColumnDefinitions>
..................
..................
..................
</Grid.ColumnDefinitions>
</Grid>
</ItemsPanelTemplate>
</StatusBar.ItemsPanel>
..................
..................
..................
</StatusBar>
2. Элемент управления ListView(главный элемент в нашем интерфейсе), расположен в левой части интерфейса
DockPanel.Dock="Left"
. Не смотря на то, что он унаследован от класса другого элемента ListBox, является более "продвинутым" т.к. ещё можно добавлять "заголовки столбцов" т.е. у него есть свойство "View", которое имеет свой элемент(объект) GridView, который позволяет создавать более сложную структуры таблицы(со своими названиями столбцов)2.1. Короткий пример(добавление "Заголовков " столбцов т.е. "Headers"):
<ListView.View>
<GridView>
<GridViewColumn>№</GridViewColumn>
<GridViewColumn>Кол-во штук</GridViewColumn>
<GridViewColumn>Цена</GridViewColumn>
</GridView>
</ListView.View>
2.2. Элемент управления TextBlock - служит для вывода текстовой информации и имеет свойство
Foreground="White".
В котором устанавливается цвет, переднего фона элемента, в нашем случае "цвет текста".3. Переходим к след. элементу управления StatusBar (главный элемент в нашем интерфейсе), располагается в нижней части интерфейса
DockPanel.Dock="Bottom".
Интересный момент: Многие элементы управления имеют ограничения в оформлении и для того, чтобы убрать их необходимо использовать другие элементы, которые будут вложены в текущие.
3.1. Обратимся к свойству ItemsPanel у элемента StatusBar т.е.
<StatusBar.ItemsPanel>
3.2. Далее обратимся к элементу ItemsPanelTemplate, который будет в какой-то степени отвечать за оформления нашего StatusBar.
Элемент ItemsPanelTemplate, необходимо будет использовать довольно часто при работе с WPF.
3.3. В ItemsPanelTemplate добавляем такой элемент управления, как Grid
Grid - ЭТО мощный и часто используемый контейнер, напоминающий обычную таблицу. Прошу запомнить это т.к. без него интерфейс напоминал "беспорядочность".
3.3.1. Элемент Grid имеет два интересных свойств:
а)
<Grid.ColumnDefinitions>
- для работы с размерами столбцов - шириной.б)
<Grid.RowDefinitions>
- для работы с размерами столбцов - высотой.На этом всё.
Продолжение следует.....
#WPF, #Csharp
Отойду от темы WPF, и покажу довольно "тривиальную задачу".
Работают два разных приложения:
Одно создаёт текстовый файл и записывает в него содержимое.
Второе читает это файл.
Проблема заключается в том, что первое приложение не успевает записывать в него информацию, как тут же второе его считывает, получая при этом ошибку "Файл пуст".
Решение для этой проблемы весьма простое:
1. Создаём метод "IsLockedFile" с возвращаемым типом данных bool.
2. Создаём конструкцию try...catch, для того чтобы словить исключение.
3. Добавляем оператор "using" - для того, чтобы правильно освобождать,сбрасывать,удалять неуправляемые ресурсы(аналог метода Dispose)
4. Обращаемся к классу "File" и его методу Open с его параметрами(где задаём enum или ещё называют перечисление: FileMode.Open, FileAccess.Read, FileShare.None) и создаем конструктор класса "FileStream".
5. Если файл успешно открылся и прочитался, то возвращаем false(закрывая при этом объект класса FileStream), если нет то true. И в том и в том случае выходим из метода IsLockedFile.
6. В коде вызываю этот метод передавая путь к файлу. Используя цикл "while" т.е. этот будет работать до тех пор, пока возвращает true.
Пример кода:
Очень удобное вещь, особенно если работаете также в многопоточном режиме. Советую это сохранить и использовать.
#Csharp, #File
Работают два разных приложения:
Одно создаёт текстовый файл и записывает в него содержимое.
Второе читает это файл.
Проблема заключается в том, что первое приложение не успевает записывать в него информацию, как тут же второе его считывает, получая при этом ошибку "Файл пуст".
Решение для этой проблемы весьма простое:
1. Создаём метод "IsLockedFile" с возвращаемым типом данных bool.
2. Создаём конструкцию try...catch, для того чтобы словить исключение.
3. Добавляем оператор "using" - для того, чтобы правильно освобождать,сбрасывать,удалять неуправляемые ресурсы(аналог метода Dispose)
4. Обращаемся к классу "File" и его методу Open с его параметрами(где задаём enum или ещё называют перечисление: FileMode.Open, FileAccess.Read, FileShare.None) и создаем конструктор класса "FileStream".
5. Если файл успешно открылся и прочитался, то возвращаем false(закрывая при этом объект класса FileStream), если нет то true. И в том и в том случае выходим из метода IsLockedFile.
6. В коде вызываю этот метод передавая путь к файлу. Используя цикл "while" т.е. этот будет работать до тех пор, пока возвращает true.
Пример кода:
string pathFile = "D:\Example.txt";
while (IsLockedFile(pathFile));
public bool IsLockedFile(string fileName)
{
try
{
using (FileStream fs = File.Open(fileName, FileMode.Open, FileAccess.Read, FileShare.None))
{
fs.Close();
return false;
}
}
catch (Exception ex)
{
return true;
}
return true;
}
Очень удобное вещь, особенно если работаете также в многопоточном режиме. Советую это сохранить и использовать.
#Csharp, #File
Продолжаю знакомство с WPF.
В прошлой статье остановился на рассмотрение такого элемента как Grid.
Одно из важных свойств этого элемента(и не только этого) ширина и высота.
Есть несколько вариантов установки размеров:
"Auto" - установка ширины элемента согласно его содержанию.
"100" - фиксированный размер.
"*" - пропорциональный размер(маленький лайфхак, хотите увеличить этот размер в 2 в 3 раза, просто сделайте запись таким образом "2*" или "3*" ).
Для того, чтобы необходимый элемент имел правильные очертания(в моём случае это элемент "Grid"), то рекомендуется комбинировать эти размеры по необходимости.
Завершаем знакомство с элементами ItemsPanelTemplate и StatusBar.ItemsPanel - которые отвечали за основное оформление(т.е. своего рода "заготовки") и перехожу к след.-му.
Здесь появляется новый элемент StatusBarItem. Если прошлые элементы StatusBar.ItemsPanel и ItemsPanelTemplate служили нам заготовкой(разметкой), то уже этот служит нам для заполнения нужной информацией.
Каждый элемент размещается в своей колонке, привязка к определенной колонке происходит таким образом: Grid.Column="1" , где "1" это номер нашей колонки. Таким образом добавив нужные элементы(TextBlock и Separator) и привязав их к нужным колонкам у нас получится готовый StatusBar.
Продолжение следует.....
#WPF,#Csharp
В прошлой статье остановился на рассмотрение такого элемента как Grid.
Одно из важных свойств этого элемента(и не только этого) ширина и высота.
Есть несколько вариантов установки размеров:
"Auto" - установка ширины элемента согласно его содержанию.
"100" - фиксированный размер.
"*" - пропорциональный размер(маленький лайфхак, хотите увеличить этот размер в 2 в 3 раза, просто сделайте запись таким образом "2*" или "3*" ).
Для того, чтобы необходимый элемент имел правильные очертания(в моём случае это элемент "Grid"), то рекомендуется комбинировать эти размеры по необходимости.
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="100" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
</Grid>
Завершаем знакомство с элементами ItemsPanelTemplate и StatusBar.ItemsPanel - которые отвечали за основное оформление(т.е. своего рода "заготовки") и перехожу к след.-му.
<StatusBarItem>
<TextBlock Text="Статус:" />
</StatusBarItem>
<Separator Grid.Column="1" />
<StatusBarItem Grid.Column="2">
<TextBlock Text="Не отправлено" />
</StatusBarItem>
<Separator Grid.Column="3" />
<StatusBarItem Grid.Column="4">
<TextBlock Text="Кол-во знаков:" />
</StatusBarItem>
<Separator Grid.Column="5" />
<StatusBarItem Grid.Column="6">
<TextBlock Text="259" />
</StatusBarItem>
Здесь появляется новый элемент StatusBarItem. Если прошлые элементы StatusBar.ItemsPanel и ItemsPanelTemplate служили нам заготовкой(разметкой), то уже этот служит нам для заполнения нужной информацией.
Каждый элемент размещается в своей колонке, привязка к определенной колонке происходит таким образом: Grid.Column="1" , где "1" это номер нашей колонки. Таким образом добавив нужные элементы(TextBlock и Separator) и привязав их к нужным колонкам у нас получится готовый StatusBar.
Продолжение следует.....
#WPF,#Csharp
В прошлом посте про WPF, рассмотрел элемент: StatusBar.
В текущем коснусь такого элемента, как TextBox и некоторых его свойств.
Свойства:
AcceptsReturn="True" - служит для того, чтобы переводить по нажатию на клавишу Enter курсор на следующую строку.
VerticalScrollBarVisibility="Auto" и HorizontalScrollBarVisibility="Auto" - служит для отображения полос прокрутки TextBox поддерживает свойства.
Элемент: Button - где ему дал имя в свойстве: x:Name="buttonSentMessage"(это имя будет использоваться в коде).
Надпись(содержание), которая отображается на самой кнопке находится в свойстве: Content="Отправить".
Событие: Click="Button_Click" с собственным названием.
В коде будет примерно так(при нажатие на эту кнопку, выскакивает сообщение "Кнопка была нажата!"):
На этом шаге с оформлением останавливаюсь.
Продолжение следует.....
#WPF,#Csharp
В текущем коснусь такого элемента, как TextBox и некоторых его свойств.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="5*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBox Grid.Column="0" AcceptsReturn="True" VerticalScrollBarVisibility="Auto"
HorizontalScrollBarVisibility="Auto"/>
<Button Grid.Column="1" x:Name="buttonSentMessage" Width="80" Height="30" Content="Отправить" Click="Button_Click" />
</Grid>
Свойства:
AcceptsReturn="True" - служит для того, чтобы переводить по нажатию на клавишу Enter курсор на следующую строку.
VerticalScrollBarVisibility="Auto" и HorizontalScrollBarVisibility="Auto" - служит для отображения полос прокрутки TextBox поддерживает свойства.
Элемент: Button - где ему дал имя в свойстве: x:Name="buttonSentMessage"(это имя будет использоваться в коде).
Надпись(содержание), которая отображается на самой кнопке находится в свойстве: Content="Отправить".
Событие: Click="Button_Click" с собственным названием.
В коде будет примерно так(при нажатие на эту кнопку, выскакивает сообщение "Кнопка была нажата!"):
private
void
Button_Click(object
sender, RoutedEventArgs e)
{
MessageBox.Show("Кнопка была нажата!");
}
На этом шаге с оформлением останавливаюсь.
Продолжение следует.....
#WPF,#Csharp
Продолжаю работать с ZennoPoster - ом. На этот раз задача состоит в том, чтобы отсылать сообщения в Telegram используя бота.
В начале, для того чтобы пользоваться им, необходимо получить токен доступа для него в telegram.
Наши действия:
1. Находим и добавляем в телеграм контакт @BotFather.
2. Заходим к нему в чат. Вызываем команду: /start
далее: /newbot.
3. Печатаем имя нашего бота(например имя моего бота "vkbotanswer").
4. Далее username(обязательно с окончанием "bot")
5. В ответном сообщение получаем токен нашего бота.
6. Дальше добавляем нашего бота(как "администратора") в необходимый канал и одновременно получаем id этого канала, перейдя по ссылке.
https://api.telegram.org/bot1351987:AAGvMM26veDkzXyV72L1PU_7L0jjkO/getUpdates
где: 1351987:AAGvMM26veDkzXyV72L1PU_7L0jjkO(полученный токен доступа).
Внимание: id канала имеет всегда знак "-" т.е. такой вид: -1005758311 .
7. На этом бот наш готов и мы можем отсылать наше сообщение(пример запроса):
https://api.telegram.org/bot1351987:AAGvMM26veDkzXyV72L1PU_7L0jjkO/sendMessage?chat_id=-1005758311&text=Приветствую!Меня зовут vkbotanswer и я готов к вашим командам.
Продолжение следует.....
#ZennoPoster
В начале, для того чтобы пользоваться им, необходимо получить токен доступа для него в telegram.
Наши действия:
1. Находим и добавляем в телеграм контакт @BotFather.
2. Заходим к нему в чат. Вызываем команду: /start
далее: /newbot.
3. Печатаем имя нашего бота(например имя моего бота "vkbotanswer").
4. Далее username(обязательно с окончанием "bot")
5. В ответном сообщение получаем токен нашего бота.
6. Дальше добавляем нашего бота(как "администратора") в необходимый канал и одновременно получаем id этого канала, перейдя по ссылке.
https://api.telegram.org/bot1351987:AAGvMM26veDkzXyV72L1PU_7L0jjkO/getUpdates
где: 1351987:AAGvMM26veDkzXyV72L1PU_7L0jjkO(полученный токен доступа).
Внимание: id канала имеет всегда знак "-" т.е. такой вид: -1005758311 .
7. На этом бот наш готов и мы можем отсылать наше сообщение(пример запроса):
https://api.telegram.org/bot1351987:AAGvMM26veDkzXyV72L1PU_7L0jjkO/sendMessage?chat_id=-1005758311&text=Приветствую!Меня зовут vkbotanswer и я готов к вашим командам.
Продолжение следует.....
#ZennoPoster
Forwarded from vladimir
Сегодня продолжю работать с ZennoPoster и Telegram, но уже в видео формате.
Основные шаги.
1. Создание проекта.
2. Создание переменных.
3. Отправка сообщения в ТГ, 2-мя способами.
#ZennoPoster, #Telegram
Основные шаги.
1. Создание проекта.
2. Создание переменных.
3. Отправка сообщения в ТГ, 2-мя способами.
#ZennoPoster, #Telegram
Media is too big
VIEW IN TELEGRAM
Отправление фото и видео в Telegram используя ZennoPoster и библиотеку "Telegram.Bot"
#ZennoPoster, #Telegram
#ZennoPoster, #Telegram