Может кому пригодится:
Фрагмент кода, добавляющего в системное меню окна пункт "Always On Top" ("Поверх остальных окон"). Может быть переделан под обработку любых других сообщений.
Вывод системного меню собровождается сообщением WM_SYSCOMMAND. Перехват этого сообщения и организуем.
В первую очередь, необходимо определить Qt'шный фильтр сообщений (он не определен ни в одном заголовочнике Qt (по крайней мере в Qt 3.3), поэтому сделаем это ручками):
typedef int ( *QWinEventFilter )( MSG* );
extern Q_EXPORT QWinEventFilter qt_set_win_event_filter( QWinEventFilter );
const UINT MENU_PINUP_ID = 433973;
bool MENU_PINUP_STATE = false;
HWND _hWnd = NULL;
HMENU _hSysMenu = NULL;
QWinEventFilter _EventFilter = NULL;
Устанавливаем наш фильтр:
void init( HWND winId, const WCHAR* swzMenuText ) {
_EventFilter = qt_set_win_event_filter( wlogWindowEventFilter );
_hWnd = winId;
_hSysMenu = ::GetSystemMenu( _hWnd, FALSE );
::RemoveMenu( _hSysMenu, SC_CLOSE, MF_BYCOMMAND );
::AppendMenuW( _hSysMenu, MF_STRING | MF_UNCHECKED, MENU_PINUP_ID, swzMenuText );
}
Код нашего фильтра:
int wlogWindowEventFilter( MSG *pMsg ) {
switch( pMsg->message ) {
case WM_SYSCOMMAND: {
switch( pMsg->wParam ) {
case MENU_PINUP_ID:
onAlwaysOnTop();
break;
}
}
}
return _EventFilter ? _EventFilter( pMsg ) : false;
}
Собственно функция, устанавливающая наше окно поверх остальных:
void onAlwaysOnTop() {
UINT uCheck = MF_UNCHECKED;
HWND hWndInsertAfter = HWND_NOTOPMOST;
if( MENU_PINUP_STATE = !MENU_PINUP_STATE ) {
uCheck = MF_CHECKED;
hWndInsertAfter = HWND_TOPMOST;
}
::SetWindowPos( _hWnd, hWndInsertAfter, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE );
::CheckMenuItem( _hSysMenu, MENU_PINUP_ID, uCheck );
}
Как это вызывать:
WSysMenu::init( parent->winId(), tr( "Always On Top" ).ucs2());
А это результат:
Обратите внимание, что за счет того, что мы убрали пункт меню "Закрыть" (::RemoveMenu( _hSysMenu, SC_CLOSE, MF_BYCOMMAND )) кнопка закрытия окна тоже стала недоступной.