MDI.f contains classes that form the basis for writing MDI aplications (like MS Word and MS Excel). Each document in an MDI application is displayed in a separate child window within the client area of the application's main window.
:Class MDIClientWindow <super Control
MDI client control class. This control is used by the MDIFrameWindow class. You shouldn't create instances of this class within your application.
:M Start: ( hWindowMenu Parent -- )
Start the control.
:M CreateStruct: ( -- CreateStrucPointer )
Get the address of CLIENTCREATESTRUCT structure. It contains information about the menu and first multiple document interface (MDI) child window of an MDI client window. An application passes a pointer to this structure as the lpvParam parameter of the CreateWindow function when creating an MDI client window.
;Class
End of MDIClientWindow class
:Class MDIFrameWindow <super Window
All MDI child windows are displayed within the client area of this window.
:M WindowMenuNo: ( -- n )
Override this method to set the menu number in whitch all child windows should be displayed.
:M WindowTitle: ( -- z" )
Get the title text for the frame window.
:M SetRedraw: ( f -- )
Set the redraw state of the window.
f Specifies the redraw state. If this parameter is TRUE, the content can be redrawn after a change. If this parameter is FALSE, the content cannot be redrawn after a change.
:M Tile: ( f -- )
Arrange all child windows in a tile format.
f can be one of the following values optionally combined with MDITILE_SKIPDISABLED to prevent disabled MDI child windows from being tiled.
MDITILE_HORIZONTAL | Tiles windows horizontally. |
MDITILE_VERTICAL | Tiles windows vertically. |
:M Arrange: ( -- )
Arrange all minimized child windows. It does not affect child windows that are not minimized.
:M Cascade: ( -- )
Arrange all child windows in a cascade format.
:M RefreshMenu: ( -- )
Refresh the window menu of the MDI frame window.
:M MDISetMenu: ( hmenuWindow hmenuFrame -- )
Replace the entire menu of an MDI frame window, replace the window menu
of the frame window, or both.
:M DrawMenuBar: ( -- )
Redraws the menu bar of the window. If the menu bar changes after the system has created the window, this function must be called to draw the changed menu bar.
:M Restore: ( hWnd -- )
Restore an MDI child window from maximized or minimized size.
:M Maximize: ( hWnd -- )
M maximize an MDI child window. The system resizes the child window to make its client area fill the client window. The system places the child window's window menu icon in the rightmost position of the frame window's menu bar, and places the child window's restore icon in the leftmost position. The system also appends the title bar text of the child window to that of the frame window.
:M GetActive: ( -- Maximized handle )
Retrieve the handle to the active MDI child window.
:M Activate: ( hWnd -- )
Activate a MDI child window.
:M Next: ( f hWnd -- )
Activate the next or previous child window.
:M Destroy: ( hWnd -- )
Destroy an MDI child window.
:M CloseChild: ( hWnd -- )
Close an MDI child window.
:M EnumChildWindows: ( lparam pCallBack -- f )
Enumerate the MDI child windows
:M CloseAll: ( -- )
Close all MDI child windows.
:M GetFirstChild: ( -- hWndChild )
Get handle of the first child window
:M GetNextChild: ( -- hWndChild )
Get handle of the next child window.
NOTE: you must call GetFirstChild: first.
:M SendMessageToAllChildren: { wParam lParam msg -- }
Send a message to all child windows
:M PostMessageToAllChildren: { wParam lParam msg -- }
Post a message to all child windows
;Class
End of MDIFrameWindow class
:Class MDIChildWindow <super child-window
This is the base class for all windows that should be displayed within the client area of a MDIFrameWindow.
:M DefaultIcon: ( -- hIcon )
Return the handle of the Icon whitch should be displayed in the upper left corner of the MDi child window.
:M ParentWindow: ( -- hParent )
Teturn the handle of parent, 0 = no parent
:M Start: ( Parent -- )
Create a new MDI child window object
:M WindowTitle: ( -- z" )
Get the title text for the MDI child window.
:M On_QueryEnd: ( -- f )
This method is called when the user chooses to end the session or when an application calls the ExitWindows function. If any application returns zero, the session is not ended.
The default method returns TRUE, so that the session will be ended.
:M On_Close: ( -- f )
This method is called when the user chooses to close the MDI child window. If it returns FALSE the window will not be closed.
Override the method to check if the document within the child window need's to be saved.
The default method returns TRUE, so that the window will be closed.
:M On_ChildActivate: ( -- )
Handle the WM_CHILDACTIVATE message. This message is sent to a child window when the user clicks the window's title bar or when the window is activated, moved, or sized.
:M On_GetMinMaxInfo: ( pMinMaxInfo -- pMinMaxInfo )
Handle the WM_GETMINMAXINFO message. This message is sent to a window when the size or position of the window is about to change. An application can use this message to override the window's default maximized size and position, or its default minimum or maximum tracking size.
pMinMaxInfo Pointer to a MINMAXINFO structure that contains the default maximized position and dimensions, and the default minimum and maximum tracking sizes. An application can override the defaults by setting the members of this structure.
:M On_MenuChar: ( w l -- w l )
Handle the WM_MENUCHAR message. This message is sent when a menu is active and the user presses a key that does not correspond to any mnemonic or accelerator key. This message is sent to the window that owns the menu.
:M On_Move: ( l -- l )
Handle the WM_MOVE message. This message is sent after a window has been moved.
:M On_SysCommand: ( h m w l -- h m w l f )
Handle the WM_SYSCOMMAND message. A window receives this message when the user chooses a command from the window menu or when the user chooses the maximize button, minimize button, restore button, or close button.
:M On_Command: ( h m w l -- h m w l f )
Handle the WM_COMMAND message. This message is sent when the user selects a command item from a menu, when a control sends a notification message to its parent window, or when an accelerator keystroke is translated.
;Class
End of MDIChildWindow class
Needs MDI 0 value CurrentWindow 0 value ActiveChild Create CurrentFile 256 allot \ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ \ Messages and Dialogs \ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ : ?SaveMessage ( -- n ) \ IDYES, IDNO or IDCANCEL s" Do you want to save " pad place CurrentFile count "to-pathend" pad +place s" ?" pad +place pad +NULL pad 1+ z" MDI Example" [ MB_ICONEXCLAMATION MB_YESNOCANCEL or ] literal NULL MessageBox ; \ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ \ Simple TextBox to place on child windows \ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ :Class TextBox <Super Control :M Start: ( Parent -- ) to Parent z" EDIT" Create-Control ;M :M WindowStyle: ( -- style ) [ WS_VISIBLE WS_CHILD or ES_MULTILINE or WS_VSCROLL or WS_HSCROLL or ] literal ;M ;Class \ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ \ Define application menu \ \ The frame window of an MDI application should include \ a menu bar with a Window menu. The Window menu should \ include command items that arrange the child windows \ within the client window or that close all child windows. \ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ 200 value (NewID) : NewID ( <name> -- ) defined IF drop ELSE count "header (NewID) dup 1+ to (NewID) DOCON , , THEN ; NewID IDM_NEW NewID IDM_CLOSE NewID IDM_EXIT NewID IDM_TILE NewID IDM_ARRANGE NewID IDM_CASCADE NewID IDM_CLOSE_ALL NewID IDM_OPEN_FILE Create MenuTable (NewID) 200 - 4 * allot : DoMenu ( ID -- ) 200 - 4 * MenuTable + @ ?dup IF execute THEN ; : SetMenu ( ID -- ) last @ name> swap 200 - 4 * MenuTable + ! ; MENUBAR MDIMenu POPUP "&File" MENUITEM "&New... \tCtrl+N" IDM_NEW DoMenu ; MENUITEM "C&lose" IDM_CLOSE DoMenu ; \ 9 RECENTFILES RecentFiles IDM_OPEN_FILE DoMenu ; MENUSEPARATOR MENUITEM "E&xit \tAlt-F4" IDM_EXIT DoMenu ; POPUP "&Window" MENUITEM "&Tile" IDM_TILE DoMenu ; MENUITEM "&Arrange" IDM_ARRANGE DoMenu ; MENUITEM "Ca&scade" IDM_CASCADE DoMenu ; MENUITEM "&Close all" IDM_CLOSE_ALL DoMenu ; ENDBAR \ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ \ Define application window \ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ :Object Frame <Super MDIFrameWindow :M Classinit: ( -- ) ClassInit: super MDIMenu to CurrentMenu ;M :M WindowMenuNo: ( -- n ) 1 ;M \ the Window menu where the child window titles will be placed :M WindowStyle: ( -- style ) WindowStyle: SUPER WS_CLIPCHILDREN or ;M :M ExWindowStyle: ( -- exstyle ) WS_EX_ACCEPTFILES ;M :M WM_DROPFILES { hndl message wParam lParam \ drop$ -- res } SetForegroundWindow: self MAXSTRING LocalAlloc: drop$ 0 0 -1 wParam Call DragQueryFile 0 DO MAXCOUNTED drop$ 1+ i wParam Call DragQueryFile drop$ c! drop$ IDM_OPEN_FILE DoMenu LOOP wParam Call DragFinish ;M :M MinSize: ( -- width height ) 106 0 ;M :M WindowTitle: ( -- z" ) z" MDI Example" ;M :M On_Size: ( h m w -- ) 0 0 Width Height Move: MDIClient ;M (( This is equivalent to :M WM_SIZE ( h m w l -- f ) DefFrameProc ;M but if space for a Toolbar or StatusBar is needed MDIClient needs to be smaller )) :M On_Init: ( -- ) On_Init: super 100 appinst Call LoadIcon \ Win32For.ico GCL_HICON hWnd Call SetClassLong drop ;M :M OnWmCommand: ( hwnd msg wparam lparam -- hwnd msg wparam lparam ) OnWmCommand: Super over LOWORD ( Menu ID ) dup 200 (NewID) within \ intercept Menu commands IF DoMenu ELSE drop THEN ;M :M WM_CLOSE ( h m w l -- res ) CloseAll: self NotCancelled \ if we don't cancel the close IF WM_CLOSE WM: super \ then just terminate the program ELSE 1 \ else abort program termination THEN ;M :M On_Done: ( -- ) Turnkeyed? IF 0 call PostQuitMessage drop THEN On_Done: Super ;M ;Object \ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ \ Define Child Window class \ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ :Class MDIChild <Super MDIChildWindow int EditWindow 256 bytes FileName int Modified :M WindowTitle: ( -- z" ) CurrentFile count FileName place FileName +null FileName 1+ ;M :M WindowStyle: ( -- style ) WindowStyle: super WS_CLIPCHILDREN or GetActive: Frame 0= or IF WS_MAXIMIZE or THEN \ start new child maximised unless ;M \ the active child is not maximised :M DefaultIcon: ( -- hIcon ) 101 appInst Call LoadIcon \ App_icon.ico ;M :M Start: ( parent -- ) New> TextBox to EditWindow Start: super self start: EditWindow 0 0 Width Height Move: EditWindow SetFocus: EditWindow True to Modified ;M :M On_SetFocus: ( -- ) \ A child window can be selected by clicking on it, SetFocus: EditWindow \ selecting it from the Window menu or using CTRL+F6 EditWindow to CurrentWindow self to ActiveChild FileName count CurrentFile place CurrentFile +null ;M :M On_Size: ( h m w l -- h m w l ) 0 0 Width Height Move: EditWindow \ make TextBox fit child window ;M :M On_Close: ( -- f ) \ True = close, False = cancel close Modified IF ?SaveMessage Case IDCANCEL Of FALSE Endof IDYES Of TRUE Endof ( otherwise IDNO ) TRUE swap EndCase ELSE TRUE THEN dup dup to NotCancelled IF \ if we don't cancel the close GetHandle: self Destroy: Frame \ close child window first EditWindow dispose \ so we can safely dispose self dispose \ of both the EditControl THEN \ and the child window ;M ;Class \ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ \ Activate Menu \ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ 0 value New# : New ( -- ) 1 +to New# s" File " currentfile place New# (.) currentfile +place New> MDIChild to ActiveChild MDIClientWindow: Frame Start: ActiveChild ; IDM_NEW SetMenu : Close ( -- ) GetHandle: ActiveChild CloseChild: Frame ; IDM_CLOSE SetMenu : ExitApp ( -- ) bye ; IDM_EXIT SetMenu : Tile ( -- ) 0 Tile: Frame ; IDM_TILE SetMenu : Arrange ( -- ) Arrange: Frame ; IDM_ARRANGE SetMenu : Cascade ( -- ) Cascade: Frame ; IDM_CASCADE SetMenu : CloseAll ( -- ) CloseAll: Frame ; IDM_CLOSE_ALL SetMenu : OpenFile ( File$ -- ) count currentfile place New> MDIChild to ActiveChild ( File opening stuff ) MDIClientWindow: Frame Start: ActiveChild ; IDM_OPEN_FILE SetMenu******* many menu items not implemented here **********
\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ \ Handle MDI Accelerators: ALT+ - (minus), CTRL+ F4, CTRL+ F6 \ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ : DoMDIMsg ( pMsg f -- pMsg f ) dup MDIClient: Frame 0<> and IF drop dup MDIClient: Frame Call TranslateMDISysAccel 0= THEN ; msg-chain chain-add DoMDIMsg \ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ \ The word to start the application \ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ : go ( -- ) zeromenu: mdimenu start: Frame 0 to New# New Cascade Turnkeyed? IF Begin key drop again THEN ;
Document $Id: mdi.htm,v 1.10 2007/05/26 10:24:13 dbu_de Exp $