• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 343
  • Last Modified:

Create Buttons, Labels, Forms and other objects in ANOTHER Application

I would like to do somethinig like this :

  h := findwindow(nil, 'Calculator');

  b := tbutton.Create(nil);
  b.ParentWindow := h;
  b.left := 200;
  b.Top := 75;
  b.caption := 'test';
  b.Width := 75;
  b.height := 25;
  b.OnClick := clt; // <-- This procedure doesn't work, it is supposed to do showmessage('blah');

This doesn't work of course, because button isn't visible, only when i click it it becomes visible but it disapears after i move the mouse over other buttons. I would like to create or should i say inject some control, in this example TButton and put it into another application like Calculator. What i want to do is add an Extra button to some other application like an ADD ON. Please help. I can't get this to work correctly, it keeps dissapearing so please give me some code, i am sure somebody has already done similar thing.....like making holes in other windows :)) ...Thanks in advance..
  • 2
1 Solution
Wim ten BrinkSelf-employed developerCommented:
In general, this is considered a very bad practice. Besides, you don't have any control over your buttons in the other process. It won't be easy either since you'll have to inject a DLL (that will manage those controls for you) into the address space of the other process, and this DLL must also capture any messages that are sent through the application and capture those that apply to it.
Furthermore, you will need to know very specific information about the windows that you want to modify. You need to know the (Windows) classname to find the correct window that you want to modify. Since these are Windows classes and not Delphi classes (even for Delphi applications!) you would have to dig deep into the Windows API to create the controls that you like to add. Just adding a TButton or TLabel isn't as easy as it seems...

I don't know if anyone here has a good solution here for you but it's definitely not an easy thing...
FranusAuthor Commented:
Thank you for your kind answer. I know this is not a piece of cake as i woudl say :) but to be exact i must create an ADDON for existing application. Imagine for example Calculator window and for example i would like to remove the BACKSPACE Button and put my Button there. So far i can do it but as you said, i cannot attach event handler to my Button OnClick event since it is parented by Calculator and not my Application. Btw Winsight32 is a gift from god application for this. If anyone can just give me a solution for this problem please. You can use the Calculator for example. Here is the task i would like. Create my Button on the calculator window and execute some code when i press it. My application would be invisible, just an icon in system tray and when user clicks on that Button, my application Form would then become visible. I think you understand what i would like to do. I don't need to go deeper into this, this is enough. Just one button.

hello Franus, Here is some code for two button clicks, the first one will find the Calculator window and get it's handle, then create a button in that window, which is Sub-Classed to get the left button Up message for a click, , ,
I do not think it is a good idea to create a window from one hInstance to another hInstance, I had problems in XP with painting this button, since XP uses a new painting techique with themes, As far as the other controls over-drawing this button, I think it is because they are NOT created with the  WS_CLIPSIBLINGS,  so they will draw on other controls that they overlap and is independent of the button that you create or it's properties.

    { Private declarations }
    hButton1: Cardinal;
    PButProc: Pointer;

procedure TForm1.FormCreate(Sender: TObject);
hButton1 := 0; // initialize hButton

function ButFunc(hWnd, iMsg, WParam, LParam: Integer): Integer; stdcall;
// new Window Proc for hButton1
Result := CallWindowProc(Form1.PButProc,hWnd,iMsg,wParam,lParam);
if iMsg = WM_LBUTTONUP then
  Form1.Label2.Caption := 'hButton1 LBUTTONUP '+IntToStr(LParam);
  // other button click event code here

procedure TForm1.sbut_CalButtonClick(Sender: TObject);
hCalWnd: Cardinal;
// Button Click to find calculator and make button

if hButton1 <> 0 then Exit; // do not make 2 buttons with same handle
hCalWnd := FindWindow(nil, 'Calculator');
if hCalWnd <> 0 then
  // DO NOT USE Delphi VCL control components, it's more trouble that it's worth
  hButton1 := CreateWindow('BUTTON', 'Button1', WS_CHILD or BS_PUSHBUTTON or
              BS_TEXT or WS_CLIPSIBLINGS,3,18,64,30,hCalWnd,0,hInstance,nil);
  // use API control creation so you can have half a chance at message handling
  if hButton1 = 0 then
    ShowMessage('hButton1 WAS not Created');
  SetWindowPos(hButton1,HWND_TOP, 0,0,0,0, SWP_NOMOVE or SWP_NOSIZE or
               SWP_SHOWWINDOW or SWP_NOACTIVATE); // need to get this button to top
  InvalidateRect(hButton1, nil, True); // needed for new paint process in XP
  Sleep(15); // allow initial create and paint, remember this button is in another hInstance
  PButProc := Pointer(SetWindowLong(hButton1, GWL_WNDPROC, Integer(@ButFunc)));
  // to get any events for this you will need to Sub-Class this button
  // I think it is a BAD IDEA to subclass a window in another process
  end else
  ShowMessage('Calculator is NOT running');

procedure TForm1.sbut_KillCalButtonClick(Sender: TObject);
StopHook: function: Boolean;
// this button click will destroy hButton1
hButton1 := 0;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
// IMPORTANT, you must destroy the new button when you exit this form !

// now that the hButton1 Window Proc message handling is in this program,
// if you close this program without destroying the hButton1, it will have NO
// Window Proc to handle it's messages, and bad things will happen

= = = = = = = = = = = = = = = =  = = = = = = = = =  = = = = = = =

I think you may ask more questions, but working in another process may get difficult, or I may have no knowledge of what to try
FranusAuthor Commented:
Thank you for your answer. I solved my problem...well..almost...working in another process is really painful :) but i have a project which requires this so i had to it like this. Once again thanks very much!!!
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Keep up with what's happening at Experts Exchange!

Sign up to receive Decoded, a new monthly digest with product updates, feature release info, continuing education opportunities, and more.

  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now