HTSpy (HitTester)

Тема в разделе "WASM.PROJECTS", создана пользователем kero, 6 июл 2007.

  1. kero

    kero Модератор SOURCES & 2LZ Команда форума

    Публикаций:
    0
    Регистрация:
    4 апр 2006
    Сообщения:
    1.074
    Адрес:
    Москва
    ---
    Исчерпывающая информация о HTSpy содержится, понятно, в исходнике, см. аттач. Там же и короткая инструкция по применению, на языке, похожем на английский. Если этого мало - ну, вот еще несколько слов.

    Написать HTSpy подтолкнула wasm-овская ветка Окно с изменяемым размером без бордюра, прежде всего - чрезмерным оптимизмом данного там совета:
    HTSpy (обходясь без хуков) демонстрирует зависимость обработки мышиных сообщений от свойств окна, распознает "природные" и "искусственные" HT-зоны окон, и может еще кое что, о чем позже. Последняя версия этой учебной тулзы выглядит так:

    [​IMG]

    [​IMG]

    О HT-зонах читаем в MSDN-овской статье WM_NCHITTEST Notification:

    Код (Text):
    1. The return value of the DefWindowProc function is one of the following values, indicating the position of the cursor hot spot.
    2.  
    3. Value         Location of hot spot
    4.  
    5. HTBORDER      In the border of a window that does not have a sizing border.
    6. HTBOTTOM      In the lower-horizontal border of a resizable window (the user can click the mouse to resize the window vertically).
    7. HTBOTTOMLEFT  In the lower-left corner of a border of a resizable window (the user can click the mouse to resize the window diagonally).
    8. HTBOTTOMRIGHT In the lower-right corner of a border of a resizable window (the user can click the mouse to resize the window diagonally).
    9. HTCAPTION     In a title bar.
    10. HTCLIENT      In a client area.
    11. HTCLOSE       In a Close button.
    12. HTERROR       On the screen background or on a dividing line between windows (same as HTNOWHERE, except that the DefWindowProc function produces a system beep to indicate an error).
    13. HTGROWBOX     In a size box (same as HTSIZE).
    14. HTHELP        In a Help button.
    15. HTHSCROLL     In a horizontal scroll bar.
    16. HTLEFT        In the left border of a resizable window (the user can click the mouse to resize the window horizontally).
    17. HTMENU        In a menu.
    18. HTMAXBUTTON   In a Maximize button.
    19. HTMINBUTTON   In a Minimize button.
    20. HTNOWHERE     On the screen background or on a dividing line between windows.
    21. HTREDUCE      In a Minimize button.
    22. HTRIGHT       In the right border of a resizable window (the user can click the mouse to resize the window horizontally).
    23. HTSIZE        In a size box (same as HTGROWBOX).
    24. HTSYSMENU     In a window menu or in a Close button in a child window.
    25. HTTOP         In the upper-horizontal border of a window.
    26. HTTOPLEFT     In the upper-left corner of a window border.
    27. HTTOPRIGHT    In the upper-right corner of a window border.
    28. HTTRANSPARENT In a window currently covered by another window in the same thread (the message will be sent to underlying windows in the same thread until one of them returns a code that is not HTTRANSPARENT).
    29. HTVSCROLL     In the vertical scroll bar.
    30. HTZOOM        In a Maximize button.
    Т.е. встроенный редактор оконных стилей фактически неизбежен: большинство HT-зон связаны с WS_ и/или WS_EX_ стилями.
    А с учетом того, что CS_NOCLOSE как-то же влияет на территорию HTCLOSE, - добавлены и CS_ стили, пусть уж будут в поле зрения...
    Кстати, этот редактор еще и монитор и работает "в один клик".

    (Стили стандартных контролов остались за бортом, но есть же ControlSpy, чем не мишень для HTSpy.
    А отслеживать стили контролов "на лету" можно через WinID... только следует иметь в виду убийственную несовместимость WinID и Spy++).

    Комбобокс в HTSpy обеспечивает автоматическое восстановление исходных значений Id (контролов) и hMenu (окон), которые то и дело обнуляются при игре со стилями.
    Кроме того, в тот же комбобокс можно вводить 8-значную hex-запись произвольного hWnd, фиксируя тем самым в HTSpy соответствующее окно, если таковое существует.

    Патентованный способ получить окно, которое можно таскать, вцепившись не в заголовок, а в клиентскую область, - это подмена HTCLIENT на HTCAPTION в обработчике WM_NCHITTEST.
    Но ведь подменять HTCLIENT можно не только целиком, но и частично, и не только на HTCAPTION, и не только HTCLIENT.
    Именно так и встроена в HTSpy таблица HT-зон (где каждое число - это соответствующее "return value").

    Теперь пора пояснить мелькнувшие выше самопальные термины.
    HTCAPTION в заголовке окна - это "природная HT-зона", а HTCAPTION в таблице HT-зон - это "искусственная HT-зона".
    Смысл такого разделения в том, что "искусственная HT-зона" действительно обладает МНОГИМИ свойствами "природной", но - НЕ ВСЕМИ, и в каких-то случаях от месторасположения не отмахнуться.
    (Пример: окно закрывается после дабл-клика и по "природному", и по "искусственному" HTSYSMENU, но только после клика по "природному" HTSYSMENU всплывает системное меню).

    И вот какой критерий заложен в HTSpy:
    DefWindowProc(WM_NCHITTEST) возвращает "природное",
    а SendMessage(WM_NCHITTEST) - когда не совпадает с DefWindowProc - "искусственное".

    Правда, если окно задизаблено - картина осложняется...

    (Продолжение воспоследует)
     
  2. kero

    kero Модератор SOURCES & 2LZ Команда форума

    Публикаций:
    0
    Регистрация:
    4 апр 2006
    Сообщения:
    1.074
    Адрес:
    Москва
  3. IceStudent

    IceStudent Active Member

    Публикаций:
    0
    Регистрация:
    2 окт 2003
    Сообщения:
    4.300
    Адрес:
    Ukraine
    kero
    Я бы посоветовал использовать DEFAULT_GUI_FONT, а то смотрится плохо.
     
  4. asmfan

    asmfan New Member

    Публикаций:
    0
    Регистрация:
    10 июл 2006
    Сообщения:
    1.004
    Адрес:
    Abaddon
    kero
    Лучше складировать в 1й пост всё - ибо во всех версиях (бажных и нет) чёрт ногу сломит.
     
  5. kero

    kero Модератор SOURCES & 2LZ Команда форума

    Публикаций:
    0
    Регистрация:
    4 апр 2006
    Сообщения:
    1.074
    Адрес:
    Москва
    IceStudent,
    asmfan

    Спасибо, учтено.
     
  6. kero

    kero Модератор SOURCES & 2LZ Команда форума

    Публикаций:
    0
    Регистрация:
    4 апр 2006
    Сообщения:
    1.074
    Адрес:
    Москва
    Что-то не соображу, как сэмулировать в обычном окне область MDI окна, обведенную на скриншоте красным...

    [​IMG]

    То, что очерченные "стандартные кнопки заголовка" - на самом деле добавленные в меню итемы (id которых = SC_ командам), - ясно.
    Но как устроено, что наведение на них курсора вызывает стандартное всплытие "афишки" #32774 ?
    Ведь HTSpy показывает, что все нарисовано на HTMENU и наложения HTMINBUTTON/HTMAXBUTTON/HTCLOSE вроде бы нет...
     
  7. kero

    kero Модератор SOURCES & 2LZ Команда форума

    Публикаций:
    0
    Регистрация:
    4 апр 2006
    Сообщения:
    1.074
    Адрес:
    Москва
    Одна из иллюстраций к будущему практикуму, который предполагаю сюда дописать:

    [​IMG]

    Этот пример из другого форума ("PtInWindow ? - Part 2: Non-Layered Dialog with Layered Controls") -
    - "левая" хирургическая операция над окном, приносящая занятную инфу о HitTest-е, посмотрите через HTSpy.

    Пример НЕ работает на Win2k (на 2k вообще проблемы с WS_EX_LAYERED), работает на XP (проверено на pro-sp2), как на Висте - не знаю.

    P.S. Кстати, этот эксперимент - ни что иное как развития примера из wasm-овской ветки WS_EX_LAYERED+CS_PARENTDC+WS_CHILD+EDIT, что само по себе является ответом на вопрос: "зачем затевать пустые дискуссии?". Пустых дискуссий не бывает :) .
     
  8. kero

    kero Модератор SOURCES & 2LZ Команда форума

    Публикаций:
    0
    Регистрация:
    4 апр 2006
    Сообщения:
    1.074
    Адрес:
    Москва
  9. kero

    kero Модератор SOURCES & 2LZ Команда форума

    Публикаций:
    0
    Регистрация:
    4 апр 2006
    Сообщения:
    1.074
    Адрес:
    Москва
    Еще кусочек из практикума: красоты Windows Visual Styles в WinXP.

    Итак, мы - на XP.
    Устанавливаем тему "Windows XP".
    Запускаем, ясен пень, виндовский калькулятор.
    Наводим на него курсор и шлепаем F8, тем самым фиксируя окно калькулятора в HTSpy (что подтверждается отметкой в чекбоксе "Lock").
    Наводим курсор на "2 HTCAPTION" в HTSpy, шлепаем SHIFT key, - и в окне калькулятора закрашивается черным полученный через DefWindowProc регион HTCAPTION.

    И вот она, красотища: почти вся территория кнопки минимизации (т.е. HTMINBUTTON) - черная !
    И так и есть: с закрашенной части этой кнопки можно преспокойненько вызывать системное меню, как с заголовка.

    [​IMG]

    Видимо, в MS относятся к этому философски: "по сельской местности сойдет" и "плевать, из него не стрелять"...

    Однако если на правый клик по HTMINBUTTON что-то повешено, - то приоритет, слава MS, за ним (ncrbutton в аттаче).

    ----

    Ай! Так ведь у ncrbutton - переключение по DOWN (для скорости).
    При обычном же для кнопок переключении по UP - MS подсовывает именно системное меню!
    И юзеру от HTMINBUTTON достается только узенькая полоска справа, см. ncrbuttonup.
     
  10. kero

    kero Модератор SOURCES & 2LZ Команда форума

    Публикаций:
    0
    Регистрация:
    4 апр 2006
    Сообщения:
    1.074
    Адрес:
    Москва
  11. Mikl_

    Mikl_ New Member

    Публикаций:
    0
    Регистрация:
    14 ноя 2006
    Сообщения:
    907
    kero
    "Ложка дегтя" (XP SP2) в mdi_case если закрыть mdiclient тогда mdi_frame можно завершить только через диспетчер задач :)
     
  12. kero

    kero Модератор SOURCES & 2LZ Команда форума

    Публикаций:
    0
    Регистрация:
    4 апр 2006
    Сообщения:
    1.074
    Адрес:
    Москва
    Mikl__
    Так я ж не предлагал закрывать mdiclient :)
    я дал ему ручки, ножки и головку токмо того для, чтоб стандартных кнопок заголовка было дофигее :)

    А по всплытию над псевдокнопками меню мыслей нет ?
     
  13. kero

    kero Модератор SOURCES & 2LZ Команда форума

    Публикаций:
    0
    Регистрация:
    4 апр 2006
    Сообщения:
    1.074
    Адрес:
    Москва
    Размеры "природных" HT-зон

    Для системы в целом размеры многих HT-зон можно изменять путем SystemParametersInfo,
    например - с пульта NcSysMetrics.

    (Теперь тут вместо фотки старой версии - фотка предпоследней,
    v.2011-04-26: http://files.rsdn.ru/42164/ncsysmetrics.zip.
    Пришлось кое-что добавить, после обнаружившегося очередного бага Windows 7 Aero,
    см. http://rsdn.ru/forum/winapi/4244908.flat.aspx.

    [​IMG]

    [2011-05-01] Поскольку баг оказался не в Aero, а у меня - привожу последнюю, исправленную для Vista/Windows 7, версию 2011-05-01.
    Ага, решил не прятать свою идиотскую ошибку, а наоборот - выставить напоказ: она мне кажется довольно поучительной. Итак:
    Начальную версию NcSysMetrics состряпал задолго до Висты, потом апериодически апгрейдил...
    И вот только что осенило: для Висты/7 выложенный здесь NcSysMetrics - устарел!

    Точнее - для Висты/7 требуется, чтоб у exe SubsystemVersion >= 6,
    тогда как NcSysMetrics.exe слинкован привычно машинально, и получил SubsystemVersion = 4.
    И поэтому в нескольких моментах - врет. Так что в данном конкретном случае - никакого бага Aero нет.

    Поправленный для Висты/7 вариант - http://files.rsdn.ru/42164/ncsysmetrics_6.zip, сравните картинки:

    [​IMG]

    P.S. Перелинковывать, кстати, не обязательно: можно просто перебить в exe один полубайт (4 на 6) :)
    --------

    Кстати, предлагаю головоломку: найти систему в системных метриках.
    Например, сопоставьте (как при "классическом", так и при XP стиле) для кнопки оконного заголовка
    высоту системнометрическую, высоту визуальную, и ту, что выдает HTSpy для этого региона
    (причем последнее легко проверяется координатами из-под курсора). И ведь все в пикселях :)

    А для отдельного окна есть WM_NCCALCSIZE, хотя действует только на некоторые HT-зоны,
    вот отчет:

    [​IMG]

    Стоит всмотреться в окно NCCALCSIZE, там есть, на что поглазеть (опять же - как при "классическом", так и при XP стиле).
    Например, HTBOTTOMRIGHT разорван надвое, рисунок фрейма WS_EX_CLIENTEDGE отодран от ставшего невидимым HTBORDER...

    А не хотите ли поэкспериментировать?
    Окно NCCALCSIZE делаем WS_EX_LAYERED+SetLayeredWindowAttributes, например, при помощи HTSpy:
    наводим курсор на это окно, шмякаем F8 (=> отметка в чекбоксе "lock"), и - правый клик по чекбоксу "ws_ex_layered **".

    А теперь мышиным колесиком растягиваем клиентскую область окна NCCALCSIZE.
    У меня на XP-pro-sp2: сначала десктоп забавно искажается, а чуть позже - перезапуск виндов.
    (На XP-pro-sp3 этого глюка, кажется, уже нет).

    ---
    Кроме того (по крайней мере на XP-pro-sp2) механизм свертывания окна позволяет заголовок окна растянуть на все окно.

    Пример 1. Фиксируем окно в HTSpy (курсор над окном + клавиша F8), устанавливаем окну бит WS_MINIMIZE (помечаем соответствующий чекбокс) - и все.

    Пример 2. Обработка WM_WINDOWPOSCHANGING после нажатия стандартной кнопки минимизации в htcaption_minimize :
    .asm
    Код (Text):
    1. .const
    2.   id  equ  100
    3. .data
    4. .data?
    5. .code
    6.  
    7. DlgProc proc hWnd:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM
    8.  
    9.   .if uMsg==WM_CLOSE
    10.     invoke EndDialog,hWnd,0
    11.     mov eax,TRUE
    12.    
    13.   .elseif uMsg==WM_WINDOWPOSCHANGING
    14.     invoke IsIconic,hWnd
    15.     .if eax!=0
    16.       mov eax,lParam
    17.       assume eax:PTR WINDOWPOS
    18.       or [eax].flags,SWP_NOMOVE or SWP_NOSIZE
    19.       assume eax:nothing
    20.     .endif
    21.     mov eax,FALSE
    22.        
    23.   .else
    24.     mov eax,FALSE
    25.   .endif
    26.   ret
    27. DlgProc endp
    28.  
    29. start:
    30.  invoke GetModuleHandle,0
    31.  invoke DialogBoxParam,eax,id,0,addr DlgProc,0
    32.  invoke ExitProcess,eax
    33. end start
    .rc
    Код (Text):
    1. #define id 100
    2.  
    3. id DIALOGEX 10,10,100,80
    4. STYLE WS_OVERLAPPEDWINDOW | WS_VSCROLL | WS_HSCROLL
    5. EXSTYLE WS_EX_CLIENTEDGE
    6. CAPTION "Caption"
    7. MENU id
    8. {}
    9.  
    10. id MENU
    11. {MENUITEM "&Menu",id}
    При "классическом" и "XP стиле":

    [​IMG]

    Windows 7 Classic
    [​IMG]
    Windows 7 Aero Basic
    [​IMG]
    Windows 7 Aero Standard
    [​IMG]
    В качестве упражнения - попробуйте воспроизвести и вот такое,
    одновременно и максимизированное, и минимизированное
    (не во весь экран - из экономии жилплощади):
    [​IMG]
    (может посодействовать демка "WindowPlacement and Other").

    Вариант для нормальной отрисовки "свернутого" окна при "классическом" стиле:
    наличие WS_EX_LAYERED или WS_EX_COMPOSITED.
     
  14. kero

    kero Модератор SOURCES & 2LZ Команда форума

    Публикаций:
    0
    Регистрация:
    4 апр 2006
    Сообщения:
    1.074
    Адрес:
    Москва
  15. kero

    kero Модератор SOURCES & 2LZ Команда форума

    Публикаций:
    0
    Регистрация:
    4 апр 2006
    Сообщения:
    1.074
    Адрес:
    Москва
  16. kero

    kero Модератор SOURCES & 2LZ Команда форума

    Публикаций:
    0
    Регистрация:
    4 апр 2006
    Сообщения:
    1.074
    Адрес:
    Москва
  17. letika

    letika New Member

    Публикаций:
    0
    Регистрация:
    10 апр 2007
    Сообщения:
    28
    kero
    Интересные заметки.
     
  18. calidus

    calidus Member

    Публикаций:
    0
    Регистрация:
    27 дек 2005
    Сообщения:
    618
    =) klassnaya proga
     
  19. Noble Ghost

    Noble Ghost New Member

    Публикаций:
    0
    Регистрация:
    28 апр 2004
    Сообщения:
    204
    Адрес:
    Russia
    заведи блог, больно уж полезная инфа :)
     
  20. kero

    kero Модератор SOURCES & 2LZ Команда форума

    Публикаций:
    0
    Регистрация:
    4 апр 2006
    Сообщения:
    1.074
    Адрес:
    Москва
    Спасибо за внимание :)