Faq события нажатия на системные кнопки формы (минимизация, закрытие )


Содержание

Переопределить стандартную кнопку закрытия (X) в форме Windows

Как мне изменить, что происходит, когда пользователь нажимает кнопку закрытия (красный X) в приложении Windows Forms (на С#)?

Вы можете переопределить OnFormClosing, чтобы сделать это. Просто будьте осторожны, вы не делаете ничего слишком неожиданного, так как щелчок «X» для закрытия — это хорошо понятое поведение.

ВНИМАНИЕ: Вам нужно проверить CloseReason и изменить поведение только в том случае, если это UserClosing. Вы не должны помещать что-либо здесь, что остановило бы процедуру отключения Windows.

Одна вещь, которой эти ответы не хватает, и какие новички, вероятно, ищут, заключается в том, что, хотя приятно иметь событие:

Он ничего не собирается делать, если вы не зарегистрируете событие. Поместите это в конструктор класса:

Либо переопределите OnFormClosing, либо зарегистрируйтесь для события FormClosing.

Это пример переопределения функции OnFormClosing в производной форме:

Это пример обработчика события, чтобы остановить закрытие формы, которая может быть в любом классе:

Чтобы получить дополнительные возможности, проверьте свойство CloseReason на FormClosingEventArgs, чтобы убедиться, что выполнено соответствующее действие. Вы можете выполнить только альтернативное действие, если пользователь пытается закрыть форму.

как сказал Джон Б, но вы также захотите проверить ApplicationExitCall и TaskManagerClosing CloseReason:

Одна из ситуаций, когда весьма полезно иметь возможность обрабатывать событие нажатия кнопки x, — это когда вы используете форму, являющуюся контейнером MDI. Причина в том, что закрытие и закрытие событий воспитываются сначала с детьми и, наконец, с родителем. Таким образом, в одном сценарии пользователь нажимает кнопку x для закрытия приложения, а родитель MDI запрашивает подтверждение. В случае, если он решает не закрывать приложение, но продолжать то, что он делает, дети уже обработали событие закрытия, которое потенциально потеряло информацию/работа. Одним из решений является перехват сообщения WM_CLOSE из цикла сообщений Windows в основной форме приложения (т.е. Закрытой, завершает приложение) следующим образом:

Это довольно часто задаваемый вопрос. Один хороший ответ здесь:

Если вы не чувствуете себя комфортно, добавляя свой код в событие Form_Closing, единственная другая опция, о которой я знаю, — это «взлом», который я использовал один или два раза. Не нужно прибегать к этому взлому, но вот оно:

Не используйте обычную кнопку закрытия. Вместо этого создайте свою форму, чтобы она не имела ControlBox. Вы можете сделать это, установив ControlBox = false в форме, и в этом случае вы все равно будете иметь нормальный бар в верхней части формы или вы можете установить форму FormBorderStyle в «None». Если вы идете по этому второму маршруту, не будет ни одного бара в верхней части или любой другой видимой границы, поэтому вам придется имитировать их либо путем рисования формы, либо путем художественного использования элементов управления Panel.

Практическое руководство. Обработка события нажатия кнопки в Windows Forms How to: Respond to Windows Forms Button Clicks

Самый простой способ использования форм Windows Button элемент управления должен выполнять определенный код, при нажатии кнопки. The most basic use of a Windows Forms Button control is to run some code when the button is clicked.

Щелкнув Button создает элемент управления также ряд других событий, таких как MouseEnter, MouseDown, и MouseUp события. Clicking a Button control also generates a number of other events, such as the MouseEnter, MouseDown, and MouseUp events. Если вы планируете присоединить обработчики событий для этих связанных событий, убедитесь, что их действия не конфликтуют. If you intend to attach event handlers for these related events, be sure that their actions do not conflict. Например если нажатие кнопки удаляет сведения, которые пользователь ввел в текстовое поле, при наведении указателя мыши на кнопку не должно отображать подсказки с несуществующими сведениями. For example, if clicking the button clears information that the user has typed in a text box, pausing the mouse pointer over the button should not display a tool tip with that now-nonexistent information.

Если пользователь пытается получить дважды щелкните Button элемента управления, каждый щелчок будет обрабатываться отдельно; то есть элемент управления не поддерживает события двойного щелчка. If the user attempts to double-click the Button control, each click will be processed separately; that is, the control does not support the double-click event.

Реагировать на нажатие кнопки To respond to a button click

На кнопке панели Click EventHandler напишите код для выполнения. In the button’s Click EventHandler write the code to run. Button1_Click должен быть привязан к элементу управления. Button1_Click must be bound to the control. Дополнительные сведения см. в разделе Как Создание обработчиков событий во время выполнения для форм Windows Forms. For more information, see How to: Create Event Handlers at Run Time for Windows Forms.

Обработка событий

Некоторые программы с применением JavaScript event работают напрямую с вводимыми пользователем данными. Момент возникновения и порядок таких взаимодействий не могут быть предсказаны заранее.

Обработчики событий

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

Именно так обрабатывался ввод данных на примитивных машинах. Более прогрессивным является определение нажатия клавиши и его постановка в очередь. Затем программа может периодически проверять очередь новых событий и реагировать на то, что там находит. В таком случае программа должна не забывать просматривать очередь и делать это часто.

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

Большинство программистов стараются избегать его, если это возможно.

Самым лучшим способом считается реализация системы, которая дает коду возможность реагировать на события, когда они происходят. Браузеры реализуют ее, предоставляя возможность регистрировать функции обработчиков для конкретных JavaScript event :

Функция addEventListener регистрируется таким образом, что ее второй аргумент вызывается всякий раз, когда происходит событие, описанное первым аргументом.

События и узлы DOM

Каждый обработчик событий браузера регистрируется в контексте. При вызове функции addEventListener она вызывается как метод для всего окна, так как в браузере глобальный диапазон эквивалентен объекту window . Каждый элемент DOM имеет свой собственный метод addEventListener , который позволяет отслеживать события именно в этом элементе:

В данном примере обработчик подключен к узлу кнопки. JavaScript mouse events приводит в действие обработчик, а клик в остальной части документа — нет.

Установив для узла атрибут onclick , мы получим тот же результат. Но узел имеет только один атрибут onclick , поэтому можно зарегистрировать для каждого узла только один обработчик. Метод addEventListener позволяет добавлять любое количество обработчиков. Так мы застрахованы от случайной замены обработчика, который уже был зарегистрирован.

Метод removeEventListener , вызывается с аргументами, аналогичными addEventListener . Он удаляет обработчик:

Чтобы отменить функцию обработчика, мы задаем для нее имя ( например, once ). Так мы передаем ее как в addEventListener , так и в removeEventListener .

Объекты событий

Хотя мы не упоминали об этом в приведенных выше примерах, в функции обработчиков JavaScript event передается аргумент: объект события. Он предоставляет дополнительную информацию о событии. Например, если мы хотим знать, какая клавиша мыши была нажата, нужно получить значение свойства объекта события which :

Информация, хранящаяся в объекте, различается зависимости от типа события. Свойство объекта type всегда содержит строку, идентифицирующую событие (например, « click » или « mousedown «).

Распространение

Обработчики событий ( например, JavaScript touch events ), зарегистрированные для родительских узлов, также будут принимать события, которые происходят в дочерних элементах. Если была нажата кнопка, находящаяся внутри абзаца, обработчики событий абзаца также получат событие click .

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

В любой момент обработчик события может вызвать для объекта события метод stopPropagation , чтобы предотвратить распространение события дальше. Это может быть полезно, когда у вас есть кнопка внутри другого интерактивного элемента, и вы не хотите, чтобы при нажатии кнопки активировалось поведение, заданное для клика мышью по внешним элементам.

В следующем примере мы регистрируем обработчики « MouseDown » как для кнопки, так и для абзаца. При клике правой клавишей ( JavaScript mouse events ) обработчик вызывает метод stopPropagation , который предотвращает запуск обработчика абзаца. При нажатии на кнопку другой клавишей мыши запускаются оба обработчика:

Большинство объектов событий имеют свойство target , которое указывает на узел, в котором они возникли. Вы можете использовать это свойство, чтобы случайно не обрабатывать какое-то событие, которое распространяется вверх из узла.

Также можно использовать JavaScript event target , чтобы расширить диапазон события определенного типа. Например, если у вас есть узел, содержащий длинный список кнопок, более удобно зарегистрировать один обработчик клика для внешнего узла и использовать свойство target , чтобы отслеживать, была ли нажата кнопка, а не регистрировать экземпляры обработчика для всех кнопок:

Действия по умолчанию

Со многими событиями связаны действия по умолчанию. Если вы нажмете на ссылку, то перейдете к целевому элементу ссылки. Если нажмете стрелку вниз, браузер прокрутит страницу вниз. Если вы кликните правой клавишей мыши, откроется контекстное меню.

Для большинства типов событий обработчики JavaScript event вызываются до выполнения действий по умолчанию. Если не нужно, чтобы выполнялось поведение по умолчанию, нужно вызвать для объекта события метод preventDefault .

Его использовать для реализации пользовательских сочетаний клавиш или контекстных меню. Или, чтобы переопределить поведение, которое ожидают пользователи. Ниже приводится ссылка, по которой нельзя перейти:

Старайтесь не делать так, если у вас нет на это веских причин.

В зависимости от браузера некоторые события не могут быть перехвачены. В Google Chrome , например, сочетание клавиш ( event keycode JavaScript ) для закрытия текущей вкладки ( Ctrl-W или Command-W ) не может быть обработано с помощью JavaScript .

События клавиш


Когда пользователь нажимает клавишу на клавиатуре, браузер запускает событие « keydown «. Когда он отпускает клавишу, срабатывает событие « keyup «:

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

В предыдущем примере использовано свойство объекта event keycode JavaScript . С его помощью определяется, какая именно клавиша была нажата или отпущена. Ноне всегда очевидно, как привести числовой код клавиши к фактической клавише.

Для считывания значений клавиш букв и цифр используется код символа Unicode . Он связан с буквой ( в верхнем регистре ) или цифрой, обозначенной на клавише. Метод charCodeAt для строк позволяет получить это значение:

С другими клавишами связаны менее предсказуемые коды клавиш. Лучший способ определить нужный код, это поэкспериментировать. Зарегистрировать обработчик события нажатия клавиши, который фиксирует коды клавиш, которые он получает, и нажать нужную клавишу.

Такие клавиши, как Shift , Ctrl , Alt порождают события, как обычные клавиши. Но при отслеживании комбинаций клавиш также можно определить, нажаты ли эти клавиши, по свойствам событий клавиатуры и JavaScript mouse events : shiftKey , ctrlKey , altKey и metaKey :

События « keydown » и « keyup » предоставляют информацию о фактическом нажатии клавиш. Но что, если нам нужен сам вводимый текст? Получать текст из кодов клавиш неудобно. Для этого существует событие, « keypress «, которое срабатывает сразу после « keydown «. Оно повторяется вместе с « keydown «, пока клавиша нажата. Но только для клавиш, с помощью которых производится ввод символов.

Свойство charCode в объекте события содержит код, который может быть интерпретирован, как код символа Unicode . Мы можем использовать функцию String.fromCharCode , чтобы преобразовать этот код в строку из одного символа.

Узел DOM , в котором происходит событие зависит, от того элемента, который находился в фокусе ввода при нажатии клавиши. Обычные узлы не могут находиться в фокусе ввода ( если не установить для них атрибут tabindex ), но такие элементы, как ссылки, кнопки и поля формы, могут.

Если никакой конкретный элемент не выделен фокусом ввода, то в качестве целевого узла для событий клавиши и JavaScript touch events выступает document.body .

Клики мыши

Нажатие клавиши мыши также приводит в действие ряд событий. События « mousedown » и « mouseup » похожи на « keydown » и « keyup «. Они запускаются, когда нажата и отпущена клавиша мыши. Данные события возникают в узлах DOM, на которые был наведен указатель мыши, когда возникло событие.

Для общего узла, к которому относилось как нажатие, так и освобождение клавиши мыши, после события « mouseup » запускается событие « click «. Например, если нажать клавишу мыши на одном пункте, а затем переместить курсор на другой пункт и отпустить кнопку, то событие « click » будет происходить в элементе, который содержит оба эти пункта.

Если два клика возникли близко друг к другу, также запускается событие « dblclick » ( двойной клик ). Оно возникает после второго клика. Чтобы получить точную информацию о месте, где произошло событие мыши, нужно получить значение свойств pageX и pageY , которые содержат координаты события ( в пикселях ) относительно левого верхнего угла документа.

Ниже приведена реализация примитивной программы для рисования. Каждый раз при нажатии мыши в документе ( под курсором ) добавляется точка:

Свойства clientX и clientY подобны pageX и pageY , но они относятся к видимой части документа. Они могут использоваться для сравнения координат мыши с координатами, возвращаемыми функцией getBoundingClientRect .

Движение мыши

Каждый раз, когда перемещается курсов мыши, срабатывает событие « mousemove » из набора JavaScript mouse events . Оно может быть использовано для отслеживания положения мыши. Это применяется при реализации возможности перетаскивания элементов мышью.

В следующем примере программа выводит на экран панель и устанавливает обработчики событий таким образом, что при перетаскивании эта панель становится уже или шире:

Обратите внимание, что обработчик « mousemove » зарегистрирован для всего окна. Даже если во время изменения размеров мышь выходит за пределы панели, мы все равно обновляем ширину панели и прекращаем JavaScript touch events , когда клавиша мыши была отпущена.

Мы должны прекратить изменение размера панели, когда пользователь отпускает клавишу мыши. К сожалению, не все браузеры устанавливают для событий « mousemove » свойство which . Существует стандартное свойство buttons , которое предоставляет аналогичную информацию, но оно также поддерживается не во всех браузерах. К счастью, все основные браузеры поддерживают что-то одно: либо buttons , либо which . Функция buttonPressed в приведенном выше примере сначала пытается использовать свойство buttons , и, если оно не доступно, переходит к which .

Когда курсор мыши наводится или покидает узел, запускаются события « mouseover » или « mouseout «. Они могут использоваться для создания эффектов при наведении курсора мыши, вывода какой-нибудь подписи или изменения стиля элемента.

Чтобы создать такой эффект, недостаточно просто начать его отображение при возникновении события « mouseover » и завершить после события « mouseout «. Когда мышь перемещается от узла к одному из его дочерних элементов, для родительского узла происходит событие « mouseout «. Хотя указатель мыши не покинул диапазон распространения узла.

Что еще хуже, эти JavaScript event распространяются так же, как и другие события. Когда мышь покидает один из дочерних узлов, для которого зарегистрирован обработчик, возникнет событие « mouseout «.

Илон Маск рекомендует:  Что такое код swf_shapefillsolid

Чтобы обойти эту проблему, можно использовать свойство объекта события relatedTarget . В случае возникновения события « mouseover » оно указывает, на какой элемент был наведен курсор мыши до этого. А в случае возникновения « mouseout » — к какому элементу перемещается указатель. Мы будем изменять эффект наведения мыши только, когда relatedTarget находится вне нашего целевого узла.

В этом случае мы изменяем поведение, потому что курсор мыши был наведен на узел из-за его пределов ( или наоборот ):

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

Эффект наведения гораздо проще создать с помощью псевдоселектора CSS :hover , как показано в следующем примере. Но когда эффект наведения предполагает что-то более сложное, чем просто изменение стиля целевого узла, тогда нужно использовать прием с использованием событий « mouseover » и « mouseout » ( JavaScript mouse events ):

События прокрутки

Каждый раз, когда элемент прокручивается, в нем срабатывает JavaScript scroll event . Его можно использовать для отслеживания того, что в данный момент просматривает пользователь; для отключения анимации, расположенной вне окна просмотра.

В следующем примере мы выводим индикатор прогресса в правом верхнем углу документа и обновляем его, чтобы он по частям заливался другим цветом по мере прокрутки страницы вниз:

Установив для элемента свойство position или fixed , мы получим тот же результат, что и при установке position:absolute . Но так мы также блокируем прокрутку элемента вместе с остальной частью документа. В результате индикатор прогресса будет статически закреплен в верхнем углу. Внутри него находится еще один элемент, размер которого изменяется в соответствии с текущим прогрессом.

В качестве единиц измерения при установке ширины мы используем % , а не рх , чтобы размеры элемента изменялись пропорционально размеру индикатора прогресса.

Глобальная переменная innerHeight содержит высоту окна, которую мы должны вычесть из общей доступной прокручиваемой высоты документа. Нельзя прокручивать окно ниже при достижении нижней части документа. С innerHeight также может использоваться innerWidth . Разделив pageYOffset ( текущую позицию окна прокрутки ) на максимально допустимую позицию прокрутки и умножив на 100, мы получаем процент для индикатора прогресса.

Вызов preventDefault для JavaScript scroll event не предотвращает прокрутку. Обработчик события вызывается только после того, как происходит прокручивание.

События фокуса ввода

Когда элемент находится в фокусе ввода, браузер запускает в нем событие « focus «. Когда фокус ввода снимается, запускается событие « blur «.

Эти два события не имеют распространения. Обработчик родительского элемента не уведомляется, когда дочерний элемент выделяется фокусом ввода.

В следующем примере выводится подсказка для текстового поля, которое в данный момент находится в фокусе ввода:

Объект окна получает события « focus » и « blur «, когда пользователь переходит или покидает вкладку, окно браузера, в котором выводится документ.

Событие загрузки

Когда завершается загрузка страницы, для объектов тела документа и окна возникает JavaScript event «load» . Оно используется для планирования инициализации действий, для которых требуется загрузка всего документа. Не забывайте, что содержимое

Иногда нужно отменить функцию, которую мы запланировали. Это делается путем сохранения значения, возвращаемого функцией setTimeout , и вызова для нее clearTimeout :

Функция cancelAnimationFrame работает так же, как clearTimeout . Она вызывается значением, возвращаемым requestAnimationFrame , чтобы отменить кадр ( если он еще не был вызван ).

Похожий набор функций, setInterval и clearInterval используется для установки таймера, который должен повторять действие каждые X миллисекунд:

Дробление

Некоторые типы событий могут запускаться много раз в течение короткого периода времени ( например, « mousemove » и javascript scroll event ). При обработке таких событий, нужно быть осторожным, чтобы это не происходило очень долго, иначе обработчик будет выполнять действие столько времени, что взаимодействие с документом станет медленным и скачкообразным.

Если нужно сделать что-то нестандартное в таком обработчике, можно использовать setTimeout , чтобы быть уверенными, что это не растянется слишком надолго. Это обычно называют дроблением события. Существует несколько отличающихся друг от друга подходов к дроблению.

В первом примере мы хотим сделать что-то, когда пользователь печатает. Но не хотим делать это после каждого события нажатия клавиши. Когда пользователь быстро печатает, нужно подождать, пока не произойдет пауза. Вместо немедленного выполнения действия в обработчике события мы устанавливаем задержку. Мы также очищаем предыдущую задержку ( если таковая имеется ). Если события происходят через короткие интервалы времени ( меньше, чем установленная нами задержка ), то задержка от предыдущего события отменяется:

Передача неопределенного значения для clearTimeout или его вызов для задержки, которая уже запущена, не даст никакого результата. Нам больше не нужно быть осторожными относительно того, когда его вызывать, мы просто делаем это для каждого события.

Можно использовать иной сценарий, если нужно разделить ответы небольшим промежутком времени. Но чтобы при этом они запускались во время серии событий, а не только после нее. Например, можно отправлять в ответ на события « mousemove » ( JavaScript mouse events ) текущие координаты мыши, но только через каждые 250 миллисекунд:

Заключение


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

Каждое событие относится к определенному типу (« keydown «, « focus » и так далее ), который идентифицирует его. Большинство событий вызывается для конкретного элемента DOM , а затем распространяются на родительские узлы элемента. Это позволяет обработчикам, связанным с этими элементами, обрабатывать их.

Когда вызывается обработчик, ему передается объект события с дополнительной информацией о действии. Этот объект также содержит методы, позволяющие остановить дальнейшее распространение события ( stopPropagation ) или предотвратить обработку события браузером по умолчанию ( preventDefault ).

Нажатие клавиш порождает события « keydown «, « keypress » и « keyup «. Нажатие мыши порождает события « mousedown «, « mouseup » и « click «. Перемещение мыши — « mousemove «, « mouseenter » и « mouseout «.

JavaScript scroll event можно определить с помощью события « scroll «, а смена фокуса — « focus » и « blur «. После завершения загрузки документа для окна возникает событие « load «.

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

Данная публикация представляет собой перевод статьи « Handling Events » , подготовленной дружной командой проекта Интернет-технологии.ру

Минимизация формы при минимизации нажатия кнопки в VB.NET

У меня есть форма, которая максимизируется с этим свойством:

и с FormBorderStyle = None . Это означает, что когда эта форма открыта, ее нельзя свести к минимуму, а это поведение, которое я хочу.

В этой основной форме есть кнопка, открывающая еще одну небольшую форму под названием «Консоль», где я могу видеть сообщения, которые вызывается основной формой. Форма «Консоль» — FormBorderStyle = FixedSingle , а это значит, что можно свести к минимуму.

Проблема в том, что, когда я сворачиваю форму «Консоль», я не могу открыть ее снова, потому что основная форма занимает весь экран.

То, что я пытаюсь сделать, — это свести к минимуму «Консоль» и увидеть его, чтобы максимально увеличить его, когда захочу.

Я попытался использовать события формы «Консоль», такие как SizeChanged или KeyUp , и управлять при нажатии кнопки минимизации.

Все, что я пробовал, пошло не так, и всегда, когда я нажимаю кнопку «Свернуть», форма сводится к минимуму.

Возможно, когда я минимизирую форму, нажав кнопку «Свернуть», чтобы увидеть окно с минимизацией, чтобы максимизировать его, когда я хочу?

Принимаю любые предложения!

Создан 31 авг. 17 2020-08-31 09:55:02 daniel lozano

Ну, вам нужно решить, как вы хотите подходить к нему. «видеть окно минимизации, чтобы максимизировать его» ничего не значит. У вас есть кнопка, подумайте над ее использованием, чтобы восстановить окно. Или просто не позволяйте минимизировать его вообще. Или закройте окно, когда оно будет сведено к минимуму. Или дайте ему кнопку на панели задач. Или используйте диспетчер компоновки стыковки. – Hans Passant 31 авг. 17 2020-08-31 10:06:24

1 ответ

Окончательный вариант Я использовал этот параметр: когда я нажимаю для сведения к минимуму, я просто перемещаю форму и изменяю ее размер. Возможно, это простой и ручной вариант, и наверняка это будут лучшие способы сделать это, но это дает мне то, что мне нужно сейчас.

@ HansPassant благодарит за вашу помощь! Я собираюсь найти информацию о менеджере компоновки стыковки, как вы предложили.

Я использовал некоторые кнопки расположение главной формы, чтобы найти форму «Console», но это может быть любое значение.

Создан 31 авг. 17 2020-08-31 11:31:48 daniel lozano

Тонкости свойства disable у кнопок формы, отправляемой на сервер (Как делать кнопки неактивными)

Уже неоднократно на хабре (вот в этой публикации и в этой) ставился вопрос о том, что было бы хорошо кнопкам формы, отправляемой на сервер, ставить свойство disabled = «disabled» .

Однако, до сих пор так и не разобрались, зачем это нужно и как все-таки это делать. Казалось бы, что может быть проще и о чем здесь вообще можно разговаривать, ан нет — на поверку все оказалось не так тривиально. Сразу замечу, что нижеследующие рассуждения применимы к обеим типам форм: как отправляемым через обычный SUBMIT, так и с помощью AJAX.

Зачем нужно делать кнопки неактивными

  1. Чтобы пользователю стало очевидным, что он уже нажал на кнопку, и что форма отправляется
  2. Чтобы сервер не загружался лишними запросами, и чтобы уменьшить вероятность какой-либо ошибки

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

Понятно также, что лишние запросы можно предотвратить, повесив на форму какой-нибудь , и при всяком сабмите проверять на наличие этого класса. Но зачем делать эти проверки, когда можно обойтись без них, просто сделав кнопку неактивной?

Как делать кнопки неактивными

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

Почему недостаточно просто делать нажатую кнопку неактивной:

  1. Submit формы может произойти и по нажатию на Enter. Поэтому обработку кнопок надо вешать на событие onsubmit самой формы. К тому же, у формы может быть несколько кнопок, и было бы логичным делать их все неактивными, а не только ту кнопку, которую нажали.
  2. Если после сабмита формы вновь вернуться на страницу с формой (по кнопке «Назад» в браузере), то сработает кеширование: мы столкнемся с неактивными кнопками и не сможем отправить форму еще раз — без принудительной перезагрузки страницы с потерей всех заполненных ранее полей (Возврат к поисковой форме со страницы результатов поиска тут живейший пример).
  3. Если у формы несколько кнопок (например, «Опубликовать» и «Отмена»), то мы не сможем передать серверу, какая именно кнопка была нажата: неактивная кнопка не передает свое имя и значение — даже если мы делаем ее неактивной по событию onsubmit

Итак, сценарий создания неактивных кнопок

Минимизация формы при минимизации нажатия кнопки в VB.NET

У меня есть форма, которая максимизируется с этим свойством:

и с FormBorderStyle = None . Это означает, что когда эта форма открыта, ее нельзя свести к минимуму, а это поведение, которое я хочу.

В этой основной форме есть кнопка, открывающая еще одну небольшую форму под названием «Консоль», где я могу видеть сообщения, которые вызывается основной формой. Форма «Консоль» — FormBorderStyle = FixedSingle , а это значит, что можно свести к минимуму.

Проблема в том, что, когда я сворачиваю форму «Консоль», я не могу открыть ее снова, потому что основная форма занимает весь экран.

То, что я пытаюсь сделать, — это свести к минимуму «Консоль» и увидеть его, чтобы максимально увеличить его, когда захочу.

Я попытался использовать события формы «Консоль», такие как SizeChanged или KeyUp , и управлять при нажатии кнопки минимизации.

Все, что я пробовал, пошло не так, и всегда, когда я нажимаю кнопку «Свернуть», форма сводится к минимуму.

Возможно, когда я минимизирую форму, нажав кнопку «Свернуть», чтобы увидеть окно с минимизацией, чтобы максимизировать его, когда я хочу?

Принимаю любые предложения!

Создан 31 авг. 17 2020-08-31 09:55:02 daniel lozano

Ну, вам нужно решить, как вы хотите подходить к нему. «видеть окно минимизации, чтобы максимизировать его» ничего не значит. У вас есть кнопка, подумайте над ее использованием, чтобы восстановить окно. Или просто не позволяйте минимизировать его вообще. Или закройте окно, когда оно будет сведено к минимуму. Или дайте ему кнопку на панели задач. Или используйте диспетчер компоновки стыковки. – Hans Passant 31 авг. 17 2020-08-31 10:06:24

1 ответ

Окончательный вариант Я использовал этот параметр: когда я нажимаю для сведения к минимуму, я просто перемещаю форму и изменяю ее размер. Возможно, это простой и ручной вариант, и наверняка это будут лучшие способы сделать это, но это дает мне то, что мне нужно сейчас.

@ HansPassant благодарит за вашу помощь! Я собираюсь найти информацию о менеджере компоновки стыковки, как вы предложили.

Я использовал некоторые кнопки расположение главной формы, чтобы найти форму «Console», но это может быть любое значение.

Создан 31 авг. 17 2020-08-31 11:31:48 daniel lozano


Faq события нажатия на системные кнопки формы (минимизация, закрытие )

Уважаемые мастера, в некоторые моменты работы приложения (в частности открытые запросы или датасеты, ну и пр.) запрещаю его закрытие вот таким образом:

SysMenu := GetSystemMenu(Handle, False);
Windows.EnableMenuItem(SysMenu, SC_CLOSE, MF_DISABLED);

При компиляции под D5 все нормально, однако под D2009 системная кнопка закрытия не «дисейблится».
Подскажите, возможно ли каким либо другим способом, осуществить это под D2009?

а почему просто не обработать событие разрешения закрытия?

> KilkennyCat © (16.08.09 14:18) [1]
> а почему просто не обработать событие разрешения закрытия?
>

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

Конечно. Гораздо проще задисэйблить. Начнем с кнопки. Потом задисейблим Альт+Ф4. Потом Ctrl+alt+del. Потом кнопку «Пуск». Потом повербуттон на системнике. успокоимся при попытке задисэйблить резет.

Причем, условие задисэйбливания, похоже, оказывается проще проверки CanClose. Блеск.

А вот с CanClose действительно красиво.
Не додумался:(

> KilkennyCat (16.08.2009 14:37:03) [3]

Не надо успокаиваться на Reset — уже есть программные, и даже на кабели питания тоже не стоит, поскольку есть встроеные UPS


> а почему просто не обработать событие разрешения закрытия?

потому что интерфейс должен показывать то, что он может обрабатывать. В данном случае кнопка закрытия не должна срабатывать, и надо дать понять пользователю, а не строить отвратные конструкции которые мессаджбоксом (перехватив фокус) расскажут юзеру, что в данный момент нельзя нажимать эту кнопку. Но убирать ее совсем — не красиво.


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

это где такой бред написан? или сами придумали?

> потому что интерфейс должен показывать то, что он может
> обрабатывать. В данном случае кнопка закрытия не должна
> срабатывать, и надо дать понять пользователю, а не строить
> отвратные конструкции которые мессаджбоксом (перехватив
> фокус) расскажут юзеру, что в данный момент нельзя нажимать
> эту кнопку. Но убирать ее совсем — не красиво.

Пользователь хочеть закрыть окно, он не понимает, что в окне
есть какие-то открытые датасеты и запросы и пр., крестик
задисейблен, закрыть окно нельзя. Что делать пользователю?
Как дать ему понять, что нужно сперва закрыть запрос, датасет и пр.?


> это где такой бред написан?

там, где ты его не читал, разумеется.

Илон Маск рекомендует:  Asp программное администрирование iis


> Loginov Dmitry © (16.08.09 18:06) [9]

если в это время идет запрос и появляется окошко в котором написано «обработка данных» то было бы логично встроить туда функцию «прервать».
Я не говорю за все случаи.

> однако под D2009 системная кнопка закрытия не «дисейблится»

Проверил код под Delphi 2009/2010
Всё отлично работает. ОС Windows Vista

> Проверил код под Delphi 2009/2010
> Всё отлично работает. ОС Windows Vista

У меня XP
:(


> antonn © (16.08.09 16:05) [7]

> потому что интерфейс должен показывать то, что он может

Для показывать нужен MF_GRAYED.


> KilkennyCat © (16.08.09 14:37) [3]

> Конечно. Гораздо проще задисэйблить. Начнем с кнопки. Потом
> задисейблим Альт+Ф4.

Затем меню (окна) Application вместе с его Альт+Ф4..

> У меня XP

Точно? А почему в шапке темы написано что Windows 2003 Server?

Сейчас специально проверю в виртуальной XP :) Даже скриншот выложу. Мне почему-то кажется что всё получится и там.

Более того — под XP этот код сразу и отключает «крестик» (под Vista — только затемняет и делает некликабельным)

Скомпилировал два exe-шника: под Delphi 2009 и под Delphi 2010. Нормлаьно работают оба.

Вот код кнопки, которая нажималась:
var SysMenu: Cardinal;
begin
SysMenu := GetSystemMenu(Handle, False);
Windows.EnableMenuItem(SysMenu, SC_CLOSE, MF_DISABLED);
end;

Уж не знаю, где ошибка, то среда разработки и компилятор тут точно не замешаны. Хотя стоп. У меня стоит Update 3 для D2009. Последний шанс — установить его, если это ещё не сделано, и проверить )))

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

KilkennyCat, бред про то, что интерфейс должен показывать что с ним можно делать, а что нельзя вы можете прочесть в книгах Интерфейс Джефа Раскина и Дизайн привычных вещей Дональда Нормана.

Конкретно, если интересно, можно полагать, что человек выполняет различные задачи за семь шагов:

1. Формирование цели.
2. Формирование намерения.
3. Определение необходимых действий.
4. Исполнение действий.
5. Восприятия состояния окружающего пространства.
6. Интерпретация окружающего пространства.
7. Оценка результатов действия.
Подробнее про это есть в моем блоге (http://ksoftware.ya.ru/replies.xml?item_no=1877).

В данном случае представим, что цель человека — закрыть окно. Так как кнопка закрытия активна, то вполне вероятно, что человек сформирует намерение нажать её. Определит нужные действия (передвижение мыши, клик и т. д.) и выполнит их. Однако ожидаемого результата не получит и ему придется придумывать новые намерения или пересматривать цель.

Таким образом целая туча ментальных и других усилий пропадут за зря, а это не может не раздражать.

Поэтому предложение Антона, в общем, верное, если на кнопку нельзя нажимать, то она и должна выглядеть не нажимаемой.

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

Я думаю, что автор топика пытается таким образом запретить пользователю закрывать окно пока он, допустим, не сохранит данные. В этому случае решение запретить закрытие плохое. Нужно попытаться сделать так, чтобы и окно закрывалось когда угодно и данные не терялись. Как этого достичь зависит от конкретной задачи.

Автор, озвучьте задачу пожалуйста.


> Kolan © (18.08.09 23:43) [18]

Многа буков.

Интерфейс не должен ввергать пользователя в ступор. Он должен быть логичен и удобен. Этот крестик всегда был для закрытия. Независимо ни от чего. И если закрыть нельзя, потому что что-то там не так, то об этом сообщается.
Умные слова, типа
> 5. Восприятия состояния окружающего пространства.

это конечно, круто.
Собственно, мне пофиг. Я умных книг не читаю. Я сам думаю, я очень много лет обучаю юзверей и решаю их проблемы с непониманием интерфейсов и вполне вправе заявить еще раз:
> нтерфейс должен показывать то, что он может обрабатывать
— это бред.

Кстати, окошечко с обратным отсчётом «завершение работы системы» (shutdown) как раз с disable-крестиком )


> TIF © (19.08.09 00:09) [20]

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

Жаль, что вы столько лет потратили зря, ведь дело не в «юзверях», как вы их называете, это интерфейсы тех программ, что «юзвери», а на самом деле обычные люди, плохие и не понятные.

Но так как вам на все пофиг и вы ничего не читаете, то и спорить с вами не буду.
Не буду рассказывать про то, что модальные окна — это введение режима, а режимы приводят к ошибкам. Не буду еще раз повторять, что в данном случае дисэблить кнопку действительно не нужно, а лучше сделать программу по другому. Не буду, потому что это бесполезно. На вашей стороне опыт, да. Спор я проиграю априори. И букаф многа будет — зачем?

> что такое «априори»?

http://ru.wikipedia.org/wiki/%D0%90%D0%BF%D1%80%D0%B8%D0%BE%D1%80%D0%B8
Априо?ри (лат. a priori — буквально «от предшествующего») — знание, полученное до опыта и независимо от него (знание априори, априорное знание). Этот философский термин получил важное значение в теории познания и логике благодаря Канту. Идея знания априори связана с представлением о внутреннем источнике активности мышления. Учение, признающее знание априори, называется априоризмом. Противоположностью априори является апостериори (лат. a posteriori — от последующего) — знание, полученное из опыта (опытное знание). В современной философии априори (как и апостериори) считается видом дескриптивного знания.

имхо по сабж: крестик закрытия активен, и при нажатии появляется мессадж, который объясняет пользователю, что, надо подождать или сделать что-то,или чтобы он подтердил прекращение текущего действия, но дисэйблить, яб лично не стал.

Априори = к гадалке не ходи. То есть получится: Спор я проиграю, к гадалке не ходи.


> Kolan © (19.08.09 09:26) [26]

ну так, так бы и сказал. нафига усложнять?

Не думал, что это слово может вызвать затруднения.


> Kolan © (18.08.09 23:43) [18]
> Не понятно как и где объяснять почему она не работает и что делать, если
> хочется закрыть окно.

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

Хинт — хорошее решение, наверняка он окажется в локусе внимания.


А интересно, почему программу бывает нельзя закрыть?

> Kolan (19.08.2009 11:44:30) [30]

Ну допустим идет форматирование винчестера или подготовка чего то, чего недопустимо прерывать.
У меня на одном из серверов даже кнопка RESET блокируется в подобных случаях.

> [31] Anatoly Podgoretsky © (19.08.09 11:58)
> У меня на одном из серверов даже кнопка RESET блокируется
> в подобных случаях.

Ничего се, это уже и не ресет получается.

Не убедительный пример. Форматирование диска можно прервать даже в Виндоусе. Более того это процесс можно даже на паузу поставить.

Блокирование кнопки Ресета мне кажется таким же бессмысленны как и запрещение закрытия программы. А вдруг свет выключат и что тогда?
— А надо бесперебойник иметь!
— А свет вырубили 7 часов назад.

То есть я считаю, что такой подход по сути плох. Лучше сделать так, чтобы при закрытии работа сохранялась сама, а потом её можно было бы продолжить.

Пример того, «чего недопустимо прерывать» еще жду.

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

А если я нажму питание, программа не даст Виндоусу выключится?

> Kolan (19.08.2009 13:29:33) [33]

Я вспомнил более точно, это был серверный раид и не все операции допустимо прерывать, например перепрошивка БИОС

Кнопка питания уже давно программная, а кнопку Reset я встретил уже на двух машинах, на серверах Интел и на ноутбуках НР определенных моделей. И при некоторых операциях блокируются обе. А питание можно выключить или клавишей на блоке питания или выдергиванием шнура питания. Для некоторых операциях с BMC/FRU недостаточно выключения питания кнопкой или сброса, а требуется физическое отключение.

В свое время тоже смеялись над клавишей Power и программным выключением питания, ой как смеялись. Дошла очередь и до Reset и никаких проблем с Reset нет, точно также можно подержать 4 секунды, и произойдет сброс, даже при полностью зависшим компьютером.


> Kolan © (19.08.09 13:57) [35]

Даст. Ну ты же программист, что не знаешь как разобраться в сообщениях или в цепочке событий?

Andy BitOff, так а что в этом случае будет с длительным процессом? Он прервется? Если да, то выходит случайная ошибка все равно возможна и необратима.

Тогда он прервется по «Остановить процесс» и программа завершится. Но это уже не моя проблема. Необратимого в данном случае ничего нет, просто придется начинать с начала.

Я не могу обеспечить всем вселенское счастье, но могу оградить неумелого юзера, от опрометчивых поступков.

Получается что дисэйбление кнопки закрытия виляет только на вероятность возникновения ошибки, причем неизвестно как. Видимо с БИОСом тоже самое примерно.

Я сильно не настаиваю, общего хорошего решения наверно не существует.

Просто часто ребята лепят формы типа «А вы уверены что хотите. ?» и не понимают, что это почти всегда плохо и что от формы можно избавится.


> Andy BitOff © (19.08.09 13:43) [34]

> У меня есть процесс, который длится очень долго, в зависимости
> от входных значений может длится до получаса (еще и от мощностей
> зависит), так вот я не даю закрыть программу юзеру, пока
> он не нажмет кнопку «Остановит процесс», о чем честно ему
> и сообщаю. Если он решил закончить, то пусть сознательно
> остановит процесс и потом не жалуется.

Не очень понятно, чем эти полчаса юзер занимается.
Могу предположить два варианта: вводит для оной программы
доп.данные или, ожидая результатов, режется в сапера.

В первом случае юзер, все равно, не простит автора, если его
кропотливая работа пропала даром (даже если э/п выключили).

Во втором случае дополнительная кнопка спасет, если по ней трудней
попасть мышью в азарте игры, но проблема остается — куча ресурсов
и времени потеряно. По уму, если юзеру нужны только результаты,
то лучше всего поручать такие задачи некому серверу, а юзеру
присылать квитанцию — готово, можно забирать.

> Kolan (19.08.2009 14:36:42) [42]

> «А вы уверены что хотите. ?»

Или, Леонид, например выполнять работу в фоне, свернувшись, прости Господи, в трей. Хорошо бы только на случай отрубания питания иметь кнопку «продолжить то, что делалось».


> Leonid Troyanovsky © (19.08.09 14:52) [43]

Именно второй случай. Он волен заниматься чем хочет.
Не совсем понял, что за дополнительная кнопка. Мы же, вроде, про отлючение возможности клиикнуть по крестику в углу формы. Если он попадет туда случайно, то ничего потеряно не будет.
В той задаче по уму надо было делать другое. Надо было делать другую структуру хранения входных данных. Но. Как всегда но. Данные есть, структура их самих (данных) ужастна, структура их хранения не оптимальна, но разрабатывалась еще в 94 году и с того времени пополнялась и поддерживалась. И т.д. и т.п.
В общем с чем дали с тем и работали.

> Leonid Troyanovsky (19.08.2009 14:52:43) [43]

А чтобы не резался, запрещать клавиатуру и мышь.


> Kolan © (19.08.09 15:11) [45]

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

Вот вспомнил реальный случай. Пришел к юзеру. Давай, говорю, полную проверку включай, посмотрим. Запускает. Я говорю, ладно, покажи мне пока то-то и то-то. Перед ним окно с процессом проверки. Кликает крест. Хинт. Недоумение. Я говорю, не надо закрывать, сверни. Вот вам и реальная история.


> В той задаче по уму надо было делать другое.

По другому наверно :)

Правильно ли я понял, что если вашу программу (данные, структуру, базу и пр.) переделать, то дисэбление крестика не понадобится?


> Kolan © (19.08.09 15:22) [49]
> Правильно ли я понял

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


> Andy BitOff © (19.08.09 15:12) [46]

> Не совсем понял, что за дополнительная кнопка.

Которая «Убить процесс», она ж разрешает закрытие по крестику.

> Andy BitOff © (19.08.09 15:21) [48]

> говорю, не надо закрывать, сверни.

Ну сделай для таких настройку: крестиком — сворачивать (в трей :)


> Anatoly Podgoretsky © (19.08.09 15:16) [47]

> А чтобы не резался, запрещать клавиатуру и мышь.

Чего-то уж давненько не спрашивали про оное.


> Leonid Troyanovsky © (19.08.09 15:34) [51]
> Которая «Убить процесс», она ж разрешает закрытие по крестику.

В эту кнопку сложно попасть случайно ;)


> Ну сделай для таких настройку: крестиком — сворачивать (в трей :)

А вот это действительно интересно. Как-то не подумал. Но не в трей, а просто minimize. Но это опять же блокировка закрытия. То, о чем мы тут и говорим.


> Andy BitOff © (19.08.09 15:42) [53]

> не в трей, а просто minimize. Но это опять же блокировка
> закрытия.

Но, это уже осознанный выбор, особенно хорошо, если настраивать
будет админ, уже не отмажешься :)

Ну, и там тоже не просто minimize, надо еще корректно обработать
WM_QUERYENDSESSION.


> Leonid Troyanovsky © (19.08.09 16:04) [54]
> надо еще корректно обработать WM_QUERYENDSESSION.

Ну, это само-собой ;)

Не надо только делать сворачивание по кнопке закрыть. Это много хуже варианта с хинтом, это дезинформация. Хотя смайлик всё объясняет.

Лично, мне не очень нравится, когда стандартный виндовый функционал переделывают на иной: раз «крестик» — значит «закрыть», а не «свернуть», «скрыть» и т.п.
Я бы полностью согласился с > Andy BitOff © (19.08.09 13:43) [34], но, прочитав > Leonid Troyanovsky © (19.08.09 14:52) [43] задумался..
Все же, надо исходить от важности задач. Если прерывание длительного процесса чревато, то лучше пользователя заранее предупредить о том, что процесс прерывать нельзя под страхом смерти и уже после убрать из поля видимости любимый ими крестик, ну, и заблокировать что только можно, как > Anatoly Podgoretsky © (19.08.09 11:58) [31]

И еще, обычные пользователи не любят читать, особенно, то, что им пишет система (или собственная программа, я познал это на своем опыте), они клацают Enter не читая. Поэтому везде, где «Да» — чревато, активной делаю кнопку «Нет»:)

> Leonid Troyanovsky (19.08.2009 15:41:52) [52]

Уже стали Махоткина забывать



> Kolan © (19.08.09 16:20) [56]

> много хуже варианта с хинтом, это дезинформация. Хотя смайлик
> всё объясняет.

Вовсе не смайлик, а то, что юзер находясь в здравом и т.д.
определяет свой выбор.

Вот, некоторые, например, предпочитают Enter vs Tab, чего им
твои лекции об оной неправильности с точки зрения MS.


> И еще, обычные пользователи не любят читать, особенно, то,
> что им пишет система (или собственная программа, я познал
> это на своем опыте), они клацают Enter не читая. Поэтому
> везде, где «Да» — чревато, активной делаю кнопку «Нет»:)

Хорошая программа вообще вредных действий по умолчанию не должна предлагать.

Илон Маск рекомендует:  Поиск нужного слова на странице или в документе

Вы сделали хорошее наблюдение, но неправильный вывод. Люди так же быстро научаются жать Нет, Да, Закрыть или ЧтоУгодно, поэтому ваше решение не надёжное.

Если изучить ошибки, которые допускают люди, а их несколько видов, то можно дать два совета:

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

> MonoLife (19.08.2009 16:21:57) [57]

Фи как ограничено, надо просто оставить только кнопку НЭТ


> чего им
> твои лекции об оной неправильности с точки зрения MS

Где это я читал такие лекции? Особенно про точку зрения МС?


> MonoLife © (19.08.09 16:21) [57]

> 13:43) [34], но, прочитав > Leonid Troyanovsky © (19.08.
> 09 14:52) [43] задумался..

Классно, когда твои сообщения заставляют задуматься.
Я аж перечитал, чего такого умного сообщил :)

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

Предупреждения к делу не пришьешь :)
Однако, тотальное логирование вызывает негатив.
Проще, если заинтересованные лица разберуться междусобойчиком.

> ну, и заблокировать что только можно, как > Anatoly
> Podgoretsky © (19.08.09 11:58) [31]

Это Анатолий шутит.


> Вы сделали хорошее наблюдение, но неправильный вывод. Люди
> так же быстро научаются жать Нет, Да, Закрыть или ЧтоУгодно,
> поэтому ваше решение не надёжное.
>

Я и не говорил что мое решение надёжное)) и пришел я к этим выводам не за год. У меня, просто, так сложилось, за 4 года круг моих подопечных пользователей различными приложениями особо не изменился, и наблюдения мои не голословные..
Опять же, зависит от цели. можно все равно подвести какой-то итог за многолетние пользование виндой.. Большинство программ, в диалоге которых предлагается выполнить какое-то необратимое действие, но требуемое пользователю (к примеру, удалить что-нить) «подставят под Enter», в первую очередь кнопку «Нет». А кнопку Esc для «Отмена».. Что бы юзер «7 раз отмерил, прежде, чем что-то отрезать»..


> Kolan © (19.08.09 16:36) [62]

> Где это я читал такие лекции? Особенно про точку зрения
> МС?

Крестик для закрытия (твое).
Ентер против таб (мое).

Доктор сказал: в морг, значит — в морг.

Ты, чего не в курсе, какие клавиши за что отвечают в приложениях by MS?

> Kolan (19.08.2009 16:34:00) [60]

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

> Leonid Troyanovsky (19.08.2009 16:41:03) [63]

Леонид я не шучу.

> Leonid Troyanovsky (19.08.2009 16:46:05) [65]

Кстати кнопка вредная и в некоторых компьютерах брендов ее нет, это они подчеркивают, что наши компьютеры настолько хороши, что им кнопка RESET не нужна. И это тоже не шутка.


> Anatoly Podgoretsky © (19.08.09 16:49) [67]

> Леонид я не шучу.

Это я сразу просек: в каждой шутке есть доля шутки.
Ну, и за меня не беспокойся :)

Запрет кнопки имеет право на существование, но пользователям это не указ.

Что-то я не пойму о чем речь, если честно

Вряд ли я был бы против перехода по полям по энтеру, так как это может сэкономить несколько действий, но меня не спрашивали об этом. Лучше давайте про крестик, чтобы тема ветки не испортилась.


> Лучше давайте про крестик

или крестик на теме))

Я лично считаю, что решение Andy с дисэйблением и хинтом можно советовать автору, пока не сообщено подробностей конкретной задачи.


> пользователей не пользуются клавиатурой и им пофигу ухищрения
> с кнопками по умолчанию

это да, к сожалению.
от крестика надо как-то избавляться))

> Kolan © (19.08.09 17:02) [73]
> с дисэйблением и хинтом

Не, кнопку я не отключал, иначе как я узнаю, что юзер по ней кликать пытается. Не пости же в реальном времени положение мыши ;) Куда проще взвести флаг в программе и при обработке выхода посмотреть взведен ли он и если да, то хинт и отказ от выхода.

> MonoLife (19.08.2009 17:11:14) [74]

FAQ по работе с формой

// Чтобы запретить кнопку закрытия формы, напишите следующий
// код (Form1- ваша форма, Button1 — кнопка на ней):
void __fastcall TForm1::Button1Click( TObject *Sender)
<
HMENU MenuHandle = GetSystemMenu(Handle, false);
if(MenuHandle)
DeleteMenu(MenuHandle, SC_CLOSE, MF_BYCOMMAND);
>

// Чтобы запретить кнопку максимизации формы, напишите
// следующий код (Form1- ваша форма, Button1 — кнопка на ней):
void __fastcall TForm1::Button1Click( TObject *Sender)
<
HMENU MenuHandle = GetSystemMenu(Handle, false);
if(MenuHandle)
DeleteMenu(MenuHandle, SC_MAXIMIZE, MF_BYCOMMAND);
>
// ПРИМЕЧАНИЕ: максимизация формы двойным щелчком мыши
// по заголовку также будет невозможна

// Чтобы запретить кнопку минимизации формы, напишите
// следующий код (Form1- ваша форма, Button1 — кнопка на ней):
void __fastcall TForm1::Button1Click( TObject *Sender)
<
HMENU MenuHandle = GetSystemMenu(Handle, false);
if(MenuHandle)
DeleteMenu(MenuHandle, SC_MINIMIZE, MF_BYCOMMAND);
>

// Чтобы форма не закрывалась при нажатии комбинации клавиш
// Alt+F4, разместите на форме компонент TActionList(ActionList1),
// создайте новый TAction(Action1), и в свойстве ShortCut у Action1
// пропишите комбинацию клавиш Alt+F4, а обработчик события
// OnExecute должен выглядеть следующим образом
// (Form1- ваша форма):
void __fastcall TForm1::Action1Execute( TObject *Sender)
<
// чтобы при сохранении C++Builder не уничтожил обработчик
>

//В обpаботчике FormKeyDown пишешь:
if (Shift.Contains(ssAlt)&&Key==VK_F4) Tag=1;

//В обpаботчике FormCloseQuery:
if(Tag)
<
CanClose=false;
Tag=0;
>

// Напишите следующий обработчик события OnMouseDown формы
void __fastcall TForm1::FormMouseDown(TObject *Sender, TMouseButton Button,
TShiftState Shift, int X, int Y)
<
long SC_DRAGMOVE = 0xF012;
if(Button == mbLeft)
<
ReleaseCapture();
SendMessage(Handle, WM_SYSCOMMAND, SC_DRAGMOVE, 0);
>
>

// Напишите следующий код:
Form1->WindowState = wsMaximized; // развернуть
Form1->WindowState = wsMinimized; // минимизировать
Form1->WindowState = wsNormal; // первоначальный размер

Как сделать кусок окна прозрачным

// Для того чтобы сделать кусок формы прозрачным,
// напишите следующий код:

//Прямоугольный кусок
HRGN R1= CreateRectRgn(0, 0, Width, Height);
HRGN R2= CreateRectRgn(4, 24, Width-4, Height-4);
CombineRgn(R1, R1,R2, RGN_DIFF);
SetWindowRgn(Handle, R1, TRUE);

//Кусок в виде элипса
HRGN hRgn1 = CreateRectRgn(0, 0, Width, Height);
HRGN hRgn2 = CreateEllipticRgn(0, 0, Width, Height);
HRGN hRgn3 = CreateRectRgn(0, 0, Width, Height);
CombineRgn(hRgn3, hRgn1, hRgn2, RGN_DIFF);
SetWindowRgn(Handle, hRgn3, TRUE);
//можно заменить hRgn3 на hRgn2

//Кусок в виде пятиугольника
HRGN Reg1, Reg2;
HRGN Region;
POINT p[5];
p[0] = Point(100, 0);
p[1] = Point(Width-100, 0);
p[2] = Point(Width, Height/2);
p[3] = Point(Width/2, Height);
p[4] = Point(0, Height/2);
Region = CreatePolygonRgn(p, 5, ALTERNATE);
SetWindowRgn(Handle, Region, true);

// Для того чтобы создать новую форму напишите:
// следующих код:
TForm * Formik= new TForm( this);
TButton* button= new TButton(Application);
button->Parent=Formik;
button->Caption=»New Button»;
button->Left=10;
button->Top=15;
button->Show();
Formik->Caption=123;
Formik->ShowModal();
delete Formik;

// Для того чтобы сделать прозрачную форму напишите:
int Transparency = 75; //насколько прозрачным будет окно (0-100%)
long ExtStyle = GetWindowLong(Handle, GWL_EXSTYLE);
SetWindowLong(Handle, GWL_EXSTYLE, ExtStyle | WS_EX_LAYERED);
SetLayeredWindowAttributes(Handle, 0 , (255 * Transparency) / 100,
LWA_ALPHA);


// Для того чтобы создать форму напишите:
void __fastcall TForm1::Photo()
<
int X0,Y0;
bool Flag;
TRect ScreenRect;
TCanvas* ScreenCanvas=new TCanvas;
try
<
Top=0;
Left=Screen->Width;
W >Width;
Height=Screen->Height;
ScreenRect=Rect(0,0,Width,Height);
ScreenCanvas->Handle=GetDC(0);
Image1->Canvas->CopyRect(ScreenRect, ScreenCanvas,ScreenRect);
ReleaseDC(Handle,ScreenCanvas->Handle);
Left=Top;
> __finally
<
delete ScreenCanvas;
>
>

// Для того чтобы создать новую форму напишите:
void __fastcall TForm1::CreateParams(TCreateParams& Params)
<
TForm::CreateParams(Params);
Params.WndParent = 0;
>

Создайте новый проект. Дальше: Project->Remove from project

Для того чтобы определить класс определённого приложения напишите следующий код:

HWND hWnd= FindWindow(NULL,»Калькулятор»); //для русскоязычной Windows
if (hWnd)
<
char buff[100];
GetClassName(hWnd,buff,100);
ShowMessage(buff);
>
Автор: Srpj Сайт: http://srpj.narod.ru/

// Напишите следующий код:
PaintDesktop(Form1->Canvas->Handle);

Процедура обработки события для кнопки формы в Access 2003

Создание процедуры IF в СУБД Access 2003

Создадим новую форму FormIgra с кнопкой «Запуск» в базе данных Access 2003. Базу данных можно скачать по ссылке Training_students_O_F.zip. Назначим кнопке «Событие» — «Нажатие кнопки». Технология создания формы и кнопки, которой назначено Событие (Нажатие кнопки), рассмотрена в статье «Редактор VBA».

В режиме «Конструктор» добавим в форму FormIgra текстовую строку, щелкнув на элемент «Поле» в панели элементов. Метку можно удалить. Присвоим текстовой строке имя — glftext. Для этого используем контекстное меню, в котором выберем команду свойства, и в поле «Имя» введем glftext.

Закроем форму (рис. 1), сохранив при этом изменения в форме. Текстовую строку мы добавили для того чтобы в нее можно было помещать какие-либо слова при нажатии кнопки Запуск. Откроем редактор VB, нажав сочетание клавиш Alt+F11. Откроется редактор VB. В окне «Projekt — Деканат» в директории Microsoft Access Class Objects (директории объектов классов Access, которые включают модули форм и отчетов) появится новый стандартный модуль: «Form_FormIgra».

В окне редактора кода Training_students_O — Form_FormIgra (Code), скриншот которого представлен на рисунке 3, отображается рассматриваемая заготовка модуля. Код модуля содержит первый Sub cmdPusk_Click и последний End Sub операторы процедуры, т.е. представляет собой заготовку процедуры. В заготовке процедуры отсутствует исполняемый код обработки события.

Для создания процедуры обработки события при нажатии кнопки «Запуск» необходимо в заготовку модуля (рис.3) между операторами Sub cmdPusk_Click () и End Sub вставить соответствующий исполняемый код. Ввод исполняемого кода обработки событий или ввод текста программы выполним непосредственно в окне редактора кода. Итак, создадим процедуру, которая при нажатии кнопки будет помещать в текстовое поле слова «Орел» или «Решка». При нажатии кнопки должны производиться два различных действия, одно при соблюдении условия, а второе — нет. В этом случае надо воспользоваться полной формой оператора IF.

Применим оператор условного перехода IF. Then. Else. End If, который имеет две альтернативные ветви процедуры:
IF условие Then
инструкция 1
Else
инструкция 2
End If.

Если условие соблюдается, выполняется инструкция 1 (оператор или группа операторов), расположенная между ключевыми словами Then и Else, а если не соблюдается — то инструкция 2, расположенная между ключевыми словами Else и End if

С учетом того, что при нажатии кнопки в текстовой строке с именем «glftex» должно отображаться слово «Орел» или «Решка», запишем процедуру в таком виде:

If (glftext = «Орел») Then
glftext = «Решка»
Else
glftext = «Орел»
End If

В окне редактора кода (Code) будет отображаться код программы на Visual Basic (процедура).

Таким образом, создана процедура обработки события Click (нажатия кнопки) объекта cmdPusk. Если в текстовой строке отображается слово «Орел», то после выполнения такого события как нажатие кнопки «Запуск» в текстовую строку будет помещено слово «Решка». Если в текстовой строке не отображается слово «Орел», то после выполнения такого события как нажатие кнопки «Запуск» в текстовую строку будет помещено слово «Орел». Переходим в окно базы данных на вкладку Формы, выделяем FormIgra и щелкаем на кнопке Открыть. Откроется форма «FormIgra: форма».

Щелкаем на кнопке «Запуск», запускается процедура обработки события и в результате в текстовую строку помещается слово «Орел».

При следующем нажатии кнопки «Запуск» в текстовой строке появится слово «Решка».

При следующем нажатии кнопки «Запуск» в текстовой строке появится слово «Орел». Таким образом, при каждом нажатии кнопки «Запуск» слова «Орел» и «Решка» сменяя друг друга, будут отображаться в текстовом поле формы FormIgra.

Faq события нажатия на системные кнопки формы (минимизация, закрытие )

Требуется нажатием одной клавиши закрыть форму VBA (например Esc).

Этот код не всегда срабатывает из-за того, что фокус находится на других элементах формы.

Как сделать, чтобы форма по любому закрывалась по нажатию одной кнопки, вне зависимости от фокуса?
Не писать же обработчик нажатия клавиши на все объекты формы
Alt-F4 — тоже не устраивает

Спасибо Дмитрий, но не совсем помогает,
если фокус был на другом объекте формы, то по нажатию Esc фокус сначала переходит на кнопку с .Cancel=True,
а уже после повторного нажатия Esc срабатывает код на закрытие формы.

Возможно ли обойтись одним нажатием?

keypreview = true поставь у формы и все будет.

Добавлено 20.01.06, 10:56
ой-ой, простите, я не в тот раздел попал! хотя может в вба и сработает.

I’ve said too much. I have not said enough. © R.E.M.

Программное обеспечение для заполнения аттестатов о полном среднем образовании: http://www.cfprinter.narod.ru/

Такой вариант:
Правда он несколько дубовый.
Используем API windows. (Решение аналогично описанному тут: Нестандартная задача)

Работает всегда, даже если активно вообще другое приложение.

SV(), есть огромный минус, даже два.
1. DoEvents в цикле — приводит к постоянной загрузке проца в 100%. Систему это действительно не вешает, но мне, например, не нравится видеть индикатор постоянно красным.

2. Следует из п.1 — отключается программное охлаждение проца (HALT). (кстати, — это можно использовать для уменьшения помех при видеозахвате с тюнера. )

Нет! Загрузку в 100% даёт сам цикл.
DoEvents как раз позволяет в любой момент прервать цикл, на время выполнения других приложений или процедур.
В итоге цикл забирает только свободное время процессора, как бы заменяя собой процесс “бездействие системы”, но все другие приложения и локальные процедуры нормально выполняются, не замечая этого цикла.

Добавление паузы в 1/4 сек (с помощью Sleep) может привести к тому, что будет пропущено нажатие горячей клавиши, произошедшее в момент этой паузы — создается впечатление, что приложение работает нестабильно.
И мне кажется немногие пользователи в реальном времени следят за индикатором загрузки своего процессора.

Бесконечный цикл это не очень хорошо, но что делать: надо непрерывно «опрашивать» клавишу.
Конечно, что-то вроде ловушки было бы предпочтительней, но по моему, к сожалению, в vba это недоступно.

Ну да. Загрузку 100% даёт цикл, ПОЛНОСТЬЮ занимаемый DoEvents. Sleep позволяет решить эту ДЕЙСТВИТЕЛЬНО ВАЖНУЮ проблему. Может и не все пользователи смотрят на индикатор, но тот факт, что отключается HALT-охлаждение, намного важнее индикатора.

Рекоммендую вам уточнить инфу о работе GetKeyState. Она будет нормально работать, даже если выполнять проверку раз в минуту. 250 мс я рекоммендую, т.к. этот интервал практически исключает двойное нажатие (да, двойное нажатие не будет определено.)

Если есть сомнения — поставьте не 250 мс, а 100. Это полностью исключит возможность двойного нажатия.

В боевых условиях работать не захотело,
в предложенных вами вариантах цикл выполняется непрерывно.
А по условиям моего приложения, где используется встроенный VBA, требуется окончание выполнения скрипта, иначе другие работать не будут.
Наверно придеться каждому объекту формы событие _KeyDown писать, топорно — но верно.

А такое поведение в VBA не работатет?
1. При нажатии клавиши проверяются события _KeyDown уровня объектов формы.
2. Если у объекта с фокусом события _KeyDown нет, проверяется событие на уровень выше — у самой формы,
если нет, то может еще где — для всех форм проекта .

У нас просто в SCADA-пакете работает такая иерархия на ловлю нажатия клавиш для объектов мнемосхем, затем — для самой мнемосхемы, а затем уже для глобальной области — всего приложения.

Есть идейка. написать OCX, в нём таймер. По таймеру в ОСХ-е происходит проверка нажатия, если чё — генерим эвент, который получает твой вба и обрабатывает как хочет.
Единственный минус — на каждой машине где это должно работать, надо будет установить этот ocx и библу msvbvm6 .

добавлено четь позже
Я подумал, решил что я не жадный и вот тебе контрол. Я его проверял в ворде и экселе, работает.

Хоть это уже и не актуально, всё-таки напишу:

1. Не DoEvents грузит на 100%, а цикл.
код

Однако никто не скажет, что присвоение загружает проц на 100%.
Очевидно это даже не цикл, а сам basic так устроен: грузит проц на полную во время выполнения кода. Цикл он не кончается, в отличие от например, обработчика клика по кнопке, вот и горит 100% все время.

А что тут уточнять? Написал простенькую прогу и протестировал. Реально пропускает со sleep. (Прога прилагается)

3. Теперь по делу: Написал о ловушках и задумался, а действительно, что это я всё циклы да циклы.
Да, глобальную ловушку не поставишь, vba длл-ок не делает, да и функция ловушки в dll “живет” отдельно от приложения, и никак на него не влияет – толку от неё мало. А вот локальная, с функцией непосредственно в модуле – это можно.
Вот порылся в инете, повспоминал…
В основном модуле:

Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL