2012-05-05 4 views
2

Я пытаюсь создать пользовательский элемент управления Combobox, который отображает Treeview. Все выглядит хорошо. Но когда я пытаюсь добавить функциональность изменения времени выполнения для этого элемента управления, всплывающее окно (Treeview) просто перемещается и не изменяет его размер.Как динамически изменять всплывающее окно во время выполнения?

Любое предложение будет оценено.

Snippets для всплывающего окна:

On Создать:

ControlStyle := ControlStyle + [csNoDesignVisible, csReplicatable, csDoubleClicks]; 

На Создать Params:

begin 
    inherited CreateParams(Params); 
    with Params do 
    begin 
    Style := Style or WS_POPUP or WS_VSCROLL or WS_BORDER; 
    ExStyle := WS_EX_TOOLWINDOW; 
    AddBiDiModeExStyle(ExStyle); 
    //WindowClass.Style := CS_SAVEBITS; {this would prevent ondoubleclick event} 
    end; 

На мышь Move:

var 
    ARect, RR: TRect; 
    DragStyle: TDragStyle; 
    Procedure SetDragStyle(ds:TDragStyle; c:TCursor); 
    begin 
    FDragStyle:=ds; 
    Cursor:=c; 
    end; 
begin 
    inherited; 
    FMouseMoveSelected := GetNodeAt(x, y); 
    if FDragged then begin 
    case FDragStyle of 
     dsSizeLeft :begin 
         SetWindowPos(Handle, HWND_TOP, Left+(x-FDragPos.X), Top, Width, Height, 
         SWP_NOACTIVATE or SWP_SHOWWINDOW); 
         //Left:=Left+(x-FDragPos.X); {alternate code that doesn't work either} 
        end; 
    end; 
    FDragPos:=Point(x,y); 
    end else begin 
    SetDragStyle(dsMove,crDefault); 
    ARect := GetClientRect; 
    RR:=ARect; 
    InflateRect(RR,-2,-2); 
    if (x>=0) and (x<=Width) and (y>=0) and (y<=Height) and (not PtInRect(RR,Point(x,y))) then begin 
     if (x<=RR.Left) then begin 
     //if (y<=RR.Top) then SetDragStyle(dsSizeTopLeft,crSizeNWSE)else 
     if (y>=RR.Bottom) then SetDragStyle(dsSizeBottomLeft,crSizeNESW) 
     else SetDragStyle(dsSizeLeft,crSizeWE); 
     end else if (x>=RR.Right) then begin 
     //if (y<=RR.Top) then SetDragStyle(dsSizeTopRight,crSizeNESW) else 
     if (y>=RR.Bottom) then SetDragStyle(dsSizeBottomRight,crSizeNWSE) 
     else SetDragStyle(dsSizeRight,crSizeWE); 
     end else begin 
     //if (y<=RR.Top) then SetDragStyle(dsSizeTop,crSizeNS) else 
     if (y>=RR.Bottom) then SetDragStyle(dsSizeBottom,crSizeNS) 
     else SetDragStyle(dsMove,crDefault); 
     end; 
    end; 
    end; 
end; 
end; 

На мышь вниз:

begin 
    inherited; 
    if FDragStyle<>dsMove then begin 
    FDragPos:=point(x,y); 
    FDragged:=true; 
    end; 
end; 

На Mouse Up:

begin 
    inherited; 
    FDragged:=false; 
end; 
+0

Почему вы не установить стиль WS_THICKFRAME и сделать с ним? –

+0

Да, правильно. Очень хорошее предложение. Он менял размер без необходимости моего кода на события мыши. Я пробовал это. Теперь проблема в том, что она изменяет размеры всего направления, поэтому я должен реализовать дополнительные процедуры, чтобы предотвратить изменение размера слева и сверху. **Благодаря**. – theodorusap

+0

Добро пожаловать. Используете ли вы это или нет, я отправил ответ за то, что, по моему мнению, было неправильным. –

ответ

4

Вы смешивания клиента координаты с экрана координат в SetWindowPos вызова. Это потому, что вы плаваете окно, которое не должно плавать, и VCL не знает об этом. Когда вы ссылаетесь на свой Left, VCL возвращает координату относительно ее родителя, возможно, в форме. Также не изменить точку сохраненную в то время как вы начали перетаскивать во время перетаскивания (что, будучи FDragPos):

procedure TPanel.MouseMove(Shift: TShiftState; X, Y: Integer); 
var 
    ARect, RR: TRect; 
    DragStyle: TDragStyle; 

    Procedure SetDragStyle(ds:TDragStyle; c:TCursor); 
    begin 
    FDragStyle:=ds; 
    Cursor:=c; 
    end; 

    var 
    DragOffset: Integer; 
begin 
    inherited; 
    FMouseMoveSelected := GetNodeAt(x, y); 
    if FDragged then begin 
    case FDragStyle of 
     dsSizeLeft: 
     begin 
      DragOffset := X - FDragPos.X; 
      winapi.windows.GetWindowRect(Handle, ARect); 
      SetWindowPos(Handle, HWND_TOP, 
            ARect.Left + DragOffset, 
            ARect.Top, 
            ARect.Right - ARect.Left - DragOffset, 
            ARect.Bottom - ARect.Top, 
            SWP_NOACTIVATE or SWP_SHOWWINDOW); 
      //Left:=Left+(x-FDragPos.X); {alternate code that doesn't work either} 
     end; 
    end; 
// FDragPos:=Point(x,y); // do not change drag origin while you're dragging 
    end else begin 
    .. 
+0

Спасибо за этот фрагмент. Это абсолютно ответит на мой вопрос с некоторыми изменениями: (1) ** FDragPos: = Point (x, y) ** следует установить на Bottom and BottomRight DragStyle и ** FDragPos.y: = y ** на BottomLeft DragStyle. (2) Мы должны захватить дескриптор (** setcapture (handle) **) при событии кнопки мыши или изменение размера не будет выполняться при перемещении курсора. Еще раз спасибо. – theodorusap

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