![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Проверка видимости контекстного меню [D7, WinXP]
dmitry_12_08_73 © (2009-08-28 16:09:00)Как проверить, видимо ли в своем приложении хоть одно контекстное меню?
Германн (2009-08-31 02:44:00) [1]
> Юрий Зотов © (31.08.09 02:23) [17]
Юр, я уже и сам это проверил прежде чем написать
> Германн © (31.08.09 01:53) [16]
:)
Только в своём примере inherited написал только один раз.
Я "чел" отсталый от времени, почти как мастодонт, но всё же не без рук и мозгов! :)
P.S. А по поводу "своей новой работы" я готов потрепаться на ММП. Если выберусь на неё ещё когда-то. :(
Юрий Зотов (2009-08-31 02:23:00) [2]> Германн © (31.08.09 01:53) [16]
Вот иллюстрация. TForm2 - наследник TForm1. При двойном щелчке по Form2 она сама себе посылает сообщение. Но мы сначала видим надпись 'Это Form1' (срабатывает inherited), а уж потом - 'Это Form2' (срабатывает собственный код TForm2).
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs;
const
WM_UserPlus100 = WM_USER + 100;
type
TForm1 = class(TForm)
procedure FormActivate(Sender: TObject);
protected
procedure WMUserPlus100(var Message: TMessage); message WM_UserPlus100;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
{ TForm1 }
uses
Unit2;
procedure TForm1.WMUserPlus100(var Message: TMessage);
begin
inherited;
ShowMessage('Это Form1')
end;
procedure TForm1.FormActivate(Sender: TObject);
begin
if Form2 = nil then
begin
Form2 := TForm2.Create(Application);
Form2.Show
end
end;
======================
unit Unit2;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, Unit1;
type
TForm2 = class(TForm1)
procedure FormDblClick(Sender: TObject);
protected
procedure WMUserPlus100(var Message: TMessage); message WM_UserPlus100;
end;
var
Form2: TForm2;
implementation
{$R *.dfm}
{ TForm2 }
procedure TForm2.WMUserPlus100(var Message: TMessage);
begin
inherited;
ShowMessage('Это Form2')
end;
procedure TForm2.FormDblClick(Sender: TObject);
begin
PostMessage(Handle, WM_UserPlus100, 0, 0)
end;
Германн (2009-08-31 01:53:00) [3]
> Перекрывается. Методы обработки сообщений - динамические
> по умолчанию. Да даже и в статическом "заменяющем" методе
> никто не запрещает вызвать "замененный" метод предка через
> inherited.
>
((((
Похоже мне придётся очень много заново учить, если я хочу удержаться на новой работе. :(
Юрий Зотов (2009-08-31 01:46:00) [4]> Германн © (31.08.09 01:33) [13]
> Как наследник класса TForm может узнать, что некие "стандартные
> системные контролы" используют данное сообщение?
А ему и знать об этом не надо. Вызвал inherited - и все. VCL сама разрулит. Если обработчик в цепочке есть - он быдет вызван, если нет - ничего не произойдет.
> как вызвать inherited, если процедура не перекрывается, а заменяется?
Перекрывается. Методы обработки сообщений - динамические по умолчанию. Да даже и в статическом "заменяющем" методе никто не запрещает вызвать "замененный" метод предка через inherited.
Германн (2009-08-31 01:45:00) [5]
> Германн © (31.08.09 01:33) [13]
P.S.
Да. Я понимаю, что inherited (в данном случае) вреда не принесёт. Но не похоже ли это его использование на "дуть на воду"?
Германн (2009-08-31 01:33:00) [6]
> Юрий Зотов © (30.08.09 21:19) [11]
Не. Всё-таки не понимаю полностью.
Как наследник класса TForm может узнать, что некие "стандартные системные контролы" используют данное сообщение?
Даже если класс TForm им пользуется, то как вызвать inherited, если процедура не перекрывается, а заменяется?
Германн (2009-08-30 21:25:00) [7]Понятно.
Юрий Зотов (2009-08-30 21:19:00) [8]> Германн © (30.08.09 20:29) [10]
Насколько помню, какие-то из сообщений WM_USER + X с некоторых пор используются стандартными системными контролами. Копать документацию, честно говоря, просто лень, проще задать WM_USER+100 и написать inherited. Если обработчик существует, то inherited даст ему нормально сработать, после чего нормально сработает и наш код. А если обработчик не существует, то inherited ничему не помешает. То есть, вреда от inherited в любом случае нет, а польза может быть.
Германн (2009-08-30 20:29:00) [9]
> Юрий Зотов © (30.08.09 15:56) [8]
А зачем "В теле метода пишете слово inherited"?
dmitry_12_08_73 (2009-08-30 18:32:00) [10]Спасибо большое, буду пробовать
Юрий Зотов (2009-08-30 15:56:00) [11]> dmitry_12_08_73 © (30.08.09 15:25) [7]
В модуле Вашей невидимой формы:
1. В секции interface перед словом type пишете:
const
WM_UserPlus100 = WM_USER + 100;
2. В секции protected класса формы пишете объявление метода:
procedure WMUserPlus100(var Message: TMessage); message WM_UserPlus100;
Потом ставите курсор на эту строчку, жмете Ctrl+Shift+C и получаете тело метода.
3. В теле метода пишете слово inherited, а после него - код копирования экрана (просто переносите этот код из MenuItem.OnClick).
4. В MenuItem.OnClick пишете строчку:
PostMessage(Handle, WM_UserPlus100, 0, 0);
Больше в MenuItem.OnClick ничего не должно быть.
===================
Суть в том, что при клике по пункту меню форме будет послано сообщение WM_UserPlus100. Но поскольку программа в этот момент крутится в цикле меню, то обработано это сообщение будет не сразу, а встанет в очередь. Когда цикл меню завершится (то есть, когда меню исчезнет), сообщения из очереди начнут обрабатываться и произойдет копирование экрана.
Во всяком случае, такой способ стоит попробовать. Он намного проще, чем городить второй поток и из него отслеживать пропадание меню.
dmitry_12_08_73 (2009-08-30 15:25:00) [12]Юрий. Честно говоря не понял этого Вашего совета.
Я отображаю контекстное меню, нажимаю его пункт (при этом меню начинает плавно исчезать), затем в событии MenuItem.OnClick запускаю процедуру копирования экрана BitBlt. и получается так, что BitBlt при копировании экрана копирует и исчезающее меню.
Юрий Зотов (2009-08-30 13:52:00) [13]> dmitry_12_08_73 © (30.08.09 12:39) [4]
Попробуйте сначала сделать проще. Пункт меню не копирует экран, а через PostMessage посылает Вашей невидимой форме сообщение. Получив это сообщение, форма копирует экран.
dmitry_12_08_73 (2009-08-30 12:44:00) [14]Я так понял, что ответ Юрия Зотова мне подходит
dmitry_12_08_73 (2009-08-30 12:39:00) [15]Вы знаете, проблема в следующем.
Моя программа находится в трее, я нажимаю правой кнопкой мыши на контекстном меню, выбираю нужный пункт, затем делаю копирование образа экрана. При этом (если в винде в настройках установлена анимация меню). то моё контекстное меню не успевает исчезнуть и копируется с экраном, а меня это не устравивает.
Поэтому я как-то хочу проверять видимость контекстного меню (пока оно полностью не исчезнет), а потом уже копировать экран.
Юрий Зотов (2009-08-29 23:35:00) [16]> dmitry_12_08_73 © (28.08.09 16:09)
procedure TForm1.OnAppMessage(var Msg: TMsg; var Handled: Boolean);
begin
FFlag := Msg.message = WM_ENTERMENULOOP;
Caption := BoolToStr(FFlag, True)
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Application.OnMessage := OnAppMessage
end;
procedure TForm1.PopupMenu1Popup(Sender: TObject);
begin
FFlag := True;
Caption := BoolToStr(FFlag, True)
end;
Но проверку флага FFlag надо делать из НЕглавного потока, потому что в главном она не имеет смысла (см. [1] - если меню нет, то флаг заведомо будет равен False, а если оно есть, то код проверки в главном потоке просто не сработает).
oldman (2009-08-29 13:12:00) [17]
> dmitry_12_08_73 ©
а в чем проблема?
оно невидимо?
код в студию!
Rouse_ (2009-08-29 00:19:00) [18]Эмм... меню модально, т.е. если из основного потока код проверки выполнился - меню нет.