• Как повторить структуру treeview в menu?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    Рекурсия:
    private void button1_Click(object sender, EventArgs e)
    {
      // создаем меню
      var menu = new MenuStrip();
      menu.Items.Add("Меню");
    
      // перебираем узлы
      foreach (TreeNode n in treeView1.Nodes)
      {
        // создаем элемент меню
        var menuItem = new ToolStripMenuItem();
        menuItem.Text = n.Text;
        // перебирем детей
        ConvertNodeToMenu(menuItem, n);
        // добавляем элемент в меню
        ((ToolStripMenuItem)menu.Items[0]).DropDownItems.Add(menuItem);
      }
          
      // добавляем меню на форму
      this.Controls.Add(menu);
    }
    
    private void ConvertNodeToMenu(ToolStripMenuItem menuParent, TreeNode node)
    {
      foreach (TreeNode n in node.Nodes)
      {
        // создаем элемент меню
        var menuItem = new ToolStripMenuItem();
        menuItem.Text = n.Text;
        // перебираем детей
        ConvertNodeToMenu(menuItem, n);
        // добавляем элемент в меню
        menuParent.DropDownItems.Add(menuItem);
      }
    }

    Вариант с LINQ:
    private void button1_Click(object sender, EventArgs e)
    {
      // создаем меню
      var menu = new MenuStrip();
      menu.Items.Add("Меню");
      // берем первый элемент меню
      var menuItem = (ToolStripMenuItem)menu.Items[0];
      // получаем узлы и добавляем в меню
      menuItem.DropDownItems.AddRange
      (
        treeView1.Nodes.Cast<TreeNode>().Select
        (
          n => new ToolStripMenuItem(n.Text, null, ConvertNodeToMenu(n))
        ).ToArray()
      );
      // добавляем меню на форму
      this.Controls.Add(menu);
    }
    
    private ToolStripMenuItem[] ConvertNodeToMenu(TreeNode node)
    {
      return node.Nodes.Cast<TreeNode>().Select
      (
        n => new ToolStripMenuItem(n.Text, null, ConvertNodeToMenu(n))
      ).ToArray();
    }
    Ответ написан
    6 комментариев
  • Возможна ли авторизация OAuth 2.0 без браузера?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    Поставщик может позволить принимать у пользователя логин и пароль и преобразовывать их в маркер доступа (accsss token). Но, как правило в целях безопасности, никто не дает такой возможности.

    Попробуйте: если grant_type будет password, то данные пользователя можно передавать в параметрах username и password при получении маркера доступа. Либо использовать grant_type равный client_credentials, тогда данные пользователя должны передаваться в HTTP заголовке Authorization (при использовании HTTPS это более безопасный способ, чем password).

    Например, если бы Facebook позволял это делать, то запрос маркера доступа мог бы быть таким:
    https://graph.facebook.com/oauth/access_token?client_id=123&client_secret=abc&
    grant_type=password&username=pupkin&password=000


    В моей библиотеке пока нет возможности менять grant_type снаружи, но можно внутри поменять. Например, InstagramClient.cs, в конструкторе указать GrantType:

    base.GrantType = GrantType.ClientCredentials;

    И далее использовать клиент:

    var client = new InstagramClient
    (
      "9fcad1f7740b4b66ba9a0357eb9b7dda", 
      "3f04cbf48f194739a10d4911c93dcece"
    );
    client.ReturnUrl = "http://oauthproxy.nemiro.net/";
    client.Username = "aleksey";
    client.Password = "Frif#dser#23dssd@Dsdfjjfsi";
    var accessToken = client.AccessToken;

    И сервер ответит:
    {"code": 400, "error_type": "OAuthException", "error_message": "Invalid grant_type"}

    Плохой пример :P

    А вот Facebook, на удивление, вернул маркер доступа:
    var client = new FacebookClient("1435890426686808", "c6057dfae399beee9e8dc46a4182e8fd");
    client.Username = "aleksey";
    client.Password = "a6lGmDZsCb1SuHsIQw89ZqK9";
    var accessToken = client.AccessToken;

    Но у меня сомнения, что поставщик просто так позволит это использовать кому попало, в реальных условиях, без ограничений. Наверняка придется жесткую проверку модератором проходить.
    Ответ написан
    Комментировать
  • Как синхронизировать положение ползунков полос прокрутки в двух RichTextBox?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using System.Runtime.InteropServices;
    
    namespace WindowsFormsApplication9
    {
      public partial class Form1 : Form
      {
    
        /// <summary>
        /// Получает текущее положение ползунка полосы прокрутки.
        /// </summary>
        /// <param name="hWnd">Дескриптор.</param>
        /// <param name="nBar">Тип.</param>
        /// <returns></returns>
        [DllImport("User32.dll")]
        public extern static int GetScrollPos(IntPtr hWnd, int nBar);
    
        /// <summary>
        /// Функция для отправки сообщений.
        /// </summary>
        /// <param name="hWnd">Дескриптор.</param>
        /// <param name="msg">Само сообщение.</param>
        /// <param name="wParam">Параметры.</param>
        /// <param name="lParam">Дополнительные параметры.</param>
        [DllImport("User32.dll")]
        public extern static int SendMessage(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);
    
        public enum ScrollBarType : uint
        {
          SbHorz = 0,
          SbVert = 1,
          SbCtl = 2,
          SbBoth = 3
        }
    
        public enum Message : uint
        {
          /// <summary>
          /// Сообщение для вертикальной полосы прокрутки
          /// </summary>
          WM_VSCROLL = 0x0115
        }
    
        public enum ScrollBarCommands : uint
        {
          /// <summary>
          /// Положение ползунка полосы прокрутки в конце операции
          /// </summary>
          SB_THUMBPOSITION = 4
        }
    
        private RichTextBox rich1 = new RichTextBox();
        private RichTextBox rich2 = new RichTextBox();
    
    
        public Form1()
        {
          InitializeComponent();
    
          // тестовый текст
          string text = "";
          for (int i = 0; i < 99; i++)
          {
            text += "Имеется 2 richTextBox, нужно установить значение текущего вертикального скролла первого, как у в данный момент у второго. Пробовал всякие offset, копался в гугле, но ничего внятного не нашел.\r\n";
          }
    
          // добавляем поля на форму
          rich1.Name = "rich1";
          rich1.Dock = DockStyle.Top;
          rich1.Text = text;
          rich1.VScroll += rich_VScroll;
          this.Controls.Add(rich1);
    
          rich2.Name = "rich2";
          rich2.Dock = DockStyle.Top;
          rich2.Text = text;
          rich2.VScroll += rich_VScroll;
          this.Controls.Add(rich2);
        }
    
        /// <summary>
        /// Обработчик изменения положения ползунка полосы прокрутки.
        /// </summary>
        private void rich_VScroll(object sender, EventArgs e)
        {
          // кто вызвал событие
          RichTextBox currentRich = (RichTextBox)sender;
          // если событие вызвал rich2, то второй будет rich1 и наоборот
          RichTextBox otherRich = currentRich.Name.Equals("rich1") ? rich2 : rich1;
    
          // получаем позицию ползунка полосы прокрутки текущего поля
          int pos = GetScrollPos(currentRich.Handle, (int)ScrollBarType.SbVert);
          pos <<= 16;
    
          // чтобы не застрять в бесконечности 
          // (можно так не делать и прикрутить обработчик только к одному полю)
          otherRich.VScroll -= rich_VScroll; 
          // --
    
          // передаем позицию во второе поле
          uint par = (uint)ScrollBarCommands.SB_THUMBPOSITION | (uint)pos;
          SendMessage(otherRich.Handle, (int)Message.WM_VSCROLL, new IntPtr(par), new IntPtr(0));
          otherRich.VScroll += rich_VScroll;
        }
      }
    }
    Ответ написан
    2 комментария
  • Приложение не запускается на WinXP, как можно исправить?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    На Windows XP должен быть установлен .NET Framework. В данном случае, версия 2.0. Также может потребоваться Service Pack 3.

    Лучше ниже .NET Framework 3.5 не использовать.
    И .NET Framework 4.0 под Windows XP вполне нормально работает, если установить. Версия 4.5 уже не поддерживается

    .NET 2.0, если не изменяет память, по умолчанию не входил в состав Windows XP (если хотелось именно этого).
    Ответ написан
    2 комментария
  • Как заставить Newtonsoft.Json вернуть чистый json?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    Newtonsoft.Json тут не причем. Дело в запросе, со стороны клиента. Нужно указать тип содержимого application/json и передать JSON в data:
    $.ajax({
    	type: "POST",
    	url: "WebService1.asmx/VerifySignature",
    	contentType: "application/json",
    	data: JSON.stringify({ certInfo: keyInfo }), // обернуть все параметры
    	success: function (result) {
    		alert(result);
    		console.log(result);
    	}
    });
    Ответ написан
    2 комментария
  • Сортировка элементов строки?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    Можно разбить на массив по пробелу и выполнить сортировку массива, затем обратно склеить:
    var value = "a ack fghjy fghfh asn";
    // разбиваем на массив
    var arr = value.Split();
    // сортируем массив
    Array.Sort(arr);
    // склеиваем массив в строку
    string result = String.Join(" ", arr);
    // выводим результат
    Console.WriteLine(result);

    Или при помощи OrderBy:
    Console.WriteLine(String.Join(" ", "a ack fghjy fghfh asn".Split().OrderBy(itm=>itm)));

    Первый вариант оптимальней.
    Посмотреть пример.
    Ответ написан
    5 комментариев
  • Как правильно работать с большой базой через C# + MsSQLL?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    Если есть возможность, лучше удалять данные полностью, а потом добавлять новые при помощи SqlBulkCopy.

    Таким образом можно будет большие, я бы даже сказал огромные, объемы данных помещать в базу за короткий промежуток времени. Лучше всего не все сразу, а частями. Например, если 5 000 000 записей, то пачкой 10 000, или по 1 000. Зависит от объема данных и вероятности возникновения ошибок в процессе переноса. Если там простые данные, типа чисел, то можно их одним махом залить в базу. Если пачка будет слишком большой, серверу может памяти не хватить на её обработку.

    Быстро удалить данные можно при помощи инструкции TRUNCATE TABLE [имя таблицы], но не всегда просто, зависит от связей.

    Организовать обновление будет сложнее. Лучше всего выбирать пачку данных, обрабатывать и отправлять обратно на сервер. Размер пачки необходимо определять в зависимости от ресурсов сервера и объема данных в пачке.
    Запросы при обновлении должны быть максимально простыми. Можно использовать XML, но тоже очень простой и небольших объемов, а в идеале обойтись без этого. Чем все будет проще, тем быстрее будет работать. Циклы и курсоры в запросах стараться не использовать.

    Проверку наличия данных можно реализовать на стороне приложения, а не базы. Практика показывает, что это работает быстрее. Перед обновлением можно получить только идентификаторы данных (в DataTable). Далее проверять, есть необходимый идентификатор в DataTable или нет. Чтобы было проще, можно обновлять все данные, если идентификатор будет найден. А если нет, то добавлять данные. Это позволит не делать EXISTS на стороне SQL Server и обновление можно будет выполнить пачкой. Если использовать XML, то примерно так это может выглядеть:

    -- временная таблица
    -- в моем примере всего два поля id и value
    CREATE TABLE #tmp
    (
      num int primary key identity,
      id bigint,
      value nvarchar(max)
    );
    
    -- структура xml:
    -- <items>
    -- <item id="123">значение</item>
    -- <item id="456">значение</item>
    -- </items>
    
    -- переносим xml в таблицу
    INSERT INTO #tmp
    SELECT 
    ISNULL(n.value('@id', 'bigint'), 0), -- идентификатор существующих данных
    n.value('.', 'nvarchar(max)') -- значение данных
    FROM @xml.nodes('/items/item') AS node(n);
    
    -- обновляем записи в таблице [table], у которых есть идентификатор
    UPDATE a SET value = b.value
    FROM table AS a 
    INNER JOIN #tmp AS b ON a.id = b.id
    WHERE b.id <> 0;
    
    -- добавляем записи, у которых нет идентификатора
    INSERT INTO table (value)
    SELECT value FROM #tmp AS b WHERE b.id = 0;
    
    -- удаляем временную таблицу
    DROP TABLE #tmp;

    Если есть возможность, лучше обойтись без XML, JOIN-ов и всяких ISNULL.

    Базу необходимо правильно настроить. Добавить индексы, где будет уместно. Но не переборщить и учитывать, что они (индексы) могут фрагментироваться и сильно замедлять работу базы. Про фрагментацию самой базы, тоже не стоит забывать. Если будете удалять большие объемы данных, то не забывайте выполнять резервное копирование и сжатие базы.

    Соединения с базой лучше использовать одноразовые. Т.е. открыл, выполнил запрос, закрыл и так далее. Если использовать одно соединение, то со временем скорость выполнения запросов будет существенно снижаться.

    Универсального решения подобных задач нет, но это примерно то, от чего можно отталкиваться.
    Ответ написан
    9 комментариев
  • Как Достать часть из строки в c#?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    Раз пошла такая пьянка, предложу вариант без регулярных выражений:
    // входящие данные
    string data = "0x00 00 00 00 00 00 00 00 00 00 00 00 00 00 30 39 ..............09";
    // получаем позицию первой найденной точки
    int endIndex =  data.IndexOf(".");
    // получаем позицию первого вхождения символов 00
    // с конца строки начиная с endIndex
    int startIndex = data.LastIndexOf("00", endIndex) + 2; // + размер искомых символов
    		
    // выделяем часть строки и удаляем лишние пробелы по бокам
    string result = data.Substring(startIndex, endIndex - startIndex).Trim();
    		
    // выводим результат
    Console.WriteLine(result);
    
    // можно одной строкой написать, но так проще понять

    Посмотреть, как это работает, можно тут.

    Регулярные выражения имеет смысл использовать, если шаблон поиска и/или данные будут сложными. В рамках текущего вопроса, все вроде бы просто, можно без потенциально опасных регулярных выражений обойтись (прожорливость, зацикливание).

    Еще вот такой можно сделать вариант:
    string data = "0x00 00 00 00 00 00 00 00 00 00 00 00 00 3D 12 7E ..............01";
    string result = data.Replace("0x", "").Replace("00", "").TrimEnd("0123456789.".ToCharArray()).Trim();
    Console.WriteLine(result);

    Или:
    string data = "0x00 00 00 00 00 00 00 00 00 00 00 00 00 3D 12 7E ..............00";
    string result = data.Substring(2).TrimStart("0 ".ToCharArray()).TrimEnd("0123456789.".ToCharArray()).Trim();
    Console.WriteLine(result);
    Ответ написан
    7 комментариев
  • Как сконвертировать строку decimal to hex в с#?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    string hex = 10008.ToString("x2");
    Посмотреть пример
    int num = 255;
    string hex = num.ToString("x2");
    // переменная hex будет иметь значение ff
    hex = num.ToString("X2");
    // переменная hex будет иметь значение FF

    Массив байт в HEX:
    byte[] data = new byte[] {1,2,3,4,5,128,255};
    string hex = String.Join(" ", data.Select(b=> b.ToString("x2")).ToArray());
    Console.WriteLine(hex);

    На выходе будет:
    01 02 03 04 05 80 ff

    Набор символов в HEX:
    string data = "Привет, человеки!";
    string hex =  String.Join(" ", data.ToString().Select(ch => ((byte)ch).ToString("x2")).ToArray());
    Console.WriteLine(hex);

    или лучше через Encoding получить массив байт из строки:
    string data = "Привет, человеки!";
    string hex =  String.Join(" ", System.Text.Encoding.GetEncoding(1251).GetBytes(data).Select(b => b.ToString("x2")).ToArray());
    Console.WriteLine(hex);

    На выходе будет:
    cf f0 e8 e2 e5 f2 2c 20 f7 e5 eb ee e2 e5 ea e8 21

    В String.Join первым параметром, вместо пробела, можно указать любой набор символов, которым будет объединен массив полученных hex-данных.
    string data = "Привет, человеки!";
    string hex =  String.Join("-", System.Text.Encoding.GetEncoding(1251).GetBytes(data).Select(b => b.ToString("x2")).ToArray());
    Console.WriteLine(hex);

    На выходе:
    cf-f0-e8-e2-e5-f2-2c-20-f7-e5-eb-ee-e2-e5-ea-e8-21
    Ответ написан
    5 комментариев
  • Как создать переменные и хранить их до определённого момента?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    Обычно поиск выполняется один раз. Для повышения производительности, результаты поиска кэшируются и при последующих обращениях берутся из кэша. Кэш может храниться где угодно. Данные автоматически удаляются по истечению указанного срока жизни.

    Как выдавать данные частями - зависит от того, как они получаются.

    Разделение на страницы можно реализовать со стороны базы данных и получать данные только для конкретной страницы. Код не буду показывать, вариантов может быть множество. Решение будет зависеть от количества данных, ресурсоемкости запросов на поиск.

    Что касается кэширования, то самый простой вариант:
    // или HttpContext.Current.Cache
    if (HttpContext.Cache["Ключ"] == null) 
    {
      // данных в кэше нет, получаем из базы и добавляем в кэш
      HttpContext.Cache.Add
      (
        "Ключ",
        "тут сами данные",
        null,
        DateTime.Now.AddMinutes(5), // срок годности пять минут
        TimeSpan.Zero,
        System.Web.Caching.CacheItemPriority.Normal,
        null
      );
    }
    else
    {
      // есть данные в кэше, используем их
      var data = HttpContext.Cache["Ключ"]; // типы строгие лучше использовать
    }

    Или использовать атрибут OutputCache и кэшировать страницы.

    Дополнительно, можно в базе создавать сессии со ссылками на результаты поиска. Т.е. выполнять поиск, записывать ключ в таблицу, затем делать выборку, используя найденные ключи. Устаревшие результаты можно удалять, либо со стороны ASP.NET, периодически выполнять запрос. Либо, если есть возможность, настроить SQL Server Agent. Это если данных много и поиск дорого обходится.
    Ответ написан
  • Как повторить текущую итерацию while C#?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    Зависит от логики. Если, как показано ниже, то можно использовать continue:
    int i = 0;
    bool b = false;
    while (i < 10)
    {
    	Console.WriteLine("Текущее: {0}", i);
    			
    	if (i == 5 && !b)
    	{
    		b = true;
    		continue;
    	}
    			
    	i++;
    }

    В крайнем случае есть goto:
    int i = 0; 
    bool b = false;
    while (i < 10)
    {
    	again: // точка возврата
    	Console.WriteLine("Текущее: {0}", i);
    			
    	if (i == 5 && !b)
    	{
    		b = true;
    		goto again;
    	}
    			
    	i++;
    }

    Посмотреть online-пример

    Однако не следует злоупотреблять подобными переходами. От обилия операторов goto в коде, у программиста может случиться разрыв мозга, что приведет к неминуемой гибели проекта и его возрождению в новом виде, если, конечно, сам программист не скопытится. Травма та серьезная :-) Если есть возможность, желание и время, лучше изменить логику так, чтобы не приходилось делать такие «прыжки».

    Для получения файлов или вообще работы с файлами (ожидание доступа для чтения или удаления, получение данных из сети и т.п.), можно использовать вложенный цикл, который будет пробовать выполнить задачу до тех пор, пока она будет успешно выполнена или не истечет отведенное время на выполнение задачи (или количество попыток):
    // пауза между попытками (100 мс)
    var interval = new TimeSpan(0, 0, 0, 0, 100); 
    // максимальное время ожидания (1 секунда)
    var timeout  = new TimeSpan(0, 0, 0, 1); 
    while (true)
    {
      var totalTime = new TimeSpan(); // счетчик времени
      var заданиеВыполнено = false;
    
      while(!заданиеВыполнено) // повторять, пока задание не будет выполнено
      {
        try
        {
          // тут код задания
          // если ошибок не будет, то
          заданиеВыполнено = true; // работа цикла будет завершена
        }
        catch
        {
          // если ошибка, делаем паузу
          System.Threading.Thread.Sleep(100);
          // увеличиваем счетчик времени
          totalTime += interval;
          if (totalTime > timeout)
          {
    				// превышен таймаут, выходим
    				Console.WriteLine("Превышено время ожидания");
    				break;
          }
        }
      }
    }
    Ответ написан
  • Что не так делаю при получении xml serializer C#?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    Для представленного XML, классы будут примерно такими:
    [Serializable]
    [XmlRoot("ValCurs")]
    public class ValCurs
    {
    
      [XmlAttribute("Date")]
      public string Date { get; set; }
    
      [XmlAttribute("name")]
      public string Name { get; set; }
    
      [XmlElement("Valute")]
      public Valute[] Items { get; set; }
    
    }
    
    [Serializable]
    public class Valute
    {
    
      [XmlAttribute("ID")]
      public string Id { get; set; }
      public string NumCode { get; set; }
      public string CharCode { get; set; }
      public string Name { get; set; }
      public string Nominal { get; set; }
      public string Value { get; set; }
    
    }

    Посмотреть пример работы этого кода в .NET Fiddle.
    Ответ написан
    Комментировать
  • Как защитить HTML5 игры?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    Flash можно же декомпилировать, так что уповать на то, что исходный код будет защищен, не стоит.

    Пишите код, патентуйте, отслеживайте и судитесь с нарушителями.

    Основной функционал можно вывести на сервер, чтобы клиентская часть была бесполезной.

    Клиентский код можно сделать плохочитаемым, обфусцировать.
    Ответ написан
    Комментировать
  • Как сделать так, чтобы после нажатия кнопки можно было щелкнуть мышкой в PictureBox и там бы нарисовался круг?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    Фигуры фиксированного размера можно нарисовать так:
    public partial class Form1 : Form
    {
    
        private int BrushType = 1;
    
        public Form1()
        {
          InitializeComponent();
    
          // создаем PictureBox
          var pic = new PictureBox { Dock = DockStyle.Fill, BackColor = Color.White };
          pic.MouseClick += PictureBox_MouseClick;
          this.Controls.Add(pic);
    
          // создаем панель для кнопок
          var panel = new FlowLayoutPanel { Dock = DockStyle.Top, AutoSize = true };
          this.Controls.Add(panel);
    
          // кнопки
          var btn = new RadioButton 
          { 
            Text = "Круг", 
            Tag = 1, 
            Appearance = Appearance.Button, 
            Checked = true, 
            AutoSize = true 
          };
          btn.Click += Button_Click;
          panel.Controls.Add(btn);
    
          btn = new RadioButton
          {
            Text = "Не круг",
            Tag = 2,
            Appearance = Appearance.Button,
            AutoSize = true
          };
          btn.Click += Button_Click;
          panel.Controls.Add(btn);
    
          btn = new RadioButton
          {
            Text = "Квадратный круг",
            Tag = 3,
            Appearance = Appearance.Button,
            AutoSize = true
          };
          btn.Click += Button_Click;
          panel.Controls.Add(btn);
        }
    
        private void Button_Click(object sender, EventArgs e)
        {
          var btn = (RadioButton)sender;
          this.BrushType = (int)btn.Tag;
        }
    
        private void PictureBox_MouseClick(object sender, MouseEventArgs e)
        {
          // получаем ссылку на PictureBox
          var pic = (PictureBox)sender;
          // получаем Graphics из PictureBox
          var g = pic.CreateGraphics();
    
          if (this.BrushType == 2)
          {
            // рисуем не круглый квадрат
            g.DrawRectangle(Pens.Black, e.X, e.Y, 50, 50);
          }
          else if (this.BrushType == 3)
          {
            // рисуем квадратный круг
            Point[] points = new Point[6];
            int half = 50 / 2;
            int quart = 50 / 4;
            points[0] = new Point(e.X + quart, e.Y);
            points[1] = new Point(e.X + 50 - quart, e.Y);
            points[2] = new Point(e.X + 50, e.Y + half);
            points[3] = new Point(e.X + 50 - quart, e.Y + 50);
            points[4] = new Point(e.X + quart, e.Y + 50);
            points[5] = new Point(e.X, e.Y + half);
            g.DrawPolygon(Pens.Black, points);
          }
          else
          {
            // рисуем эллипс
            g.DrawEllipse(Pens.Black, e.X, e.Y, 50, 50);
          }
        }
    
    }

    В качестве кнопок используются RadioButton, т.к. это удобней.
    Чтобы не стиралось, можно сделать Bitmap:
    var pic = (PictureBox)sender;
    if (pic.Image == null) { pic.Image = new Bitmap(pic.Width, pic.Height); }
    var bmp = new Bitmap(pic.Image);
    var g = Graphics.FromImage(bmp);

    И после завершения рисования, передать картинку в PictureBox:
    pic.Image = bmp;

    Результат:
    c141d6f9ebe44712a5d9c5f9aa67dcb1.png
    Ответ написан
    1 комментарий
  • Как преобразовать строку в C#?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    string data = "FF CA 00 00 00";
    string result = "0x" + String.Join(",0x", data.Split());
    Console.WriteLine(result);

    Посмотреть пример в .NET Fiddle.

    Еще можно регулярные выражения задействовать, но через обычный Split и Join проще всего.
    Ответ написан
    1 комментарий
  • Как вставить в HTML полученную строку из адресной строки?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    Выделить нужную часть адреса после решетки (#) можно примерно так:
    var hash = window.location.hash;
    
    if (hash.length > 1) 
    {
        alert('Маркер доступа: ' + hash.substring(hash.indexOf('=') + 1));
    }

    Пример

    Этот код должен быть на странице, указанной в redirect_uri, т.е. в данном случае, на странице:
    http://localhost

    Как видно, маркер доступа (access token) вырезается из window.location.hash. Его можно передать, например, в переменную:
    var access_token = hash.substring(hash.indexOf('=') + 1);


    Если планируется использовать другой адрес, то необходимо указать его в настройках конкретного приложения.

    К сожалению, Instagram, на данный момент, позволяет указывать только один адрес обратного вызова для одного приложения.

    Адрес обратного вызова (redirect_uri) в запросе на авторизацию должен полностью совпадать с тем, который указан в настройках приложения (исключая параметры запроса).

    ----------------------------------------------------------------

    ?client_id=64c696ae6b32405a8efcd83889c571be&redirect_uri=http://localhost&response_type=token

    Лучше кодировать параметры URL, чтобы не было проблем.

    PS: Если маркер доступа (access token) в тексте вопроса настоящий, то это небезопасно. Лучше удалить и получить новый.
    Ответ написан
    1 комментарий
  • Как написать регулярное выражение, находящее в строке все слова из 9 букв, кроме определённых слов?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    Примерно так:
    \b((?!асимптота)([A-Za-zА-Яа-яЁё]{9}))\b
    \b((?!асимптота|однородно)([A-Za-zА-Яа-яЁё]{9}))\b
    Посмотреть пример
    Ответ написан
    Комментировать
  • Почему не отображаются Я.Карты?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    Переменная coord - строка:

    var coord = "<?=$data['coords'];?>";

    В center ожидается массив, но передается строка, как элемент массива:

    var myMap = new ymaps.Map('map', {
      center: [coord],
      zoom: 9,
      controls: ['zoomControl']
    });

    Можно сделать split по запятой:

    var coord = "58.6103,49.6917".split(',');
    // var coord = "<?=$data['coords'];?>".split(',');


    И передавать coord как есть:
    var myMap = new ymaps.Map('map', {
            center: coord,
            zoom: 9,
            controls: ['zoomControl']
    });

    Посмотреть пример.

    Или сразу, в скрипт передавать массив, а не строку:

    var coord = [<?=$data['coords']?>];
    Ответ написан
    1 комментарий
  • Не работает FindWindow?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    У меня работает:
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Runtime.InteropServices;
    
    namespace ConsoleApplication13
    {
      class Program
      {
        [DllImportAttribute("User32.dll")]
        private static extern int FindWindow(String ClassName, String WindowName);
    
        [DllImportAttribute("User32.dll")]
        private static extern IntPtr SetForegroundWindow(int hWnd);
    
        static void Main(string[] args)
        {
          int hWnd = FindWindow(null, "Калькулятор");
          Console.WriteLine(hWnd);
          if (hWnd > 0)
          {
            Console.WriteLine("К счастью, окно найдено...");
            SetForegroundWindow(hWnd); 
          }
          else
          {
            Console.WriteLine("Окно не найдено!");
          }
          Console.ReadKey();
        }
      }
    }

    С использованием класса Process, этот код должен активировать все открытые калькуляторы:
    static void Main(string[] args)
    {
      foreach (var p in Process.GetProcessesByName("calc"))
      {
        SetForegroundWindow(p.MainWindowHandle.ToInt32()); 
      }
    
      Console.ReadKey();
    }
    Ответ написан
    2 комментария
  • Как повысть скорость записи случайных блоков?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    Можно попробовать использовать MemoryMappedFile:
    string path = @"1.dat";
    int len = 1024 * 1024;
    
    var rnd = new Random();
    var sw = Stopwatch.StartNew();
    
    var b = new byte[4];
    
    Console.WriteLine("Test started");
    
    using (var map = MemoryMappedFile.CreateFromFile(path, FileMode.Create, path, len))
    {
      using (var accessor = map.CreateViewAccessor())
      {
        for (var i = 0; i < len / 4; ++i)
        {
          b[0] = (byte)rnd.Next(0, 255);
          b[1] = (byte)rnd.Next(0, 255);
          b[2] = (byte)rnd.Next(0, 255);
          b[3] = (byte)rnd.Next(0, 255);
    
          accessor.WriteArray(rnd.Next(0, len / 4) * 4, b, 0, 4);
        }
      }
    }
          
    Console.WriteLine("Test end time - " + sw.ElapsedMilliseconds);
    Console.ReadKey();
    Ответ написан