• Добро пожаловать на Форум пользователей ПО АСКОН. Пожалуйста, авторизуйтесь.
 

Уважаемые пользователи,

Хотим проинформировать вас о режиме работы регистрации на нашем сайте.

Зарегистрироваться возможно в рабочие дни, с 8:00 до 20:00 (мск).

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

Благодарим вас за понимание и сотрудничество. Мы ценим ваше терпение и стремимся предоставить вам лучший опыт использования нашего сервиса.

С уважением,
Команда Ascon

Обработчик к закрытию Лоцман:ПГС

Автор MaksTsk, 28.04.14, 16:41:21

« назад - далее »

0 Пользователи и 1 гость просматривают эту тему.

MaksTsk

Добрый день!

Подскажите, пожалуйста, можно ли как то внутри плагина подцепить обработчик к событию закрытия Лоцман:ПГС? Либо вообще задизейблить кнопку закрытия?

Chaa

Штатных средств для этого нет, но вы можете с помощью WINAPI найти главное окно и отключить в нем кнопку закрытия. Чтобы перехватить сообщение WM_CLOSE нужно будет пойти немного дальше, и заменить оконную процедуру, см. http://msdn.microsoft.com/en-us/library/windows/desktop/bb773183.aspx

const
    CMainFrameClassName = 'TfrmMain';
var
    MainFrameHandle: THandle;
function FindMainFrameProc(AWindow: THandle; AParam: Integer): LongBool; stdcall;
var
    OwningProcess: DWORD;
    LBuffer: array [0 .. 31] of Char;
begin
    if (GetWindowThreadProcessID(AWindow, OwningProcess) <> 0) and
        (OwningProcess = GetCurrentProcessId()) then
    begin
        GetClassName(AWindow, LBuffer, 32);
        if LBuffer = CMainFrameClassName then
        begin
            MainFrameHandle := AWindow;
            Result := False;
        end
        else
            Result := True;
    end
    else
        Result := True;
end;
procedure FindMainFrame;
var
    MenuHandle: HMENU;
begin
    MainFrameHandle := 0;
    EnumWindows(@FindMainFrameProc, 0);
    if MainFrameHandle <> 0 then
    begin
        MenuHandle := GetSystemMenu(MainFrameHandle, False);
        EnableMenuItem(MenuHandle, SC_CLOSE, MF_BYCOMMAND or MF_GRAYED);
    end;
end;
+ Благодарностей: 2

MaksTsk

Спасибо большое за совет. Реализовал у себя с помощью следующего класса (здесь класс User32Tool описывает необходимые методы из библиотеки user32.dll)

/// <summary>
    /// Класс предназначен для доступа к событиям приложения
    /// </summary>
    public class AppEventsProvider
    {
        private readonly IntPtr _loodsmanHandle;

        /// <summary> Старая window proc </summary>
        private IntPtr _oldWndProc = IntPtr.Zero;

        /// <summary> Новая процедура окна </summary>
        private User32Tool.Win32WndProc _newWndProc = null;

        public AppEventsProvider()
        {
            _loodsmanHandle = Process.GetCurrentProcess().MainWindowHandle;

            ChangeWinProc();
        }

        /// <summary>
        /// Событие закрытия приложения
        /// </summary>
        public event Action AppClosedEvent;

        /// <summary>
        /// Заменяем стандартную windows процедуру
        /// </summary>
        public void ChangeWinProc()
        {
            _newWndProc = WinProc;
            _oldWndProc = User32Tool.SetWindowLong(_loodsmanHandle, User32Tool.GWL_WNDPROC, _newWndProc);
        }

        /// <summary>
        /// Новая процедура.
        /// </summary>
        private int WinProc(IntPtr hWnd, int msg, int wParam, int lParam)
        {
            if (msg == User32Tool.WN_CLOSE)
            {
                if (AppClosedEvent != null)
                {
                    AppClosedEvent();
                }
            }

            return User32Tool.CallWindowProc(_oldWndProc, hWnd, msg, wParam, lParam);         
        }
    }


Все работает прекрасно, и при появлении сообщения о закрытии вызывается AppCloseEvent(). Но столкнулся с небольшой проблемой:

при отладке через VS и закрытии окна Лоцмана появляется следующая ошибка:

System.AppDomainUnloadedException was unhandled
Message: An unhandled exception of type 'System.AppDomainUnloadedException' occurred in Unknown Module.
Additional information: Attempted to access an unloaded AppDomain.

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

Данный класс был протестирован на другом приложении - все работало отлично. Возможно проблема в каком-то специфичном использовании домена Лоцманом.

Понимаю, что вопрос довольно специфичный, но может есть какие-то идеи.


Chaa

Возможно дело в том, что при выгрузке плагина вы не возвращается обратно старую оконную процедуру, и поэтому возникает ошибка "Attempted to access an unloaded AppDomain".

MaksTsk

В точку :)
Подписался на событие выгрузки домена и вернул старую процедуру.
Всё заработало!