2016-10-25 1 views
2

У меня есть окно без рамки, единственным дочерним элементом которого всегда является размер окна, является сторонний компонент. Этот компонент хочет иметь возможность уведомить меня, когда WM_MOUSEDOWN произошел в определенных областях, которые по своему усмотрению, для перемещения или изменения размера окна (как если бы оно не было без границ). Он также хочет решить, какое событие использовать в вопросе.Как инициировать пользовательский переход или изменение размера пользовательских границ окна в Windows в окне без полей, когда событие приходит к ребенку?

Поскольку окно без полей и дочернее окно уже получили сообщение мыши, я не думаю, что смогу переопределить WM_NCHITTEST, не так ли? (Или, другими словами, делает родительское окно всегда получают WM_NCHITTEST, прежде чем мой ребенок получает WM_LBUTTONDOWN? Или только при первой активации/во время захвата?)

GTK + используется для вызова DefWindowProc() с WM_NCLBUTTONDOWN вручную запустить этот модальный цикл событий. Это способ сделать это?

Что относительно SC_MOVE в WM_SYSCOMMAND? Это только для управляемых клавиатурой оконных движений и изменения размеров, а не для мыши?

Или мне это нужно сделать вручную? Я знаю, что это модальный цикл, который использует одну из констант фильтра сообщений, и я знаю, что Aero Snap нужно будет делать вручную, по крайней мере.

Мне нужно сделать это на Windows Vista или выше.

Спасибо.

ответ

3

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

Однако вы все же можете разрешить пользователю изменять размер родительского окна обычно с помощью небольшого дополнительного кодирования. Есть несколько различных способов, вы можете справиться с этим:

  1. подкласса окно ребенка перехватывает WM_NCHITTEST сообщений. Получив сообщение, сначала передайте сообщение обработчику сообщений по умолчанию для ребенка, и если он вернет HTCLIENT, а координаты экрана, указанные в lParam, находятся в области родительского окна, которое вы хотите использовать для изменения размера, вместо этого введите HTTRANSPARENT. Это вызовет WM_NCHITTEST для отправки в родительском окне рядом, который затем может обрабатывать WM_NCHITTEST и возвращать одно из следующих значений, в зависимости от типа изменения размера вы хотите:

    HTBOTTOM 
    HTBOTTOMLEFT 
    HTBOTTOMRIGHT 
    HTLEFT 
    HTRIGHT 
    HTTOP 
    HTTOPLEFT 
    HTTOPRIGHT 
    
  2. в MouseDown случае окна ребенка, конвертировать предоставленные клиентом координаты мыши в координаты экрана, а затем вызовите ReleaseCapture() и отправьте сообщение WM_NCLBUTTONDOWN в родительское окно, установив wParam на одно из значений, упомянутых выше, и lParam на экранные координаты.

  3. в случае MouseDown дочернего окна, вызовите ReleaseCapture() и отправить WM_SYSCOMMAND сообщение для родительского окна, установка wParam к SC_SIZE плюс нужное значение ниже, и lParam 0:

    SC_SIZE_HTLEFT = 1 
    SC_SIZE_HTRIGHT = 2 
    SC_SIZE_HTTOP = 3 
    SC_SIZE_HTTOPLEFT = 4 
    SC_SIZE_HTTOPRIGHT = 5 
    SC_SIZE_HTBOTTOM = 6 
    SC_SIZE_HTBOTTOMLEFT = 7 
    SC_SIZE_HTBOTTOMRIGHT = 8 
    

Либо путь позволит родительскому окну нормально изменять размер и все, что связано (отслеживание мыши, привязка и т. д.), за исключением одной вещи. # 1 подталкивает ОС к мысли о том, что пользователь непосредственно замалчивается над родительским окном, и поэтому он позволяет ОС визуально получать информацию о том, какая «граница размеров» используется. # 2 и # 3 не будут предоставлять визуальной обратной связи, поэтому вам придется обрабатывать это вручную через SetCursor(), если это необходимо.

Если вы хотите, чтобы позволить пользователю перетаскивать родительское окно вокруг, не меняя его размера, вы можете:

  1. подкласс ребенка WM_NCHITTEST сообщения вернуться HTTRANSPARENT в соответствующей области, а затем родительский оконный процесс WM_NCHITTEST для возврата HTCAPTION.

  2. в случае MouseDown дочернего окна, вызовите ReleaseCapture() и отправить WM_SYSCOMMAND сообщений для родительского окна, установив wParam в SC_DRAGMOVE (который без документов, но его значение $F012, иначе SC_MOVE + 2) и lParam набора 0.

+0

Так что мой единственный вариант - использовать 'WM_NCHITTEST' в любом случае? Я только спрашиваю, потому что сейчас сигнал для перетаскивания заново документируется для отправки во время обработчика 'WM_LBUTTONDOWN'; Однако я могу изменить API без проблем. Будет ли трюк с низким битом работать с 'SC_SIZE'? – andlabs

+0

'WMNCHITTEST' не ваш * только * вариант. И да, 'SC_SIZE' имеет подобный трюк с небольшими битками. Я обновил свой ответ. –

+0

Прохладный, спасибо. И только для полноты стандартным способом, будет ли когда-нибудь ситуация, когда подклассификация дочернего 'WM_NCHITTEST' будет недостаточной? – andlabs

Смежные вопросы