Delphi Detect нажатия клавиш во встроенном приложении

Я работаю над многопроцессорным приложением, где каждый документ открывается в новом процессе. Он ведет себя как Google Chrome.

Все работает нормально, кроме этого:

Когда какой-либо элемент управления во встроенном приложении активен, главное окно (которое содержит встроенные окна) не получает нажатий клавиш (например, Ctrl + N и т. П.). Я понимаю тот факт, что встроенное окно работает в другом процессе, и поэтому оно не работает.

Что я должен сделать:

  • Главное окно должно обнаруживать нажатия клавиш во встроенном окне
  • Если в главном окне что-то назначено нажатию клавиши, главное окно должно получить сочетание клавиш вместо встроенной формы.

Некоторые важные детали:

  • У меня есть контроль над исходным кодом обоих процессов (это один и тот же исполняемый файл, с разным поведением)
  • Я использую действия для нажатия клавиш
  • Обновление: я использую WM_COPYDATA для IPC (отправка записи через)
  • Обновление: есть только один процесс пользовательского интерфейса (так называемое главное окно)

Код для вставки:

Этот код встраивает окна других процессов в главное окно пользовательского интерфейса. Он вызывается непосредственно обработчиком WM_COPYDATA на основе полученных значений.

procedure TWTextAppFrame.adoptChild(WindowHandle: Cardinal; Container: TWinControl);
var
  WindowStyle : Integer;
  FAppThreadID: Cardinal;
  ts          : TTabSheet;
begin

  /// Set running app window styles.

  WindowStyle := GetWindowLong(WindowHandle, GWL_STYLE);
  WindowStyle := (WindowStyle and not WS_POPUP) or WS_CHILD;

  SetWindowLong(WindowHandle, GWL_STYLE, WindowStyle);


  /// Attach container app input thread to the running app input thread, so that
  ///  the running app receives user input.
  FAppThreadID := GetWindowThreadProcessId(WindowHandle, nil);
  AttachThreadInput(GetCurrentThreadId, FAppThreadId, True);

  /// Changing parent of the running app to our provided container control

  /// The window will be embedded on a tabsheet
  ts := TTabSheet.Create(Self);
  ts.TabVisible := false;
  ts.PageControl := WindowPages;
  ts.Tag := WindowHandle;

  Winapi.Windows.SetParent(WindowHandle,ts.Handle);
  SendMessage(Container.Handle, WM_UPDATEUISTATE, UIS_INITIALIZE, 0);
  UpdateWindow(WindowHandle);

  /// This prevents the parent control to redraw on the area of its child windows (the running app)
  SetWindowLong(Container.Handle, GWL_STYLE, GetWindowLong(Container.Handle,GWL_STYLE) or WS_CLIPCHILDREN);
  /// Make the running app to fill all the client area of the container
  SetWindowPos(
      WindowHandle,
      0,
      0,
      0,
      Container.ClientWidth,
      Container.
      ClientHeight,SWP_NOZORDER
  );

  /// This creates a small object which holds some info about the embedded window
  /// (Document dirty status, embedded window handle, file name, etc. )
  /// The main window uses this to identify an embedded window, and also for tracking the processes
  AddHandleToControlList(WindowHandle,PChar('win'+IntToStr(WindowHandle)), 0, 0, 0, 0, alClient,ts);

  /// Page control holding all the tabsheet
  WindowPages.ActivePage := ts;

  /// activate the embedded window
  SetForegroundWindow(WindowHandle);
end;

Вот как дочерние процессы уведомляют главное окно:

/// Record sent through

TSendData = Packed Record
  sender: Cardinal; /// The handle of the sender window
  s  : WideString;  /// String data
  i  : Integer;  /// Integer data, usually and identifier for a function (defined with constants)
  i2 : Integer; /// Status, or other integer data
  b  : boolean; /// boolean information 
End;

var WData: TSendData;

///...

WData.sender := Self.Handle;
WData.i := WE_SETPARENT;

/// SendCommand is a wrapper function around the WM_COPYDATA sending code
SendCommand(Self.Handle, MainWindow, WData);

Что у меня так далеко?

Я использую WM_COPYDATA для IPC.

Пока нет кода, только идея, чтобы передать список горячих клавиш во встроенную форму и зарегистрировать их как действия там. Когда действие выполняется во встроенной форме, нажатие клавиши будет отправлено в основную форму.

Эта идея не является элегантным решением, я хотел бы знать, есть ли лучшее, и если есть, то что бы это было.

0 ответов

Другие вопросы по тегам