home *** CD-ROM | disk | FTP | other *** search
/ BUG 4 / BUGCD1997_05.BIN / aplic / clip4win / clip4win.exe / C4W30E.HUF / SOURCE / MDIDEMO.PRG < prev    next >
Text File  |  1994-06-01  |  13KB  |  481 lines

  1. ////////////////////////////
  2. //
  3. //    mdidemo.prg
  4. //
  5. //    Copyright (C) 1993 Skelton Software, Kendal Cottage, Hillam, Leeds, UK.
  6. //    All Rights Reserved.
  7. //
  8. //    Sample MDI app.
  9. //
  10. ////////////////////////////
  11.  
  12. #define    WIN_WANT_MF
  13. #define    WIN_WANT_ALL
  14. #include "windows.ch"
  15. #include "wmcreate.ch"
  16. #include "mdi.ch"
  17. #include "msg.ch"
  18. #include "paint.ch"
  19.  
  20. #include "mdidemo.ch"
  21.  
  22.  
  23. #define    AUTO_FIRST_CHILD    // define if you want a child on start-up
  24.  
  25. static    hInst            // app instance handle
  26. static    hWndFrame        // main window handle
  27. static    hWndMDIClient        // MDI client handle
  28.  
  29. static    cFTitle := "Clip-4-Win MDI Demo"
  30. static    cFrame := "MDI frame"    // window class name for frame window
  31.                 // (N.B. "mdiclient" is part of Windows)
  32. static    cChild := "MDI child"    // window class name for MDI window
  33.  
  34. #define    DEFMDICHILDSTYLE 0    // default style bits for child windows
  35.  
  36. #define    TB_HEIGHT    30
  37. static    hTBWnd
  38. static    lToolBar := .t.        // whether currently wanted
  39.  
  40.  
  41.  
  42. function main()
  43. local    aMsg[MSG_LENGTH]
  44.  
  45. hInst = _GetInstance()
  46.  
  47. if _GetPrevInstance() == 0
  48.     if !InitApp()
  49.         quit
  50.     endif
  51. endif
  52.  
  53. if !InitInst()
  54.     quit
  55. endif
  56.  
  57. // main message loop 
  58. do while GetMessage(aMsg)
  59.     // give it to MDI if possible
  60.     if !TranslateMDISysAccel(hWndMDIClient, aMsg)
  61.         // getting here means it wasn't for MDI
  62.         TranslateMessage(aMsg)
  63.         DispatchMessage(aMsg)
  64.     endif
  65. enddo
  66.  
  67. return 0
  68.  
  69.  
  70.  
  71. static function InitApp()
  72. local    hInst := _GetInstance()
  73.  
  74. if _GetPrevInstance() == 0
  75.    // first register the frame class 
  76.    if RegisterClass(0,        ; // class style
  77.             hInst,    ; // application instance
  78.             LoadIcon( , ID_MDIFRAME), ; // special icon
  79.             ,        ; // default cursor
  80.             COLOR_APPWORKSPACE + 1,    ; // frame background brush
  81.             cFrame,    ; // class name
  82.             {|hWnd, nMsg, nwParam, nlParam| ;
  83.              FrameWndProc(hWnd, nMsg, nwParam, nlParam)}, ; // window proc
  84.             {WM_CREATE, WM_DESTROY, WM_CLOSE,    ;
  85.              WM_COMMAND, WM_SIZE},        ;
  86.             RCF_MDIFRAME,;
  87.             0,        ; // class extra
  88.             0,        ; // window extra
  89.             ID_MENU    ; // menu
  90.             )
  91.  
  92.     // now the MDI child class 
  93.     if RegisterClass(0,    ; // class style
  94.              hInst,    ; // application instance
  95.              LoadIcon( , ID_MDICHILD), ; // special icon
  96.              ,        ; // default cursor
  97.              ,        ; // default background brush
  98.              cChild,    ; // class name
  99.              {|hWnd, nMsg, nwParam, nlParam| ;
  100.               MDIChildWndProc(hWnd, nMsg, nwParam, nlParam)}, ; // window proc
  101.              {},        ; // not needed in this sample
  102.              RCF_MDICHILD,    ; // default to DefMDIChildProc()
  103.              0,        ; // class extra
  104.              NWNDEXTRA,    ; // window extra
  105.              nil        ; // menu
  106.             )
  107.  
  108.         // all was ok
  109.         return .t.
  110.     endif
  111.    endif
  112. endif
  113.  
  114. // something failed
  115.  
  116. // probably out of resources
  117. //quit
  118.  
  119. return .f.
  120.  
  121.  
  122.  
  123. static function InitInst()
  124. local    aButtons :=                        ;
  125. { {10, 5, 40, 20, LoadBitmap( ,IDB_NEW), IDM_FILENEW},        ;
  126.   {60, 5, 40, 20, LoadBitmap( ,IDB_CASCADE), IDM_WINDOWCASCADE},;
  127.   {110, 5, 40, 20, LoadBitmap( ,IDB_TILE), IDM_WINDOWTILE},    ;
  128.   {160, 5, 40, 20, LoadBitmap( ,IDB_CLOSE), IDM_WINDOWCLOSEALL},;
  129.   {210, 5, 40, 20, LoadBitmap( ,IDB_EXIT), IDM_FILEEXIT} }
  130. local    aRect
  131.  
  132. //
  133. // create the frame 
  134. //
  135. // Note: As with all calls to CreateWindow(), before it returns
  136. //     Windows calls the WndProc that was registered for the
  137. //     window class.  It is called twice at least, with WM_NCCREATE
  138. //     and WM_CREATE.  The MDI client window is created during
  139. //     the WM_CREATE message.  Then, the 1st MDI child is created
  140. //     below.
  141. //
  142. hWndFrame = CreateWindow(cFrame,    ; // window class
  143.              cFTitle,    ; // caption for title bar
  144.              WS_OVERLAPPEDWINDOW + WS_CLIPCHILDREN,    ; // window style
  145.              CW_USEDEFAULT,    ; // x co-ordinate
  146.              CW_USEDEFAULT,    ; // y co-ordinate
  147.              0,        ; // width
  148.              0,        ; // height
  149.              0,        ; // hWnd of parent (none)
  150.              ,        ; // hMenu of menu (use class menu)
  151.              hInst)          // our own app instance
  152.  
  153. // See the above Note: hWndMDIClient should now be valid
  154.  
  155. if hWndFrame != 0 .and. hWndMDIClient != 0
  156.  
  157.     /*
  158.      *  This sample puts the toolbar at the top of the frame window's
  159.      *  client area.  The user doesn't know the "mdiclient" exists,
  160.      *  so just make it fill the area not used by the toolbar.  Of
  161.      *  course, this means changing its size if the main window changes
  162.      *  size (msg WM_SIZE).  The toolbar size needs to change as well
  163.      *  (just the width in this example).
  164.      *
  165.      *  This same technique can be useful at other times, e.g. the child
  166.      *  might be a multi-line edit control.
  167.      *
  168.      *  If you have a status bar, the easiest way to handle it is to
  169.      *  make it another window (with no special border, no title bar,
  170.      *  etc., and using WS_CHILD + WS_VISIBLE), put it at the bottom
  171.      *  of the frame window, and reduce the mdiclient's window height
  172.      *  by the height of the status bar.  You could give any of the MDI
  173.      *  child windows their own status bar in the same sort of way.
  174.      *  (Yes, you do get a lot of windows.  Don't worry about them.)
  175.      */
  176.  
  177.     aRect = GetClientRect(hWndFrame)
  178.     hTBWnd = ToolBar(hWndFrame, 0, 0, aRect[3], TB_HEIGHT, aButtons, ID_TOOLBAR)
  179. //    lToolBar = .t.
  180.  
  181.     // make sure the frame's displayed ...
  182.     ShowWindow(hWndFrame, _GetnCmdShow())
  183.     // ... and up to date
  184.     UpdateWindow(hWndFrame)
  185.  
  186.     ShowWindow(hWndMDIClient, SW_SHOW)
  187.  
  188. #ifdef AUTO_FIRST_CHILD
  189.     // create the 1st MDI child window 
  190.     MDICreateWindow(cChild,        ; // window class
  191.             "MDI Child #1",    ; // caption for title bar
  192.             DEFMDICHILDSTYLE, ; // window style
  193.             CW_USEDEFAULT,    ; // x co-ordinate
  194.             CW_USEDEFAULT,    ; // y co-ordinate
  195.             0,        ; // width
  196.             0,        ; // height
  197.             ,        ; // reserved
  198.             ,        ; // reserved
  199.             hInst,        ; // our own app instance
  200.             )          // cParam (optional parameter)
  201. #endif // AUTO_FIRST_CHILD
  202.  
  203.     return .t.
  204. endif
  205.  
  206. MessageBox(, "Window Creation Failed!", "Error", MB_ICONEXCLAMATION + MB_OK)
  207.  
  208. return .f.
  209.  
  210.  
  211.  
  212. static function FrameWndProc(hWnd, nMsg, nwParam, nlParam)
  213. local    aCcs[CCS_LENGTH]    // Windows CLIENTCREATESTRUCT structure
  214. local    nW, nH
  215.  
  216. do case
  217. case nMsg == WM_CREATE
  218.  
  219.     // set window menu where children are listed 
  220.     aCcs[CCS_hWindowMenu]  = GetSubMenu(GetMenu(hWnd), WINDOWMENUPOS)
  221.     // set id of 1st child
  222.     aCcs[CCS_idFirstChild] = IDM_WINDOWCHILD
  223.  
  224.     // Create the MDI client 
  225.     hWndMDIClient = CreateWindow("mdiclient", ; // window class
  226.                      "",    ;   // caption for title bar
  227.                      WS_CHILD + WS_CLIPCHILDREN, ; // window style
  228.                      0,        ; // x co-ordinate
  229.                      0,        ; // y co-ordinate
  230.                      0,        ; // width
  231.                      0,        ; // height
  232.                      hWnd,    ; // hWnd of parent
  233.                      ,        ; // hMenu of menu (none)
  234.                      hInst,    ; // our own app instance
  235.                      a2bin(aCcs, CCS_STRUCT_DEF))
  236.  
  237. //    ShowWindow(hWndMDIClient, SW_SHOW)    // seems not needed
  238.  
  239. case nMsg == WM_COMMAND
  240.     // menu selection or accelerator commands come here
  241.     DoCommand(hWnd, nwParam)
  242.  
  243. case nMsg == WM_SIZE .and. lToolBar
  244.     if nwParam == SIZE_RESTORED .or. nwParam == SIZE_MAXIMIZED
  245.         nW = C4W_LoWord(nlParam)
  246.         nH = C4W_HiWord(nlParam)
  247.         // put toolbar at top of frame's client area, then mdi client
  248.         if IsWindow(hTBWnd)    // this should be true
  249.             MoveWindow(hTBWnd, 0, 0, nW, TB_HEIGHT, .t.)
  250.         endif
  251.         if IsWindow(hWndMDIClient)
  252.             MoveWindow(hWndMDIClient, 0, TB_HEIGHT, nW, nH - TB_HEIGHT, .t.)
  253.         endif
  254.     endif
  255.  
  256. case nMsg == WM_CLOSE
  257.     DestroyWindow(hWnd)
  258.  
  259. case nMsg == WM_DESTROY
  260.     PostQuitMessage(0)
  261.  
  262. otherwise
  263.     // Note: do *NOT* use DefWindowProc()
  264.     return DefFrameProc(hWnd, hWndMDIClient, nMsg, nwParam, nlParam)
  265. endcase
  266.  
  267. return 0
  268.  
  269.  
  270. static function MDIChildWndProc(hWnd, nMsg, nwParam, nlParam)
  271.  
  272. // In this demo, just pass everything along to the default handler.
  273. // NOTE: If you handle any of WM_CHILDACTIVATE, WM_GETMINMAXINFO,
  274. //     WM_MENUCHAR, WM_MOVE, WM_NEXTMENU, WM_SETFOCUS, WM_SIZE,
  275. //     or WM_SYSCOMMAND these are needed by MDI as weel, so still
  276. //     pass them to DefMDIChildProc().
  277.  
  278. return DefMDIChildProc(hWnd, nMsg, nwParam, nlParam)
  279.  
  280.  
  281.  
  282. procedure DoCommand(hWnd, nwParam)
  283.  
  284. do case
  285. case nwParam == IDM_FILENEW
  286.     // Make an empty MDI child window 
  287.     MDICreateWindow(cChild,        ; // window class
  288.             "MDI Child from File/New", ; // caption for title bar
  289.             DEFMDICHILDSTYLE, ; // window style
  290.             CW_USEDEFAULT,    ; // x co-ordinate
  291.             CW_USEDEFAULT,    ; // y co-ordinate
  292.             0,        ; // width
  293.             0,        ; // height
  294.             ,        ; // reserved
  295.             ,        ; // reserved
  296.             hInst,        ; // our own app instance
  297.             )          // cParam (optional parameter)
  298.  
  299. case nwParam == IDM_FILEEXIT
  300.     SendMessage(hWnd, WM_CLOSE, 0, 0)  // close down
  301.  
  302. case nwParam == IDM_WINDOWTILE
  303.     SendMessage(hWndMDIClient, WM_MDITILE, 0, 0)
  304.  
  305. case nwParam == IDM_WINDOWCASCADE
  306.     SendMessage(hWndMDIClient, WM_MDICASCADE, 0, 0)
  307.  
  308. case nwParam == IDM_WINDOWICONS        // auto-arrange icons
  309.     SendMessage(hWndMDIClient, WM_MDIICONARRANGE, 0, 0)
  310.  
  311. case nwParam == IDM_WINDOWCLOSEALL
  312.     CloseAllChildren()
  313.  
  314. otherwise
  315.     // This is essential, since there are frame WM_COMMANDS generated
  316.     // by the MDI system for activating child windows via the
  317.     // menu item "Window".
  318.     DefFrameProc(hWnd, hWndMDIClient, WM_COMMAND, nwParam, 0)
  319. endcase
  320. return
  321.  
  322.  
  323.  
  324. static procedure CloseAllChildren()
  325. local    hWnd
  326.  
  327. // find and destroy the MDI children
  328. do while (hWnd := GetWindow(hWndMDIClient, GW_CHILD)) != 0
  329.     // skip the icon title windows 
  330.     do while hWnd != 0 .and. GetWindow(hWnd, GW_OWNER) != 0
  331.         hWnd = GetWindow(hWnd, GW_HWNDNEXT)
  332.     enddo
  333.     if hWnd == 0
  334.         exit
  335.     endif
  336.     SendMessage(hWndMDIClient, WM_MDIDESTROY, hWnd, 0)
  337. enddo
  338.  
  339. return
  340.  
  341.  
  342.  
  343. ////////////////////////////
  344. //
  345. //  Here's how to call some underlying Windows menu functions
  346. //
  347. /////////////////////////////
  348.  
  349.  
  350. // for MDI want to use Windows functions for menus
  351. // (instead of the convenient Clip-4-Win functions, with their code blocks)
  352.  
  353. static function GetMenu(hWnd)
  354. static    cGM
  355. if cGM == nil
  356.     cGM = GetProcAddress( , "GetMenu", "Pascal", ;    // actually in USER.EXE
  357.                  "int", "int")
  358. endif
  359. return CallDLL(cGM, hWnd)
  360.  
  361.  
  362. static function GetSubMenu(hMenu, nPos)
  363. static    cGSM
  364. if cGSM == nil
  365.     cGSM = GetProcAddress( , "GetSubMenu", "Pascal", ; // in USER.EXE
  366.                   "int", "int,int")
  367. endif
  368. return CallDLL(cGSM, hMenu, nPos)
  369.  
  370.  
  371. static function GetMenuString(hMenu, nId, nFlags)
  372. static    cGMS
  373. local    i, buf := space(80)    // plenty long enough
  374. if cGMS == nil
  375.     cGMS = GetProcAddress( , "GetMenuString", "Pascal", ;  // in USER.EXE
  376.                   "int", "int,uint,str,int,uint")
  377. endif
  378. if nFlags == nil
  379.     nFlags = MF_BYCOMMAND
  380. endif
  381. i = CallDLL(cGMS, hMenu, nId, @buf, len(buf), nFlags)
  382. return left(buf, i)
  383.  
  384.  
  385. ////////////////////////////
  386. //
  387. //    NOTE:
  388. //
  389. //    This is provided as source in case you are interested.
  390. //
  391. //    Please don't ask questions about it!
  392. //
  393. //    If you alter it, you're on your own!!
  394. //
  395. /////////////////////////////
  396.  
  397.  
  398. static function MDICreateWindow(cClass,    ; // window class
  399.                 cTitle, ; // caption for title bar
  400.                 nStyle,    ; // window style
  401.                 nX, nY,    ; // x,y pos
  402.                 nW, nH,    ; // width, height
  403.                 hWndP,    ; // reserved
  404.                 hMenu,    ; // reserved
  405.                 hInst,    ; // our own app instance
  406.                 cParam)      // optional params
  407. local    hWnd
  408. local    aMcs[MCS_LENGTH]        // Windows MDICREATESTRUCT structure
  409. local    hMem1, hMem2, hMem3, cMcs
  410.  
  411. if cTitle == nil
  412.     cTitle = "Untitled"
  413. endif
  414. if nStyle == nil
  415.     nStyle = 0
  416. endif
  417. if nX == nil
  418.     nX = CW_USEDEFAULT
  419. endif
  420. if nY == nil
  421.     nY = CW_USEDEFAULT
  422. endif
  423. if nW == nil
  424.     nW = 0
  425. endif
  426. if nH == nil
  427.     nH = 0
  428. endif
  429. if hInst == nil
  430.     hInst = _GetInstance()
  431. endif
  432.  
  433. //aMcs[MCS_szClass] = cClass
  434. //aMcs[MCS_szTitle] = cTitle
  435. aMcs[MCS_hOwner]  = hInst
  436. aMcs[MCS_x]      = nX
  437. aMcs[MCS_y]      = nY
  438. aMcs[MCS_cx]      = nW
  439. aMcs[MCS_cy]      = nH
  440. aMcs[MCS_style]      = nStyle
  441. //aMcs[MCS_lParam]  = cParam
  442.  
  443. // convert to a C structure stored in a Clipper string
  444. #define    GMEM_MOVEABLE    2
  445. cClass += chr(0)            // null-terminate
  446. hMem1 = GlobalAlloc(GMEM_MOVEABLE, len(cClass))
  447. GlobalData(hMem1, cClass)
  448. aMcs[MCS_szClass] = GlobalLock(hMem1)
  449. cTitle += chr(0)            // null-terminate
  450. hMem2 = GlobalAlloc(GMEM_MOVEABLE, len(cTitle))
  451. GlobalData(hMem2, cTitle)
  452. aMcs[MCS_szTitle] = GlobalLock(hMem2)
  453. if cParam == nil
  454.     aMcs[MCS_lParam] = 0
  455. else
  456.     // null-terminate (just in case it's a string)
  457.     cParam += chr(0)
  458.     hMem3 = GlobalAlloc(GMEM_MOVEABLE, len(cParam))
  459.     GlobalData(hMem3, cParam)
  460.     aMcs[MCS_lParam] = GlobalLock(hMem3)
  461. endif
  462.  
  463. //cMcs = a2bin(aMcs, MCS_STRUCT_DEF)
  464. cMcs = a2bin(aMcs, "long[2],int[5],dword,long")     // treat C ptrs as longs
  465.  
  466. // ask the MDI client to create the child 
  467. hWnd = SendMessage(hWndMDIClient, WM_MDICREATE, 0, cMcs)
  468.  
  469. GlobalUnlock(hMem1)
  470. GlobalFree(hMem1)
  471. GlobalUnlock(hMem2)
  472. GlobalFree(hMem2)
  473. if hMem3 != nil
  474.     GlobalUnlock(hMem3)
  475.     GlobalFree(hMem3)
  476. endif
  477.  
  478. ShowWindow(hWnd, SW_SHOW)
  479.  
  480. return hWnd
  481.