C ++ Builder: создайте TForm с BorderStyle bsNone, который, тем не менее, можно перемещать и изменять размер - PullRequest
1 голос
/ 24 августа 2011

Я хотел бы иметь TForm с BorderStyle = bsNone (без границ, без заголовка), который, тем не менее, можно изменять и изменять.Я уже разобрался, как сделать изменяемый размер, но я застрял в том, чтобы сделать его подвижным.

/**
*   Overrides standard CreateParams method to create a TForm with BorderStyle
*    bsNone but is nevertheless movable and resizable
**/
void __fastcall CreateParams(TCreateParams &Params)
{
    BorderStyle = bsNone;
    TForm::CreateParams(Params);
    //set flag WS_EX_STATICEDGE
    //for more details on this flag, see http://msdn.microsoft.com/en-us/library/ms632680(v=vs.85).aspx
    Params.ExStyle = Params.ExStyle ^ 0x00020000L;
    //set flag WS_SIZEBOX
    //for more details on this flag, see http://msdn.microsoft.com/en-us/library/ff700543(v=VS.85).aspx
    Params.Style = Params.Style ^ 0x00040000L;
}

Вероятно, дело только в поиске правильных флагов.Есть идеи?

Ответы [ 2 ]

5 голосов
/ 25 августа 2011

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

Для этого вы отвечаете на сообщение WM_NCHITTEST , которое легко сделать с помощью , переопределяя форму WndProc метод .Это сообщение отправляется в нескольких ситуациях (не только щелчки мышью или движение), поэтому не думайте о том, что делает пользователь, когда вы получаете это сообщение.Обработайте его, установив для результата сообщения значение HTCAPTION, значение которого указывает на положение над строкой заголовка.

Важные моменты, на которые следует обратить внимание:

  • Этот метод будет вызываться длякаждое сообщение, которое получает форма;не делайте здесь ничего медленного или сложного.
  • Всегда позволяйте наследуемой по умолчанию реализации WndProc обрабатывать сообщение.Это важно для большинства сообщений, так как вы хотите изменить только это поведение, и если вы не вызовете унаследованную имплантацию, для сообщений вообще ничего не произойдет, но это важно и для этого сообщения, так как вы не знаетекакой код нужно отправить это сообщение.Т.е. вы хотите добавить, как ваша программа реагирует на это, а не заменить его.Это общее хорошее руководство для всей обработки сообщений, которые вы перехватываете / добавляете.В документации WndProc это тоже упоминается.
  • Вы можете установить область формы в качестве перетаскиваемого бита, проверив координаты мыши.В приведенном ниже коде будут перетаскиваться только верхние 100 пикселей формы.

Пример кода:

void __fastcall TForm1::WndProc(Messages::TMessage& Message) {
    TForm::WndProc(Message); // Inherited implementation
    if (Message.Msg == WM_NCHITTEST) {
        TWMNCHitTest& oMsg = reinterpret_cast<TWMNCHitTest&>(Message);
        TPoint oPoint(oMsg.XPos, oMsg.YPos); // Screen coordinates
        oPoint = ScreenToClient(oPoint); // Now in form-local coordinates
        // It's in the title bar (caption) if it's in a rectangle at the top of the form
        if ((oPoint.x > 0 && oPoint.x < ClientWidth) &&
            (oPoint.y > 0 && oPoint.y < 100))
        {
            oMsg.Result = HTCAPTION;
        }
    }
}
4 голосов
/ 24 августа 2011

Попробуйте поместить этот код в обработчик события Form OnMouseDown:

ReleaseCapture();
this->Perform(WM_SYSCOMMAND, 0xF012, 0);
...