Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Не могу передать фокус из StayOnTop формы в вызывающую [D6]


msguns ©   (2005-06-15 11:16:00) 

MDI - приложение.
MDIChild для просмотра длинных текстов в таблицах БД создает формочку с мемо, куда копирует содержимое поля текущей записи отображаемой в гриде таблицы (по AfterScroll), при этом FormStyle созданной формочки fsStayOnTop. Т.е. при перемещении в гриде MDIChild, содержимое окна меняется.
Когда жмется редактирование (на гл.панели или PopupMenu грида), то фокус передается формочке и TMemo.ReadOnly := false, т.е. можно редактировать текст. По завершению редактирования (кнопка на формочке) новый текст пишется в БД, мемо переводится в ReadOnly и надо, чтобы курсор возвращался назад в грид. А он не возвращается ! TDBGrid.SetFocus не помогает !

Пробовал передавать фокус просто MDIChild, эффект тот же - фокус остается в формочке. Спасибо за любую помощь !


msguns   (2005-06-22 15:26:00) [1]

>Игорь Шевченко ©   (22.06.05 14:47) [17]
>Удачи. В случае чего, можешь меня по почте теребить, адрес тебе известен :)

Списибо вторично. Уж не взыщи - при нужде потереблю ;)


Игорь Шевченко   (2005-06-22 14:47:00) [2]

msguns ©   (22.06.05 14:41) [16]


> А можно расшифровать для особо "одаренных" в чем фокус клиентского
> хэндла для гл.формы ?


Можно конечно. Дело в том, что все дочерние MDI-формы являются на самом деле дочками окна MDIClient, чем Handle и появляется в свойстве TForm.ClientHandle. И любое управление дочками происходит через посылку сообщений этому самому окну. Как только ты объявляешь стиль главной формы fsMDIForm, так при создании окна этой формы создается дополнительно окно MDIClient (оно занимает всю область главного окна, исключая меню, и прочие там статус-бары).


> Спасибо большое


Удачи. В случае чего, можешь меня по почте теребить, адрес тебе известен :)


msguns   (2005-06-22 14:41:00) [3]

Класс !!!
Вся штука была в этом: ClientHandle

А можно расшифровать для особо "одаренных" в чем фокус клиентского хэндла для гл.формы ? Из хэлпа что-то ничего не высосал.

Кстати, попробую сейчас передавать фокус в произвольную "дочку"

Спасибо большое ;)))


Игорь Шевченко   (2005-06-22 14:13:00) [4]

Вот чего я сделал:

Главная:

unit main;

interface
uses
 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
 Menus;

type
 TfMain = class(TForm)
   MainMenu: TMainMenu;
   File1: TMenuItem;
   Exit1: TMenuItem;
   Child1: TMenuItem;
   New1: TMenuItem;
   procedure New1Click(Sender: TObject);
 end;

var
 fMain: TfMain;

implementation

uses Child;

{$R *.DFM}

procedure TfMain.New1Click(Sender: TObject);
begin
 with TfChild.Create (Application) do
   Show;
end;

end.


Дочка:

unit Child;

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

type
 TfChild = class(TForm)
   Button1: TButton;
   Edit1: TEdit;
   procedure FormClose(Sender: TObject; var Action: TCloseAction);
   procedure Button1Click(Sender: TObject);
 end;

var
 fChild: TfChild;

implementation

uses OnTop;

{$R *.DFM}

procedure TfChild.FormClose(Sender: TObject; var Action: TCloseAction);
begin
 Action := caFree;
end;

procedure TfChild.Button1Click(Sender: TObject);
begin
 with TfOnTop.Create(Application, Self) do
   Show;
end;

end.


Всегда сверху:

unit OnTop;

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

type
 TfOnTop = class(TForm)
   btnReturnFocus: TButton;
   procedure btnReturnFocusClick(Sender: TObject);
 private
   FCaller: TfChild;
 public
   constructor Create (AOwner: TComponent; ACaller: TfChild); reintroduce;
 end;

var
 fOnTop: TfOnTop;

implementation

{$R *.DFM}

{ TfOnTop }

constructor TfOnTop.Create(AOwner: TComponent; ACaller: TfChild);
begin
 FCaller := ACaller;
 inherited Create (AOwner);
end;

procedure TfOnTop.btnReturnFocusClick(Sender: TObject);
begin
 PostMessage (Application.MainForm.ClientHandle, WM_MDIACTIVATE,
   FCaller.Handle, 0);
 PostMessage (FCaller.Handle, WM_SETFOCUS, Handle, 0);
end;

end.


Работает. Может, и тебе поможет метод ?


msguns   (2005-06-22 10:53:00) [5]

StayOnTop:

unit Topic;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, ExtCtrls, StdCtrls, Buttons, Unit1, Unit2;

type
 TfrmTopic = class(TForm)
   Panel1: TPanel;
   edCtrlA: TEdit;
   edCtrlB: TEdit;
   meCtrl: TMemo;
   Panel2: TPanel;
   spbReturnToParent: TSpeedButton;
   spbPassFocus: TSpeedButton;
   Label1: TLabel;
   cmbTargetForms: TComboBox;
   procedure FormCreate(Sender: TObject);
   procedure FormShow(Sender: TObject);
   procedure FormActivate(Sender: TObject);
   procedure FormClose(Sender: TObject; var Action: TCloseAction);
   procedure spbReturnToParentClick(Sender: TObject);
 private
   { Private declarations }
 public
   { Public declarations }
   ParentWindow: TfrmChild;
 end;

var
 frmTopic: TfrmTopic;

implementation

{$R *.dfm}

procedure TfrmTopic.FormCreate(Sender: TObject);
begin
//  
end;

procedure TfrmTopic.FormShow(Sender: TObject);
begin
 //
end;

procedure TfrmTopic.FormActivate(Sender: TObject);
var
 i: integer;
begin
 with cmbTargetForms do
   begin
    Clear;
    Text := '';
    for i := 0 to MainForm.MDIChildCount-1 do
      if MainForm.MDIChildren[i].Caption<>TForm(Self.Owner).Caption then
         Items.Add(MainForm.MDIChildren[i].Caption);
    ItemIndex := Items.Count-1;
   end;
end;

procedure TfrmTopic.FormClose(Sender: TObject; var Action: TCloseAction);
begin
 Action := caFree;
 TfrmChild(Owner).TopicWindow := 0;
end;

procedure TfrmTopic.spbReturnToParentClick(Sender: TObject);
begin
//  TForm(Owner).SetFocus;   // Не хочэ, тварюка !
//   MainForm.SetFocus;
  ShowMessage('Хочу передать фокус в '+ParentWindow.Caption);
  MainForm.PassFocusTo_Child_From_Topic(ParentWindow);

end;

end.


msguns   (2005-06-22 10:52:00) [6]

"Дочка":

unit Unit2;

interface

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

type
 TfrmChild = class(TForm)
   Panel1: TPanel;
   edCtrlA: TEdit;
   edCtrlB: TEdit;
   edCtrlC: TEdit;
   cmbCtrlA: TComboBox;
   cmbCtrlB: TComboBox;
   lsbCtrl: TListBox;
   procedure FormCreate(Sender: TObject);
   procedure FormClose(Sender: TObject; var Action: TCloseAction);
   procedure FormDeactivate(Sender: TObject);
   procedure FormShow(Sender: TObject);
   procedure edCtrlAEnter(Sender: TObject);
   procedure FormActivate(Sender: TObject);
 private
   { Private declarations }
 public
   { Public declarations }
   TopicWindow: HWnd;
   procedure Call_CreateTopicWindow(var Msg: TMessage); message CM_CREATE_TOPICWINDOW;
   procedure Call_CloseTopicWindow(var Msg: TMessage); message CM_CLOSE_TOPICWINDOW;
 end;

var
 frmChild: TfrmChild;

implementation

uses Topic;

{$R *.dfm}

procedure TfrmChild.Call_CreateTopicWindow(var Msg: TMessage);
begin
 if TopicWindow<>0 then
   begin
    ShowMessage('Нельзя создать более одного окна');
    exit;
   end;
 with TfrmTopic.Create(Self) do
   begin
    ParentWindow := Self;
    TopicWindow := Handle;   // Поставить отметку о наличии топик-окна
    Top := lsbCtrl.ClientOrigin.Y+2;
    Left := lsbCtrl.ClientOrigin.X+2;
    Show;
   end;
end;

procedure TfrmChild.Call_CloseTopicWindow(var Msg: TMessage);
begin
 TopicWindow := 0;
end;

procedure TfrmChild.FormCreate(Sender: TObject);
begin
//  TopicWindow := nil;
end;

procedure TfrmChild.FormShow(Sender: TObject);
begin
 Caption := Caption+IntToStr(MainForm.ChildNdx);
 edCtrlA.SetFocus;
end;

procedure TfrmChild.FormClose(Sender: TObject; var Action: TCloseAction);
begin
 Action := caFree;
end;

procedure TfrmChild.FormDeactivate(Sender: TObject);
begin
 MainForm.ShowActiveControl;
end;

procedure TfrmChild.edCtrlAEnter(Sender: TObject);
begin
 MainForm.ShowActiveControl;
end;

procedure TfrmChild.FormActivate(Sender: TObject);
begin
 MainForm.ShowActiveControl;
end;

end.


msguns   (2005-06-22 10:49:00) [7]

Main:

{ ПРОБЛЕМА: ПЕРЕДАЧА ФОКУСА ИЗ fsStayOnTop формы в создавшую
ее дочернюю форму в MDI-интерфейсе.
Имеется:
 - Главная форма (unit1) с одним визуальным контролом на панеле управления
 - Произвольное кол-во эксземпляров дочерней формы TfrmChild,
    каждая из которых открывает одно окно (форму) TfrmTopic и передает ему фокус
Задача:
 - Передать фокус из TfrmTopic в создавшее ее MDIChild-окно.
 - Передать фокус из TfrmTopic в указанное MDIChild-окно.
}

unit Unit1;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, ExtCtrls, ToolWin, ComCtrls, ActnList, ImgList, StdCtrls;

type
 TMainForm = class(TForm)
   ControlBar1: TControlBar;
   ToolBar1: TToolBar;
   ToolButton1: TToolButton;
   ActionList1: TActionList;
   ImageList1: TImageList;
   actOpenChild: TAction;
   ToolButton2: TToolButton;
   actTopForm: TAction;
   cmbMain: TComboBox;
   pnMain: TPanel;
   Label1: TLabel;
   Label2: TLabel;
   lbObjName: TLabel;
   Label3: TLabel;
   lbFormName: TLabel;
   procedure actOpenChildExecute(Sender: TObject);
   procedure actTopFormExecute(Sender: TObject);
   procedure cmbMainEnter(Sender: TObject);
 private
   { Private declarations }
 public
   { Public declarations }
   ChildNdx: integer;
   procedure ShowActiveControl;
   procedure PassFocusTo_Child_From_Topic(Child: TWinControl);
 end;

const
 CM_CREATE_TOPICWINDOW = WM_USER+201;
 CM_CLOSE_TOPICWINDOW = WM_USER+202;

var
 MainForm: TMainForm;

implementation

uses Unit2;

{$R *.dfm}

procedure TMainForm.ShowActiveControl;
begin
 lbFormName.Caption := Screen.ActiveForm.Caption;
 lbObjName.Caption := '?';
 if Screen.ActiveControl<>nil then
    lbObjName.Caption := Screen.ActiveControl.Name;
 pnMain.Update;
end;

procedure TMainForm.PassFocusTo_Child_From_Topic(Child: TWinControl);
begin
//  cmbMain.SetFocus;
//  ShowMessage(TfrmChild(Child).Caption);
 TfrmChild(Child).SetFocus;
end;

procedure TMainForm.actOpenChildExecute(Sender: TObject);
begin
 ChildNdx := ChildNdx+1;
 with TfrmChild.Create(Self) do Show;
end;

procedure TMainForm.actTopFormExecute(Sender: TObject);
begin
 if ActiveMDIChild<>nil then
   PostMessage(ActiveMDIChild.Handle,CM_CREATE_TOPICWINDOW,0,0);
end;

procedure TMainForm.cmbMainEnter(Sender: TObject);
begin
 ShowActiveControl;
end;

end.


Игорь Шевченко   (2005-06-21 18:35:00) [8]


> Создал элементарное приложение:


Код приведи ?


msguns   (2005-06-21 16:57:00) [9]

Создал элементарное приложение:
1.MDIForm с одним винконтролом на панели управления и двумя кнопками: Открыть форму-"дочку" и Открыть форму StayOnTop от текущей "дочки"
2.MDIChild с несколькими контролами для того, чтобы было кому принимать фокус.
3.fsStayOnTop форма с единственным контролом TMemo (тип не существеннен). Есть 2 кнопки: "Передать фокус своей мамке" и "Передать фокус в указанную "Дочку"

Можно создать сколько угодно "дочек" и от каждой из них по одной (не более !) форме fsStayOnTop. Если передача фокуса выполняется из fsStayOnTop напрямую, то фокус не передается вообще. Если сначала фокус в контрол MDIForm, а затем уже в соотв. "дочку", то работает ! НО !!! Если форма, куда требуется передать фокус, была открыта последней, фокус остается в контроле Гл.формы !!! Что за суматоха, не пойму. Пробовал разобраться с реализацией класса TForm, но утонул ;((

Киньте же, будьте любезны, если не круг, то хотя бы соломину утопающему !


msguns   (2005-06-16 09:18:00) [10]

>КаПиБаРа ©   (16.06.05 06:25) [8]
>Странно. У меня работает

В Главную (MDIForm) фокус передается, а вот в дочь (MDIChild) - нет


КаПиБаРа   (2005-06-16 06:25:00) [11]

msguns ©   (15.06.05 16:27) [7]
Странно. У меня работает


msguns   (2005-06-15 16:27:00) [12]

>КаПиБаРа ©   (15.06.05 13:05) [6]
>SetActiveWindow(Application.MainForm.Handle);

Эффект тот же. Имхо, что-то тут в самом классе TForm при условии StayOnTop..


КаПиБаРа   (2005-06-15 13:05:00) [13]

SetActiveWindow(Application.MainForm.Handle);
Ну и потом активировать грид и т.д.


msguns   (2005-06-15 12:32:00) [14]

>КаПиБаРа ©   (15.06.05 12:14) [4]
>Может CM_ACTIVATE поможет

нет.

Уйти с формочки можно только одним способом - кликнуть мышой на MDIChild. Программно "кликнуть" не получается ;((


КаПиБаРа   (2005-06-15 12:14:00) [15]

Может CM_ACTIVATE поможет


msguns   (2005-06-15 12:06:00) [16]

>dmitry501 ©   (15.06.05 11:25) [1]
не помогает.

>TUser ©   (15.06.05 11:42) [2]
>SetForegroundWindow

fsStayOnTop !

>WM_ACTIVATE

не помогает.

>WM_CLICK (гриду :))

Ошибка компилляции

Вот текст обработчика "запись в БД"

procedure TfrmTextWin.actEditPostExecute(Sender: TObject);
var
 res: boolean;
begin
 if not CheckControls then
   begin
    ShowMessage('Ошибки в введенной информации');
    exit;
   end;
 if PFondName<>nil then
    res := TfrmListFond(ParentForm).Update_FondName(PFondName)
 else
    res := TfrmListFond(ParentForm).Update_FondPart(PFondPart);
 if not res then exit;
 Self.SetFocus;  
 EditFlag := false;
 SwitchFormOption; // Перевод формочки в режим просмотра

//  Hide;
//  Show;

//  ParentForm.SetFocus;

//  SendMessage(TfrmListFond(ParentForm).grFondsNames.Handle,WM_ACTIVATE,0,0);

//  if Assigned(PFondName) then
//     TfrmListFond(ParentForm).grFondsNames.SetFocus
//  else
//     TfrmListFond(ParentForm).grFondsParts.SetFocus;
end;


TUser   (2005-06-15 11:42:00) [17]

А эти помогают?

SetForegroundWindow
WM_ACTIVATE
WM_CLICK (гриду :))


dmitry501   (2005-06-15 11:25:00) [18]

msguns ©   (15.06.05 11:16)
временно скрыть формочку, перевести фокус, показать..


Наверх

Титульная страница Поиск, карта сайта Написать письмо