• Как растянуть форму на несколько мониторов?

    @acwartz
    Тут должна быть ваша реклама.
    В модуле Vcl.Forms есть класс TScreen, через который можно перечислить мониторы и получить их свойства.
    Класс создавать не надо, он уже создан в глобальной переменной Screen
    Примерно так:
    i, TotalWidth , TotalHeight : Integer;
    for i = 0 to Screen.MonitorCount -1 do
    begin
      TotalWidth := TotalWidth + Screen.Monitors[i].Width;
      TotalHeight := TotalHeight + Screen.Monitors[i].Heigth;
    end;
     Form.Width := TotalWidth;
     Form.Heigth := TotalHeight ;

    код на коленке писал.
    Ответ написан
    Комментировать
  • Как растянуть форму на несколько мониторов?

    HemulGM
    @HemulGM Куратор тега Delphi
    Delphi Developer, сис. админ
    Проблема в другом. Screen.DesktopWidth указывает полный размер всего рабочего стола (это сумма всех мониторов). И я проверил, окно растягивается на оба монитора. Посмотри настройки формы: WindowState
    Ответ написан
    Комментировать
  • Как реализовать сочетания клавиш только в активной форме?

    HemulGM
    @HemulGM Куратор тега Delphi
    Delphi Developer, сис. админ
    Не нужно такие сочетания "ctrl+z" регистрировать в системе.
    Чтоб форма обрабатывала сочетания, используй простое событие OnKeyUp (или если нужно OnKeyDown). Чтоб сочетание обрабатывала в первую очередь форма, а не контрол в фокусе, то у формы установи свойство KeyPreview = True

    procedure TForm1.FormKeyUp(Sender: TObject; var Key: Word; var KeyChar: Char; Shift: TShiftState);
    begin
      if [ssCtrl] = Shift then
        case Key of
          vkZ: //Ctrl+Z pressed
            ;
        end;
    end;
    Ответ написан
    Комментировать
  • Как реализовать авторизацию при запуске программы?

    @rPman
    Авторизация может выглядеть следующим образом - сервер выдает токен (некое число, секретное, временное, чье время действия может продляться при его использовании), основанный на каких то идентификационных данных клиента (идентификатор компьютера или установки приложения, сетевой ip адрес и т.п., этот вопрос не простой и ответ на него определит серьезность проверки на действия злоумышленника, который попытается украсть этот токен).

    Т.е. приложение смотрит, есть ли токен в памяти,
    * если нет - открывает форму авторизации, и в месте с данными из нее (точнее обработанные каким-нибудь алгоритмом криптонадежного хеширования) отправляет на сервер идентификатор клиента, сервер проверяет, можно ли давать доступ, прекращает работу выданных ранее этому же клиенту токенов, и выдает новый.
    * если токен есть - приложение делает запрос с этим токеном и своими идентификаторами (так же хешированными) на сервер, а он в свою очередь проверяет, не закончилось ли время действия токена и выдает либо да либо нет.

    Процесс авторизации можно воспринимать как выдачу ключа активации (например при покупке своей копии программы).

    Нужно понимать что эту проверку можно обойти, убрав этот запрос из кода в принципе. Более надежным является перенос части или всего функционала приложения на серверную сторону, в этом случаее взломать так просто не получится но и работа может быть не такой комфортной из-за лагов, да и нагрузка на сервер станет выше.
    Ответ написан
    4 комментария
  • Как реализовать авторизацию при запуске программы?

    HemulGM
    @HemulGM Куратор тега Delphi
    Delphi Developer, сис. админ
    Не надо считать, что есть "основная форма". У тебя есть много разных форм/окон. "Основным" окном считается то окно, что создано первым, но это лишь формальность.

    Более того, создано оно должно быть через конструктор форм Application. А если создавать окна простым способом
    TFormAuth.Create(...) то оно не будет считаться основным.

    Итого, для того, чтобы по уму сделать окно авторизации, тебе нужно зайти в код программы (не в код модуля, а в код программы). Да, представь, такое место тоже есть. Делфи его прячет от новичков. Открыть его можно через контекстное меню проекта "View Source" или через меню "Project" -> "View Source".

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

    UPD. Пример
    program Temp;
    
    uses
      Vcl.Forms,
      Vcl.Controls,
      Temp.Main in 'Temp.Main.pas' {FormMain},
      Temp.Auth in 'Temp.Auth.pas' {FormAuth};
    
    {$R *.res}
    
    begin
      Application.Initialize;
      Application.MainFormOnTaskbar := True;
    
      FormAuth := TFormAuth.Create(nil);
      if FormAuth.ShowModal = mrOk then
      begin
        Application.CreateForm(TFormMain, FormMain);
        Application.Run;
      end;
    end.


    Как ты видишь, я убрал автоматически созданную строку
    Application.CreateForm(TFormAuth, FormAuth);
    и создал форму сам
    FormAuth := TFormAuth.Create(nil);
    Дальше, я сделал простую проверку, если окно было закрыто с mrOk (т.е. нажата кнопка OK), то мы продолжаем, запускаем программу, в противном случае программа просто заканчивается.
    Ответ написан
    3 комментария
  • Как определить, какая тема Drupal 7 активная (выбрана как главная)?

    sakrab
    @sakrab
    Не будь побежден злом, но побеждай зло добром...
    Заходишь в Оформление, смотришь ВКЛЮЧЕННЫЕ ТЕМЫ, у кого только ссылка Настройки, та и включена.
    Ответ написан
    Комментировать
  • Почему не применяется отдельный шаблон для категории произвольного типа записей?

    wppanda5
    @wppanda5 Куратор тега WordPress
    WordPress Mедведь
    Потому, что это не категория а кастомная таксономия
    для ее терминов шаблон такой taxonomy-$taxonomy-$term.php
    https://developer.wordpress.org/themes/basics/temp...

    Ваш случай
    taxonomy-catalog-arenda.php
    Ответ написан
    Комментировать
  • Как сделать сортировку по полю ACF в WP_Query?

    wppanda5
    @wppanda5 Куратор тега WordPress
    WordPress Mедведь
    Первый вариант
    args['orderby'] = 'meta_value_num';

    Второй вариант вроде должен работать, но надо смотреть по месту
    Ответ написан
    4 комментария
  • Как собрать программу (несколько вопросов)?

    @acwartz
    Тут должна быть ваша реклама.
    Имя файла это имя проекта, можно изменить в менеджере проектов:
    5f896f9c34249105669309.png

    Расположение выходного файла меняется в настройках проекта,
    обратите внимание на наличие вагона конфигураций:
    5f896fb08365a536392909.png

    Я для output directory для all values - all platforms указываю ..\bin\, там и плодятся все бинарники.
    Но это у меня т.к. структура проектов всегда такая:
    ./prjects//bin/.exe
    ./prjects//source/DCU/{Platform}/{BuildMode}/
    ./prjects//source/.dproj
    3) В настройках проекта указал лого и иконку(почему то у exe'шника и в трее они не меняются) - их(иконки) нужно так же около exe файла держать?

    С лого и прочим тоже самое, для каждого конфига нужны свои настройки.
    Иконка в трее берется из соотв. свойства компонента.

    4)Еще такой вопрос - как лучше хранить настройки по умолчанию?(сейчас они просто прописаны в коде) Была мысль - ini файл рядом с exe положить, но среди настроек есть некоторые "секретные", поэтому нужно, чтобы обычный пользователь их не трогал и не видел - нормальное ли решение будет добавить dll в котором прописать функцию устанавливающую эти настройки(например логин, пароль, адрес сервера куда отправляются запросы)
    обычные настройки(автозапуск, горячие клавиши) записываю в реестр.

    Вдумайтесь, настройки по-умолчанию это те настройки которые есть всегда вне зависимости от доступности реестра/файлов. Они должны быть внутри самого exe, т.е. прямо в коде прописаны либо модулем с константами/функциями. И не надо городить ни в ресурсах ни рядом ни в dll ничего, никаких конф. файлов. Это лишняя и пустая трата времени, в 95% случаев вы туда только в первый раз полезете и всё.

    5) Нужно ли сжимать exe файл с помощью upx?

    И зачем это нужно делать? Чтобы лишний раз панику пользователю развести на пустом месте из ничего?
    Если задаётесь этим вопросом, ответ - НЕ НУЖНО. Соберите Release и всё.

    6) С помощью чего создать инсталлятор? сильно ли критичный вариант создать sfx-архив с exeшником, файлом реестра и dll файлам?.

    А точно нужен этот инсталлятор?
    Батника Uninstall с командой start /wait yourapp.exe --uninstall недостаточно? Программа запустится, найдет аргумент вычистит все свои данные, и завершится. Батник грохнет свою папку и себя. Всё.

    Инсталлятор нужен когда приложение очень много файлов ставит в т.ч. в систему (системные библиотеки, масса записей в ресстр). Если очень хочется модно/молодёжно, то создавайте при помощи InnoSetup.
    Ответ написан
    Комментировать
  • Как отправить post с файлом и параметром?

    HemulGM
    @HemulGM Куратор тега Delphi
    Delphi Developer, сис. админ
    Зависит от того, как его принимает сервер. Можешь передать внутри MultipartFormDataStream, а можешь в base64 формате в том же MultipartFormDataStream.

    И рекомендую использовать не Indy, а Sytem.Net.HttpClient.

    А в Indy передача файла происходит так:
    MultipartFormDataStream.AddFile('file', 'C:\test.rar', 'application/octet-stream');
    или
    MultipartFormDataStream.AddFile('file', 'test.jpg', 'application/octet-stream', image_ms);
    Ответ написан
    1 комментарий
  • Что конкретно делает эта функция mysqli_real_escape_string()?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Это хороший вопрос, в первую очередь потому что найти человека, который знает правильный ответ, практически нереально. Опроси 10 похапешников, 10 из них тебе наплетут ереси, которая не имеет с реальностью ничего общего. Любой, кто заикнется про SQL инъекции, уже облажался.

    При том что функция эта совершенно примитивная - экранировать кавычки в строках SQL. Для соблюдения корректного синтаксиса. Это единственная функция этой функции, и больше ни для чего она не нужна.

    Как ты, наверное, уже знаешь, строки в SQL берутся в кавычки:
    SELECT * FROM table WHERE name='vasya'
    Вот чтобы vasya не приняли за имя таблицы или ключевое слово, его берут в кавычки. Очень просто. Но иногда у человека имя не просто вася. Что будет вот с таким запросом?
    SELECT * FROM table WHERE name='Я Д'Артаньян, а все вокруг ...'

    Мясорубка будет. БД решит, что имя - это 'Я Д', а дальше какая-то фигня, которую она не понимает. И выдаст ошибку.
    Поэтому кавычки надо экранировать.
    SELECT * FROM table WHERE name='Я Д\'Артаньян, а все ...'

    никаких ошибок не выдаст.
    Вот mysqli_real_escape_string() как раз этим и занимается - экранирует кавычку слешем, а заодно и сам слеш, потому что если слеш окажется в конце строки,
    SELECT * FROM table WHERE text='Мну сегодня в любви вкладкой ошиблись :\'

    то БД решит, что последняя кавычка экранирована, и строка не заканчивается. Снова мясорубка.
    Также mysqli_real_escape_string() экранирует еще несколько символов, но уже из чисто эстетических соображений.

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

    Но читатель уж сучит ножками в нетерпении - а что же SQL инъекции, о которых так долго говорили большевики? Не может же быть, чтобы они были совсем не при чем. Окей, в качестве побочного эффекта, строка, в которой экранированы спецсимволы (слеш и кавычка), не пропустит инъекцию. Но здесь следует понимать две вещи:

    1. Строки надо форматировать в любом случае, независимо от того, ждем мы инъекцию, или нет. Мясорубка нам точно так же не нужна.
    2. Строками синтаксис SQL запросов не исчерпывается. Есть числовые литералы, есть имена полей. Для всех них mysqli_real_escape_string() бесполезна чуть более чем полностью.

    То есть, отсюда можно сделать вывод, что нельзя использовать mysqli_real_escape_string() для защиты от инъекций. Она предназначена для другого. Вот для этого другого, для форматирования строк, ее использовать можно. Но не нужно.

    Нашлись умные люди, которые придумали, что колупаться вручную с форматированием переменных для SQL запроса - это долго, неудобно, и можно что-то забыть или перепутать. И пусть лучше БД сама этим занимается. И придумали вместо переменных подставлять в запрос специальные маркеры, а сами переменные передавать отдельно. А БД уже потом сама разберется, что и как форматировать.

    В принципе, mysqli умеет так делать, но не так удобно как PDO. Поэтому при возможности вместо нее лучше использовать PDO:
    $stmt = $pdo->prepare("SELECT * FROM table WHERE name=? or name=?")
    $stmt->execute(["Vasya", "Д'Артаньян"]);
    $rows = $stmt->fetchAll();
    - и получить, в итоге, готовый массив с данными, которые вернула БД.
    Если же возможности нет, то кода придется написать чуть побольше
    $stmt = $mysqli->prepare("SELECT * FROM table WHERE name=? or name=?")
    $stmt->bind_param("ss", ...["Vasya", "Д'Артаньян"]);
    $stmt->execute();
    $rows = $stmt->fetch_all(MYSQLI_ASSOC);


    Но при этом всё равно никакой тебе возни с кавычками, слешами, real, escape, и прочей ерундой. Просто, быстро, лаконично и безопасно.
    Ответ написан
    4 комментария
  • Modx Revo: смена шаблона с помощью плагина?

    @alvisX
    Для смены шаблона текущего документа видел такой код через контроллер:
    $modx->controller->setProperty('template', $template);
    Ответ написан
    2 комментария
  • Как узнать количество страниц в индексе Google?

    dimonchik2013
    @dimonchik2013
    non progredi est regredi
    АПИ нет, парси селениумом

    автопарсинг Гугл требует знаний
    Ответ написан
    Комментировать
  • Как узнать количество страниц в индексе Google?

    twobomb
    @twobomb
    Не знаю, проверил у меня всё работает
    <?PHP
    $ch = curl_init();
    $site = "https://habr.com/";
    $url = "https://www.google.com/search?hl=ru&q=site:$site";
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_HEADER, 0);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER , true);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:50.0) Gecko/20100101 Firefox/50.0');
    $content = curl_exec($ch);
    if(!$content){
        echo 'Ошибка curl: ' . curl_error($ch);
    	die;
    }
    
    curl_close($ch);
    
    if(preg_match("/Результатов:\s*(примерно)?\s*([^(]+)/",$content,$matches))
    	echo "Количество: ".$matches[2];
    else
    	echo "Не найдено";
    ?>

    P.S. Ну врядли это все страницы, если вы для своего сайта, то используйте гугл сёрч консоле
    Ответ написан
    1 комментарий
  • Как вывести список записей по произвольному полю?

    @wtrouble
    $args = array(
          'posts_per_page' => 10,
          'category_name' => 'stati', 
          'post_status' => 'publish',
          'meta_query' => array(
    		   array(
    			'key'     => 'color',
    			'compare' => 'EXISTS'
    		)
    	)
    );
    $query = new WP_Query( $args );
    while ( $query->have_posts() ) {
          $query->the_post();
          the_title(); 
    }
    wp_reset_postdata();
    Ответ написан
    2 комментария