Dropdown component

Hi

I'm looking for a way do show a form ( or TWinControl with child components
) as a popup window without causing a deactivate event in the main form.
The popup form can't be modal because I need to hide the form when the user
clicks outside the form client area.

I already looked in the vcl source code for TDBLookupCombobox but they
popup only one component. This technique can not work if you've several
wincontrols on the popupform which all need their own focus.
Same for the rx - datetime picker popup component and all datetime picker
components on Delphi super page.

The popup control cannot be a child from the main window because the popup
window needs to draw outside the main windows client area.

I need this popup for a component which is able to dropdown a complex
component with lots of TWinControls inside.

Anybody an idea ?

Thanks for your help.

Benny
bennyoAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

KECommented:
You should be able to take a normal form, without borders and titlebar, and place it where you want, with whatever you need in it. It should be working as a normal form, so if you can get your work done by a normal form, it's should straightforward.
Anyway, you can take a form and place it into every TWinControl.
Get the boundingbox of the control, and set your form boundings to the same positions, and make the form a parent of the control.

0
bennyoAuthor Commented:
No, displaying another form causes the deactivate event in my parent form. (exept if I show it modal, but I don't want to do that because I need to hide the popup form when the user click outside the popup form area.

Summarize :
I'm looking for a way to display a form without causing a DEACTIVATE in the parent form !!!!!!

0
KECommented:
Aint it possible to return the focus to the caller ?
Setting the StayOnTop property and the caller send the active control as a param to your form, which then set the focus to this.
0
BoRiSCommented:
Why don't who use CreateParams and create the popup form that way

if you need example then just leave a comment...

Later
BoRiS

0
Hagen040798Commented:
unit PopupPanel;
{Hi bennyo.
 Code for D3.
 TPopupPanel implem. a Panel-descend. This can use as Popup.
 You must call CloseUp(ModalResult) to Hide the Panel,
 Mouseclick's outside the Panel and Deactivation calls CloseUp(mrCancel).}
 
interface

uses ExtCtrls, Controls, Messages;

type
  TPopupPanel = class(TPanel)
  private
    FPopupResult: Integer;
    FInPopup: Boolean;
  protected
    procedure CreateParams(var Params: TCreateParams); override;
    procedure WMActivate(var Msg: TWMActivate); message wm_Activate;
  public
    function Popup(X, Y: Integer): Integer;
    procedure CloseUp(AResult: Integer);
  end;

procedure Register;

implementation

uses Windows, Classes, Forms;

const
  FMouseHook: hHook = 0;
  FInProc: Integer = 0;
  FPopupList: TList = nil;

var
  Old: LongInt;

function AcProc(Wnd: hWnd; Msg, wParam: WParam; lParam: LParam): LResult; stdcall; export;
begin
  Result := 0;
  if Msg = wm_NCActivate then wParam := 1;
  Result := CallWindowProc(Pointer(Old), Wnd, Msg, wParam, lParam);
end;

function TPopupPanel.Popup(X, Y: Integer): Integer;
var
  AWnd: hWnd;
  SaveBounds: TRect;
begin
  CloseUp(mrCancel);
  try
    FInPopup := True;
    SaveBounds := BoundsRect;
    AWnd := GetActiveWindow;
    if IsWindow(AWnd) then
    begin
      Old := GetWindowLong(AWnd, gwl_WndProc);
      SetWindowLong(AWnd, gwl_WndProc, LongInt(@AcProc));
    end;
    RecreateWnd;
    SetWindowPos(Handle, hWnd_Top, X, Y, Width, Height, swp_ShowWindow or swp_NoActivate);
    Visible := True;
    SetFocus;
    SelectNext(Self, True, True);
    FPopupList.Add(Self);
    while not Application.Terminated and IsWindowVisible(Handle) and FInPopup do
      Application.HandleMessage;
    Result := FPopupResult;
  finally
    if IsWindow(AWnd) then SetWindowLong(AWnd, gwl_WndProc, Old);
    CloseUp(mrCancel);
    BoundsRect := SaveBounds;
  end;
end;

procedure TPopupPanel.CloseUp(AResult: Integer);
begin
  if FInPopup then
  begin
    FInPopup := False;
    FPopupResult := AResult;
    if HandleAllocated and IsWindowVisible(Handle) then
      SetWindowPos(Handle, 0, 0, 0, 0, 0, swp_NoMove or swp_NoZOrder or
                   swp_NoSize or swp_HideWindow or swp_NoActivate);
    Hide;
  end;
  FPopupList.Remove(Self);
end;

procedure TPopupPanel.CreateParams(var Params: TCreateParams);
begin
  inherited CreateParams(Params);
  if FInPopup then
    with Params do
    begin
      Style := ws_ClipChildren or ws_ClipSiblings or ws_Popup;
      if TabStop then Style := Style or ws_TabStop;
      with WindowClass do
        Style := Style and not (cs_HRedraw or cs_VRedraw) or cs_ByteAlignWindow or cs_SaveBits;
    end;
end;

procedure TPopupPanel.WMActivate(var Msg: TWMActivate);
begin
  if (Msg.Active = wa_InActive) and FInPopup then CloseUp(mrCancel);
  inherited;
end;

procedure Register;
begin
  RegisterComponents('Samples', [TPopupPanel]);
end;

function MouseProc(Code: Integer; wParam: WParam; lParam: LParam): LResult; stdcall; export;
var
  P: TPoint;
  I: Integer;
  R: TRect;
begin
  if (Code = hc_Action) and (FInProc = 0) then
  try
    Inc(FInProc);  {Disables Recursion's}
    if (FPopupList <> nil) and (FPopupList.Count > 0) and
       ((wParam = wm_LButtonDown) or (wParam = wm_NCLButtonDown) or
        (wParam = wm_RButtonDown) or (wParam = wm_NCRButtonDown) or
        (wParam = wm_MButtonDown) or (wParam = wm_NCMButtonDown)) then
    begin
      GetCursorPos(P);
      for I := FPopupList.Count-1 downto 0 do
        with TPopupPanel(FPopupList[I]) do
        begin
          GetWindowRect(Handle, R);
          if not PtInRect(R, P) then CloseUp(mrCancel);
        end;
    end;
  finally
    Dec(FInProc);
  end;
  Result := CallNextHookEx(FMouseHook, Code, wParam, lParam);
end;

initialization
  FPopupList := TList.Create;
  FMouseHook := SetWindowsHookEx(WH_MOUSE, MouseProc, 0, GetCurrentThreadID);
finalization
  if FMouseHook <> 0 then UnHookWindowsHookEx(FMouseHook);
  FMouseHook := 0;
  FPopupList.Free;
end.

0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Delphi

From novice to tech pro — start learning today.