?
Solved

D3: "Docking" a window to another app

Posted on 1998-06-07
11
Medium Priority
?
163 Views
Last Modified: 2010-04-04
My program will be calling other generic Windows Applications. These generic apps should be assumed that they are NOT Delphi Apps and I don't have the source.

So, How would I go about Placing a small Delphi TFORM on top of these generic apps. It should look to the user that they are "combined". When one window is resized or move, the other will follow.

Has anyone done this? Do you have any pre-build componets to do this? Do you have any code examples?

John
0
Comment
Question by:zitt
[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
  • 6
  • 5
11 Comments
 
LVL 5

Expert Comment

by:inter
ID: 1351245
Hi,
The following code does what you want. Modify it to fit your needs.

To test open a Notepad. Paste the following code as unit1 to a new project. Adjust the HEIGHT of your window since I do not control it.

// CODE BEGINS
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, ExtCtrls;

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    procedure MoveForm(wp: TRect);
  end;

  TDockThread = class(TThread)
    procedure Execute; override;
  end;

var
  Form1: TForm1;
  DockThread: TDockThread = nil;

implementation

{$R *.DFM}

var
  hw: HWND;
  op: TRect;

procedure TForm1.MoveForm(wp: TRect);
begin
  left := wp.left;
  top := wp.top - Height;
  width := wp.right - left;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  hw := FindWindow('Notepad', nil);
  // if we find the window then proceed
  if hw <> 0 then
  begin
  //create suspended to modify properties
    DockThread := TDockThread.Create(True);
    DockThread.FreeOnTerminate := true;
    DockThread.Resume;
  end;
end;

procedure TDockThread.Execute;
var
  wp: TRect;
begin
  while not Terminated and
    not Application.Terminated do
  begin
    if hw <> 0 then
      GetWindowRect(hw, wp)
    else continue; //if the hw is invalid do not process
    if StrLComp(@wp, @op, sizeof(wp)) <> 0 then
    begin
      Form1.MoveForm(wp);
      op := wp;
    end;
    Sleep(50);
  end;
end;

end.
//CODE ENDS
Regards, Igor
0
 
LVL 5

Expert Comment

by:inter
ID: 1351246
Hi again,
Doing thread loop as follows is more efficient:

  while not Terminated and
    not Application.Terminated do
  begin
    Sleep(50);
    if hw <> 0 then
      GetWindowRect(hw, wp)
    else continue; //if the hw is invalid do not process
    if StrLComp(@wp, @op, sizeof(wp)) <> 0 then
    begin
      Form1.MoveForm(wp);
      op := wp;
    end;
  end;
Bye, Igor
0
 

Author Comment

by:zitt
ID: 1351247
Thanks for your proposed answer... however, you'll note that I stated a "generic" window. Also to clearify:

It should also be assumed that the program cannot be coded to FindWindow() a specific title bar (or class) as my app will be configurable to call _any_ app.

John
0
Independent Software Vendors: 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 5

Expert Comment

by:inter
ID: 1351248
Hi,
What do we now about that GENERIC application? We should choose the application somehow. Please explain more, I think I can help on this.
Igor
0
 

Author Comment

by:zitt
ID: 1351249
My application will provide "plug-in" support. Any user can plug any app into my app and my app will run it. The only thing we'll know about the "plug-in" is it's Process ID passed back from CreateProcess().

My research todate has shown that I can do some EnumWindows() to associate a top-level window to the process ID. Now I have a HWND I can pass to GetWindowRect() functions to find the sizes of the window.

The problem is I want to avoid "polling" the HWnd using GetWindowRect() if possible. I'd like to write a shared memory DLL to interrupt my app telling it the window moved. I have the code written... but I've getting GPFs and/or page faults.

Maybe I'll get lucky tonight and get it working. Any ideas?
John
0
 
LVL 5

Expert Comment

by:inter
ID: 1351250
Ok then,
If you have the HWND, you can inject your MessageProc to that HWND an get all the windows messages before it receives. Then position your window according to that windows WM_MOVE or WM_SIZE messages => you do not need to poll. What do you think? I see that you are an advanced programmer, anyway if you want help in injecting your windows proc I am here for help.
Regards,
Igor
0
 

Author Comment

by:zitt
ID: 1351251
I now have a working DLL. The problems getting this method to work was in getting a "shared" memory space so that "generic" applications could read/write during the HOOK callback function. Without the shared memory, other apps would GPF the DLL.

Trust me when I say this wasn't easy. And also trust me when I say there are no examples on the "net" to show this.

So, right now I'm in the process or taking what I've learned and writing a set of componets for Delphi 3.0. Since this code has taken me many days of "hacking", I proably won't offer it for free if I even offer it. I'm going to write the componets to make it easier on me and my current app. If there is interest, I'll consider release complied units as Shareware. Watch www.zittware.com for more information.

Inter, thanks for your help. As my components near completion (I expect no later than few wks) I'll award the points to you for your effort.

John
0
 
LVL 5

Expert Comment

by:inter
ID: 1351252
Hi,
I am happy that you be succeeded. May I post my prev answer so that other people can have that primitive docking code without browsing the discussion?
Regards, Igor
0
 

Author Comment

by:zitt
ID: 1351253
Sure post whatever you'd like.
0
 
LVL 5

Accepted Solution

by:
inter earned 100 total points
ID: 1351254


      To test open a Notepad. Paste the following code as unit1 to a new project. Adjust the HEIGHT of
      your window since I do not control it.

      // CODE BEGINS
      unit Unit1;

      interface

      uses
        Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
        StdCtrls, ExtCtrls;

      type
        TForm1 = class(TForm)
          procedure FormCreate(Sender: TObject);
        private
          { Private declarations }
        public
          { Public declarations }
          procedure MoveForm(wp: TRect);
        end;

        TDockThread = class(TThread)
          procedure Execute; override;
        end;

      var
        Form1: TForm1;
        DockThread: TDockThread = nil;

      implementation

      {$R *.DFM}

      var
        hw: HWND;
        op: TRect;

      procedure TForm1.MoveForm(wp: TRect);
      begin
        left := wp.left;
        top := wp.top - Height;
        width := wp.right - left;
      end;

      procedure TForm1.FormCreate(Sender: TObject);
      begin
        hw := FindWindow('Notepad', nil);
        // if we find the window then proceed
        if hw <> 0 then
        begin
        //create suspended to modify properties
          DockThread := TDockThread.Create(True);
          DockThread.FreeOnTerminate := true;
          DockThread.Resume;
        end;
      end;

      procedure TDockThread.Execute;
      var
        wp: TRect;
      begin
        while not Terminated and
          not Application.Terminated do
        begin
          if hw <> 0 then
            GetWindowRect(hw, wp)
          else continue; //if the hw is invalid do not process
          if StrLComp(@wp, @op, sizeof(wp)) <> 0 then
          begin
            Form1.MoveForm(wp);
            op := wp;
          end;
          Sleep(50);
        end;
      end;

      end.
      //CODE ENDS
      Regards, Igor
0
 

Author Comment

by:zitt
ID: 1351255
If anyone remains interested in my Generic control that will perform a "auto" DOCK to any window opened under program control, please send e-mail to zitt@bigfoot.com or watch
www.zittware.com for more information.

Ingor, thanks for attempt at helping me... Who know something seemingly simple could be so difficult.

John
0

Featured Post

Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

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

Creating an auto free TStringList The TStringList is a basic and frequently used object in Delphi. On many occasions, you may want to create a temporary list, process some items in the list and be done with the list. In such cases, you have to…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
Monitoring a network: how to monitor network services and why? Michael Kulchisky, MCSE, MCSA, MCP, VTSP, VSP, CCSP outlines the philosophy behind service monitoring and why a handshake validation is critical in network monitoring. Software utilized …
This tutorial will teach you the special effect of super speed similar to the fictional character Wally West aka "The Flash" After Shake : http://www.videocopilot.net/presets/after_shake/ All lightning effects with instructions : http://www.mediaf…
Suggested Courses

718 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