Solved

Draw or anchor a panel (or other TWinControl) over external window

Posted on 2010-09-10
6
554 Views
Last Modified: 2013-11-23
Hi, waht is the best way (if exist) to anchor over an external window a custom panel?
I need to add my custom control on a form...can I do it?
With ParentWindow, the draw of the control undergoes distortion :(
0
Comment
Question by:ISIGest
  • 4
  • 2
6 Comments
 
LVL 25

Expert Comment

by:epasquier
ID: 33644527
can you precise (with images) what you are trying to do, what do you mean by "the draw of the control undergoes distortion", and what code you have tried so far ?
0
 

Author Comment

by:ISIGest
ID: 33644633
I try to set the ParentWindow handle with the window (destination) handle.
I need to add a custom controls (like a plugin) to a specified window in an external process.
This control (panel) must be interactive using a textbox or other controls.
0
 
LVL 25

Accepted Solution

by:
epasquier earned 500 total points
ID: 33644781
It works for me. I search the handle of the main window of one of my own application, then set the parent of a panel in my controling application to that window handle, and there goes my panel from the controling application to the other application.
No pb at all.

Only thing : I cannot close the controling application while the second application is not closed, probably because we messed with Delphi "Parent" system. The solution is to get back the panel to its rightful parent (the origin form)

Here is the code for that, including my function to search a window by name
procedure TForm1.btn1Click(Sender: TObject);

Var

 Hnd:THandle;

begin

 Hnd:=SearchMainWindowByName('Caisse');

 Windows.SetParent(pnl1.Handle, Hnd );

end;



procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);

begin

 Windows.SetParent(pnl1.Handle, Handle );

end;



Var

 SearchWindowList:TStrings; // this is a global var, if set to something 

// then it will gather useful informations about the windows 

// found by EnumWindows. Ex : SearchWindowList:=ListBox1.Items;



function SearchMainWindowByName(Start:String;Mid:String='';UpC:boolean=True):THandle;

type

 RR=Record

     S,M:String;

     L:integer;

     U:boolean;

     hWindow:HWND;

    end;

 pRR=^RR;

Var

 R:RR;

 function EnumProcess(hHwnd: HWND; lParam : integer): boolean; stdcall;

 var

  pPid : DWORD;

  title, ClassName : string;

  R:pRR;

 begin

  //if the returned value in null the

  //callback has failed, so set to false and exit.

  if (hHwnd=0) then result := false else

   begin

    R:=pRR(lParam);

    //additional functions to get more

    //information about a process.

    //get the Process Identification number.

{$ifdef VER140}

      GetWindowThreadProcessId(hHwnd,pPid);

{$else}

      GetWindowThreadProcessId(hHwnd,@pPid);

{$endif}

    SetLength(ClassName, 255);

    SetLength(ClassName,

              GetClassName(hHwnd,

                           PChar(className),

                           Length(className)));

    SetLength(title, 255);

    SetLength(title, GetWindowText(hHwnd, PChar(title), Length(title)));

    //Display the process information

    //by adding it to a list box

    if Assigned(SearchWindowList) Then SearchWindowList.Add

      ('Class Name = ' + className +

       '; Title = ' + title +

       '; HWND = '+ IntToStr(hHwnd) +

       '; Pid = ' + IntToStr(pPid));

    if R^.U Then title:=UpperCase(title);

    if Copy(title,1,R^.L)=R^.S Then

     begin

      if (R^.M='')

       Or (Pos(R^.M,title)>0)

        Then R^.hWindow:=hHwnd;

     end;

    Result := true;

  end;

 end;

begin

 R.hWindow:=0;

 if UpC Then

  begin

   R.S:=UpperCase(Start);

   R.M:=UpperCase(Mid);

  end Else

  begin

   R.S:=Start;

   R.M:=Mid;

  end;

 R.L:=Length(Start);

 R.U:=Upc;

 if Assigned(SearchWindowList) Then SearchWindowList.Clear;

 EnumWindows(@EnumProcess,Integer(@R));

 Result:=R.hWindow;

end;

Open in new window

0
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 
LVL 25

Expert Comment

by:epasquier
ID: 33644850
I actually have been able to put that panel in all applications I tried : Word, Firefox, Delphi, the desktop even.. And the button code I place in that panel is executing fine each time I click it.
BUT : Once I clicked once on the button, it messes with the origin application message loop : this one will not react to my user interaction until I closed the destination application.

I knew it would not go so smoothly to do such "uncommon" things, to say the least. But I suppose your application, once launch and having setup the panel in the destination app, will hide itself and not require interaction
0
 

Author Comment

by:ISIGest
ID: 33644883
Ok it work but there are some problem:
1. The control a painter correctlly when the own form is repainted.
2. The focus of an TEdit on the panel is linked to the main window (if you tr to add a TEdit on the panel and when you are with the focus on this control and you press the tab if on the MAIN FORM there is anhoter TEdit the focus jump to it)

0
 
LVL 25

Expert Comment

by:epasquier
ID: 33645024
> 1. The control a painter correctlly when the own form is repainted.
?? can you rephrase that ?
I have no problems or repaint neither in the origin application, nor in the target application. If you have problems in the target application, then it is probably specific to this application. There have to be some problems in the edges of this technique, we are really messing with the applications...

2> yes, and that is expected, it is up to you to code onEnter/onExit, or keypress events on some  elements to control the focus moves in your form. For example, in the last element in your panel, if you move out from it and the focus get immediately in a control in your main form, then in the onEnter event of this control you call SetFocus on the first control in your panel.
Same for the last control of the main form, if you hit tab and enter in a control that is in the panel, you go back to a precise control of the main form.
In fact, you will then create 2 different loops of components. But surely Delphi designers did not have that kind of application in mind when they coded their tab behaviour.
0

Featured Post

Highfive + Dolby Voice = No More Audio Complaints!

Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

Join & Write a Comment

Suggested Solutions

A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…
This article explains how to create forms/units independent of other forms/units object names in a delphi project. Have you ever created a form for user input in a Delphi project and then had the need to have that same form in a other Delphi proj…
Polish reports in Access so they look terrific. Take yourself to another level. Equations, Back Color, Alternate Back Color. Write easy VBA Code. Tighten space to use less pages. Launch report from a menu, considering criteria only when it is filled…
When you create an app prototype with Adobe XD, you can insert system screens -- sharing or Control Center, for example -- with just a few clicks. This video shows you how. You can take the full course on Experts Exchange at http://bit.ly/XDcourse.

708 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

17 Experts available now in Live!

Get 1:1 Help Now