--- Исчерпывающая информация о HTSpy содержится, понятно, в исходнике, см. аттач. Там же и короткая инструкция по применению, на языке, похожем на английский. Если этого мало - ну, вот еще несколько слов. Написать HTSpy подтолкнула wasm-овская ветка Окно с изменяемым размером без бордюра, прежде всего - чрезмерным оптимизмом данного там совета: HTSpy (обходясь без хуков) демонстрирует зависимость обработки мышиных сообщений от свойств окна, распознает "природные" и "искусственные" HT-зоны окон, и может еще кое что, о чем позже. Последняя версия этой учебной тулзы выглядит так: О HT-зонах читаем в MSDN-овской статье WM_NCHITTEST Notification: Код (Text): The return value of the DefWindowProc function is one of the following values, indicating the position of the cursor hot spot. Value Location of hot spot HTBORDER In the border of a window that does not have a sizing border. HTBOTTOM In the lower-horizontal border of a resizable window (the user can click the mouse to resize the window vertically). HTBOTTOMLEFT In the lower-left corner of a border of a resizable window (the user can click the mouse to resize the window diagonally). HTBOTTOMRIGHT In the lower-right corner of a border of a resizable window (the user can click the mouse to resize the window diagonally). HTCAPTION In a title bar. HTCLIENT In a client area. HTCLOSE In a Close button. 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). HTGROWBOX In a size box (same as HTSIZE). HTHELP In a Help button. HTHSCROLL In a horizontal scroll bar. HTLEFT In the left border of a resizable window (the user can click the mouse to resize the window horizontally). HTMENU In a menu. HTMAXBUTTON In a Maximize button. HTMINBUTTON In a Minimize button. HTNOWHERE On the screen background or on a dividing line between windows. HTREDUCE In a Minimize button. HTRIGHT In the right border of a resizable window (the user can click the mouse to resize the window horizontally). HTSIZE In a size box (same as HTGROWBOX). HTSYSMENU In a window menu or in a Close button in a child window. HTTOP In the upper-horizontal border of a window. HTTOPLEFT In the upper-left corner of a window border. HTTOPRIGHT In the upper-right corner of a window border. 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). HTVSCROLL In the vertical scroll bar. 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 - "искусственное". Правда, если окно задизаблено - картина осложняется... (Продолжение воспоследует)
Что-то не соображу, как сэмулировать в обычном окне область MDI окна, обведенную на скриншоте красным... То, что очерченные "стандартные кнопки заголовка" - на самом деле добавленные в меню итемы (id которых = SC_ командам), - ясно. Но как устроено, что наведение на них курсора вызывает стандартное всплытие "афишки" #32774 ? Ведь HTSpy показывает, что все нарисовано на HTMENU и наложения HTMINBUTTON/HTMAXBUTTON/HTCLOSE вроде бы нет...
Одна из иллюстраций к будущему практикуму, который предполагаю сюда дописать: Этот пример из другого форума ("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, что само по себе является ответом на вопрос: "зачем затевать пустые дискуссии?". Пустых дискуссий не бывает .
Еще кусочек из практикума: красоты Windows Visual Styles в WinXP. Итак, мы - на XP. Устанавливаем тему "Windows XP". Запускаем, ясен пень, виндовский калькулятор. Наводим на него курсор и шлепаем F8, тем самым фиксируя окно калькулятора в HTSpy (что подтверждается отметкой в чекбоксе "Lock"). Наводим курсор на "2 HTCAPTION" в HTSpy, шлепаем SHIFT key, - и в окне калькулятора закрашивается черным полученный через DefWindowProc регион HTCAPTION. И вот она, красотища: почти вся территория кнопки минимизации (т.е. HTMINBUTTON) - черная ! И так и есть: с закрашенной части этой кнопки можно преспокойненько вызывать системное меню, как с заголовка. Видимо, в MS относятся к этому философски: "по сельской местности сойдет" и "плевать, из него не стрелять"... Однако если на правый клик по HTMINBUTTON что-то повешено, - то приоритет, слава MS, за ним (ncrbutton в аттаче). ---- Ай! Так ведь у ncrbutton - переключение по DOWN (для скорости). При обычном же для кнопок переключении по UP - MS подсовывает именно системное меню! И юзеру от HTMINBUTTON достается только узенькая полоска справа, см. ncrbuttonup.
kero "Ложка дегтя" (XP SP2) в mdi_case если закрыть mdiclient тогда mdi_frame можно завершить только через диспетчер задач
Mikl__ Так я ж не предлагал закрывать mdiclient я дал ему ручки, ножки и головку токмо того для, чтоб стандартных кнопок заголовка было дофигее А по всплытию над псевдокнопками меню мыслей нет ?
Размеры "природных" 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. [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, сравните картинки: P.S. Перелинковывать, кстати, не обязательно: можно просто перебить в exe один полубайт (4 на 6) -------- Кстати, предлагаю головоломку: найти систему в системных метриках. Например, сопоставьте (как при "классическом", так и при XP стиле) для кнопки оконного заголовка высоту системнометрическую, высоту визуальную, и ту, что выдает HTSpy для этого региона (причем последнее легко проверяется координатами из-под курсора). И ведь все в пикселях А для отдельного окна есть WM_NCCALCSIZE, хотя действует только на некоторые HT-зоны, вот отчет: Стоит всмотреться в окно 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): .const id equ 100 .data .data? .code DlgProc proc hWnd:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM .if uMsg==WM_CLOSE invoke EndDialog,hWnd,0 mov eax,TRUE .elseif uMsg==WM_WINDOWPOSCHANGING invoke IsIconic,hWnd .if eax!=0 mov eax,lParam assume eax:PTR WINDOWPOS or [eax].flags,SWP_NOMOVE or SWP_NOSIZE assume eax:nothing .endif mov eax,FALSE .else mov eax,FALSE .endif ret DlgProc endp start: invoke GetModuleHandle,0 invoke DialogBoxParam,eax,id,0,addr DlgProc,0 invoke ExitProcess,eax end start .rc Код (Text): #define id 100 id DIALOGEX 10,10,100,80 STYLE WS_OVERLAPPEDWINDOW | WS_VSCROLL | WS_HSCROLL EXSTYLE WS_EX_CLIENTEDGE CAPTION "Caption" MENU id {} id MENU {MENUITEM "&Menu",id} При "классическом" и "XP стиле": Windows 7 Classic Windows 7 Aero Basic Windows 7 Aero Standard В качестве упражнения - попробуйте воспроизвести и вот такое, одновременно и максимизированное, и минимизированное (не во весь экран - из экономии жилплощади): (может посодействовать демка "WindowPlacement and Other"). Вариант для нормальной отрисовки "свернутого" окна при "классическом" стиле: наличие WS_EX_LAYERED или WS_EX_COMPOSITED.