0

I'm creating an application that will add/create a win32 control/s on another application. Using CreateWindowand also multithreading, I have successfully created the controls, and also the Tabstop of the created control is running well. The problem is when the tabstop is now focused on existing controls, it will not go back to the created controls. Is there a way to fix this? here's my code:

var
  Msg        : TMSG;
procedure CreateEdit(pHWND: HWND; stxt: string; pnt: Tpoint);
var
  hFontText  : HWND;
  hEdit: HWND;
  hOldEdit: HWND;
  hIns: Integer;
  style : DWORD;

  function EnumChildren( hHandle : HWND; lParamMeter : LPARAM) : BOOL; stdcall;
  var
    style : DWORD;
  begin
    Result := True;
    style := GetWindowLong( hHandle, GWL_STYLE );
    if ((style or WS_TABSTOP) <> WS_TABSTOP) then
    begin
      SetWindowLongPtr( hHandle, GWL_STYLE, style or WS_TABSTOP);
    end;
  end;

begin
  hIns := GetWindowLong(pHWND, GWL_HINSTANCE);
  style := GetWindowLong( pHWND, GWL_STYLE );
  if ((style or WS_EX_CONTROLPARENT) <> WS_EX_CONTROLPARENT) then
  begin
    SetWindowLongPtr( pHWND, GWL_STYLE, style or WS_EX_CONTROLPARENT);
  end;
  hFontText := CreateFont(-14,0,0,0,0,0,0,0,DEFAULT_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,VARIABLE_PITCH or FF_SWISS,'Tahoma');
  hOldEdit := pHWND;
  hEdit := CreateWindow('Edit', PWideChar(Trim(stxt)),
              WS_TABSTOP OR
              WS_VISIBLE OR
              ES_READONLY OR
              WS_CHILD,
            (pnt.X),(pnt.Y), 100, 23, pHWND, 0, hIns,nil);
  SendMessage(hEdit,WM_SETFONT,hFontText,0);
  SetWindowPos(hEdit, hOldEdit, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE);
  hOldEdit := hEdit;
  hEdit := CreateWindow('Edit', PWideChar(Trim(stxt)),
              WS_TABSTOP OR
              WS_VISIBLE OR
              WS_CHILD,
            (pnt.X),(pnt.Y) + 50, 100, 23, pHWND, 0, hIns,nil);
  SendMessage(hEdit,WM_SETFONT,hFontText,0);
  SetWindowPos(hEdit, hOldEdit, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE);
  EnumChildWindows(pHWND, @EnumChildren, 0);
  while GetMessage(Msg,pHWND,0,0) do
  begin
    if not(IsDialogMessage(pHWND, Msg)) then
    begin
      TranslateMessage(Msg);
      DispatchMessage(Msg);
    end;
  end;
end;
function CreateEdtThread(data: Pointer): Integer;
var
  tsTxt: TStrCoor;
begin
  tsTxt := TStrCoor(data^);
  Form2.CreateEdit(tsTxt.ParentHWND, tsTxt.str, tsTxt.pnt);
end;
...
procedure TForm2.Button1Click(Sender: TObject);
var
  tsTxt: PStrCoor;
  thID: Cardinal;
begin
  New(tsTxt);
  with tsTxt^ do
  begin
    ParentHWND := StrToInt(edtHWND.Text);
    str := 'Edit1';
    pnt := Point(25, 30);
  end;
  BeginThread(nil, 0, @CreateEdtThread, tsTxt, 0, thID);
end;
  • 1
    Your entire approach is broken because of window/thread affinity – David Heffernan Feb 20 '15 at 08:58
  • @DavidHeffernan, is thread not useful for this? my purpose on using the Thread is to create many controls on button click – Anthoner Monzon Feb 20 '15 at 09:00
  • 3
    How is input going to work when you've got windows from multiple processes all lumped together. That's not a supported approach. You should add the controls from inside the app, in its main UI thread. – David Heffernan Feb 20 '15 at 09:04
  • Is it possible to add control inside the running app without changing the app itself? – Anthoner Monzon Feb 20 '15 at 10:04
  • 1
    It's certainly not supported to do that. Cross process parent relationships only still exist to maintain support with code from the 16 bit era. This is the classic XY problem. – David Heffernan Feb 20 '15 at 10:06

0 Answers0