Discussions related to Visual Prolog
x2060
Posts: 9
Joined: 11 Dec 2021 8:20

How to know if this window is on the top.

Unread post by x2060 »

I spent several days try find out solution but fail. so I put it here ask for help.

I have made a normal MDI application, which can open multiple instances (Form Windows) for editing pictures, etc. I have "Redo", "Undo" menu in the TaskWindow menubar. But how can I know which window is at the top, that those function can work only on this window? I tried use listener "Activate listener", "GetFocus listeners", "StateChange Listeners" but all no helpful.

Thank you
Jimmy xia
User avatar
Gukalov
VIP Member
Posts: 62
Joined: 5 Oct 2011 15:16

Re: How to know if this window is on the top.

Unread post by Gukalov »

Look at Visual Prolog Examples\editor

In implement editorForm main menu attaching:

Code: Select all

clauses     new(Parent, Filename):-         formWindow::new(Parent),         generatedInitialize(),         sciLexerStatusBar_ctl:attach(sciLexer_ctl),         filename := Filename,         addShowListener(onShow),         setContextMenuResponder(onContextMenu),         addMenuItemListener(resourceIdentifiers::id_file_save, onFileSave),         addMenuItemListener(resourceIdentifiers::id_edit_copy, onEditCopy),         addMenuItemListener(resourceIdentifiers::id_edit_cut, onEditCut),         addMenuItemListener(resourceIdentifiers::id_edit_paste, onEditPaste), ... ...
x2060
Posts: 9
Joined: 11 Dec 2021 8:20

Re: How to know if this window is on the top.

Unread post by x2060 »

Thank you for your info, probably you misunderstand my question, My goal is try to know If my own window is on the top so that my "tools" from menu will only work on this. (My form is picture edit form not standard text editor).

I jut found below code from class: navigationOverlay

Code: Select all

clauses     tryGetActiveForm() = MDIChild :-         b_true = vpi::getAttrVal(attr_win_mdi),         !,         Event = e_Native(gui_native::wm_mdigetactive, gui_api::wNull, gui_api::lNull),         MDIHWND = vpi::winSendEvent(uncheckedConvert(windowHandle, vpi::getAttrNativeVal(attr_win_mdi_client_hwnd)), Event),         not(memory::isNull(MDIHWND)),         MDIChild = window::tryConvertVPIWin2Window(uncheckedConvert(windowhandle, MDIHWND)).
User avatar
Gukalov
VIP Member
Posts: 62
Joined: 5 Oct 2011 15:16

Re: How to know if this window is on the top.

Unread post by Gukalov »

probably you misunderstand my question, My goal is try to know If my own window is on the top so that my "tools" from menu will only work on this.
I did understand)))
You try to catch active form to run menu command, in editor example another way: active form directly gets a menu command, and no matter what kind of editor the form contains. And in the example is, by the way, how to define menu tag is enable/disable BEFORE menu run. This is impossible, If you define the active form AFTER menu run.
x2060
Posts: 9
Joined: 11 Dec 2021 8:20

Re: How to know if this window is on the top.

Unread post by x2060 »

Thank you again for your patiently answer.

Now I understand the way "Editor" doing is simply put a statement like below example inside the Editor Form, then every Child Form will get Menu call.

Code: Select all

addMenuItemListener(resourceIdentifiers::id_edit_copy, onEditCopy)
I tried do this way by put this statement inside myForm, but it doesn't work, I tried trace the steps by DEBUG, In fact the "onEditCopy" process was even not called.

Then I move the statement out to TaskWindow.PRO, it works.
I will read the example again and hope can find it out what is problem.

By the way, I am using Ribbon Control and Menu together.
User avatar
Gukalov
VIP Member
Posts: 62
Joined: 5 Oct 2011 15:16

Re: How to know if this window is on the top.

Unread post by Gukalov »

I tried do this way by put this statement inside myForm, but it doesn't work,
Don't you forget in your form

Code: Select all

        menuSet(resMenu(resourceIdentifiers::id_TaskMenu)),
???

The editor example works perfect. Just check it well and do the same.
Good Luck)))
x2060
Posts: 9
Joined: 11 Dec 2021 8:20

Re: How to know if this window is on the top.

Unread post by x2060 »

It works after put below also in Form. (was only in TaskWindow)

Code: Select all

 menuSet(resMenu(resourceIdentifiers::id_TaskMenu)),


But it is still not makes me understand how to handle "TOP WINDOW"

I would like describe more details for my application, why I need to know how to check if MDI window/Form is at the top:

I have Ribbon Control, (for example) "Font custom Command Tools" can interacting with Forms, and only work with TOP MDI Form, include "Font Size", "Font Style", "Font Name", when we Click/Select the tools can change Font Specifications in my PICT-Edit Form (only for TOP MDI window). I used below code to check which FORM are on the top, so that the relative command can send to correct Form.

Code: Select all

clauses     tryGetActiveForm() = MDIChild :-         b_true = vpi::getAttrVal(attr_win_mdi),         !,         Event = e_Native(gui_native::wm_mdigetactive, gui_api::wNull, gui_api::lNull),         MDIHWND = vpi::winSendEvent(uncheckedConvert(windowHandle, vpi::getAttrNativeVal(attr_win_mdi_client_hwnd)), Event),         not(memory::isNull(MDIHWND)),         MDIChild = window::tryConvertVPIWin2Window(uncheckedConvert(windowhandle, MDIHWND)).        
But I also need those "custom Command tools" can be updated it's info when I shift to another MDI form, For example, After I set Font Size 10 on 1st MDI form, then shift to 2nd MDI form which have font size 20, the command tool shall display 20 instead. I considered set up several kind of listeners: "get Focus Listener" ," Activate Listener", or e_MDIActivate in the Form, hope can let FORM know it when in TOP, then send it's data. unfortunately it doesn't work at all. No message be sent out when we Shift the window/Form. (But I see the "WINDOW" menu of TaskWindow can exactly get it checked. I am wondering which kind of "event message" shall I catch, when this MDI window/form is on the top?


Thank you very much for any tips.
Attachments
screen.jpg
screen.jpg (184.91 KiB) Viewed 932749 times
User avatar
Gukalov
VIP Member
Posts: 62
Joined: 5 Oct 2011 15:16

Re: How to know if this window is on the top.

Unread post by Gukalov »

Code: Select all

constructors     new : (window Parent, string FileName). clauses     new(Parent, Filename):-         formWindow::new(Parent),         generatedInitialize(),  ...  ...         addActivateListener({ :- activeForm := This }),         addDeactivateListener({ :- activeForm := erroneous }).   class facts     activeForm : editorForm := erroneous.
User avatar
Gukalov
VIP Member
Posts: 62
Joined: 5 Oct 2011 15:16

Re: How to know if this window is on the top.

Unread post by Gukalov »

Code: Select all

        addActivateListener({ :- fignayEvent:notify(activated(This)) }),         addDeactivateListener({ :- fignayEvent:notify(deactivated(This)) }).     domains     finyaDomain = activated(editorForm); deactivated(editorForm).   class facts     fignayEvent : event1{handle, finyaDomain} :=         { = Event :- Event = event1::new(nullHandle), Event:addListener(fignyaListener) }().   class predicates     fignyaListener : event1{handle, finyaDomain}::listener. clauses     fignyaListener(_, Event) :-         core::nothing(Event),         succeed().
Add propertie fignayEvent : event1{handle, finyaDomain}. in the form class and
form::fignayEvent:addListener(WhatAndWhereYouWantPredicates) in all the coners of your programm.
Upgrade finyaDomain (and move it to the form class) to notify all the coners of your programm about another events in the form.
User avatar
Thomas Linder Puls
VIP Member
Posts: 1401
Joined: 28 Feb 2000 0:01

Re: How to know if this window is on the top.

Unread post by Thomas Linder Puls »

If a top level window have a menu attached then menu events will be sent to that window when it is the active(/top) window.

So your form window should attach the menu it wants to handle. Normally the menu will be the same or an extension of the window on the task window. (Avoiding to many deviations from the main window is preferable from a users point of view).

When your form becomes active; your forms menu will replace the one currently shown on the task window. And menu events are sent yo your form. When another window becomes active its menu will replace the current one and menu events are sent to that form. It a form doesn't have a menu attached the task window menu will be used and menu events are sent to the task window.

You are in the last situation, you form does not have a menu attached and therefore the menu events goes to the task window. Now you are trying to see if your form is active and then redirect the menu handling to your form if that is the case. But that is a completely "silly" approach, because if you attach a menu all that that will happen automatically.

Furthermore, menu events that you do not handle will automatically be redirected to the task window and handled by its menu handlers.

So the solution to your problem is (indeed) to attach a menu to your form (you can set it in the property editor, the resulting generatedInitialize should then contain a line like this):

Code: Select all

predicates     generatedInitialize : (). clauses     generatedInitialize() :-         ...         menuSet(resMenu(resourceIdentifiers::id_TaskMenu)),         ...
Regards Thomas Linder Puls
PDC
User avatar
Thomas Linder Puls
VIP Member
Posts: 1401
Joined: 28 Feb 2000 0:01

Re: How to know if this window is on the top.

Unread post by Thomas Linder Puls »

With regards to the ribbon: some similar behavior exist.

The basic idea is that your form will have to have its own versions of the commands it should handle. These will then automatically be used when your window is active.

I.e. again the stuff about "who is active" is handled automatically (once you set it up correctly).

You should also notice that part of dealing with "who is active" is also to enable and disable menu items and commands (and to add/remove them and to make them visible/invisible).

However, I have not invented the ribbon and the command concept and I have never used it with form dependent behavior. So I will have to make some investigations before I can advise you on this.
Regards Thomas Linder Puls
PDC
x2060
Posts: 9
Joined: 11 Dec 2021 8:20

Re: How to know if this window is on the top.

Unread post by x2060 »

Hi Gukalov, The code below is not working in Form. Actually it can only work for TaskWindow (maybe because of application window).

Code: Select all

      addActivateListener({ :- activeForm := This }),         addDeactivateListener({ :- activeForm := erroneous }).
and the code below gives lot errors when compile (I am using VP10CE)

Code: Select all

domains     finyaDomain = activated(editorForm); deactivated(editorForm).   class facts     fignayEvent : event1{handle, finyaDomain} :=         { = Event :- Event = event1::new(nullHandle), Event:addListener(fignyaListener) }().   class predicates     fignyaListener : event1{handle, finyaDomain}::listener. clauses     fignyaListener(_, Event) :-         core::nothing(Event),         succeed().
Thank you Thomas introduce the menu knowledge. I have insert the

Code: Select all

 menuSet(resMenu(resourceIdentifiers::id_TaskMenu)),
in form so it can works.

My main job is want Ribbon control interacting with Form (Data synchronization) when I shift windows to the top, it can be noticed and update the ribbon control (has lot custom controls) for show according to data of Top Form. so I still need to find out which kind of Listener can do this (for MDI window). MDI program seems a little difficult to handle data synchronization, maybe change to SDI type is better? I see a lot of modern windows application changed to SDI mode.
x2060
Posts: 9
Joined: 11 Dec 2021 8:20

Re: How to know if this window is on the top.

Unread post by x2060 »

In this morning I changed to SDI window type, it works correct anyway. I can simply add a Listener of Form activate and Deactivate, the relative Form can know its self when activated(to the top) or deactivated. So I can reduce those obscure codes.

Code: Select all

 clauses     new(Parent) :-         formWindow::new(Parent),         generatedInitialize(),         setText(string::concat("TestForm", toString(uncheckedConvert(unsigned, This)))),         addActivateListener({ (_) :- stdio::write(getText(), "testForm activated\n") }),         addDeactivateListener({ (_) :- stdio::write(getText(), "testForm Dectivated\n") }).
If someone can let me know same way under MDI window, I do much appreciated.
User avatar
Thomas Linder Puls
VIP Member
Posts: 1401
Joined: 28 Feb 2000 0:01

Re: How to know if this window is on the top.

Unread post by Thomas Linder Puls »

It turns out that the ribbon and command system does not work well in when living on the task window.

So try using code like this for your handling:

Code: Select all

        if Focus = gui::tryGetFocusWindow() then             TopContainer = Focus:getTopLevelContainerWindow(),             stdio::writef("% %\n", TopContainer, Focus)         end if,
  • gui::tryGetFocusWindow will return the window that have focus (if it is a window in the application)
  • getTopLevelContainerWindow will return the dialog/form/application window that contains that control
The "Active window" is the "application" that is active. So listening on activation/deactivation is listening on switch in and out of your application, not switching internally in your application.
Regards Thomas Linder Puls
PDC
Post Reply