home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
BUG 4
/
BUGCD1997_05.BIN
/
aplic
/
clip4win
/
clip4win.exe
/
C4W30E.HUF
/
SOURCE
/
MDIDEMO.PRG
< prev
next >
Wrap
Text File
|
1994-06-01
|
13KB
|
481 lines
////////////////////////////
//
// mdidemo.prg
//
// Copyright (C) 1993 Skelton Software, Kendal Cottage, Hillam, Leeds, UK.
// All Rights Reserved.
//
// Sample MDI app.
//
////////////////////////////
#define WIN_WANT_MF
#define WIN_WANT_ALL
#include "windows.ch"
#include "wmcreate.ch"
#include "mdi.ch"
#include "msg.ch"
#include "paint.ch"
#include "mdidemo.ch"
#define AUTO_FIRST_CHILD // define if you want a child on start-up
static hInst // app instance handle
static hWndFrame // main window handle
static hWndMDIClient // MDI client handle
static cFTitle := "Clip-4-Win MDI Demo"
static cFrame := "MDI frame" // window class name for frame window
// (N.B. "mdiclient" is part of Windows)
static cChild := "MDI child" // window class name for MDI window
#define DEFMDICHILDSTYLE 0 // default style bits for child windows
#define TB_HEIGHT 30
static hTBWnd
static lToolBar := .t. // whether currently wanted
function main()
local aMsg[MSG_LENGTH]
hInst = _GetInstance()
if _GetPrevInstance() == 0
if !InitApp()
quit
endif
endif
if !InitInst()
quit
endif
// main message loop
do while GetMessage(aMsg)
// give it to MDI if possible
if !TranslateMDISysAccel(hWndMDIClient, aMsg)
// getting here means it wasn't for MDI
TranslateMessage(aMsg)
DispatchMessage(aMsg)
endif
enddo
return 0
static function InitApp()
local hInst := _GetInstance()
if _GetPrevInstance() == 0
// first register the frame class
if RegisterClass(0, ; // class style
hInst, ; // application instance
LoadIcon( , ID_MDIFRAME), ; // special icon
, ; // default cursor
COLOR_APPWORKSPACE + 1, ; // frame background brush
cFrame, ; // class name
{|hWnd, nMsg, nwParam, nlParam| ;
FrameWndProc(hWnd, nMsg, nwParam, nlParam)}, ; // window proc
{WM_CREATE, WM_DESTROY, WM_CLOSE, ;
WM_COMMAND, WM_SIZE}, ;
RCF_MDIFRAME,;
0, ; // class extra
0, ; // window extra
ID_MENU ; // menu
)
// now the MDI child class
if RegisterClass(0, ; // class style
hInst, ; // application instance
LoadIcon( , ID_MDICHILD), ; // special icon
, ; // default cursor
, ; // default background brush
cChild, ; // class name
{|hWnd, nMsg, nwParam, nlParam| ;
MDIChildWndProc(hWnd, nMsg, nwParam, nlParam)}, ; // window proc
{}, ; // not needed in this sample
RCF_MDICHILD, ; // default to DefMDIChildProc()
0, ; // class extra
NWNDEXTRA, ; // window extra
nil ; // menu
)
// all was ok
return .t.
endif
endif
endif
// something failed
// probably out of resources
//quit
return .f.
static function InitInst()
local aButtons := ;
{ {10, 5, 40, 20, LoadBitmap( ,IDB_NEW), IDM_FILENEW}, ;
{60, 5, 40, 20, LoadBitmap( ,IDB_CASCADE), IDM_WINDOWCASCADE},;
{110, 5, 40, 20, LoadBitmap( ,IDB_TILE), IDM_WINDOWTILE}, ;
{160, 5, 40, 20, LoadBitmap( ,IDB_CLOSE), IDM_WINDOWCLOSEALL},;
{210, 5, 40, 20, LoadBitmap( ,IDB_EXIT), IDM_FILEEXIT} }
local aRect
//
// create the frame
//
// Note: As with all calls to CreateWindow(), before it returns
// Windows calls the WndProc that was registered for the
// window class. It is called twice at least, with WM_NCCREATE
// and WM_CREATE. The MDI client window is created during
// the WM_CREATE message. Then, the 1st MDI child is created
// below.
//
hWndFrame = CreateWindow(cFrame, ; // window class
cFTitle, ; // caption for title bar
WS_OVERLAPPEDWINDOW + WS_CLIPCHILDREN, ; // window style
CW_USEDEFAULT, ; // x co-ordinate
CW_USEDEFAULT, ; // y co-ordinate
0, ; // width
0, ; // height
0, ; // hWnd of parent (none)
, ; // hMenu of menu (use class menu)
hInst) // our own app instance
// See the above Note: hWndMDIClient should now be valid
if hWndFrame != 0 .and. hWndMDIClient != 0
/*
* This sample puts the toolbar at the top of the frame window's
* client area. The user doesn't know the "mdiclient" exists,
* so just make it fill the area not used by the toolbar. Of
* course, this means changing its size if the main window changes
* size (msg WM_SIZE). The toolbar size needs to change as well
* (just the width in this example).
*
* This same technique can be useful at other times, e.g. the child
* might be a multi-line edit control.
*
* If you have a status bar, the easiest way to handle it is to
* make it another window (with no special border, no title bar,
* etc., and using WS_CHILD + WS_VISIBLE), put it at the bottom
* of the frame window, and reduce the mdiclient's window height
* by the height of the status bar. You could give any of the MDI
* child windows their own status bar in the same sort of way.
* (Yes, you do get a lot of windows. Don't worry about them.)
*/
aRect = GetClientRect(hWndFrame)
hTBWnd = ToolBar(hWndFrame, 0, 0, aRect[3], TB_HEIGHT, aButtons, ID_TOOLBAR)
// lToolBar = .t.
// make sure the frame's displayed ...
ShowWindow(hWndFrame, _GetnCmdShow())
// ... and up to date
UpdateWindow(hWndFrame)
ShowWindow(hWndMDIClient, SW_SHOW)
#ifdef AUTO_FIRST_CHILD
// create the 1st MDI child window
MDICreateWindow(cChild, ; // window class
"MDI Child #1", ; // caption for title bar
DEFMDICHILDSTYLE, ; // window style
CW_USEDEFAULT, ; // x co-ordinate
CW_USEDEFAULT, ; // y co-ordinate
0, ; // width
0, ; // height
, ; // reserved
, ; // reserved
hInst, ; // our own app instance
) // cParam (optional parameter)
#endif // AUTO_FIRST_CHILD
return .t.
endif
MessageBox(, "Window Creation Failed!", "Error", MB_ICONEXCLAMATION + MB_OK)
return .f.
static function FrameWndProc(hWnd, nMsg, nwParam, nlParam)
local aCcs[CCS_LENGTH] // Windows CLIENTCREATESTRUCT structure
local nW, nH
do case
case nMsg == WM_CREATE
// set window menu where children are listed
aCcs[CCS_hWindowMenu] = GetSubMenu(GetMenu(hWnd), WINDOWMENUPOS)
// set id of 1st child
aCcs[CCS_idFirstChild] = IDM_WINDOWCHILD
// Create the MDI client
hWndMDIClient = CreateWindow("mdiclient", ; // window class
"", ; // caption for title bar
WS_CHILD + WS_CLIPCHILDREN, ; // window style
0, ; // x co-ordinate
0, ; // y co-ordinate
0, ; // width
0, ; // height
hWnd, ; // hWnd of parent
, ; // hMenu of menu (none)
hInst, ; // our own app instance
a2bin(aCcs, CCS_STRUCT_DEF))
// ShowWindow(hWndMDIClient, SW_SHOW) // seems not needed
case nMsg == WM_COMMAND
// menu selection or accelerator commands come here
DoCommand(hWnd, nwParam)
case nMsg == WM_SIZE .and. lToolBar
if nwParam == SIZE_RESTORED .or. nwParam == SIZE_MAXIMIZED
nW = C4W_LoWord(nlParam)
nH = C4W_HiWord(nlParam)
// put toolbar at top of frame's client area, then mdi client
if IsWindow(hTBWnd) // this should be true
MoveWindow(hTBWnd, 0, 0, nW, TB_HEIGHT, .t.)
endif
if IsWindow(hWndMDIClient)
MoveWindow(hWndMDIClient, 0, TB_HEIGHT, nW, nH - TB_HEIGHT, .t.)
endif
endif
case nMsg == WM_CLOSE
DestroyWindow(hWnd)
case nMsg == WM_DESTROY
PostQuitMessage(0)
otherwise
// Note: do *NOT* use DefWindowProc()
return DefFrameProc(hWnd, hWndMDIClient, nMsg, nwParam, nlParam)
endcase
return 0
static function MDIChildWndProc(hWnd, nMsg, nwParam, nlParam)
// In this demo, just pass everything along to the default handler.
// NOTE: If you handle any of WM_CHILDACTIVATE, WM_GETMINMAXINFO,
// WM_MENUCHAR, WM_MOVE, WM_NEXTMENU, WM_SETFOCUS, WM_SIZE,
// or WM_SYSCOMMAND these are needed by MDI as weel, so still
// pass them to DefMDIChildProc().
return DefMDIChildProc(hWnd, nMsg, nwParam, nlParam)
procedure DoCommand(hWnd, nwParam)
do case
case nwParam == IDM_FILENEW
// Make an empty MDI child window
MDICreateWindow(cChild, ; // window class
"MDI Child from File/New", ; // caption for title bar
DEFMDICHILDSTYLE, ; // window style
CW_USEDEFAULT, ; // x co-ordinate
CW_USEDEFAULT, ; // y co-ordinate
0, ; // width
0, ; // height
, ; // reserved
, ; // reserved
hInst, ; // our own app instance
) // cParam (optional parameter)
case nwParam == IDM_FILEEXIT
SendMessage(hWnd, WM_CLOSE, 0, 0) // close down
case nwParam == IDM_WINDOWTILE
SendMessage(hWndMDIClient, WM_MDITILE, 0, 0)
case nwParam == IDM_WINDOWCASCADE
SendMessage(hWndMDIClient, WM_MDICASCADE, 0, 0)
case nwParam == IDM_WINDOWICONS // auto-arrange icons
SendMessage(hWndMDIClient, WM_MDIICONARRANGE, 0, 0)
case nwParam == IDM_WINDOWCLOSEALL
CloseAllChildren()
otherwise
// This is essential, since there are frame WM_COMMANDS generated
// by the MDI system for activating child windows via the
// menu item "Window".
DefFrameProc(hWnd, hWndMDIClient, WM_COMMAND, nwParam, 0)
endcase
return
static procedure CloseAllChildren()
local hWnd
// find and destroy the MDI children
do while (hWnd := GetWindow(hWndMDIClient, GW_CHILD)) != 0
// skip the icon title windows
do while hWnd != 0 .and. GetWindow(hWnd, GW_OWNER) != 0
hWnd = GetWindow(hWnd, GW_HWNDNEXT)
enddo
if hWnd == 0
exit
endif
SendMessage(hWndMDIClient, WM_MDIDESTROY, hWnd, 0)
enddo
return
////////////////////////////
//
// Here's how to call some underlying Windows menu functions
//
/////////////////////////////
// for MDI want to use Windows functions for menus
// (instead of the convenient Clip-4-Win functions, with their code blocks)
static function GetMenu(hWnd)
static cGM
if cGM == nil
cGM = GetProcAddress( , "GetMenu", "Pascal", ; // actually in USER.EXE
"int", "int")
endif
return CallDLL(cGM, hWnd)
static function GetSubMenu(hMenu, nPos)
static cGSM
if cGSM == nil
cGSM = GetProcAddress( , "GetSubMenu", "Pascal", ; // in USER.EXE
"int", "int,int")
endif
return CallDLL(cGSM, hMenu, nPos)
static function GetMenuString(hMenu, nId, nFlags)
static cGMS
local i, buf := space(80) // plenty long enough
if cGMS == nil
cGMS = GetProcAddress( , "GetMenuString", "Pascal", ; // in USER.EXE
"int", "int,uint,str,int,uint")
endif
if nFlags == nil
nFlags = MF_BYCOMMAND
endif
i = CallDLL(cGMS, hMenu, nId, @buf, len(buf), nFlags)
return left(buf, i)
////////////////////////////
//
// NOTE:
//
// This is provided as source in case you are interested.
//
// Please don't ask questions about it!
//
// If you alter it, you're on your own!!
//
/////////////////////////////
static function MDICreateWindow(cClass, ; // window class
cTitle, ; // caption for title bar
nStyle, ; // window style
nX, nY, ; // x,y pos
nW, nH, ; // width, height
hWndP, ; // reserved
hMenu, ; // reserved
hInst, ; // our own app instance
cParam) // optional params
local hWnd
local aMcs[MCS_LENGTH] // Windows MDICREATESTRUCT structure
local hMem1, hMem2, hMem3, cMcs
if cTitle == nil
cTitle = "Untitled"
endif
if nStyle == nil
nStyle = 0
endif
if nX == nil
nX = CW_USEDEFAULT
endif
if nY == nil
nY = CW_USEDEFAULT
endif
if nW == nil
nW = 0
endif
if nH == nil
nH = 0
endif
if hInst == nil
hInst = _GetInstance()
endif
//aMcs[MCS_szClass] = cClass
//aMcs[MCS_szTitle] = cTitle
aMcs[MCS_hOwner] = hInst
aMcs[MCS_x] = nX
aMcs[MCS_y] = nY
aMcs[MCS_cx] = nW
aMcs[MCS_cy] = nH
aMcs[MCS_style] = nStyle
//aMcs[MCS_lParam] = cParam
// convert to a C structure stored in a Clipper string
#define GMEM_MOVEABLE 2
cClass += chr(0) // null-terminate
hMem1 = GlobalAlloc(GMEM_MOVEABLE, len(cClass))
GlobalData(hMem1, cClass)
aMcs[MCS_szClass] = GlobalLock(hMem1)
cTitle += chr(0) // null-terminate
hMem2 = GlobalAlloc(GMEM_MOVEABLE, len(cTitle))
GlobalData(hMem2, cTitle)
aMcs[MCS_szTitle] = GlobalLock(hMem2)
if cParam == nil
aMcs[MCS_lParam] = 0
else
// null-terminate (just in case it's a string)
cParam += chr(0)
hMem3 = GlobalAlloc(GMEM_MOVEABLE, len(cParam))
GlobalData(hMem3, cParam)
aMcs[MCS_lParam] = GlobalLock(hMem3)
endif
//cMcs = a2bin(aMcs, MCS_STRUCT_DEF)
cMcs = a2bin(aMcs, "long[2],int[5],dword,long") // treat C ptrs as longs
// ask the MDI client to create the child
hWnd = SendMessage(hWndMDIClient, WM_MDICREATE, 0, cMcs)
GlobalUnlock(hMem1)
GlobalFree(hMem1)
GlobalUnlock(hMem2)
GlobalFree(hMem2)
if hMem3 != nil
GlobalUnlock(hMem3)
GlobalFree(hMem3)
endif
ShowWindow(hWnd, SW_SHOW)
return hWnd