powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / вот такие фокусы
9 сообщений из 9, страница 1 из 1
вот такие фокусы
    #34736223
Фотография Cerebrum
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
win32api, vc2005sp1

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

1. у кнопки на этапе создания подменяется стандартная процедура обработки на мою BaseWindowProc(). События поступающие в эту процедуру генерят вызовы виртуальных функций BaseWnd, которые переопределены в классе кнопки

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
class BaseWnd
{
	HWND m_hWnd;
...
	virtual LRESULT OnLButtonDown(UINT nFlags, RPoint point) {return - 1 };
	virtual LRESULT WindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam);

	static LRESULT CALLBACK BaseWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
...
};

class MyButton : public BaseWnd
{
...
	virtual LRESULT WindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam);
	virtual LRESULT OnLButtonDown(UINT nFlags, RPoint point) {return - 1 };
...
};

2. В процедуре BaseWindowProc ловим сообщения

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
LRESULT CALLBACK BaseWnd::BaseWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
//-------------------------------------------------------- обработчик сообщений для всех окон
	LRESULT	lResult = - 1 ;
	switch (uMsg)
	{
....
		case WM_LBUTTONDOWN:
		{
			//получаем указатель на окно, пусть он будет в pWindow, и 
//вызываем соотвествующую функцию
			lResult = pWindow->OnLButtonDown(/*параметры*/);
		}
...
	}
//если lResult по прежнему -1 отдаем в обработку DefWindowProc
}

3. У кнопки срабатывает при получении этого сообщения функция OnLButtonDown

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
LRESULT MyButton::OnLButtonDown(UINT nFlags, RPoint point)
{
	// у кнопки установлен стиль WS_TABSTOP?
	DWORD dw = GetStyle(); // доп. функция на основе GetWindowLong
	if(dw & WS_TABSTOP)
		MessageBox("стиль WS_TABSTOP установлен",  0 ,  0 );
	// а фокус есть?
	if(::GetFocus() != m_hWnd /*<- хэндл этого окна*/)
		MessageBox("Упс! где он?",  0 ,  0 );
	return 0L:
}

Вопрос я думаю уже понятен :-)

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

СПАСИБО (даже если дочитали до сюда)
...
Рейтинг: 0 / 0
вот такие фокусы
    #34736733
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Cerebrum пишет:
> LRESULT MyButton::OnLButtonDown(UINT nFlags, RPoint point)
> {
> // у кнопки установлен стиль WS_TABSTOP?
> DWORD dw = GetStyle(); // доп. функция на основе GetWindowLong
> if(dw & WS_TABSTOP)
> MessageBox("стиль WS_TABSTOP установлен", *0*, *0*);
> // а фокус есть?
> if(::GetFocus() != m_hWnd /*<- хэндл этого окна*/)
> MessageBox("Упс! где он?", *0*, *0*);
> return 0L:
> }
> Должно ли уже в этом моменте окно иметь фокус если системой
> зафиксировано нажатие кнопки?

Что такое фокус ввода ? Это - текущее окно приложения, в которое
направляется весь ввод клавиатуры и которое получает сообщения
типа WM_KEYDOWN/WM_KEYUP/WM_CHAR etc. Обычно, но не обязательно,
окно, имеющее фокус ввода, помечается рамкой из пунктирной линии.

Нужно отметить, что WM_LBUTTONDOWN - это сообщение мышки, и оно
с клавиатурой никак не связано. В системе одно окно может иметь
фокус ввода, а другое окно получить WM_LBUTTONDOWN, не имея при
этом фокуса ввода. Это нормально. Даже наоборот, как правило,
в результате обработки WM_LBUTTONDOWN данное окно и получает
фокус ввода (если для него это осмысленно). Обычно это делает
DefWindowProc(). Так что вопрос непонятен. Но если на него отвечать,
то ответ - нет, не должно. Может иметь, а может и не иметь.

> Насколько я знаю WM_SETFOCUS асинхронное сообщение и для того чтобы оно

Это как так - "асинхронное" ? Все сообщения вообще-то синхронные.
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
вот такие фокусы
    #34736812
Фотография Cerebrum
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZiv
Так что вопрос непонятен. Но если на него отвечать,
то ответ - нет, не должно. Может иметь, а может и не иметь.

> Насколько я знаю WM_SETFOCUS асинхронное сообщение и для того чтобы оно

Это как так - "асинхронное" ? Все сообщения вообще-то синхронные.
Posted via ActualForum NNTP Server 1.4

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

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

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

Я посчитал нужным добавить в обработчик BaseWindowProc() вот это

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
	case WM_LBUTTONDOWN:
		{
			DWORD dw = pWindow->GetStyle();
			if ((dw & WS_TABSTOP) && (pWindow->GetFocus() != pWindow))
				pWindow->SetFocus();
			RPoint pt(LOWORD(lParam), HIWORD(lParam));
			lResult = pWindow->OnLButtonDown((UINT)wParam, pt);
		}
break;
и оно работает, но скорее всего это через зад, поэтому дисскусию не заканчиваю и скромно рассчитываю на любую светлую мысль от форумчан и не только.

MasterZiv отдельный респект, ты прямо таки мой, не побоюсь этого слова, кумир в C++
:-)
...
Рейтинг: 0 / 0
вот такие фокусы
    #34737198
Cerebrumя о том, что при нажатии кнопки мыши на моем контроле (MyButton) и последующей проверке на наличие фокуса, т.е. я хочу просто проверить, когда буду вызывать перерисовку, стоит ли мне рисовать пунктирную линию или же нет. Если я давлю таб, то фокус кнопка получает, но если нажимаю кнопку мыши, то кнопка остается без него, хотя по логике вещей он автоматически должен у нее появиться и клик трактоваться именно как клик по кнопке с фокусом.Фокус это системный указатель - в какое окно отправлять нажатия кнопок на клавиатуре. Мышь к фокусу отношения не имеет совсем.
...
Рейтинг: 0 / 0
вот такие фокусы
    #34737452
Фотография Cerebrum
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
я это понимаю, но когда вы кликаете на кнопке он ведь появляется на ней, если у кнопки стандартное поведение?
--------------------------------------------------------------
[не претендую на уникальность]
...
Рейтинг: 0 / 0
вот такие фокусы
    #34738502
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Cerebrum пишет:
> последующей проверке на наличие фокуса, т.е. я хочу просто проверить,
> когда буду вызывать перерисовку, стоит ли мне рисовать пунктирную линию
> или же нет. Если я давлю таб, то фокус кнопка получает, но если нажимаю
> кнопку мыши, то кнопка остается без него, хотя по логике вещей он
> автоматически должен у нее появиться и клик трактоваться именно как клик
> по кнопке с фокусом.

Дай обработчику DefWndProc() отработать - он и появится.
Если конечно в принципе это окно фокус ввода получает.

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

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

> Мой BaseWindowProc фиксирует WM_SETFOCUS при щелчке, но фокус так и
> остается не присвоенным . В инете я нашел схожую проблему и там

вызови DefWindowProc().

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

Скорее всего бред это, или ты не так излагаешь.

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


Если BaseWindowProc() - это DefWndProc(), то так и НАДО делать.
Но я что-то там в коде не видел вызова. Но смотрел невнимательно.
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
вот такие фокусы
    #34738625
Фотография Cerebrum
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DefWindowProc я вызываю в BaseWindowProc, если результат обработки сообщения отличен от -1 следующим образом

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
LRESULT CALLBACK RWnd::BaseWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
//-------------------------------------------------------- обработчик сообщений для всех окон
//*******************************************************************************************
	LRESULT	lResult = -1;											 // возвращаемое значение	
//------------ сначала обработаем сообщения при создании окон, прикрепим хэндлы к обработчику
	switch (uMsg)
	{
.....
.....
.....
.....

/////////////////////////////////////////////////////////////////////////////////////////////	
			case WM_NCDESTROY:							 // разрушили неклиентскую часть окна
			{
				if (pWindow->GetSafeHwnd())				 // хэндл остался
				{
					pWindow->Detach();					 // отстыкуем объект
					pWindow->m_hWnd			  = NULL;
					pWindow->m_lpfnOldWndProc = NULL;
				}
				return lResult;	
			}
		} // eof_switch
// если lResult до сих пор равен -1, кроме случая с созданием окна WM_CREATE и хэндл окна жив
//-------------------------------------- передаем управление в виртуальные функции этого окна
		if (((lResult == -1 && uMsg != WM_CREATE) || (lResult == -2 && uMsg == WM_CREATE)) && 
							   /*валидность хэндла проверит здесь ->*/pWindow->GetSafeHwnd())
			return pWindow->WindowProc(uMsg, wParam, lParam); // в обработчик для окна
	}
	
	return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
}

--------------------------------------------------------------
[не претендую на уникальность]
...
Рейтинг: 0 / 0
вот такие фокусы
    #34739841
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Cerebrumя это понимаю, но когда вы кликаете на кнопке он ведь появляется на ней, если у кнопки стандартное поведение?Вопрос на засыпку: Что такое стандартное поведение?
Правильный ответ: Вызов DefWindowProc().
Если ты поймаешь WM_LBUTTONDOWN, сделаешь свою собственную обработку, а потом дополнительно вызовешь еще и DefWindowProc для этой WM_LBUTTONDOWN - то система вытащит твое окно на самый верх и отрисует тебе пунктир на кнопке. Если после обработки события ты выйдешь из своей BaseWindowProc не вызывая DefWindowProc то и стандартной обработки (поднятия окна на верх, и передача в него фокуса) не произойдет.
...
Рейтинг: 0 / 0
вот такие фокусы
    #34739978
Фотография Cerebrum
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
White Owl Cerebrumя это понимаю, но когда вы кликаете на кнопке он ведь появляется на ней, если у кнопки стандартное поведение?Вопрос на засыпку: Что такое стандартное поведение?
Правильный ответ: Вызов DefWindowProc().
Если ты поймаешь WM_LBUTTONDOWN, сделаешь свою собственную обработку, а потом дополнительно вызовешь еще и DefWindowProc для этой WM_LBUTTONDOWN - то система вытащит твое окно на самый верх и отрисует тебе пунктир на кнопке. Если после обработки события ты выйдешь из своей BaseWindowProc не вызывая DefWindowProc то и стандартной обработки (поднятия окна на верх, и передача в него фокуса) не произойдет.
под стандартным я понимаю формулу

клик по кнопке = перемешение фокуса на кнопку + нажатие кнопки + всякая активация окна кнопки и прояие сопутствующие клику месседжи

а не так как у меня

клик = перемещение фокуса (WM_SETFOCUS)
еще один клик = нажатие кнопки

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

всем спасибо
...
Рейтинг: 0 / 0
9 сообщений из 9, страница 1 из 1
Форумы / C++ [игнор отключен] [закрыт для гостей] / вот такие фокусы
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]