Solved

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

Posted on 2010-09-10
6
560 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 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
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
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

[Webinar] Learn How Hackers Steal Your Credentials

Do You Know How Hackers Steal Your Credentials? Join us and Skyport Systems to learn how hackers steal your credentials and why Active Directory must be secure to stop them. Thursday, July 13, 2017 10:00 A.M. PDT

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

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…
Hello everybody This Article will show you how to validate number with TEdit control, What's the TEdit control? TEdit is a standard Windows edit control on a form, it allows to user to write, read and copy/paste single line of text. Usua…
There are cases when e.g. an IT administrator wants to have full access and view into selected mailboxes on Exchange server, directly from his own email account in Outlook or Outlook Web Access. This proves useful when for example administrator want…
Monitoring a network: why having a policy is the best policy? Michael Kulchisky, MCSE, MCSA, MCP, VTSP, VSP, CCSP outlines the enormous benefits of having a policy-based approach when monitoring medium and large networks. Software utilized in this v…

724 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