Help : Details of the opened dialogs/windows in application
Help : Details of the opened dialogs/windows in application
Friends,
Is there any function which returns or let us know the details of the opened windows and dialogs in my app. (Pls note : Details of opened windows and dialogs in my app)
I am planning to give my users both Modal and non modal dialogs in my app. which means there can be multiple instances of the same window in my app. But I should be able to restrict users from opening multiple instances of certain dialogs/windows for eg. the DBF Re-indexing window should be restricted. It can have only instance and once the user click on the reindex dialog, my app should check whether any dialogs/windows are still open. If other dialogs/windows are open, then my app should warn the users about the opened windows.
Regards
Anser
Is there any function which returns or let us know the details of the opened windows and dialogs in my app. (Pls note : Details of opened windows and dialogs in my app)
I am planning to give my users both Modal and non modal dialogs in my app. which means there can be multiple instances of the same window in my app. But I should be able to restrict users from opening multiple instances of certain dialogs/windows for eg. the DBF Re-indexing window should be restricted. It can have only instance and once the user click on the reindex dialog, my app should check whether any dialogs/windows are still open. If other dialogs/windows are open, then my app should warn the users about the opened windows.
Regards
Anser
Last edited by anserkk on Tue Sep 09, 2008 11:21 am, edited 1 time in total.
- xProgrammer
- Posts: 464
- Joined: Tue May 16, 2006 7:47 am
- Location: Australia
My application is not a single user. It is supposed to be run on a Network with multiple users.xProgrammer wrote:Hi Anser
Is your application single user? If not then I don't think that determining what windows your application has open would do the trick. You would need to use flags and / or locks. I would suggest such an approach for a single user scenario also as it would be extensible.
Regards
xProgrammer
I am porting my existing Clipper 5.01 application to FWH. I don't want to restrict my users from having multiple windows opened simultaneously to a certain extent. Because of this reason I want to reduce the Modal Dialog as much as possible. For eg. A user who is already preparing the invoice need to check for an Item in the item Master. I want my user to open the Item Master even when the invoice preperation screen is open.
Why the user should be restricted from having such facilities, which I beleive is one of the major advantages of Windows GUI app over a DOS based Clipper application. I also understand that there are lot of complications as a programmer by allowing the user to open multiple windows.
I don't open all the DBF files from the Main Fucntion itself, instead I open only the required DBf files in each and every Menu/fucntions, and I close only the DBF files opened in that particular function.
I open DBF files with different unique ALIAS names in each and every function so that there will not be any clash with the work area.
But I don't want the same user to open multiple instances of the Invoicing window. For this reason I need to know whether the user is trying to open a window which is already remaining opened.
Hope u understand my requirement. I don't know whether I am right or not. I welcome other ideas too.
Regards
Anser
- xProgrammer
- Posts: 464
- Joined: Tue May 16, 2006 7:47 am
- Location: Australia
Hi Anser
Thanks for explaining what you want to achieve. If you want to control the number of times (typically max 1) that a user can open a specific window then there are a few possibilities.
If your application is object oriented (uses classes) then using a CLASSDATA property would be ideal. For example in the invoicing window class have a property:
CLASSDATA nCount
Then before opening the window check the value of ::nCount. If it is 0 increment to 1 and open the window. If its one then don't open what would be a second invoicing window. When you close the window decrement ::nCount - maybe in a VALID clause.
If you aren't using classes you can do the same thing - you just need to decide on the variables you need to keep the count and how you tie a particular window to a particular count variable. Not at all difficult - it just depends on how you want to do it.
You might, for example, have an array of counts. You could then have a define for each window so you might have
#define id_INVOICE_WINDOW 4
so aWindowCount[id_INVOICE_WINDOW] would be the count variable you increment / decrement and have a max value for ( 1 if you only want to allow a single invoicing window). That way yoy could write some generic code to be called as part of each window you wish to control. Something like
CanOpenWindow( nWindowID )
CloseWindow( nWindowID )
If you want to handle maximums other than 1 you might want another array aWindowMaxCount[] to hold these maximum values.
Happy Programming
xProgrammer
Thanks for explaining what you want to achieve. If you want to control the number of times (typically max 1) that a user can open a specific window then there are a few possibilities.
If your application is object oriented (uses classes) then using a CLASSDATA property would be ideal. For example in the invoicing window class have a property:
CLASSDATA nCount
Then before opening the window check the value of ::nCount. If it is 0 increment to 1 and open the window. If its one then don't open what would be a second invoicing window. When you close the window decrement ::nCount - maybe in a VALID clause.
If you aren't using classes you can do the same thing - you just need to decide on the variables you need to keep the count and how you tie a particular window to a particular count variable. Not at all difficult - it just depends on how you want to do it.
You might, for example, have an array of counts. You could then have a define for each window so you might have
#define id_INVOICE_WINDOW 4
so aWindowCount[id_INVOICE_WINDOW] would be the count variable you increment / decrement and have a max value for ( 1 if you only want to allow a single invoicing window). That way yoy could write some generic code to be called as part of each window you wish to control. Something like
CanOpenWindow( nWindowID )
CloseWindow( nWindowID )
If you want to handle maximums other than 1 you might want another array aWindowMaxCount[] to hold these maximum values.
Happy Programming
xProgrammer
Thankyou xProgrammer,
That's a very useful input for me from your side. I shall apply it my work
Would have been better if FiveWin had some functions like
IsWindowDefined(WindowName) -> Returns .T. or .F. if Window is already open
aWindList:=GetOpenWindows() -> Returns Array of all OpenedWindows
Regards
Anser
That's a very useful input for me from your side. I shall apply it my work
Would have been better if FiveWin had some functions like
IsWindowDefined(WindowName) -> Returns .T. or .F. if Window is already open
aWindList:=GetOpenWindows() -> Returns Array of all OpenedWindows
Regards
Anser
- James Bott
- Posts: 4654
- Joined: Fri Nov 18, 2005 4:52 pm
- Location: San Diego, California, USA
- Contact:
Anser,
Programmers that are converting DOS apps to Windows seem to always be enamored with the possibilities of MDI. However, it is it my opinion that MDI interfaces for databases are a poor design. MDI was invented for applications like word processing where all the windows are the same and are usually full screen.
The problem with using MDI in database applications is that every window is different and to have two visible at the same time is often difficult or impossible. Also, it usually requires a lot of manual manipulation by the user which is wasted effort.
If you are interested in more on this topic I suggest getting a copy of any of Alan Cooper's books "About Face The Essentials of User Interaction Design" (there are three editions).
If you still want to design MDI app, the information below may answer some of your questions. This is from my old notes. Use it at your own risk.
Regards,
James
-----------------------------------------------------
Checking for MDI child windows
If you need to check for MDI child windows you can look at oWnd:oWndClient:aWnd which is an array of MDI child windows objects.
You can check the captions:
Here is an example of counting the number of a certain type of MDI windows that are open.
Here is a function to prevent opening more than one copy of a MDI child window. It also brings the window to the top and set the focus to it.
Then you can do something like this for a menu or button:
...ACTION if( ! wndSetFocus("Order"), TOrder():new():browse(),)
Programmers that are converting DOS apps to Windows seem to always be enamored with the possibilities of MDI. However, it is it my opinion that MDI interfaces for databases are a poor design. MDI was invented for applications like word processing where all the windows are the same and are usually full screen.
The problem with using MDI in database applications is that every window is different and to have two visible at the same time is often difficult or impossible. Also, it usually requires a lot of manual manipulation by the user which is wasted effort.
If you are interested in more on this topic I suggest getting a copy of any of Alan Cooper's books "About Face The Essentials of User Interaction Design" (there are three editions).
If you still want to design MDI app, the information below may answer some of your questions. This is from my old notes. Use it at your own risk.
Regards,
James
-----------------------------------------------------
Checking for MDI child windows
If you need to check for MDI child windows you can look at oWnd:oWndClient:aWnd which is an array of MDI child windows objects.
You can check the captions:
Code: Select all
oWnd:oWndClient:aWnd[1]:cCaption
Code: Select all
function WndCount(cCaption)
local i:=0,nCount:=0,oWnd:=wndMain()
if valtype(oWnd:oWndClient:aWnd)!=nil
for i=1 to len(oWnd:oWndClient:aWnd)
if oWnd:oWndClient:aWnd[i]:cCaption = cCaption
nCount++
endif
next
endif
return nCount
Code: Select all
//--- Sets focus to child MDI window with cTitle
static function wndSetFocus(cTitle)
local i:=0,lSuccess:=.f.
cTitle:=upper(cTitle)
for i=1 to len(wndMain():oWndClient:aWnd)
if upper( wndMain():oWndClient:aWnd[i]:cCaption )=cTitle
wndMain():oWndClient:aWnd[i]:setFocus()
lSuccess:=.t.
endif
next
return lSuccess
...ACTION if( ! wndSetFocus("Order"), TOrder():new():browse(),)
Hi,
In an MDI environment OR DIALOG NOWAIT environment, I understand that the program execution does not pause after the ACTIVATE WINDOW oWnd and the next line in the prg will get executed which probably will be the Return NIL statement.
Because of this reason all the private & local variables will die as the statement RETURN NIL quits the function.
The GETs used in the MDICHILD window is giving VARIABLE does not exist error because I have used private & Local variables
Does that means that you will have to use either Static variables or Public variables. I would like to know how this situation is handled. As far as I know we should use less static and public variables. (Correct me if I am wrong.)
As a programmer's point of view it is easy or the effort is less to develop DIALOG based apps when compared to MDI, but as a user of the app. it applies lot of restriction to the user. A user will not be able to even minimise the app's main screen without quiting the DIALOG.
The above is just one of the examples.
I would like to get some suggestion, hints and views in this regard to try writing an MDI environment application
Regards
Anser
In an MDI environment OR DIALOG NOWAIT environment, I understand that the program execution does not pause after the ACTIVATE WINDOW oWnd and the next line in the prg will get executed which probably will be the Return NIL statement.
Because of this reason all the private & local variables will die as the statement RETURN NIL quits the function.
The GETs used in the MDICHILD window is giving VARIABLE does not exist error because I have used private & Local variables
Does that means that you will have to use either Static variables or Public variables. I would like to know how this situation is handled. As far as I know we should use less static and public variables. (Correct me if I am wrong.)
As a programmer's point of view it is easy or the effort is less to develop DIALOG based apps when compared to MDI, but as a user of the app. it applies lot of restriction to the user. A user will not be able to even minimise the app's main screen without quiting the DIALOG.
The above is just one of the examples.
I would like to get some suggestion, hints and views in this regard to try writing an MDI environment application
Regards
Anser
- James Bott
- Posts: 4654
- Joined: Fri Nov 18, 2005 4:52 pm
- Location: San Diego, California, USA
- Contact:
Anser,
I would avoid privates like the plague--they often create very hard to find bugs. Locals will remain as long as they are in scope. As long the dialog or window is still in use, then the variables are still in scope. They will go out of scope when the dialog/window is closed. Resource objects like fonts and bitmaps need to be ended in the dialog/window's VALID clause.
>As a programmer's point of view it is easy or the effort is less to develop DIALOG based apps when compared to MDI,
You shouldn't even be asking this question. The question is, "What is a better interface design for the user?" Our job is to provide software to make the user's job easier and faster--even if it is more work for us.
Regards,
James
I would avoid privates like the plague--they often create very hard to find bugs. Locals will remain as long as they are in scope. As long the dialog or window is still in use, then the variables are still in scope. They will go out of scope when the dialog/window is closed. Resource objects like fonts and bitmaps need to be ended in the dialog/window's VALID clause.
>As a programmer's point of view it is easy or the effort is less to develop DIALOG based apps when compared to MDI,
You shouldn't even be asking this question. The question is, "What is a better interface design for the user?" Our job is to provide software to make the user's job easier and faster--even if it is more work for us.
Regards,
James
Dear Mr.James,
Thank you for your views & suggestions.
Let me make a summary statement of what I have understood about the tips of developing a database app in an MDI environment.
1. Never use Private variables
2. use only local variables
3. If the variable are required in sub functions then pass those variables as parameters to sub fuctions.
4. objects like fonts,bmp's which needs to be ended should be used via the windows valid clause.
5. Closing of DBF files opened in that particular function should be closed using the Windows Valid clause.
Mr.James, I never open all the DBF files together during the app start up. Instead I open the required DBF files only in each and every function and I close all the DBF opened in that particular fucntion when I quit the function.
Regards
Anser
Thank you for your views & suggestions.
Let me make a summary statement of what I have understood about the tips of developing a database app in an MDI environment.
1. Never use Private variables
2. use only local variables
3. If the variable are required in sub functions then pass those variables as parameters to sub fuctions.
4. objects like fonts,bmp's which needs to be ended should be used via the windows valid clause.
5. Closing of DBF files opened in that particular function should be closed using the Windows Valid clause.
Mr.James, I never open all the DBF files together during the app start up. Instead I open the required DBF files only in each and every function and I close all the DBF opened in that particular fucntion when I quit the function.
Regards
Anser
See if these codes to help you.
with this code you can open tables without closing them:
with this code you can better control the opening of windows:
with this code you can open tables without closing them:
Code: Select all
#command OPEN <(db)> ;
[VIA <rdd>] ;
[ALIAS <a>] ;
[<new: NEW>] ;
[<ex: EXCLUSIVE>] ;
[<sh: SHARED>] ;
[<ro: READONLY>] ;
[INDEX <(index1)> [, <(indexn)>]] ;
=> if Select( <(db)> )==0 ;
; dbUseArea( <.new.>, <rdd>, <(db)>, <(a)>, if(<.sh.> .or. <.ex.>, !<.ex.>, NIL), <.ro.>, 0 )[; dbSetIndex( <(db)> )];
;else ;
; dbSelectArea( <(db)> ) ;
;end
OPEN clients SHARED NEW INDEX clients
OPEN products SHARED NEW INDEX products
Code: Select all
function main()
...
PUBLIC oChildWnd:=nil, cTitle, nChildNum
...
return .t.
function module01( oWnd )
PUBLIC lFecha := .f.
//
cTitle := "Clients"
nChildNum := 1 // Unique number for this window
if lChildWnd // if any window is open...
if nChildWnd == nChildNum // If the window is the same...
return nil // returns without modifying
endif
lFecha := .t. // free last window to close
dbCommitAll() // commit all changes
dbCloseAll() // free all areas
oChildWnd:end() // close last window
oChildWnd := nil // free object window
endif
//
nChildWnd := nChildNum // Renew a window control
lChildWnd := .t. // There window open
DEFINE WINDOW oChildWnd TITLE cTitle MDICHILD STYLE nOr(WS_CHILD,DS_SYSMODAL,DS_MODALFRAME)
ACTIVATE WINDOW oChildWnd MAXIMIZED ON INIT BuildDialog( oChildWnd )
return nil
function module02( oWnd )
PUBLIC lFecha := .f.
//
cTitle := "Clients"
nChildNum := 2 // Unique number for this window
if lChildWnd // if any window is open...
if nChildWnd == nChildNum // If the window is the same...
return nil // returns without modifying
endif
lFecha := .t. // free last window to close
dbCommitAll() // commit all changes
dbCloseAll() // free all areas
oChildWnd:end() // close last window
oChildWnd := nil // free object window
endif
//
nChildWnd := nChildNum // Renew a window control
lChildWnd := .t. // There window open
DEFINE WINDOW oChildWnd TITLE cTitle MDICHILD STYLE nOr(WS_CHILD,DS_SYSMODAL,DS_MODALFRAME)
ACTIVATE WINDOW oChildWnd MAXIMIZED ON INIT BuildDialog( oChildWnd )
return nil
STATIC FUNCTION BuildDialog( oChild )
LOCAL oDlg
//
DEFINE DIALOG oDlg RESOURCE "YOUR_DIALOG" OF oChild
...
ACTIVATE DIALOG oDlg NOWAIT ;
ON INIT ChangeParent( oDlg, oChild ) ;
CENTER
return .t.
STATIC FUNCTION ChangeParent( oDlg, oChild )
...
return .t.
- James Bott
- Posts: 4654
- Joined: Fri Nov 18, 2005 4:52 pm
- Location: San Diego, California, USA
- Contact:
Anser,
Yes to all points.
However, if you build your own class then all of the points 2-6 can be handled much easier. You can use class data and and an End method. With class data you don't need to pass all the needed variables to a method. With an End method you can end all resource objects and databases. For more information about this read the articles on object-oriented programming my website.
http://ourworld.compuserve.com/homepage ... rogram.htm
Regards,
James
Yes to all points.
However, if you build your own class then all of the points 2-6 can be handled much easier. You can use class data and and an End method. With class data you don't need to pass all the needed variables to a method. With an End method you can end all resource objects and databases. For more information about this read the articles on object-oriented programming my website.
http://ourworld.compuserve.com/homepage ... rogram.htm
Regards,
James
Mr.James,
Thanks for the information. My level of knowledge on FWH and OOPS has to improve much more to make a CLASS of my own as you said. I am just reading the material in your web site.
Mr.Rochina,
I could not understand the purpose of the function ChangeParent( oDlg, oChild ) and what exactly it does and the advantage. Excuse me if my question is very silly, I am only a beginner in FWH as well as in developing Windows based apps.
If I am not wrong
2. At any point of time there can be only one child window opened ( I am NOT talking about the Openening of a Child window which is already Open)
If you don't mind I would like to get more samples in this regard.
I have not tested your code.
Regards
Anser
Thanks for the information. My level of knowledge on FWH and OOPS has to improve much more to make a CLASS of my own as you said. I am just reading the material in your web site.
Mr.Rochina,
I could not understand the purpose of the function ChangeParent( oDlg, oChild ) and what exactly it does and the advantage. Excuse me if my question is very silly, I am only a beginner in FWH as well as in developing Windows based apps.
Code: Select all
ACTIVATE DIALOG oDlg NOWAIT ;
ON INIT ChangeParent( oDlg, oChild ) ;
CENTER
return .t.
STATIC FUNCTION ChangeParent( oDlg, oChild )
...
return .t.
1) Regarding the closing of DBF files, you are taking a different approach ie instead of closing DBF's while closing the window, you are trying to close all open DBF files during the initialisation/opening of each and every module. Suppose a user opens a child window, the required DBF files are opened along with the module, but the files are left open till the user opens an another child window. And it has nothing to do with the command OPEN which you have given. Am I right ?with this code you can open tables without closing them:
Code: Select all
#command OPEN <(db)> ;
[VIA <rdd>] ;
[ALIAS <a>] ;
[<new: NEW>] ;
[<ex: EXCLUSIVE>] ;
[<sh: SHARED>] ;
[<ro: READONLY>] ;
[INDEX <(index1)> [, <(indexn)>]] ;
=> if Select( <(db)> )==0 ;
; dbUseArea( <.new.>, <rdd>, <(db)>, <(a)>, if(<.sh.> .or. <.ex.>, !<.ex.>, NIL), <.ro.>, 0 )[; dbSetIndex( <(db)> )];
;else ;
; dbSelectArea( <(db)> ) ;
;end
OPEN clients SHARED NEW INDEX clients
OPEN products SHARED NEW INDEX products
If you don't mind I would like to get more samples in this regard.
I have not tested your code.
Regards
Anser
Anserkk,
Take a look in this code and sample in http://www.5volution.com/forum/custxbrw.zip
It´s only one explanation, without functioning.anserkk wrote:I could not understand the purpose of the function ChangeParent( oDlg, oChild ) and what exactly it does and the advantage...
Yes. This avoids mistakes of openness.anserkk wrote:Regarding the closing of DBF files, you are taking a different approach ie instead of closing DBF's...
Take a look in this code and sample in http://www.5volution.com/forum/custxbrw.zip
- Antonio Linares
- Site Admin
- Posts: 37481
- Joined: Thu Oct 06, 2005 5:47 pm
- Location: Spain
- Contact:
Anser,
This code may help you:
This code may help you:
Code: Select all
#include "FiveWin.ch"
function Main()
local oDlg
DEFINE DIALOG oDlg TITLE "Modal" FROM 3, 3 TO 15, 40
@ 2, 2 BUTTON "Search" ACTION MsgInfo( SearchNonModal( "Non modal" ) )
@ 2, 10 BUTTON "Create" ACTION CreateNonModal()
ACTIVATE DIALOG oDlg ;
ON INIT CreateNonModal()
return nil
function SearchNonModal( cNonModalTitle )
return AScan( GetAllWin(), { | o | ValType( o ) == "O" .and. ;
Upper( o:ClassName() ) == "TDIALOG" .and. o:cTitle == "Non modal" } )
function CreateNonModal()
local oDlg
if SearchNonModal( "Non modal" ) != 0 // the non modal is already created
MsgAlert( "already exists" )
return nil
endif
DEFINE DIALOG oDlg TITLE "Non modal"
ACTIVATE DIALOG oDlg NOWAIT CENTERED
return nil