Nano Hash - криптовалюты, майнинг, программирование

Как создать немодальную форму, но блокирующую?

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

что-то вроде этого:

     void Foo()
     {
         CustomMsgBox.Show("do you really wanna delete?", CustomMsgBox.Buttons.YesNo);
         //block the code here, but user should be able to click on form, so that its equivalent to have clicked No;
         //if clicked No, return;

         //delete.
     }

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

Это будет выглядеть так:

 void Foo()
 {
     NonModalMsgBox.Show("do you really wanna delete?", CustomMsgBox.Buttons.YesNo);
     //block thread till user clicks on form or messagebox buttons.
     //unblock when user clicks.
     //if No, return;

     //delete.
 }

Изменить: я знаю, что это не стандартная практика, и я знаю, что немодальные формы не блокируются, а модальные - блокируются. Поэтому, пожалуйста, не рекомендуйте довольствоваться поведением модальной или немодальной формы. Мой вопрос: есть ли способ имитировать поведение ContextMenu с оконные формы.


  • Это невозможно, потому что это было бы повторным входом, который, вероятно, испортил бы вас. 20.12.2011
  • Я не верю, что это невозможно в конечном счете. Я могу заблокировать поток на неопределенный срок, но он также зависает в основной форме ... это мое беспокойство. Я надеюсь, что более знающие люди могут предоставить обходной путь. Я просто играю с различными аспектами .net в основном.. должно быть приятно знать, как этого можно достичь 20.12.2011
  • Для этого требуется цикл, вызывающий Application.DoEvents(). С опасностями, связанными с этим методом. См. stackoverflow.com/questions/5181777/use-of -application-doevents/ 20.12.2011
  • @HansPassant дай мне посмотреть. Спасибо.. 20.12.2011

Ответы:


1

Вы можете сделать что-то вроде:

public void ShowMe() {
    Show();
    while (!_receivedDeactivateEvent)
        Application.DoEvents();
}

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

19.12.2011
  • Люди говорят, что это плохой метод, но пока я получаю, чтобы он работал в соответствии с моими потребностями, и я не могу понять чужие методы без кода, я отмечу это как ответ. Я могу справиться с остальными условиями, о которых вы говорили. Спасибо :) 20.12.2011
  • @nawfal Это ответ на ваш вопрос, но это очень плохой поступок. Я почти гарантирую, что у вас будут проблемы с вашей программой, которые вы вырвете уйму волос, пытаясь понять... 20.12.2011
  • @Andrew Barber Я бы, конечно, не стал играть с основами .net в своих приложениях, которые я отправлю или разверну в другом месте. Это всего лишь простая программа для хобби, с помощью которой я в основном пытаюсь изучить поведение компонента .net gui и т. Д. Не имеет значения. кроме того, я позаботился о ситуациях, о которых уже говорил ответчик 20.12.2011
  • @AndrewBarber, это можно заставить работать - в основном так работает PopupMenu. Но да, это очень подвержено ошибкам и требует много работы, чтобы сделать это правильно. 20.12.2011
  • @JoeWhite, нет, я не думаю, что всплывающие окна работают именно так. Всплывающие окна автоматически закрываются, когда они теряют фокус. Всплывающее окно полностью автономное и не требует внешнего кода, чтобы сообщить ему, когда закрыть. Цикл while () в этом ответе требует, чтобы внешний код сообщал ему, когда закрывать, что звучит очень сложно правильно и поддерживать во многих особых случаях. 20.12.2011
  • @BrianEnsink, я не говорю о WPF Popup, я говорю о всплывающих меню (иначе контекстных меню). Win32 TrackPopupMenu показывает всплывающее меню и не возвращается, пока это меню не будет закрыто. WinForms ContextMenu.Show ведет себя так же: возвращайтесь, пока всплывающее меню не будет закрыто. 20.12.2011
  • @JoeWhite, это хорошие примеры, но ни один из них не требует внешнего нажатия из пользовательского кода, чтобы закрыть их. Всплывающие окна будут использовать свой собственный цикл отправки сообщений (именно так они могут блокировать вызовы функций), но им не требуется подверженный ошибкам внешний код, чтобы сообщить им, когда закрыться. Чем больше я думаю об этом, OP нужно использовать какое-то всплывающее меню. Кажется, это именно то, чего он хочет. 20.12.2011

  • 2

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

    19.12.2011
  • Можете ли вы предоставить основной код или ссылку на пример кода? я новичек в этих делах.. 20.12.2011

  • 3

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

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

  • 4

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

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

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

    19.12.2011
  • Я могу сделать все это, Брайан, но проблема в том, что немодальная форма не блокирует и, следовательно, не блокирует код в ситуациях YesNo. Это не то, что я в основном ищу. 20.12.2011
  • Главной особенностью модального диалога является то, что он блокирует. Главной особенностью немодального диалога является то, что он не блокируется. Вы хотите заблокировать немодальное диалоговое окно, которое кажется своего рода противоречием. Всплывающие меню автоматически закрываются, когда они теряют фокус, и это очень похоже на то, что вы описываете. 20.12.2011
  • Можете ли вы сказать мне, какой компонент .net gui является всплывающим элементом управления? Тоже блокирует? 20.12.2011
  • Вы можете использовать метод ContextMenu.Show, если достаточно простого меню. . В противном случае создайте новое диалоговое окно и определите, когда фокус покинет диалоговое окно. 20.12.2011
  • это кажется крутым. на самом деле это то, что вы упомянули в своем сообщении в качестве ответа, но с той разницей, что здесь вы упоминаете модальный диалог, а в своем ответе вы упомянули немодальный диалог. вы можете отредактировать свой вопрос, чтобы иметь больше смысла .. 20.12.2011
  • на самом деле вы не можете закрыть модальный диалог на основе пользовательских событий в родительской форме, таких как проверка, наведение мыши, потеря фокуса, уход и т. д., поскольку эти события не запускаются, пока модальная форма блокирует все это. Контекстные меню — хороший выход, но они слишком отличаются от обычных окон сообщений. 21.12.2011
  • @nawfal, используйте немодальное диалоговое окно и обнаружьте потерю фокуса. 21.12.2011
  • немодальный диалог не блокируется, и поэтому я пришел сюда. У меня есть решение, Джо Уайт. Я знаю, как закрыть дочернюю форму при щелчке пользователя, потере фокуса и т.д. 21.12.2011
  • @nawfal, опять же, то, что вы хотите, не существует в той форме, в которой вы этого хотите. Вам нужен блокирующий вызов в основном потоке, но вы все же настаиваете на том, чтобы основной поток мог обрабатывать событие, такое как щелчок. У вас не может быть и того, и другого. Я предлагаю использовать всплывающее меню или немодальное диалоговое окно и обрабатывать событие фокуса. При этом вы можете позволить пользователю щелкнуть основную форму и автоматически закрыть диалоговое окно. 21.12.2011
  • Я все равно знаю, как закрыть немодальную форму, мой вопрос здесь был не об этом. Я не понимаю, почему вы все время повторяете о немодальной форме, когда она не блокируется. //Вы хотите блокирующий вызов в основном потоке, но все же настаиваете на том, чтобы основной поток мог обрабатывать событие, такое как щелчок.// Это не выдерживает критики, ваше более позднее предложение с всплывающим меню делает именно то, что я ищу . Как .net добился этого? Я искал выход, чтобы имитировать это поведение с помощью элемента управления формой. 21.12.2011
  • Я думал спросить об этом в сообществе с более знающими людьми. Я подробно описал требование в своем вопросе. Я не хочу блокировать основной поток как таковой, я хотел заблокировать функцию, сохраняя обработчики событий готовыми к ответу. В некотором смысле, как указал Джо Уайт в контекстных меню. Немодальные формы никоим образом не делают этого, если только методом, снова указанным Джо Уайтом. Пожалуйста, не рекомендуйте использовать немодальные формы так, как вы это делаете в другой раз. 21.12.2011
  • @nawfal, хорошо, извини, я не мог быть более полезным. Кажется, я не совсем понимаю, чего ты хочешь. Я попытался объяснить, как заставить диалоговое окно вести себя как всплывающее меню. Я не знаю вашего опыта программирования под Windows, но вам может быть интересно узнать больше о цикле сообщений Win32. Это может помочь вам лучше понять, как работают некоторые из этих вещей, и цикл обработки сообщений по-прежнему является частью WinForms. (Прошу прощения, если вы уже все об этом знаете!) Удачи вам! 22.12.2011
  • ха-ха, спасибо, приятель.. Да, ты пытался, но меня больше раздражало то, что ты не понимаешь моего требования, несмотря на то, что ясно дал понять. Каждый раз, когда вы говорите, что у вас немодальная форма, но это не блокирует. Закрытие формы одним щелчком мыши не моя проблема, но блокировка потока до тех пор, пока я не нажму :) Ура :) 22.12.2011

  • 5

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

    [DllImport("user32.dll")]
    private static extern bool EnableWindow(IntPtr hWnd, bool enable);
    
    internal static DialogResult ShowDialogSpecial(this Form formToBeShown, Form parent)
    {
        parent.BeginInvoke(new Action(() => EnableWindow(parent.Handle, true)));
        formToBeShown.ShowDialog(parent);
    
        return formToBeShown.DialogResult;
    }
    

    Просто вызовите метод расширения из любой родительской формы следующим образом:

    var f = new Form();
    f.ShowDialogSpecial(this);
    //blocks but parent window will be active.
    

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

    05.09.2012

    6

    Более простой способ: установите для свойства TopMost формы значение True. Тогда это будет действовать как блокировка

    22.02.2016
    Новые материалы

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

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

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

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

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

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

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..