Я сделал большую разработку Spring/Быть в спящем режиме. Со временем способ, которым люди использовали обоих в комбинации, изменился немного. Исходный подход HibernateTemplate оказался трудным отладить, так как он глотает и обертывает в других отношениях полезные исключения; говорите с API Hiberante непосредственно!
продолжайте смотреть на сгенерированный SQL (настройте свою разработку, регистрирующуюся для показа SQL). Наличие уровня абстракции к базе данных не означает, что Вы не должны больше думать в SQL; Вы не получите хорошую производительность если Вы иначе.
Рассматривают проект. У меня есть choosen iBatis, несколько раз В спящем режиме, где у нас были строгие требования к производительности, сложные схемы прежней версии или хороший DBa's, способный к записи превосходного SQL.
EDIT: полный вопрос переписан, я неправильно понял исходный вопрос
Давайте обобщим проблему: элемент управления или компонент, который вы не контролируете, может вызывать FlashWindow
(функцию Win32 API), чтобы привлечь внимание пользователя. Вы этого не хотите.
Обычно существует два решения для этого: использование подключения API или подключение сообщений. Поскольку перехват API сложен и сложен, я представлю решение для перехвата сообщений.
Microsoft не очень подробно объясняет, что делает FlashWindow
. К сожалению, он не отправляет конкретное сообщение (скажем, WM_FLASH
или подобное), которое упростило бы захват и аннулирование этого поведения. Вместо этого FlashWindow
выполняет три действия:
WM_NCACTIVATE
для первой вспышки Сообщение WM_NCACTIVATE
по истечении таймера (при получении WM_SYSTIMER
) В зависимости от того, как компонент вызывает FlashWindow, это может быть неопределенным, пока не наступит другой тайм-аут, пока он не получит фокус, или только один раз. Каждое сообщение WM_NCACTIVATE активирует или деактивирует зону ЧПУ (панель заголовка, кнопка на панели задач). Это не меняет входной фокус.
Любое решение для предотвращения мигания требует некоторого внимания. Основные проблемы:
WM_SYSTIMER
отправляется асинхронно с PostMessage и не принимается методом WndProc
формы (он обрабатывает только синхронные сообщения) Сообщения WM_NCACTIVATE
также используются, когда пользователь нажимает кнопку в строке заголовка или панели задач, чтобы установить фокус ввода, простая отмена этих сообщений будет иметь нежелательные побочные эффекты. WM_SYSTIMER
срабатывает или нет. Сообщение WM_SYSTIMER
недокументировано. Он имеет значение 0x0118
и используется внутри Windows для измерения времени, например, мигания курсора, задержки открытия меню и т. Д. Здесь он используется для времени между миганиями.
Решение, которое я представляю здесь, является основой для дальнейшего развития. Это не полное решение, но во многих случаях оно решает проблему. Поместите в код формы следующее:
protected override void WndProc(ref Message m)
{
bool messageHandled = false;
if (m.Msg == WM_NCACTIVATE)
{
// add logic here to determine user action, losing focus etc and set
// messageHandled and m.Result only when user action is not the cause
// of triggering WM_NCACTIVATE
m.Result = IntPtr.Zero;
messageHandled = true;
}
if(!messageHandled)
base.WndProc(ref m);
}
Приведенный выше код уже полностью предотвращает перепрошивку. Вам придется добавить некоторую логику для изменения строки заголовка, потому что полное игнорирование WM_NCACTIVATE
означает, что строка заголовка будет все время выглядеть активной, даже если это не так.
Следующий код дает вам больше контроля. Вы можете использовать его, чтобы реагировать на саму мигание. Как обычно, главное окно не так часто получает события WM_SYSTIMER
, но вам придется поэкспериментировать, следует ли делать исключения. Похоже, что для FlashWindow
параметр wParam
всегда установлен на 0xFFF8
, но поэкспериментируйте с ним, поскольку это нигде не задокументировано.
public class MyMessageFilter : IMessageFilter
{
// an application can have many windows, only filter for one window at the time
IntPtr FilteredHwnd = IntPtr.Zero;
public MyMessageFilter(IntPtr hwnd)
{
this.FilteredHwnd = hwnd;
}
public bool PreFilterMessage(ref Message m)
{
if (this.FilteredHwnd == m.HWnd && m.Msg == WM_SYSTIMER)
return true; // stop handling the message further
else
return false; // all other msgs: handle them
}
}
Чтобы активировать этот фильтр сообщений, просто добавьте следующую строку где-нибудь в вашем событии загрузки формы:
Application.AddMessageFilter(new MyMessageFilter(this.Handle));
Следующие константы должны быть размещены на уровне класса. Они используются в обоих разделах кода выше:
public const UInt32 WM_SYSTIMER = 0x0118;
public const UInt32 WM_NCACTIVATE = 0x86;
Хотя проблема сама по себе разрешима, это далеко не просто. С указанными выше ручками вы должны уйти довольно далеко. Используйте фильтр, чтобы предотвратить мигание, но тогда первая «вспышка» все равно произойдет. Используйте переопределение WinProc
, чтобы предотвратить и первое, но добавьте некоторую логику, чтобы ваше приложение не работало слишком странно (то есть: всегда неактивная строка заголовка или всегда активная). У вас уже есть код, который можно комбинировать с этим, чтобы установить некоторые логические флаги.
Реализовать IProtectFocus :: AllowFocusChange в объекте
Реализовать IServiceProvider на том же объекте, который реализует IOleClientSite, затем ответить на IServiceProvider :: QueryService для SID_SProtectFocus с помощью объекта, который предоставляет IProtectFocus
Это новый интерфейс в IE7, поэтому старым версиям не повезло.