home *** CD-ROM | disk | FTP | other *** search
/ BUG 4 / BUGCD1997_05.BIN / aplic / clip4win / clip4win.exe / C4W30E.HUF / SOURCE / DIALOG.PRG < prev    next >
Text File  |  1995-07-04  |  65KB  |  2,035 lines

  1. ////////////////////////////
  2. //
  3. //    Clip-4-Win dialog demo
  4. //
  5. //    Copyright (C) 1993 Skelton Software, Kendal Cottage, Hillam, Leeds, UK.
  6. //    All Rights Reserved.
  7. //
  8. //    Shows modal and modeless dialogs, both dynamic dialogs and
  9. //    using dialog resources.
  10. //
  11. //    Also, how to get a dialog from a DLL.  In this case, it is a
  12. //    resource-only DLL, but the same technique applies to any DLL.
  13. //    (See BigDialog(), below.)  See the clip4win\dll directory for
  14. //    information about creating a resource-only DLL, and an empty
  15. //    DLL you can copy and use.
  16. //
  17. //    Compile and link:    rmake dialog
  18. //
  19. //    NOTE: Some people have whether they can distribute CTL3D.DLL
  20. //          with their apps.  Yes.  Say thanks to Microsoft.  They
  21. //          want you to use it because it provides the sort of
  22. //          appearance that's going to be standard in future versions
  23. //          of Windows.
  24. //
  25. //    There are some lengthy comments further on about validating input.
  26. //
  27. //    Data-driven: can be done using dynamic dialogs (obviously),
  28. //             but also using a resource dialog which has just some
  29. //             of the fields you will need.  Then, during the
  30. //             WM_INITDIALOG, make the rest of the dialog
  31. //             using CreateWindow() and the hWndDlg as the parent
  32. //             window.  If you wish, you can change the details of
  33. //             some existing controls using e.g. SetWindowText().
  34. //             This is useful with static text and other controls.
  35. //
  36. //    NOTE: To understand the usage of the dialog resources, you
  37. //    need to look closely at the DIALOG.RC file.  It defines
  38. //    three dialogs (called "dlg", "dlg2" and sample3d), containing
  39. //    various controls.  The file is as follows:
  40. /*
  41.  
  42. #define WIN_WANT_CB
  43. #define WIN_WANT_LBS
  44. #include "windows.ch"
  45. #include "dlog.ch"
  46.  
  47. dlg DIALOG 6, 18, 160, 100
  48. STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
  49. CAPTION "Main Dialog"
  50. FONT 8, "MS Sans Serif"
  51. BEGIN
  52.     EDITTEXT        IDD_EDIT, 9, 15, 32, 12, ES_AUTOHSCROLL
  53.     PUSHBUTTON      "&Ok", IDOK, 92, 44, 40, 14
  54.     PUSHBUTTON      "&Cancel", IDCANCEL, 93, 72, 40, 14
  55.     PUSHBUTTON      "&Push", IDD_PUSH, 91, 12, 40, 14
  56.     GROUPBOX        "Group", IDD_GROUP, 6, 36, 54, 54, WS_GROUP
  57.     CONTROL         "&A", IDD_A, "Button", BS_AUTORADIOBUTTON, 11, 50, 39, 10
  58.     CONTROL         "&B", IDD_B, "Button", BS_AUTORADIOBUTTON, 12, 70, 39, 10
  59. END
  60.  
  61. dlg2 DIALOG 200, 18, 160, 100
  62. STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
  63. CAPTION "Dialog #2"
  64. FONT 12, "MS Sans Serif"
  65. BEGIN
  66.     CONTROL         "Check", IDD_CHECK, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 5, 
  67.                     87, 40, 10
  68.     LTEXT           "Text", IDD_TEXT, 71, 68, 55, 16
  69.     EDITTEXT        IDD_EDIT2, 4, 26, 32, 12, ES_AUTOHSCROLL
  70.     PUSHBUTTON      "&OK", IDD_OK, 59, 22, 40, 14
  71. END
  72.  
  73. dlguser DIALOG 20, 20, 183, 127
  74. STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
  75. CAPTION "User Details"
  76. FONT 10, "MS Sans Serif"
  77. BEGIN
  78.     PUSHBUTTON      "&Ok", IDOK, 132, 13, 37, 12
  79.     PUSHBUTTON      "&Cancel", IDCANCEL, 132, 37, 37, 12
  80.     PUSHBUTTON      "&Next", IDD_NEXT, 132, 61, 37, 12
  81.     PUSHBUTTON      "&Previous", IDD_PREV, 132, 85, 37, 12
  82.     PUSHBUTTON      "&Save", IDD_SAVE, 132, 109, 37, 12
  83.     LTEXT           "User ID:", IDD_TUSERID, 7, 2, 50, 8
  84.     EDITTEXT        IDD_USERID, 7, 13, 115, 13, ES_AUTOHSCROLL
  85.     LTEXT           "User Name:", IDD_TUSERNAME, 7, 28, 50, 8
  86.     EDITTEXT        IDD_USERNAME, 7, 37, 115, 13, ES_AUTOHSCROLL
  87.     LTEXT           "Department:", IDD_TDEPT, 7, 52, 50, 8
  88.     EDITTEXT        IDD_DEPT, 7, 61, 115, 13, ES_AUTOHSCROLL
  89.     LTEXT           "Phone:", IDD_TPHONE, 7, 76, 50, 8
  90.     EDITTEXT        IDD_PHONE, 7, 85, 115, 13, ES_AUTOHSCROLL
  91.     LTEXT           "Extension:", IDD_T_EXT, 7, 100, 50, 8
  92.     EDITTEXT        IDD_EXT, 7, 109, 115, 13, ES_AUTOHSCROLL
  93. END
  94.  
  95.  
  96. sample3d DIALOG 0, 0, 327, 195 
  97. STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION
  98. CAPTION "CTL3D Samples"
  99. FONT 8, "Helv"
  100. BEGIN
  101.     DEFPUSHBUTTON   "&OK", IDOK, 261, 174, 56, 16
  102.     PUSHBUTTON      "&Message Box", 130, 261, 129, 56, 16
  103.     PUSHBUTTON      "&File Open", 131, 261, 151, 56, 16
  104.     EDITTEXT        101, 9, 17, 72, 12, ES_AUTOHSCROLL
  105.     EDITTEXT        102, 89, 17, 72, 31, ES_MULTILINE | ES_AUTOVSCROLL | 
  106.                     ES_AUTOHSCROLL | WS_VSCROLL | WS_HSCROLL
  107.     COMBOBOX        105, 15, 80, 72, 35, CBS_SIMPLE | CBS_SORT | WS_VSCROLL |
  108.                     WS_TABSTOP
  109.     COMBOBOX        106, 119, 80, 72, 35, CBS_DROPDOWN | CBS_SORT |
  110.                     WS_VSCROLL | WS_TABSTOP
  111.     LISTBOX         107, 15, 139, 72, 43, LBS_SORT | LBS_DISABLENOSCROLL |
  112.                     WS_VSCROLL | WS_HSCROLL | WS_TABSTOP
  113.     CONTROL         "", 108, "Static", SS_BLACKFRAME, 121, 167, 37, 16
  114.     COMBOBOX        109, 219, 80, 72, 35, CBS_DROPDOWNLIST | CBS_SORT |
  115.                     WS_VSCROLL | WS_TABSTOP
  116.     CONTROL         "", 110, "Static", SS_BLACKRECT, 121, 139, 36, 16
  117.     CONTROL         "Check", 112, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 
  118.                     186, 15, 40, 10
  119.     CONTROL         "Check", 113, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 
  120.                     186, 25, 40, 10
  121.     CONTROL         "Check", 114, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 
  122.                     186, 35, 40, 10
  123.     CONTROL         "Radio", 115, "Button", BS_AUTORADIOBUTTON, 252, 15, 39, 
  124.                     10
  125.     CONTROL         "Radio", 116, "Button", BS_AUTORADIOBUTTON, 252, 25, 39, 
  126.                     10
  127.     CONTROL         "Radio", 117, "Button", BS_AUTORADIOBUTTON, 252, 35, 39, 
  128.                     10
  129.     GROUPBOX        "Check / Radio Buttons", 121, 175, 3, 140, 52
  130.     GROUPBOX        "Edit Controls", 103, 4, 3, 165, 52
  131.     LTEXT           "Simple", 104, 13, 70, 72, 8
  132.     LTEXT           "Drop Down", 122, 118, 70, 72, 8
  133.     LTEXT           "Drop Down List", 123, 218, 70, 72, 8
  134.     GROUPBOX        "Combo Boxes", 124, 3, 60, 313, 58
  135.     GROUPBOX        "List Box", 125, 3, 124, 98, 65
  136.     CONTROL         "", 111, "Static", SS_GRAYRECT, 166, 139, 36, 16
  137.     CONTROL         "", 118, "Static", SS_WHITERECT, 210, 139, 36, 16
  138.     CONTROL         "", 119, "Static", SS_WHITEFRAME, 210, 167, 37, 16
  139.     CONTROL         "", 120, "Static", SS_GRAYFRAME, 166, 167, 37, 16
  140.     GROUPBOX        "Static Frames and Rects", 126, 110, 125, 139, 65
  141.     LTEXT           "Black", 127, 130, 157, 20, 8
  142.     LTEXT           "Gray", 128, 173, 157, 20, 8
  143.     LTEXT           "White", 129, 214, 157, 25, 8
  144. END
  145.  
  146. */
  147. //
  148. ////////////////////////////
  149.  
  150. #define    WIN_WANT_ALL
  151. #define    WIN_WANT_EN
  152. #define    WIN_WANT_LBS
  153. #define    WIN_WANT_CLIPBOARD
  154. #define    WIN_WANT_CTL_CODES
  155. #define    WIN_WANT_GETDEVCAPS
  156. #include "windows.ch"
  157. #include "font.ch"
  158. #include "dialog.ch"
  159. //#define    SAY_IN_WINDOW
  160. //#include "say.ch"
  161. #include "dlog.ch"
  162.  
  163.  
  164. //////////
  165. //
  166. //  Try defining this to see a trace of the messages sent during the
  167. //  life of a dialog (it's less intrusive than MessageBox):
  168. //
  169. //////////
  170.  
  171. //#define SEE_MESSAGES            // can be interesting
  172.  
  173.  
  174.  
  175. #define    CR    chr(13)
  176.  
  177.  
  178. static    cAppName := "C4WDialogs"
  179. static    hWnd
  180. static    cText := ""
  181. static    cFontName := "MS Sans Serif"
  182. static    nPointSize := 8
  183. static    hLibCtl3d
  184.  
  185. #ifdef SEE_MESSAGES
  186. static    aDlg := {}
  187. static    hDlg
  188. static    aDlog := {}
  189. static    aEdit := {}
  190. #endif // SEE_MESSAGES
  191.  
  192.  
  193. function main()
  194. local    hMenu, nEvent
  195.  
  196. set scoreboard off
  197. set confirm on
  198. SetColor("n/w,+w/n,+w,+w,+w/n")
  199. hWnd = WinSetup(cAppName, "Clip-4-Win Dialog Demo")
  200. hMenu = MenuSetup()
  201. Ctl3d(.t.)            // default to 3D controls
  202. HideCaret(hWnd)
  203. AddHandler(hWnd, {|nEvent| MainEvent(nEvent)})
  204. #ifdef SEE_MESSAGES
  205. MessageBox( , "Compiled with SEE_MESSAGES", cAppName)
  206. #else
  207. MessageBox( , "Compiled without SEE_MESSAGES", cAppName)
  208. #endif // SEE_MESSAGES
  209.  
  210. do while .t.
  211.    do while (nEvent := ChkEvent()) == EVENT_NONE
  212.    enddo
  213.    HandleEvent(nEvent)
  214.    if nEvent == EVENT_QUIT
  215.     DoExit()
  216.    endif
  217. enddo
  218. return nil
  219.  
  220.  
  221.  
  222. procedure MainEvent(nEvent)
  223. #ifdef SEE_MESSAGES
  224. local    i, a := array(10)
  225. if nEvent == EVENT_RCLICK
  226.     MessageBox( , asString(cText), "cText")
  227.     MessageBox( , asString(IsWindow(hDlg)), "IsWindow(hDlg)")
  228.     MessageBox( , asString(len(aDlg)), "len(aDlg)")
  229.     MessageBox( , asString(atail(aDlg)), "atail(aDlg)")
  230.     if len(aDlg) > len(a)
  231.         // just show the last few msgs
  232.         for i = 1 to len(a)
  233.             a[i] = aDlg[len(aDlg) - len(a) + i]
  234.         next i
  235.     else
  236.         a = aDlg
  237.     endif
  238.     MessageBox( , asString(a), "a")
  239. endif
  240. #endif // SEE_MESSAGES
  241. return
  242.  
  243.  
  244. procedure DoAbout()
  245. MessageBox( , "Demo written by John Skelton", "About", ;
  246.            MB_ICONEXCLAMATION + MB_OK)
  247. return
  248.  
  249.  
  250. static procedure DoFont()
  251. local    aFont[14], nPt, hDC := GetDC(hWnd)
  252. aFont[LF_FaceName] = cFontName
  253. // the following scales the font from point size to screen size:
  254. aFont[LF_Height] = - GetDeviceCaps(hDC, LOGPIXELSY) * nPointSize / 72
  255. ReleaseDC(hWnd, hDC)
  256. if ChooseFont(aFont, @nPt) != nil
  257.     cFontName = aFont[LF_FaceName]
  258.     // the returned value is in tenths of a point
  259.     nPointSize = nPt / 10
  260. endif
  261. return
  262.  
  263.  
  264. procedure DoExit(c)
  265. MessageBox(0, "Thanks for running this Clip-4-Win demo!", "Exiting", ;
  266.        MB_ICONHAND + MB_OK)
  267. Ctl3d(.f.)            // stop using 3D controls
  268. if IsWindow(hWnd)
  269.     DestroyWindow(hWnd)
  270. endif
  271. UnregisterClass(cAppName)
  272. quit
  273. return
  274.  
  275.  
  276.  
  277. function DynModal()
  278. local    aDlg, cText := "Some text"
  279. aDlg = CreateDialog("DynModal",                        ;
  280.             DS_MODALFRAME + WS_POPUP + WS_VISIBLE + WS_CAPTION    ;
  281.             + WS_SYSMENU,                    ;
  282.             6, 18, 160, 100,                    ;
  283.             nPointSize, cFontName)
  284. aDlg = AppendDialog(aDlg, "edit", DLG_EDIT,                ;
  285.             ES_AUTOHSCROLL + WS_BORDER                ;
  286.             + WS_TABSTOP + WS_CHILD + WS_VISIBLE,        ;
  287.             9, 15, 32, 12,                    ;
  288.             cText,                        ;
  289.             {|hDlg, nMsg, nwParam, nlParam|            ;
  290.              DynEdit(hDlg, nMsg, nwParam, nlParam)})
  291. aDlg = AppendDialog(aDlg, "ok", DLG_BUTTON,                ;
  292.             BS_DEFPUSHBUTTON + WS_TABSTOP + WS_CHILD + WS_VISIBLE,;
  293.             92, 44, 40, 14,                    ;
  294.             "&Ok")
  295. aDlg = AppendDialog(aDlg, "cancel", DLG_BUTTON,                ;
  296.             BS_PUSHBUTTON + WS_TABSTOP + WS_CHILD + WS_VISIBLE,    ;
  297.             93, 72, 40, 14,                    ;
  298.             "&Cancel",                        ;
  299.             {|hDlg, nMsg, nwParam, nlParam|            ;
  300.              DynCancel(hDlg, nMsg, nwParam, nlParam)})
  301. aDlg = AppendDialog(aDlg, "push", DLG_BUTTON,                ;
  302.             BS_PUSHBUTTON + WS_TABSTOP + WS_CHILD + WS_VISIBLE,    ;
  303.             91, 12, 40, 14,                    ;
  304.             "&Push",                        ;
  305.             {|hDlg, nMsg, nwParam, nlParam|            ;
  306.              DynPush(hDlg, nMsg, nwParam, nlParam)})
  307. aDlg = AppendDialog(aDlg, "group", DLG_BUTTON,                ;
  308.             BS_GROUPBOX + WS_GROUP + WS_CHILD + WS_VISIBLE,    ;
  309.             6, 36, 54, 54,                    ;
  310.             "Group")
  311. aDlg = AppendDialog(aDlg, "radioa", DLG_BUTTON,                ;
  312.             BS_AUTORADIOBUTTON                    ;
  313.             + WS_CHILD + WS_VISIBLE,                ;
  314.             11, 50, 39, 10,                    ;
  315.             "&A")
  316. aDlg = AppendDialog(aDlg, "radiob", DLG_BUTTON,                ;
  317.             BS_AUTORADIOBUTTON + WS_CHILD + WS_VISIBLE,        ;
  318.             12, 70, 39, 10,                    ;
  319.             "&B")
  320.  
  321. if ModalDialog(aDlg, , hWnd) = 0 .or. GetDialogResult(aDlg, "cancel") = .T.
  322.     cText = "<cancelled>"
  323. else
  324.     cText = GetDialogResult(aDlg, "edit")
  325. endif
  326. MessageBox( , asString(cText), "Edit Control result")
  327. return nil
  328.  
  329.  
  330.  
  331. // This demonstrates using numeric id's _and_ a code block with ModalDialog().
  332. // NOTE:  You must do _both_ at the same time.
  333. // ALSO:  You can't use code blocks with individual controls as well.
  334.  
  335. function DynModalGet()
  336. local    i, aDlg
  337. local    nVar            // used by DIALOG GET in DynDlgModal()
  338. aDlg = CreateDialog("DynModalGet",                    ;
  339.             DS_MODALFRAME + WS_POPUP + WS_VISIBLE + WS_CAPTION    ;
  340.             + WS_SYSMENU,                    ;
  341.             6, 18, 160, 100,                    ;
  342.             nPointSize, cFontName)
  343. aDlg = AppendDialog(aDlg, IDD_EDIT, DLG_EDIT,                ;
  344.             ES_AUTOHSCROLL + WS_BORDER                ;
  345.             + WS_TABSTOP + WS_CHILD + WS_VISIBLE,        ;
  346.             9, 15, 32, 12,                    ;
  347.             cText)
  348. aDlg = AppendDialog(aDlg, IDOK, DLG_BUTTON,                ;
  349.             BS_DEFPUSHBUTTON + WS_TABSTOP + WS_CHILD + WS_VISIBLE,;
  350.             92, 44, 40, 14,                    ;
  351.             "&Ok")
  352. aDlg = AppendDialog(aDlg, IDCANCEL, DLG_BUTTON,                ;
  353.             BS_PUSHBUTTON + WS_TABSTOP + WS_CHILD + WS_VISIBLE,    ;
  354.             93, 72, 40, 14,                    ;
  355.             "&Cancel")
  356. aDlg = AppendDialog(aDlg, IDD_PUSH, DLG_BUTTON,                ;
  357.             BS_PUSHBUTTON + WS_TABSTOP + WS_CHILD + WS_VISIBLE,    ;
  358.             91, 12, 40, 14,                    ;
  359.             "&Push")
  360. aDlg = AppendDialog(aDlg, IDD_GROUP, DLG_BUTTON,                ;
  361.             BS_GROUPBOX + WS_GROUP + WS_CHILD + WS_VISIBLE,    ;
  362.             6, 36, 54, 54,                    ;
  363.             "Group")
  364. aDlg = AppendDialog(aDlg, IDD_A, DLG_BUTTON,                ;
  365.             BS_AUTORADIOBUTTON                    ;
  366.             + WS_CHILD + WS_VISIBLE,                ;
  367.             11, 50, 39, 10,                    ;
  368.             "&A")
  369. aDlg = AppendDialog(aDlg, IDD_B, DLG_BUTTON,                ;
  370.             BS_AUTORADIOBUTTON + WS_CHILD + WS_VISIBLE,        ;
  371.             12, 70, 39, 10,                    ;
  372.             "&B")
  373.  
  374. i = ModalDialog(aDlg, , hWnd,                ;
  375.         {|hDlg, msg, wparam, lparam|        ;
  376.          DynDlgModal(hDlg, msg, wparam, lparam, @nVar)})
  377. if i == 0    // .or. GetDialogResult(aDlg, IDCANCEL) = .T.
  378.     cText = "<cancelled>"
  379. else
  380.     // NOT this (will be NIL): cText = GetDialogResult(aDlg, IDD_EDIT)
  381.     MessageBox( , asString(nVar), "Dialog GET result (nVar)")
  382. endif
  383. MessageBox( , asString(cText), "Edit Control result")
  384. return nil
  385.  
  386.  
  387.  
  388. // This demonstrates using numeric id's _and_ a code block with ModalDialog().
  389. // NOTE:  You must do _both_ at the same time.
  390. // ALSO:  You can't use code blocks with individual controls as well.
  391. //
  392. // This is the dynamic version of UserModal() below.
  393.  
  394. function DynUserModal()
  395. local    i, aDlg
  396.  
  397. // This demonstrates stepping through a DBF file.  It doesn't
  398. // return anything much, but if you wanted just to have a
  399. // dialog for a single set of values (and return any alterations),
  400. // pass them by reference (i.e. @cVar) in the code block below,
  401. // (_after_ lparam makes most sense).
  402.  
  403. aDlg = CreateDialog("User Details (Dynamic)",                ;
  404.             DS_MODALFRAME + WS_POPUP + WS_VISIBLE + WS_CAPTION    ;
  405.             + WS_SYSMENU,                    ;
  406.             20, 20, 183, 127,                    ;
  407.             nPointSize, cFontName)
  408. aDlg = AppendDialog(aDlg, IDOK, DLG_BUTTON,                ;
  409.             BS_PUSHBUTTON + WS_TABSTOP + WS_CHILD + WS_VISIBLE, ;
  410.             132, 13, 37, 12,                    ;
  411.             "&Ok")
  412. aDlg = AppendDialog(aDlg, IDCANCEL, DLG_BUTTON,                ;
  413.             BS_PUSHBUTTON + WS_TABSTOP + WS_CHILD + WS_VISIBLE,    ;
  414.             132, 37, 37, 12,                    ;
  415.             "&Cancel")
  416. aDlg = AppendDialog(aDlg, IDD_NEXT, DLG_BUTTON,                ;
  417.             BS_PUSHBUTTON + WS_TABSTOP + WS_CHILD + WS_VISIBLE,    ;
  418.             132, 61, 37, 12,                    ;
  419.             "&Next")
  420. aDlg = AppendDialog(aDlg, IDD_PREV, DLG_BUTTON,                ;
  421.             BS_PUSHBUTTON + WS_TABSTOP + WS_CHILD + WS_VISIBLE,    ;
  422.             132, 85, 37, 12,                    ;
  423.             "&Previous")
  424. aDlg = AppendDialog(aDlg, IDD_SAVE, DLG_BUTTON,                ;
  425.             BS_PUSHBUTTON + WS_TABSTOP + WS_CHILD + WS_VISIBLE,    ;
  426.             132, 109, 37, 12,                    ;
  427.             "&Save")
  428. aDlg = AppendDialog(aDlg, IDD_TUSERID, DLG_STATIC,            ;
  429.             SS_LEFT + WS_CHILD + WS_VISIBLE,            ;
  430.             7, 2, 50, 8,                    ;
  431.             "User ID:")
  432. aDlg = AppendDialog(aDlg, IDD_USERID, DLG_EDIT,                ;
  433.             ES_AUTOHSCROLL + WS_BORDER                ;
  434.             + WS_TABSTOP + WS_CHILD + WS_VISIBLE,        ;
  435.             7, 13, 115, 13)
  436. aDlg = AppendDialog(aDlg, IDD_TUSERNAME, DLG_STATIC,            ;
  437.             SS_LEFT + WS_CHILD + WS_VISIBLE,            ;
  438.             7, 28, 50, 8,                    ;
  439.             "User Name:")
  440. aDlg = AppendDialog(aDlg, IDD_USERNAME, DLG_EDIT,            ;
  441.             ES_AUTOHSCROLL + WS_BORDER                ;
  442.             + WS_TABSTOP + WS_CHILD + WS_VISIBLE,        ;
  443.             7, 37, 115, 13)
  444. aDlg = AppendDialog(aDlg, IDD_TDEPT, DLG_STATIC,            ;
  445.             SS_LEFT + WS_CHILD + WS_VISIBLE,            ;
  446.             7, 52, 50, 8,                    ;
  447.             "Department:")
  448. aDlg = AppendDialog(aDlg, IDD_DEPT, DLG_EDIT,                ;
  449.             ES_AUTOHSCROLL + WS_BORDER                ;
  450.             + WS_TABSTOP + WS_CHILD + WS_VISIBLE,        ;
  451.             7, 61, 115, 13)
  452. aDlg = AppendDialog(aDlg, IDD_TPHONE, DLG_STATIC,            ;
  453.             SS_LEFT + WS_CHILD + WS_VISIBLE,            ;
  454.             7, 76, 50, 8,                    ;
  455.             "Phone:")
  456. aDlg = AppendDialog(aDlg, IDD_PHONE, DLG_EDIT,                ;
  457.             ES_AUTOHSCROLL + WS_BORDER                ;
  458.             + WS_TABSTOP + WS_CHILD + WS_VISIBLE,        ;
  459.             7, 85, 115, 13)
  460. aDlg = AppendDialog(aDlg, IDD_T_EXT, DLG_STATIC,            ;
  461.             SS_LEFT + WS_CHILD + WS_VISIBLE,            ;
  462.             7, 100, 50, 8,                    ;
  463.             "Extension:")
  464. aDlg = AppendDialog(aDlg, IDD_EXT, DLG_EDIT,                ;
  465.             ES_AUTOHSCROLL + WS_BORDER                ;
  466.             + WS_TABSTOP + WS_CHILD + WS_VISIBLE,        ;
  467.             7, 109, 115, 13)
  468.  
  469. i = ModalDialog(aDlg, , hWnd,                ;
  470.         {|hDlg, msg, wparam, lparam|        ;
  471.          UserDlgModal(hDlg, msg, wparam, lparam)})
  472.  
  473. if i == 0    // .or. GetDialogResult(aDlg, IDCANCEL) = .T.
  474.     MessageBox( , "Results ignored", "Cancel")
  475. endif
  476. return nil
  477.  
  478.  
  479.  
  480. function ResModal()
  481. local    nVar            // used by DIALOG GET in ResDlgModal()
  482. local    i
  483. #ifdef SEE_MESSAGES
  484. aDlg = {}
  485. aDlog := {}
  486. aEdit := {}
  487. #endif // SEE_MESSAGES
  488.  
  489. // This demonstrates getting values for a file-wide static (cText),
  490. // and a local (nVar).  Both could be file-wide statics, or locals,
  491. // or even statics within this function.  If file-wide statics are not
  492. // used, be sure to pass the variables in the parameter list of
  493. // ResDlgModal(), otherwise it won't be able to access them.
  494. //
  495. // In this example, cText is the result of an edit control, and
  496. // nVar is a DIALOG GET.
  497. //
  498. // A more general technique would be to pass an array of values,
  499. // together with valid code blocks, initial values, etc.  That would
  500. // just obscure this code, though.
  501.  
  502. // Note: the dialog id ("dlg" in this example) can be numeric if you prefer.
  503. i = DialogBox( , "dlg", ,                ;
  504.           {|hDlg, msg, wparam, lparam|        ;
  505.            ResDlgModal(hDlg, msg, wparam, lparam, @nVar)})
  506.  
  507. if i == IDCANCEL
  508.     MessageBox( , "Results ignored", "Cancel")
  509. else
  510.     MessageBox( , asString(cText), "Edit Control result")
  511.     MessageBox( , asString(nVar), "Dialog GET result (nVar)")
  512. endif
  513.  
  514. #ifdef SEE_MESSAGES
  515. DumpDlog()
  516. DumpEdit()
  517. #endif // SEE_MESSAGES
  518. return nil
  519.  
  520.  
  521.  
  522. function ResModify()
  523. local    nVar            // used by DIALOG GET in ResDlgModal()
  524. local    i
  525. #ifdef SEE_MESSAGES
  526. aDlg = {}
  527. aDlog := {}
  528. aEdit := {}
  529. #endif // SEE_MESSAGES
  530.  
  531. // Note: the dialog id ("dlg" in this example) can be numeric if you prefer.
  532. i = DialogBox( , "dlg", ,                ;
  533.           {|hDlg, msg, wparam, lparam|        ;
  534.            ResDlgModify(hDlg, msg, wparam, lparam, @nVar)})
  535.  
  536. if i == IDCANCEL
  537.     MessageBox( , "Results ignored", "Cancel")
  538. else
  539.     MessageBox( , asString(cText), "Edit Control result")
  540.     MessageBox( , asString(nVar), "Dialog GET result (nVar)")
  541. endif
  542.  
  543. #ifdef SEE_MESSAGES
  544. DumpDlog()
  545. DumpEdit()
  546. #endif // SEE_MESSAGES
  547. return nil
  548.  
  549.  
  550.  
  551. function UserModal()
  552. local    i
  553.  
  554. // This demonstrates stepping through a DBF file.  It doesn't
  555. // return anything much, but if you wanted just to have a
  556. // dialog for a single set of values (and return any alterations),
  557. // pass them by reference (i.e. @cVar) in the code block below,
  558. // (_after_ lparam makes most sense).
  559.  
  560. i = DialogBox( , "dlguser", ,                ;
  561.           {|hDlg, msg, wparam, lparam|        ;
  562.            UserDlgModal(hDlg, msg, wparam, lparam)})
  563.  
  564. if i == IDCANCEL
  565.     MessageBox( , "Results ignored", "Cancel")
  566. endif
  567.  
  568. return nil
  569.  
  570.  
  571.  
  572. function DynModeless()
  573. local    i, aDlg, cText := "Some text"
  574. aDlg = CreateDialog("DynModeless",                        ;
  575.             DS_MODALFRAME + WS_POPUP + WS_VISIBLE + WS_CAPTION    ;
  576.             + WS_SYSMENU,                    ;
  577.             6, 18, 160, 100,                    ;
  578.             nPointSize, cFontName)
  579. aDlg = AppendDialog(aDlg, "edit", DLG_EDIT,                ;
  580.             ES_AUTOHSCROLL + WS_BORDER                ;
  581.             + WS_TABSTOP + WS_CHILD + WS_VISIBLE,        ;
  582.             9, 15, 32, 12,                    ;
  583.             cText,                        ;
  584.             {|hDlg, nMsg, nwParam, nlParam|            ;
  585.              DynEdit(hDlg, nMsg, nwParam, nlParam)})
  586. aDlg = AppendDialog(aDlg, "ok", DLG_BUTTON,                ;
  587.             BS_DEFPUSHBUTTON + WS_TABSTOP + WS_CHILD + WS_VISIBLE,;
  588.             92, 44, 40, 14,                    ;
  589.             "&Ok")
  590. aDlg = AppendDialog(aDlg, "cancel", DLG_BUTTON,                ;
  591.             BS_PUSHBUTTON + WS_TABSTOP + WS_CHILD + WS_VISIBLE,    ;
  592.             93, 72, 40, 14,                    ;
  593.             "&Cancel",                        ;
  594.             {|hDlg, nMsg, nwParam, nlParam|            ;
  595.              DynCancel(hDlg, nMsg, nwParam, nlParam)})
  596. aDlg = AppendDialog(aDlg, "push", DLG_BUTTON,                ;
  597.             BS_PUSHBUTTON + WS_TABSTOP + WS_CHILD + WS_VISIBLE,    ;
  598.             91, 12, 40, 14,                    ;
  599.             "&Push",                        ;
  600.             {|hDlg, nMsg, nwParam, nlParam|            ;
  601.              DynPush(hDlg, nMsg, nwParam, nlParam)})
  602. aDlg = AppendDialog(aDlg, "group", DLG_BUTTON,                ;
  603.             BS_GROUPBOX + WS_GROUP + WS_CHILD + WS_VISIBLE,    ;
  604.             6, 36, 54, 54,                    ;
  605.             "Group")
  606. aDlg = AppendDialog(aDlg, "radioa", DLG_BUTTON,                ;
  607.             BS_AUTORADIOBUTTON                    ;
  608.             + WS_CHILD + WS_VISIBLE,                ;
  609.             11, 50, 39, 10,                    ;
  610.             "&A")
  611. aDlg = AppendDialog(aDlg, "radiob", DLG_BUTTON,                ;
  612.             BS_AUTORADIOBUTTON + WS_CHILD + WS_VISIBLE,        ;
  613.             12, 70, 39, 10,                    ;
  614.             "&B")
  615.  
  616. #ifdef NOTDEF    // Don't define this !!  (There is no ModelessDialog() yet.)
  617.  
  618. i = ModelessDialog(aDlg, , hWnd)
  619. #ifdef SEE_MESSAGES
  620. hDlg = i
  621. #endif // SEE_MESSAGES
  622.  
  623. #else
  624.  
  625. MessageBox( , "Sorry, not yet implemented", "Notice")
  626.  
  627. #endif // NOTDEF
  628.  
  629. return nil
  630.  
  631.  
  632.  
  633. function ResModeless()
  634. local    i
  635. #ifdef SEE_MESSAGES
  636. aDlg = {}
  637. #endif // SEE_MESSAGES
  638. i = CreateDialog( , "dlg", ,                    ;
  639.          {|hDlg, msg, wparam, lparam|            ;
  640.           ResDlgModeless(hDlg, msg, wparam, lparam)})
  641. #ifdef SEE_MESSAGES
  642. MessageBox( , asString(i), "CreateDialog( ) result")
  643. MessageBox( , "cText = " + asString(cText), "DialogBox")
  644. hDlg = i
  645. #endif // SEE_MESSAGES
  646. return nil
  647.  
  648.  
  649.  
  650. function DynDialog()
  651. return nil
  652.  
  653.  
  654.  
  655. function DynEdit(hDlg, nMsg, nwParam, nlParam)
  656. local    nEN
  657. if (nEN := _LastHilParam()) == EN_ERRSPACE .or. nEN == EN_MAXTEXT
  658.     MessageBox(hDlg, "Edit control full", "Info")
  659. endif
  660. return 0    // means msg not processed (and want default action)
  661.  
  662.  
  663. function DynCancel(hDlg, nMsg, nwParam, nlParam)
  664. if MessageBox(hDlg, "Really Cancel?", "Cancel", MB_YESNO) == IDYES
  665.     EndDialog(hDlg, 0)
  666. endif
  667. return .t.
  668.  
  669.  
  670. function DynPush(hDlg, nMsg, nwParam, nlParam)
  671. local    aDlg, cText := "DynPush"
  672. aDlg = CreateDialog("DynPush",                        ;
  673.             WS_CAPTION + WS_SYSMENU + WS_GROUP + WS_TABSTOP    ;
  674.             + WS_THICKFRAME + WS_VISIBLE + WS_POPUP,        ;
  675.             200, 18, 160, 100,                    ;
  676.             12, "MS Sans Serif")
  677. aDlg = AppendDialog(aDlg, "check", DLG_BUTTON,                ;
  678.             BS_AUTOCHECKBOX + WS_TABSTOP + WS_CHILD + WS_VISIBLE,;
  679.             5, 87, 40, 10,                    ;
  680.             "Check")
  681. aDlg = AppendDialog(aDlg, "", DLG_STATIC,                ;
  682.             SS_LEFT + WS_CHILD + WS_VISIBLE,            ;
  683.             71, 68, 55, 16,                    ;
  684.             "Text")
  685. aDlg = AppendDialog(aDlg, "edit2", DLG_EDIT,                ;
  686.             ES_AUTOHSCROLL + WS_BORDER                ;
  687.             + WS_TABSTOP + WS_CHILD + WS_VISIBLE,        ;
  688.             4, 26, 32, 12,                    ;
  689.             cText)
  690. aDlg = AppendDialog(aDlg, "ok", DLG_BUTTON,                ;
  691.             BS_DEFPUSHBUTTON + WS_TABSTOP + WS_CHILD + WS_VISIBLE,;
  692.             59, 22, 40, 14,                    ;
  693.             "&Ok")
  694.  
  695. if ModalDialog(aDlg, , hDlg) = 0 .or. GetDialogResult(aDlg, "cancel") = .T.
  696.     cText = "<cancelled>"
  697. else
  698.     cText = GetDialogResult(aDlg, "edit2")
  699. endif
  700. MessageBox( , asString(cText), "Edit Control result")
  701. return .t.
  702.  
  703.  
  704. static function ValidChk(nVar, hWndDlg)
  705. if nVar > 0
  706.     return .t.
  707. endif
  708. MessageBox(GetFocus(), "Must be > 0", "ValidChk failed")
  709. SetFocus(GetDlgItem(hWndDlg, IDD_EDIT))
  710. return .f.
  711.  
  712.  
  713.  
  714. function DynDlgModal(hWndDlg, nMsg, nwParam, nlParam, nVarRet)
  715. // this example uses the same function as Modal/Resource
  716. // just to show that dynamic dialogs can be treated almost
  717. // like resource dialogs if you wish
  718. return ResDlgModal(hWndDlg, nMsg, nwParam, nlParam, @nVarRet)
  719.  
  720.  
  721.  
  722. function ResDlgModal(hWndDlg, nMsg, nwParam, nlParam, nVarRet)
  723. static    nCtrl := IDD_A
  724. static    GetList, nVar, cBmp
  725. local    i, hWnd, hDC, nX, nY
  726. #ifdef SEE_MESSAGES
  727. aadd(aDlg, {hWndDlg, nMsg, nwParam, nlParam})
  728. aadd(aDlog, {hWndDlg, nMsg, nwParam, nlParam})
  729. #endif // SEE_MESSAGES
  730. do case
  731. case nMsg == WM_INITDIALOG
  732.     CheckDlgButton(hWndDlg, nCtrl, 1)
  733. //    SendDlgItemMessage(hWndDlg, IDD_EDIT, WM_SETTEXT, 0, "Initial Text")
  734.  
  735.     cBmp = ReadDIB("c4wtiny.bmp")
  736.  
  737.     /////////////
  738.     //
  739.     //  The code below does validation using a GET object.
  740.     //  There's some sample code later on showing how you might
  741.     //  use the edit controls themselves to do your own
  742.     //  validation.  You can use a combination of the two, of course.
  743.     //
  744.     /////////////
  745.  
  746.     GetList := {}
  747.     nVar = 0
  748.  
  749.     @ dialog hWndDlg id IDD_EDIT get nVar when nVar < 15    ;
  750.       font GetStockObject(ANSI_VAR_FONT) valid ValidChk(nVar, hWndDlg)
  751.  
  752.     return 1            // want system to set the focus
  753.  
  754. case nMsg == WM_SYSCOMMAND
  755.     if nwParam == SC_CLOSE        // system menu double click, or Alt-F4
  756.         CANCEL DIALOG hWndDlg
  757.     endif
  758.  
  759. // You don't have to handle this message, but here's how you can
  760. case nMsg == WM_PAINT
  761.     // this shows one way of dynamically doing output (in this case a bitmap)
  762.     hWnd = GetDlgItem(hWndDlg, IDD_GROUP)
  763.     i = GetClientRect(hWnd)
  764.     nX = i[3] / 2            // half-way across
  765.     nY = i[4] / 3            // a third of the way down
  766.     hDC = GetDC(hWnd)
  767. //    ShowDIB(hDC, cBmp, nX, nY)
  768.     StretchDIBits(hDC,          ;
  769.               nX, nY, nX / 2, nY, ; // quarter width, third height
  770.                , , , ,          ;
  771.                , cBmp)
  772.     ReleaseDC(hWnd, hDC)
  773.  
  774. case nMsg == WM_COMMAND
  775.     do case
  776.     case nwParam == IDD_OK        ;
  777.     .or. nwParam == IDOK
  778.         if IsDialogOK(hWndDlg, nwParam)
  779.             cText = GetDlgItmText(hWndDlg, IDD_EDIT)
  780.             // could do:
  781.             // nVarRet := val(cText)
  782.             nVarRet := nVar
  783.             EndDialog(hWndDlg, nwParam)    // *not* DestroyWindow()
  784.         endif
  785.         return 1        // means msg has been processed
  786.     case nwParam == IDCANCEL
  787.         // don't change cText
  788.         CANCEL DIALOG hWndDlg        // cancel any GETs
  789.         EndDialog(hWndDlg, nwParam)    // *not* DestroyWindow()
  790.         return 1        // means msg has been processed
  791.     case nwParam == IDABORT        ;
  792.     .or. nwParam == IDRETRY        ;
  793.     .or. nwParam == IDIGNORE    ;
  794.     .or. nwParam == IDYES        ;
  795.     .or. nwParam == IDNO
  796.         // not used in this example
  797.     case nwParam == IDD_EDIT
  798. #ifdef SEE_MESSAGES
  799.         aadd(aEdit, {hWndDlg, nMsg, nwParam, nlParam})
  800. #endif // SEE_MESSAGES
  801.         if (i := _LastHilParam()) == EN_ERRSPACE .or. i == EN_MAXTEXT
  802.             MessageBox(hWndDlg, "Edit control full", "Info")
  803.         endif
  804.     case nwParam == IDD_PUSH
  805.         // start a sub-dialog
  806.         i = DialogBox( , "dlg2", hWndDlg,        ;
  807.                   {|hDlg, msg, wparam, lparam|    ;
  808.                    ResDlg2(hDlg, msg, wparam, lparam)})
  809. #ifdef SEE_MESSAGES
  810.         MessageBox(hWndDlg, asString(i), "ResDialog (from Push)")
  811. #endif // SEE_MESSAGES
  812.         MessageBox(hWndDlg , asString(cText), "Edit Control result")
  813.  
  814.     case nwParam == IDD_GROUP
  815. #ifdef SEE_MESSAGES
  816.         MessageBox(hWndDlg, asString(nwParam), "DialogBox (IDD_GROUP)")
  817. #endif // SEE_MESSAGES
  818.  
  819.     case nwParam == IDD_A
  820. #ifdef SEE_MESSAGES
  821.         MessageBox(hWndDlg, asString(nwParam), "DialogBox (IDD_A)")
  822. #endif // SEE_MESSAGES
  823.         nCtrl = IDD_A
  824.  
  825.     case nwParam == IDD_B
  826. #ifdef SEE_MESSAGES
  827.         MessageBox(hWndDlg, asString(nwParam), "DialogBox (IDD_B)")
  828. #endif // SEE_MESSAGES
  829.         nCtrl = IDD_B
  830.  
  831.     case nwParam == IDD_CHECK
  832.         MessageBox(hWndDlg, asString(nwParam), "WRONG FUNCTION: DialogBox (IDD_CHECK)")
  833.     case nwParam == IDD_TEXT
  834.         MessageBox(hWndDlg, asString(nwParam), "WRONG FUNCTION: DialogBox (IDD_TEXT)")
  835.     case nwParam == IDD_EDIT2
  836.         MessageBox(hWndDlg, asString(nwParam), "WRONG FUNCTION: DialogBox (IDD_EDIT2)")
  837.     endcase
  838. endcase
  839. return 0    // means msg not processed (and want default action)
  840.  
  841.  
  842. //
  843. //  Perform major surgery on the dialog, to show the kinds of things
  844. //  that can be done (e.g. for data-driven dialogs).
  845. //
  846. function ResDlgModify(hWndDlg, nMsg, nwParam, nlParam, nVarRet)
  847. local    w, h, pt
  848. do case
  849. case nMsg == WM_INITDIALOG
  850.     w = GetDialogBaseUnits()
  851.     h = C4W_Int(C4W_HiWord(w) / 8)
  852.     w = C4W_Int(C4W_LoWord(w) / 4)
  853.     ClientToScreen(hWndDlg, pt := {40,40})
  854.     MoveWindow(hWndDlg, pt[1], pt[2], 145*w, 115*h, .f.)
  855.     ShowWindow(GetDlgItem(hWndDlg, IDD_A), SW_HIDE)
  856.     ShowWindow(GetDlgItem(hWndDlg, IDD_B), SW_HIDE)
  857.     ShowWindow(GetDlgItem(hWndDlg, IDD_GROUP), SW_HIDE)
  858.     SetWindowText(GetDlgItem(hWndDlg, IDD_PUSH), "&Sub-dialog")
  859.     MoveWindow(GetDlgItem(hWndDlg, IDD_PUSH), 10*w, 70*h, 40*w, 15*h, .f.)
  860.     MoveWindow(GetDlgItem(hWndDlg, IDOK), 90*w, 15*h, 40*w, 15*h, .f.)
  861.     MoveWindow(GetDlgItem(hWndDlg, IDCANCEL), 90*w, 70*h, 40*w, 15*h, .f.)
  862. endcase
  863.  
  864. // now pass the msg along
  865. return ResDlgModal(hWndDlg, nMsg, nwParam, nlParam, @nVarRet)
  866.  
  867.  
  868.  
  869. function UserDlgModal(hWndDlg, nMsg, nwParam, nlParam)
  870. static    GetList
  871. static    cUserID, cUserName, cDept, cPhone, cExt
  872. static    oUserID, oUserName, oDept, oPhone, oExt
  873. // these are tiny functions/procedures:
  874. static    bScatter := {|| cUserID   := users->UserID,    ;
  875.             cUserName := users->UserName,    ;
  876.             cDept     := users->Department,    ;
  877.             cPhone    := users->Phone,    ;
  878.             cExt      := users->Extension }
  879. static    bGather := {||    users->UserID     := cUserID,    ;
  880.             users->UserName   := cUserName,    ;
  881.             users->Department := cDept,    ;
  882.             users->Phone      := cPhone,    ;
  883.             users->Extension  := cExt }
  884. static    bUpdate := {||    oUserID   :killFocus()            ;
  885.                   :varPut( users->UserID     ),    ;
  886.             oUserName :killFocus()            ;
  887.                   :varPut( users->UserName   ),    ;
  888.             oDept     :killFocus()            ;
  889.                   :varPut( users->Department ),    ;
  890.             oPhone    :killFocus()            ;
  891.                   :varPut( users->Phone      ),    ;
  892.             oExt      :killFocus()            ;
  893.                   :varPut( users->Extension  ) }
  894. static    hBrush            // only used for example of WM_CTLCOLOR
  895. #define    C_WHITE    RGB(255,255,255)
  896.  
  897. do case
  898. case nMsg == WM_INITDIALOG
  899.  
  900.     use users new shared
  901.     users->( dbGoTop() )
  902.  
  903.     eval(bScatter)        // fetch fields to static vars
  904.  
  905.     /////////////
  906.     //
  907.     //  The code below does validation using GET objects.
  908.     //
  909.     //  The objects need to be saved because we want to change
  910.     //  them as we move from record to record.
  911.     //
  912.     /////////////
  913.  
  914.     GetList = {}
  915.     @ dialog hWndDlg id IDD_USERID   get cUserID
  916.     oUserID = ATail(GetList)
  917.     @ dialog hWndDlg id IDD_USERNAME get cUserName
  918.     oUserName = ATail(GetList)
  919.     @ dialog hWndDlg id IDD_DEPT     get cDept
  920.     oDept = ATail(GetList)
  921.     @ dialog hWndDlg id IDD_PHONE    get cPhone
  922.     oPhone = ATail(GetList)
  923.     @ dialog hWndDlg id IDD_EXT      get cExt
  924.     oExt = ATail(GetList)
  925.  
  926.     hBrush = CreateSolidBrush(C_WHITE) // only used for example WM_CTLCOLOR
  927.     return 1            // want system to set the focus
  928.  
  929. case nMsg == WM_SYSCOMMAND
  930.     if nwParam == SC_CLOSE        // system menu double click, or Alt-F4
  931. #ifdef ThisIsTheDefault
  932.         // By default, Windows sends a WM_COMMAND with IDCANCEL,
  933.         // which does the same as this code:
  934.  
  935.         // cancel the GETs
  936.         CANCEL DIALOG hWndDlg
  937.         close users
  938.         EndDialog(hWndDlg, IDCANCEL)    // *not* DestroyWindow()
  939.         return 1        // means msg has been processed
  940. #endif // ThisIsTheDefault
  941.     endif
  942.  
  943. case nMsg == WM_COMMAND
  944.     do case
  945.     case nwParam == IDOK
  946.         // don't change record
  947.         // (it's only done if SAVE button pressed, i.e. IDD_SAVE)
  948.         CANCEL DIALOG hWndDlg        // cancel any GETs
  949.         close users
  950.         EndDialog(hWndDlg, nwParam)    // *not* DestroyWindow()
  951.         DeleteObject(hBrush)
  952.         return 1        // means msg has been processed
  953.  
  954.     case nwParam == IDCANCEL
  955.         // don't change record
  956.         CANCEL DIALOG hWndDlg        // cancel any GETs
  957.         close users
  958.         EndDialog(hWndDlg, nwParam)    // *not* DestroyWindow()
  959.         DeleteObject(hBrush)
  960.         return 1        // means msg has been processed
  961.  
  962.     case nwParam == IDD_NEXT
  963.  
  964.  
  965. // Don't define NOT_DEFINED !!!   (It's just used for commenting)
  966.  
  967. #ifdef NOT_DEFINED    // this is to avoid using /* ... */ over many lines
  968.             // which causes problems if you have another
  969.             // /* ... */ comment within the code
  970.  
  971.     /*
  972.      *  This code is commented out because it's NOT the
  973.      *  way to do it!!  You're not closing the dialog.
  974.      *  You're just moving to a new record.  If you use
  975.      *  this code you get very confused edit controls.
  976.      */
  977.  
  978.         // need to cancel current GETs, skip, and re-issue them
  979.  
  980.         CANCEL DIALOG hWndDlg        // cancel any GETs
  981.  
  982.         users->( dbSkip(1) )
  983.         if users->( Eof() )
  984.             users->( dbGoBottom() )
  985.         endif
  986.  
  987.         eval(bScatter)        // fetch fields to static vars
  988.  
  989.         GetList = {}
  990.         @ dialog hWndDlg id IDD_USERID   get cUserID
  991.         @ dialog hWndDlg id IDD_USERNAME get cUserName
  992.         @ dialog hWndDlg id IDD_DEPT     get cDept
  993.         @ dialog hWndDlg id IDD_PHONE    get cPhone
  994.         @ dialog hWndDlg id IDD_EXT      get cExt
  995. #else
  996.  
  997.     /*
  998.      *  Here's how to make moving to a different record work.
  999.      */
  1000.  
  1001.         // need to skip, then update GETs
  1002.  
  1003.         users->( dbSkip(1) )
  1004.         if users->( Eof() )
  1005.             users->( dbGoBottom() )
  1006.         endif
  1007.  
  1008.         eval(bUpdate)        // update the GETs and vars
  1009.  
  1010. #ifdef YouCanDoItThisWay
  1011.         // this way is a little slower, but uses the PICTURE
  1012.         // (if any) -- see GETSYS.PRG for the function
  1013.         // DReadSetInfo().
  1014.         DReadSetInfo(hWndDlg, IDD_USERID,   GetList, 1)
  1015.         DReadSetInfo(hWndDlg, IDD_USERNAME, GetList, 2)
  1016.         DReadSetInfo(hWndDlg, IDD_DEPT,     GetList, 3)
  1017.         DReadSetInfo(hWndDlg, IDD_PHONE,    GetList, 4)
  1018.         DReadSetInfo(hWndDlg, IDD_EXT,      GetList, 5)
  1019. #else // OrThisWay
  1020.         // This is good enough for char vars with no picture.
  1021.         //
  1022.         // For the general-case, use:
  1023.         //    SetDlgItem(hWndDlg, IDD_xxx,    ;
  1024.         //           transform(oXXX:varGet(), oXXX:picture))
  1025.         // which currently works even if the picture is nil.
  1026.         // CA may "fix" that, of course, in which case you
  1027.         // need cautious code as in DReadSetInfo().
  1028.         SetDlgItem(hWndDlg, IDD_USERID,   oUserID  :varGet())
  1029.         SetDlgItem(hWndDlg, IDD_USERNAME, oUserName:varGet())
  1030.         SetDlgItem(hWndDlg, IDD_DEPT,     oDept    :varGet())
  1031.         SetDlgItem(hWndDlg, IDD_PHONE,    oPhone   :varGet())
  1032.         SetDlgItem(hWndDlg, IDD_EXT,      oExt     :varGet())
  1033. #endif
  1034.  
  1035. #endif // NOT_DEFINED
  1036.  
  1037.         return 1        // means msg has been processed
  1038.  
  1039.     case nwParam == IDD_PREV
  1040.  
  1041.         // need to skip, then update GETs
  1042.  
  1043.         users->( dbSkip(-1) )
  1044.         if users->( Bof() )
  1045.             users->( dbGoTop() )
  1046.         endif
  1047.  
  1048.         eval(bUpdate)        // update the GETs and vars
  1049.  
  1050.         SetDlgItem(hWndDlg, IDD_USERID,   oUserID  :varGet())
  1051.         SetDlgItem(hWndDlg, IDD_USERNAME, oUserName:varGet())
  1052.         SetDlgItem(hWndDlg, IDD_DEPT,     oDept    :varGet())
  1053.         SetDlgItem(hWndDlg, IDD_PHONE,    oPhone   :varGet())
  1054.         SetDlgItem(hWndDlg, IDD_EXT,      oExt     :varGet())
  1055.  
  1056.         return 1        // means msg has been processed
  1057.  
  1058.     case nwParam == IDD_SAVE
  1059.         if IsDialogOK(hWndDlg, nwParam)
  1060.             users->( RLock() )
  1061.             eval(bGather)    // update the fields from the vars
  1062.             users->( dbUnlock() )
  1063.         endif
  1064.         return 1        // means msg has been processed
  1065.  
  1066.     endcase
  1067.  
  1068. // You don't have to handle this message, but here's how you do it
  1069. //
  1070. // You have to create a brush to be used for the control's background
  1071. // during (or before) WM_INITDIALOG, return it here, and remember to
  1072. // free the brush using DeleteObject() after calling EndDialog().
  1073. //
  1074. //  NOTE: Turn off the 3-D effects if you want this to do anything!
  1075.  
  1076. case nMsg == WM_CTLCOLOR
  1077.     if C4W_HiWord(nlParam) == CTLCOLOR_STATIC .and. hLibCtl3d == nil
  1078.         // hDC is given to us in nwParam
  1079.         SetTextColor(nwParam, RGB(255,0,0))
  1080.         SetBkColor(nwParam, C_WHITE)
  1081.         return hBrush
  1082.     endif
  1083. endcase
  1084. return 0    // means msg not processed (and want default action)
  1085.  
  1086.  
  1087.  
  1088. // Don't define NOT_DEFINED !!!   (It's just used for commenting)
  1089.  
  1090. #ifdef NOT_DEFINED    // this is to avoid using /* ... */ over many lines
  1091.             // which causes problems if you have another
  1092.             // /* ... */ comment within the code
  1093. /////////////
  1094. //
  1095. //  The code below does validation using the edit controls
  1096. //  themselves to do your own validation.  You can use this as
  1097. //  well as GETs in a dialog, of course.
  1098. //
  1099. //  NOTE: There are two approaches to this.  Both check all the fields
  1100. //  on exit from the dialog box.  Prior to that, the first one below does
  1101. //  validation on each field as it is entered _and_ all lower-numbered
  1102. //  fields.  (So that in effect it forces you to enter them in sequence.)
  1103. //  The second approach lets you enter the data in any order, validating
  1104. //  each field as it is finished, and then validates all the values at
  1105. //  the end.
  1106. //
  1107. //  With thanks for the help of Hugh and Jerry.
  1108. //
  1109. /////////////
  1110. //  Approach 1...
  1111. /////////////
  1112.  
  1113. STATIC FUNCTION RatePage1(lEdit)
  1114.        LOCAL hOldWnd := GetFocus()
  1115.        LOCAL nResults
  1116.        LOCAL aValids := {{101,{|hDlg|ChkRateCode(hDlg)}},;
  1117.              {102,{|hDlg|ChkRateDisc(hDlg)}},;
  1118.              {112,{|hDlg|ChkRateMaxD(hDlg)}},;
  1119.              {113,{|hDlg|ChkRateDHrs(hDlg)}},;
  1120.              {114,{|hDlg|ChkRatePHrs(hDlg)}}}
  1121.  
  1122.        nResults :=DialogBox(_GetInstance() , "rate1", , ;
  1123.          {|hDlg, msg, wparam, lparam|        ;
  1124.           MRatePg1(hDlg, msg, wparam, lparam,aValids)})
  1125.        SetFocus(hOldWnd)
  1126. RETURN(nResults)
  1127.  
  1128. STATIC FUNCTION MRatePg1(hDlgWnd, nMsg, nwParam, nlParam,aValids)
  1129.        STATIC lForceFocus // Flag to indicate focus has been forced backward
  1130.        STATIC nHasFocus   // Counter to show which control/field has focus
  1131.        STATIC lValid      // Flag to indicate if a valid check failed/passed
  1132.        LOCAL  nCtr        // Counter to go through array of valids
  1133.  
  1134.        DO CASE
  1135.       CASE nMsg == WM_INITDIALOG
  1136.            // Set all our defaults/initial values
  1137.            // this function is in center.zip, but is not required
  1138.            CenterWindow(hDlgWnd)    // Thanks Gerald this one is great!
  1139.            SetDlgItemText(hDlgWnd,  101, S_RATE_CODE)
  1140.            SetDlgItemText(hDlgWnd,  102, S_DESCRIPT )
  1141.            SendDlgItemMessage(hDlgWnd, 103, BM_SETCHECK,IIF(S_BILL_PER=='W',1,0))
  1142.            SendDlgItemMessage(hDlgWnd, 104, BM_SETCHECK,IIF(S_BILL_PER=='M',1,0))
  1143.            SendDlgItemMessage(hDlgWnd, 105, BM_SETCHECK,IIF(S_BILL_PER=='B',1,0))
  1144.  
  1145.            SendDlgItemMessage(hDlgWnd, 106, BM_SETCHECK,IIF(S_BREAKFAST=='Y',1,0))
  1146.            SendDlgItemMessage(hDlgWnd, 107, BM_SETCHECK,IIF(S_LUNCH    =='Y',1,0))
  1147.            SendDlgItemMessage(hDlgWnd, 108, BM_SETCHECK,IIF(S_DINNER   =='Y',1,0))
  1148.            SendDlgItemMessage(hDlgWnd, 109, BM_SETCHECK,IIF(S_SNACK    =='Y',1,0))
  1149.  
  1150.            SetDlgItemText(hDlgWnd, 112, LTRIM(STR(S_MAXDAYS)))
  1151.            SetDlgItemText(hDlgWnd, 113, LTRIM(STR(S_DREGHRS)))
  1152.            SetDlgItemText(hDlgWnd, 114, LTRIM(STR(S_PREGHRS)))
  1153.            // Set initial state of our flags
  1154.            lForceFocus := .F.
  1155.            nHasFocus   := 101
  1156.            lValid      := .T.
  1157.            RETURN(1)
  1158.  
  1159.        CASE nMsg == WM_COMMAND
  1160.         DO CASE
  1161.            CASE nwParam == IDCANCEL            // Real clean no need for special
  1162.             EndDialog(hDlgWnd,nwParam)  // checks or other junk
  1163.             RETURN(1)
  1164.  
  1165.            CASE lForceFocus == .T.         // Filters out gain/kill focus
  1166.             IF nwParam == nHasFocus  // messages caused by a validation
  1167.                lForceFocus := .F.    // failure - we just ignore everything
  1168.             ENDIF             // until the new control id is received
  1169.             RETURN(1)
  1170.  
  1171.            // The "heart" of the validation routine
  1172.  
  1173.            CASE (nwParam != nHasFocus) .AND.;
  1174.             (C4W_HiWord(nlParam) == EN_SETFOCUS .OR.;
  1175.              C4W_HiWord(nlParam) == 0) // Buttons return 0
  1176.  
  1177.             // If the control id is not equal to the current value
  1178.             // of the focus counter and we got a setfocus message
  1179.             // or a button was pressed then we have to check the
  1180.             // fields that have valids
  1181.  
  1182.             FOR nCtr := 1 TO LEN(aValids)
  1183.             IF aValids[nCtr][1] < nwParam .OR.;
  1184.                nwParam == 1 // Ok button look at all valids
  1185.  
  1186.                // Set your flags to indicate a failure ahead of time
  1187.                // cause if one occurs you will not get control back
  1188.                // until all the junk has been processed!
  1189.                lForceFocus := .T.
  1190.                lValid      := .F.
  1191.  
  1192.                IF EVAL(aValids[nCtr][2],hDlgWnd) == .F.
  1193.                   nHasFocus := aValids[nCtr][1]
  1194.                   SetFocus(GetDlgItem(hDlgWnd,nHasFocus))
  1195.                   EXIT
  1196.                ELSE
  1197.                   nHasFocus   := aValids[nCtr][1]
  1198.                   lForceFocus := .F.
  1199.                   lValid      := .T.
  1200.                ENDIF
  1201.             ELSE
  1202.                EXIT
  1203.             ENDIF
  1204.             NEXT
  1205.  
  1206.             // If we get here without interruption then everything was
  1207.             // valid now we check to see if the Ok button was pressed
  1208.  
  1209.             IF lValid == .T.
  1210.                IF nwParam == IDOK
  1211.               Page1Vals(hDlgWnd)
  1212.               EndDialog(hDlgWnd,1)
  1213.                ENDIF
  1214.  
  1215.                // This routine has two "pages" of data to be input so
  1216.                // we have a next page button to contend with
  1217.  
  1218.                IF nwParam == 16 // Next Page
  1219.               Page1Vals(hDlgWnd)
  1220.               EndDialog(hDlgWnd,3)
  1221.                ENDIF
  1222.             ENDIF
  1223.             RETURN(1)
  1224.            ENDCASE
  1225.        ENDCASE
  1226. RETURN(0)
  1227.  
  1228. // This gets the values of the controls and assigns them to some
  1229. // statics used in place of the database fields.  Since it is
  1230. // called from two different places it makes sense to make it
  1231. // a stand-alone funciton - also gets all that code out of
  1232. // the case statement.  Could do the same thing with the setup
  1233. // part to make the basic function shorter and neater.
  1234.  
  1235. STATIC FUNCTION Page1Vals(hDlgWnd)
  1236.  
  1237.        S_RATE_CODE := GetDlgItmText(hDlgWnd,101)
  1238.        S_DESCRIPT  := GetDlgItmText(hDlgWnd,102)
  1239.        S_BILL_PER  := IIF(IsDlgButtonChecked(hDlgWnd,103)==1,'W',;
  1240.               IIF(IsDlgButtonChecked(hDlgWnd,104)==1,'M','B'))
  1241.        S_BREAKFAST := IIF(IsDlgButtonChecked(hDlgWnd,106)==1,'Y','N')
  1242.        S_LUNCH     := IIF(IsDlgButtonChecked(hDlgWnd,107)==1,'Y','N')
  1243.        S_DINNER    := IIF(IsDlgButtonChecked(hDlgWnd,108)==1,'Y','N')
  1244.        S_SNACK     := IIF(IsDlgButtonChecked(hDlgWnd,109)==1,'Y','N')
  1245.        S_MAXDAYS   := VAL(GetDlgItmText(hDlgWnd,112))
  1246.        S_DREGHRS   := VAL(GetDlgItmText(hDlgWnd,113))
  1247.        S_PREGHRS   := VAL(GetDlgItmText(hDlgWnd,114))
  1248. RETURN(NIL)
  1249.  
  1250. // Following are the validation functions
  1251.  
  1252. STATIC FUNCTION ChkRateCode(hDlgWnd)
  1253.  
  1254.        S_RATE_CODE := GetDlgItmText(hDlgWnd,101)
  1255.        IF EMPTY(S_RATE_CODE)
  1256.       SelectWindow(hDlgWnd)
  1257.       ErrorMsg("RATE CODE CANNOT BE BLANK!","PROBLEM")
  1258.       RETURN(.F.)
  1259.        ENDIF
  1260. RETURN(.T.)
  1261.  
  1262. STATIC FUNCTION ChkRateDisc(hDlgWnd)
  1263.  
  1264.        S_DESCRIPT := GetDlgItmText(hDlgWnd,102)
  1265.        IF EMPTY(S_DESCRIPT)
  1266.       SelectWindow(hDlgWnd)
  1267.       ErrorMsg("DESCRIPTION CANNOT BE BLANK!",'E')
  1268.       RETURN(.F.)
  1269.        ENDIF
  1270. RETURN(.T.)
  1271.  
  1272. STATIC FUNCTION ChkRateMaxD(hDlgWnd)
  1273.  
  1274.        S_MAXDAYS := GetDlgItmText(hDlgWnd,112)
  1275.        IF EMPTY(S_MAXDAYS) .OR.;
  1276.       ISDIGIT(S_MAXDAYS) == .F.
  1277.       SelectWindow(hDlgWnd)
  1278.       ErrorMsg("MAXDAYS CANNOT BE BLANK/INVALID DATA ENTERED!","E")
  1279.       RETURN(.F.)
  1280.        ENDIF
  1281. RETURN(.T.)
  1282.  
  1283. STATIC FUNCTION ChkRateDHrs(hDlgWnd)
  1284.  
  1285.        S_DREGHRS := GetDlgItmText(hDlgWnd,113)
  1286.        IF VAL(S_DREGHRS) < 0 .OR.;
  1287.       EMPTY(S_DREGHRS)
  1288.       SelectWindow(hDlgWnd)
  1289.       ErrorMsg("DAILY HOURS CANNOT BE BLANK!",'E')
  1290.       RETURN(.F.)
  1291.        ENDIF
  1292. RETURN(.T.)
  1293.  
  1294. STATIC FUNCTION ChkRatePHrs(hDlgWnd)
  1295.  
  1296.        S_PREGHRS := GetDlgItmText(hDlgWnd,114)
  1297.        IF EMPTY(S_PREGHRS) .OR.;
  1298.       ISDIGIT(S_PREGHRS) == .F.
  1299.       SelectWindow(hDlgWnd)
  1300.       ErrorMsg("PERIOD HOURS CANNOT BE BLANK!",'E')
  1301.       RETURN(.F.)
  1302.        ENDIF
  1303. RETURN(.T.)
  1304.  
  1305.  
  1306. /////////////
  1307. //  Approach 2...
  1308. /////////////
  1309.  
  1310. // Program..: Enternam.prg
  1311. // Author...: Gerald Barber
  1312. // Date.....: Sun  1-31-1993; Last Updated June 19, 1993 04:25 pm
  1313. // Notice...: Copyright 1993, Gerald Barber
  1314. // Notes....: Name Entry Dialog Box for Rebreath Program
  1315.  
  1316. #define WIN_WANT_ALL
  1317. #define WIN_WANT_EN
  1318.  
  1319. #include "windows.ch"
  1320. #include "\clipper5\userinc\clip.ch"
  1321. #include "resource.h"
  1322. #include "rebreath.h"
  1323.  
  1324. static aData_[2]
  1325.  
  1326. function entername(hWnd)
  1327. local aResult_[2]
  1328. local aValids_ := {{IDC_LNAME, {|hDlg|ChkName(hDlg, IDC_LNAME)}}, ;
  1329.            {IDC_FNAME, {|hDlg|ChkName(hDlg, IDC_FNAME)}}}
  1330. afill(aData_, "")
  1331. afill(aResult_, "")
  1332. if DialogBox(_GetInstance(), "DEMO", hWnd, { |hDlg, msg, wparam, lparam|    ;
  1333.         DemoDialog(hDlg, msg, wparam, lparam, aValids_) } ) <> IDCANCEL
  1334.     aResult_ := aData_
  1335. endif
  1336. return (aResult_)
  1337.  
  1338. static function DemoDialog(hWndDlg, nMsg, nwParam, nlParam, aValids_)
  1339. static lForceFocus // Flag to indicate focus has been forced backward
  1340. static nHasFocus   // Counter to show which control/field has focus
  1341. static lValid      // Flag to indicate if a valid check failed/passed
  1342. local  nCtr        // Counter to go through array of valids
  1343.  
  1344. DO CASE
  1345.     CASE nMsg == WM_INITDIALOG
  1346.     center(hWndDlg)
  1347.     // Set all our defaults/initial values
  1348.     nHasFocus   := SayData(hWndDlg)
  1349.     // Set initial state of our flags
  1350.     lForceFocus := .F.
  1351.     lValid      := .T.
  1352.     RETURN(1)
  1353.  
  1354.     CASE nMsg == WM_COMMAND
  1355.     DO CASE
  1356.         CASE nwParam == IDCANCEL .OR.  ; // Real clean no need for special
  1357.          nwParam == IDABORT  .OR.  ; // checks or other junk
  1358.          nwParam == IDRETRY  .OR.  ;
  1359.          nwParam == IDIGNORE .OR.  ;
  1360.          nwParam == IDNO
  1361.          EndDialog(hWndDlg, IDCANCEL)
  1362.          return(1)
  1363.  
  1364.         CASE lForceFocus == .T.          // Filters out gain/kill focus
  1365.          if nwParam == nHasFocus     // messages caused by a validation
  1366.              lForceFocus := .F.      // failure - we just ignore everything
  1367.          endif                       // until the new control id is received
  1368.          return(1)
  1369.  
  1370.         // The "heart" of the validation routine
  1371.  
  1372.         CASE (nwParam != nHasFocus) .AND.             ;
  1373.          (C4W_HiWord(nlParam) == EN_SETFOCUS .OR.;
  1374.           C4W_HiWord(nlParam) == 0)  // Buttons return 0
  1375.  
  1376.         // If the control id is not equal to the current value
  1377.         // of the focus counter and we got a setfocus message
  1378.         // or a button was pressed then we have to check the
  1379.         // fields that have valids
  1380.  
  1381.         for nCtr := 1 to len(aValids_)
  1382.  
  1383.             // 06/11/93 GB - Modified so that
  1384.             // On IDOK - all fields get validity check
  1385.             //    Else - only modified field gets validity check
  1386.             // This solves problem that occurs when the order
  1387.             // of fields selected does not correspond with the order
  1388.             // in aValids_
  1389.             // Was
  1390.             //  if aValids_[nCtr][1] < nwParam .OR.   ;
  1391.             //      nwParam == 1        // Ok button look at all valids
  1392.             // Now
  1393.             if aValids_[nCtr][1] == nHasFocus .OR.  ;
  1394.             nwParam == 1        // Ok button look at all valids
  1395.  
  1396.             // Set your flags to indicate a failure ahead of time
  1397.             // cause if one occurs you will not get control back
  1398.             // until all the junk has been processed!
  1399.             lForceFocus := .T.
  1400.             lValid      := .F.
  1401.  
  1402.             if eval(aValids_[nCtr][2],hWndDlg) == .F.
  1403.                 nHasFocus := aValids_[nCtr][1]
  1404.                 SetFocus(GetDlgItem(hWndDlg,nHasFocus))
  1405.                 exit
  1406.               else
  1407.                 nHasFocus   := aValids_[nCtr][1]
  1408.                 lForceFocus := .F.
  1409.                 lValid      := .T.
  1410.             endif
  1411.  
  1412.               // 06/11/93 GB - Deleted so that
  1413.               // On IDOK - all fields get validity check
  1414.               //    Else - only modified field gets validity check
  1415.               // This solves problem that occurs when the order
  1416.               // of fields selected does not correspond with the order
  1417.               // in aValids_
  1418.               // Was
  1419.               // else
  1420.               //   exit
  1421.               // Now
  1422.               // No Exit - continue processing until all
  1423.               // entries in aValid_ checked for possible
  1424.               // match with nHasFocus
  1425.  
  1426.             endif
  1427.         next
  1428.  
  1429.         // If we get here without interruption then everything was
  1430.         // valid now we check to see if the Ok button was pressed
  1431.  
  1432.         if lValid == .T. .AND. nwParam == IDOK
  1433.             GetData(hWndDlg)
  1434.             EndDialog(hWndDlg,IDOK)
  1435.  
  1436.           // 06/11/93 GB - Added so that
  1437.           // On IDOK - all fields get validity check
  1438.           //    Else - only modified field gets validity check
  1439.           // This solves problem that occurs when the order
  1440.           // of fields selected does not correspond with the order
  1441.           // in aValids_
  1442.           elseif lValid == .T.
  1443.             // No errors and not exiting dialog
  1444.             // Set nHasFocus to the newly selected field
  1445.             nHasFocus := nwParam
  1446.  
  1447.         endif
  1448.         return(1)
  1449.     ENDCASE
  1450. ENDCASE
  1451. return(0)
  1452.  
  1453. // Following are the data display functions
  1454.  
  1455. static function SayData(hWndDlg)
  1456. SetDlgItemText(hWndDlg,IDC_LNAME,aData_[IDD_LNAME])
  1457. SetDlgItemText(hWndDlg,IDC_FNAME,aData_[IDD_FNAME])
  1458. return (IDC_LNAME)
  1459.  
  1460. // Following are the data retrieval functions
  1461.  
  1462. static function GetData(hWndDlg)
  1463. aData_[IDD_LNAME] := alltrim(GetDlgItmText(hWndDlg, IDC_LNAME))
  1464. aData_[IDD_FNAME] := alltrim(GetDlgItmText(hWndDlg, IDC_FNAME))
  1465. return .T.
  1466.  
  1467. // Following are the validation functions
  1468.  
  1469. static function ChkName(hWndDlg,nID)
  1470. local cText := alltrim(GetDlgItmText(hWndDlg,nID))
  1471. if !ChkAlpha(hWndDlg,nID)
  1472.     return(.F.)
  1473. endif
  1474. if Empty(cText)
  1475.     SelectWindow(hWndDlg)
  1476.     MessageBox(hWndDlg,"Please Try Again","Invalid Entry", ;
  1477.             MB_OK + MB_ICONEXCLAMATION)
  1478.     return(.F.)
  1479. endif
  1480. return(.T.)
  1481.  
  1482. #endif // NOT_DEFINED        // and not meant to be!
  1483.  
  1484.  
  1485.  
  1486.  
  1487. function ResDlgModeless(hWndDlg, nMsg, nwParam, nlParam)
  1488. static    nCtrl := IDD_A
  1489. local    i
  1490. #ifdef SEE_MESSAGES
  1491. aadd(aDlg, {hWndDlg, nMsg, nwParam, nlParam})
  1492. #endif // SEE_MESSAGES
  1493. do case
  1494. case nMsg == WM_INITDIALOG
  1495.     CheckDlgButton(hWndDlg, nCtrl, 1)
  1496.     SendDlgItemMessage(hWndDlg, IDD_EDIT, WM_SETTEXT, 0, "Initial Text")
  1497.     return 1            // want system to set the focus
  1498. case nMsg == WM_COMMAND
  1499.     do case
  1500.     case nwParam == IDD_OK        ;
  1501.     .or. nwParam == IDOK
  1502.         cText = GetDlgItmText(hWndDlg, IDD_EDIT)
  1503.         DestroyWindow(hWndDlg)    // *not* EndDialog()
  1504.         return 1        // means msg has been processed
  1505.     case nwParam == IDCANCEL
  1506.         // don't change cText
  1507.         DestroyWindow(hWndDlg)    // *not* EndDialog()
  1508.         return 1        // means msg has been processed
  1509.     case nwParam == IDABORT        ;
  1510.     .or. nwParam == IDRETRY        ;
  1511.     .or. nwParam == IDIGNORE    ;
  1512.     .or. nwParam == IDYES        ;
  1513.     .or. nwParam == IDNO
  1514.         // not used in this example
  1515.     case nwParam == IDD_EDIT
  1516.         if (i := _LastHilParam()) == EN_ERRSPACE .or. i == EN_MAXTEXT
  1517.             MessageBox(hWndDlg, "Edit control full", "Info")
  1518.         endif
  1519.     case nwParam == IDD_PUSH
  1520.         // start a sub-dialog
  1521.         i = DialogBox( , "dlg2", hWndDlg,        ;
  1522.                   {|hDlg, msg, wparam, lparam|    ;
  1523.                    ResDlg2(hDlg, msg, wparam, lparam)})
  1524. #ifdef SEE_MESSAGES
  1525.         MessageBox(hWndDlg, asString(i), "ResDialog (from Push)")
  1526. #endif // SEE_MESSAGES
  1527.         MessageBox(hWndDlg , asString(cText), "Edit Control result")
  1528.  
  1529.     case nwParam == IDD_GROUP
  1530. #ifdef SEE_MESSAGES
  1531.         MessageBox(hWndDlg, asString(nwParam), "DialogBox (IDD_GROUP)")
  1532. #endif // SEE_MESSAGES
  1533.  
  1534.     case nwParam == IDD_A
  1535. #ifdef SEE_MESSAGES
  1536.         MessageBox(hWndDlg, asString(nwParam), "DialogBox (IDD_A)")
  1537. #endif // SEE_MESSAGES
  1538.         nCtrl = IDD_A
  1539.  
  1540.     case nwParam == IDD_B
  1541. #ifdef SEE_MESSAGES
  1542.         MessageBox(hWndDlg, asString(nwParam), "DialogBox (IDD_B)")
  1543. #endif // SEE_MESSAGES
  1544.         nCtrl = IDD_B
  1545.  
  1546.     case nwParam == IDD_CHECK
  1547.         MessageBox(hWndDlg, asString(nwParam), "WRONG FUNCTION: DialogBox (IDD_CHECK)")
  1548.     case nwParam == IDD_TEXT
  1549.         MessageBox(hWndDlg, asString(nwParam), "WRONG FUNCTION: DialogBox (IDD_TEXT)")
  1550.     case nwParam == IDD_EDIT2
  1551.         MessageBox(hWndDlg, asString(nwParam), "WRONG FUNCTION: DialogBox (IDD_EDIT2)")
  1552.     endcase
  1553. endcase
  1554. return 0    // means msg not processed (and want default action)
  1555.  
  1556.  
  1557.  
  1558. function ResDlg2(hWndDlg, nMsg, nwParam, nlParam)
  1559. local    i
  1560. do case
  1561. case nMsg == WM_INITDIALOG
  1562.     return 1            // want system to set the focus
  1563. case nMsg == WM_COMMAND
  1564.     do case
  1565.     case nwParam == IDD_OK        ;
  1566.     .or. nwParam == IDOK
  1567.         cText = GetDlgItmText(hWndDlg, IDD_EDIT2)
  1568.         EndDialog(hWndDlg, nwParam)    // *not* DestroyWindow()
  1569.         return 1        // means msg has been processed
  1570.     case nwParam == IDCANCEL
  1571.         // don't change cText
  1572.         EndDialog(hWndDlg, nwParam)    // *not* DestroyWindow()
  1573.         return 1        // means msg has been processed
  1574.     case nwParam == IDABORT        ;
  1575.     .or. nwParam == IDRETRY        ;
  1576.     .or. nwParam == IDIGNORE    ;
  1577.     .or. nwParam == IDYES        ;
  1578.     .or. nwParam == IDNO
  1579.         // not used in this example
  1580.     case nwParam == IDD_CHECK
  1581. #ifdef SEE_MESSAGES
  1582.         MessageBox(hWndDlg, asString(nwParam), "DialogBox (IDD_CHECK)")
  1583. #endif // SEE_MESSAGES
  1584.     case nwParam == IDD_TEXT
  1585. #ifdef SEE_MESSAGES
  1586.         MessageBox(hWndDlg, asString(nwParam), "DialogBox (IDD_TEXT)")
  1587. #endif // SEE_MESSAGES
  1588.     case nwParam == IDD_EDIT2
  1589. #ifdef SEE_MESSAGES
  1590.         MessageBox(hWndDlg, asString(nwParam), "DialogBox (IDD_EDIT2)")
  1591. #endif // SEE_MESSAGES
  1592.     endcase
  1593. endcase
  1594. return 0    // means msg not processed (and want default action)
  1595.  
  1596.  
  1597.  
  1598. static procedure Ctl3dColorChange()
  1599. local    cDLL := GetProcAddress(hLibCtl3d, "Ctl3dColorChange", "Pascal",   ;
  1600.                    "void", "")
  1601. CallDLL(cDLL)
  1602. return
  1603.  
  1604.  
  1605. static procedure Ctl3dRegister(hInst)
  1606. local    cDLL := GetProcAddress(hLibCtl3d, "Ctl3dRegister", "Pascal",   ;
  1607.                    "void", "int")
  1608. CallDLL(cDLL, hInst)
  1609. return
  1610.  
  1611.  
  1612. static procedure Ctl3dAutoSubclass(hInst)
  1613. local    cDLL := GetProcAddress(hLibCtl3d, "Ctl3dAutoSubclass", "Pascal",   ;
  1614.                    "void", "int")
  1615. CallDLL(cDLL, hInst)
  1616. return
  1617.  
  1618.  
  1619. static procedure Ctl3dUnregister(hInst)
  1620. local    cDLL := GetProcAddress(hLibCtl3d, "Ctl3dUnregister", "Pascal",   ;
  1621.                    "void", "int")
  1622. CallDLL(cDLL, hInst)
  1623. return
  1624.  
  1625.  
  1626. //
  1627. // Dialog Procedure
  1628. //
  1629. static function Ctl3dDialog(hDlg, nMsg, nwParam, nlParam)
  1630.  
  1631. do case
  1632. case nMsg == WM_INITDIALOG
  1633.     SendDlgItemMessage(hDlg, 101, WM_SETTEXT, 0, "Try Tabbing")
  1634.     SendDlgItemMessage(hDlg, 102, WM_SETTEXT, 0, "Try Tabbing")
  1635.     return 1            // want system to set the focus
  1636. case nMsg == WM_COMMAND
  1637.     do case
  1638.     case nwParam == IDOK
  1639.            EndDialog(hDlg, nwParam)
  1640.     case nwParam == 130
  1641.         MessageBox(hDlg, "This is a sample Message Box", "3d Look", MB_OK)
  1642.     endcase
  1643. case nMsg == WM_SYSCOLORCHANGE
  1644.     // this only happens if the desktop colours are changed
  1645.     // (so you can omit it if you like)
  1646.     Ctl3dColorChange()
  1647. otherwise
  1648.     return 0
  1649. endcase
  1650. return 1
  1651.  
  1652.  
  1653. static procedure BigDialog()
  1654. local    hDLL
  1655. // first, from this app's EXE file
  1656. DialogBox( , "sample3d", ,    ;
  1657.       {|hWndDlg, msg, wparam, lparam| Ctl3dDialog(hWndDlg, msg, wparam, lparam)})
  1658. // next, from a resource-only DLL
  1659. hDLL = LoadLibrary("dlgres.dll")
  1660. DialogBox(hDLL, "sample3d", ,    ;
  1661.       {|hWndDlg, msg, wparam, lparam| Ctl3dDialog(hWndDlg, msg, wparam, lparam)})
  1662. FreeLibrary(hDLL)
  1663. return
  1664.  
  1665.  
  1666. static procedure Ctl3d(lOn)
  1667. local    hInst := _GetInstance()
  1668.  
  1669. if lOn .and. hLibCtl3d == nil
  1670.     hLibCtl3d := LoadLibrary("ctl3d.dll")
  1671.     if hLibCtl3d == nil .or. hLibCtl3d < 32
  1672.         MessageBox( , "Unable to find CTL3D.DLL", "Error", MB_ICONSTOP)
  1673.         hLibCtl3d := nil
  1674.     else
  1675.         Ctl3dRegister(hInst)
  1676.         Ctl3dAutoSubclass(hInst)
  1677.     endif
  1678. elseif !lOn .and. hLibCtl3d != nil
  1679.     Ctl3dUnregister(hInst)
  1680.     FreeLibrary(hLibCtl3d)
  1681.     hLibCtl3d := nil
  1682. endif
  1683. Menu3dUpdate()
  1684. return
  1685.  
  1686.  
  1687. static procedure Menu3dUpdate()
  1688. local cItem := "3d"
  1689. local hMenu
  1690.  
  1691. if !IsWindow(hWnd)
  1692.     return
  1693. endif
  1694.  
  1695. hMenu := GetMenu(hWnd)            // get reference to main menu
  1696. if hLibCtl3d == nil
  1697.     // either turned it off, or an error (e.g. no DLL)
  1698.     CheckMenuItem(hMenu, cItem, MF_UNCHECKED)
  1699. else
  1700.     // 3d is now on
  1701.     CheckMenuItem(hMenu, cItem, MF_CHECKED)
  1702. endif
  1703. return
  1704.  
  1705.  
  1706. static procedure DoMenu3d(cItem)
  1707. local hMenu := GetMenu(hWnd)            // get reference to main menu
  1708. local nCheck := CheckMenuItem(hMenu, cItem)    // current state
  1709. Ctl3d(nCheck != MF_CHECKED)            // want opposite of current
  1710. return
  1711.  
  1712.  
  1713.  
  1714. function nstr(n)
  1715. return alltrim(str(n)) + " "
  1716.  
  1717.  
  1718.  
  1719. function asString(x)
  1720. local    v := valtype(x), i, n, c
  1721. do case
  1722.    case v == "C"
  1723.    case v == "N"
  1724.       return nstr(x)
  1725.    case v == "L"
  1726.       return iif(x, ".T.", ".F.")
  1727.    case v == "D"
  1728.       return dtoc(x)
  1729.    case v == "U"
  1730.       return "NIL"
  1731.    case v == "A"
  1732.     c = "{"
  1733.     n := len(x)
  1734.     for i = 1 to n
  1735.         c += asString(x[i])
  1736.         if i != n
  1737.             c += ", "
  1738.         endif
  1739.     next i
  1740.     c += "}"
  1741.     return c
  1742.    case v == "O"
  1743.       return x:classname() + " {...}"
  1744.    case v == "B"
  1745.       return "{|| ...}"
  1746.    otherwise
  1747.       return ""
  1748. end case
  1749. return x
  1750.  
  1751.  
  1752.  
  1753. #ifdef SEE_MESSAGES
  1754.  
  1755.  
  1756.  
  1757. function asMsg(nMsg)
  1758. static    aMsg :=                            ;
  1759. {                                ;
  1760.     {WM_COMPACTING,        "WM_COMPACTING"},        ;
  1761.     {WM_WININICHANGE,    "WM_WININICHANGE"},        ;
  1762.     {WM_SYSCOLORCHANGE,    "WM_SYSCOLORCHANGE"},        ;
  1763.     {WM_QUERYNEWPALETTE,    "WM_QUERYNEWPALETTE"},        ;
  1764.     {WM_PALETTEISCHANGING,    "WM_PALETTEISCHANGING"},    ;
  1765.     {WM_PALETTECHANGED,    "WM_PALETTECHANGED"},        ;
  1766.     {WM_FONTCHANGE,        "WM_FONTCHANGE"},        ;
  1767.     {WM_SPOOLERSTATUS,    "WM_SPOOLERSTATUS"},        ;
  1768.     {WM_DEVMODECHANGE,    "WM_DEVMODECHANGE"},        ;
  1769.     {WM_TIMECHANGE,        "WM_TIMECHANGE"},        ;
  1770.     {WM_NULL,        "WM_NULL"},            ;
  1771.     {WM_USER,        "WM_USER"},            ;
  1772.     {WM_PENWINFIRST,    "WM_PENWINFIRST"},        ;
  1773.     {WM_PENWINLAST,        "WM_PENWINLAST"},        ;
  1774.     {WM_COALESCE_FIRST,    "WM_COALESCE_FIRST"},        ;
  1775.     {WM_COALESCE_LAST,    "WM_COALESCE_LAST"},        ;
  1776.     {WM_POWER,        "WM_POWER"},            ;
  1777.     {WM_QUERYENDSESSION,    "WM_QUERYENDSESSION"},        ;
  1778.     {WM_ENDSESSION,        "WM_ENDSESSION"},        ;
  1779.     {WM_QUIT,        "WM_QUIT"},            ;
  1780.     {WM_SYSTEMERROR,    "WM_SYSTEMERROR"},        ;
  1781.     {WM_CREATE,        "WM_CREATE"},            ;
  1782.     {WM_DESTROY,        "WM_DESTROY"},            ;
  1783.     {WM_NCCREATE,        "WM_NCCREATE"},            ;
  1784.     {WM_NCDESTROY,        "WM_NCDESTROY"},        ;
  1785.     {WM_SHOWWINDOW,        "WM_SHOWWINDOW"},        ;
  1786.     {WM_SETREDRAW,        "WM_SETREDRAW"},        ;
  1787.     {WM_ENABLE,        "WM_ENABLE"},            ;
  1788.     {WM_SETTEXT,        "WM_SETTEXT"},            ;
  1789.     {WM_GETTEXT,        "WM_GETTEXT"},            ;
  1790.     {WM_GETTEXTLENGTH,    "WM_GETTEXTLENGTH"},        ;
  1791.     {WM_WINDOWPOSCHANGING,    "WM_WINDOWPOSCHANGING"},    ;
  1792.     {WM_WINDOWPOSCHANGED,    "WM_WINDOWPOSCHANGED"},        ;
  1793.     {WM_MOVE,        "WM_MOVE"},            ;
  1794.     {WM_SIZE,        "WM_SIZE"},            ;
  1795.     {WM_QUERYOPEN,        "WM_QUERYOPEN"},        ;
  1796.     {WM_CLOSE,        "WM_CLOSE"},            ;
  1797.     {WM_GETMINMAXINFO,    "WM_GETMINMAXINFO"},        ;
  1798.     {WM_PAINT,        "WM_PAINT"},            ;
  1799.     {WM_ERASEBKGND,        "WM_ERASEBKGND"},        ;
  1800.     {WM_ICONERASEBKGND,    "WM_ICONERASEBKGND"},        ;
  1801.     {WM_NCPAINT,        "WM_NCPAINT"},            ;
  1802.     {WM_NCCALCSIZE,        "WM_NCCALCSIZE"},        ;
  1803.     {WM_NCHITTEST,        "WM_NCHITTEST"},        ;
  1804.     {WM_QUERYDRAGICON,    "WM_QUERYDRAGICON"},        ;
  1805.     {WM_DROPFILES,        "WM_DROPFILES"},        ;
  1806.     {WM_ACTIVATE,        "WM_ACTIVATE"},            ;
  1807.     {WM_ACTIVATEAPP,    "WM_ACTIVATEAPP"},        ;
  1808.     {WM_NCACTIVATE,        "WM_NCACTIVATE"},        ;
  1809.     {WM_SETFOCUS,        "WM_SETFOCUS"},            ;
  1810.     {WM_KILLFOCUS,        "WM_KILLFOCUS"},        ;
  1811.     {WM_KEYDOWN,        "WM_KEYDOWN"},            ;
  1812.     {WM_KEYUP,        "WM_KEYUP"},            ;
  1813.     {WM_CHAR,        "WM_CHAR"},            ;
  1814.     {WM_DEADCHAR,        "WM_DEADCHAR"},            ;
  1815.     {WM_SYSKEYDOWN,        "WM_SYSKEYDOWN"},        ;
  1816.     {WM_SYSKEYUP,        "WM_SYSKEYUP"},            ;
  1817.     {WM_SYSCHAR,        "WM_SYSCHAR"},            ;
  1818.     {WM_SYSDEADCHAR,    "WM_SYSDEADCHAR"},        ;
  1819.     {WM_KEYFIRST,        "WM_KEYFIRST"},            ;
  1820.     {WM_KEYLAST,        "WM_KEYLAST"},            ;
  1821.     {WM_MOUSEMOVE,        "WM_MOUSEMOVE"},        ;
  1822.     {WM_LBUTTONDOWN,    "WM_LBUTTONDOWN"},        ;
  1823.     {WM_LBUTTONUP,        "WM_LBUTTONUP"},        ;
  1824.     {WM_LBUTTONDBLCLK,    "WM_LBUTTONDBLCLK"},        ;
  1825.     {WM_RBUTTONDOWN,    "WM_RBUTTONDOWN"},        ;
  1826.     {WM_RBUTTONUP,        "WM_RBUTTONUP"},        ;
  1827.     {WM_RBUTTONDBLCLK,    "WM_RBUTTONDBLCLK"},        ;
  1828.     {WM_MBUTTONDOWN,    "WM_MBUTTONDOWN"},        ;
  1829.     {WM_MBUTTONUP,        "WM_MBUTTONUP"},        ;
  1830.     {WM_MBUTTONDBLCLK,    "WM_MBUTTONDBLCLK"},        ;
  1831.     {WM_MOUSEFIRST,        "WM_MOUSEFIRST"},        ;
  1832.     {WM_MOUSELAST,        "WM_MOUSELAST"},        ;
  1833.     {WM_NCMOUSEMOVE,    "WM_NCMOUSEMOVE"},        ;
  1834.     {WM_NCLBUTTONDOWN,    "WM_NCLBUTTONDOWN"},        ;
  1835.     {WM_NCLBUTTONUP,    "WM_NCLBUTTONUP"},        ;
  1836.     {WM_NCLBUTTONDBLCLK,    "WM_NCLBUTTONDBLCLK"},        ;
  1837.     {WM_NCRBUTTONDOWN,    "WM_NCRBUTTONDOWN"},        ;
  1838.     {WM_NCRBUTTONUP,    "WM_NCRBUTTONUP"},        ;
  1839.     {WM_NCRBUTTONDBLCLK,    "WM_NCRBUTTONDBLCLK"},        ;
  1840.     {WM_NCMBUTTONDOWN,    "WM_NCMBUTTONDOWN"},        ;
  1841.     {WM_NCMBUTTONUP,    "WM_NCMBUTTONUP"},        ;
  1842.     {WM_NCMBUTTONDBLCLK,    "WM_NCMBUTTONDBLCLK"}        ;
  1843. }
  1844. // these 2 arrays are separate because some Clipper compiler
  1845. // versions fail with Memory Overbooked or other errors
  1846. static    aMsg2 :=                        ;
  1847. {                                ;
  1848.     {WM_MOUSEACTIVATE,    "WM_MOUSEACTIVATE"},        ;
  1849.     {WM_CANCELMODE,        "WM_CANCELMODE"},        ;
  1850.     {WM_TIMER,        "WM_TIMER"},            ;
  1851.     {WM_INITMENU,        "WM_INITMENU"},            ;
  1852.     {WM_INITMENUPOPUP,    "WM_INITMENUPOPUP"},        ;
  1853.     {WM_MENUSELECT,        "WM_MENUSELECT"},        ;
  1854.     {WM_MENUCHAR,        "WM_MENUCHAR"},            ;
  1855.     {WM_COMMAND,        "WM_COMMAND"},            ;
  1856.     {WM_HSCROLL,        "WM_HSCROLL"},            ;
  1857.     {WM_VSCROLL,        "WM_VSCROLL"},            ;
  1858.     {WM_SETCURSOR,        "WM_SETCURSOR"},        ;
  1859.     {WM_SYSCOMMAND,        "WM_SYSCOMMAND"},        ;
  1860.     {WM_MDICREATE,        "WM_MDICREATE"},        ;
  1861.     {WM_MDIDESTROY,        "WM_MDIDESTROY"},        ;
  1862.     {WM_MDIACTIVATE,    "WM_MDIACTIVATE"},        ;
  1863.     {WM_MDIRESTORE,        "WM_MDIRESTORE"},        ;
  1864.     {WM_MDINEXT,        "WM_MDINEXT"},            ;
  1865.     {WM_MDIMAXIMIZE,    "WM_MDIMAXIMIZE"},        ;
  1866.     {WM_MDITILE,        "WM_MDITILE"},            ;
  1867.     {WM_MDICASCADE,        "WM_MDICASCADE"},        ;
  1868.     {WM_MDIICONARRANGE,    "WM_MDIICONARRANGE"},        ;
  1869.     {WM_MDIGETACTIVE,    "WM_MDIGETACTIVE"},        ;
  1870.     {WM_MDISETMENU,        "WM_MDISETMENU"},        ;
  1871.     {WM_CHILDACTIVATE,    "WM_CHILDACTIVATE"},        ;
  1872.     {WM_INITDIALOG,        "WM_INITDIALOG"},        ;
  1873.     {WM_NEXTDLGCTL,        "WM_NEXTDLGCTL"},        ;
  1874.     {WM_PARENTNOTIFY,    "WM_PARENTNOTIFY"},        ;
  1875.     {WM_ENTERIDLE,        "WM_ENTERIDLE"},        ;
  1876.     {WM_GETDLGCODE,        "WM_GETDLGCODE"},        ;
  1877.     {WM_CTLCOLOR,        "WM_CTLCOLOR"},            ;
  1878.     {WM_SETFONT,        "WM_SETFONT"},            ;
  1879.     {WM_GETFONT,        "WM_GETFONT"},            ;
  1880.     {WM_DRAWITEM,        "WM_DRAWITEM"},            ;
  1881.     {WM_MEASUREITEM,    "WM_MEASUREITEM"},        ;
  1882.     {WM_DELETEITEM,        "WM_DELETEITEM"},        ;
  1883.     {WM_COMPAREITEM,    "WM_COMPAREITEM"},        ;
  1884.     {WM_VKEYTOITEM,        "WM_VKEYTOITEM"},        ;
  1885.     {WM_CHARTOITEM,        "WM_CHARTOITEM"},        ;
  1886.     {WM_QUEUESYNC,        "WM_QUEUESYNC"},        ;
  1887.     {WM_COMMNOTIFY,        "WM_COMMNOTIFY"},        ;
  1888.     {WM_CUT,        "WM_CUT"},            ;
  1889.     {WM_COPY,        "WM_COPY"},            ;
  1890.     {WM_PASTE,        "WM_PASTE"},            ;
  1891.     {WM_CLEAR,        "WM_CLEAR"},            ;
  1892.     {WM_UNDO,        "WM_UNDO"},            ;
  1893.     {WM_RENDERFORMAT,    "WM_RENDERFORMAT"},        ;
  1894.     {WM_RENDERALLFORMATS,    "WM_RENDERALLFORMATS"},        ;
  1895.     {WM_DESTROYCLIPBOARD,    "WM_DESTROYCLIPBOARD"},        ;
  1896.     {WM_DRAWCLIPBOARD,    "WM_DRAWCLIPBOARD"},        ;
  1897.     {WM_PAINTCLIPBOARD,    "WM_PAINTCLIPBOARD"},        ;
  1898.     {WM_SIZECLIPBOARD,    "WM_SIZECLIPBOARD"},        ;
  1899.     {WM_VSCROLLCLIPBOARD,    "WM_VSCROLLCLIPBOARD"},        ;
  1900.     {WM_HSCROLLCLIPBOARD,    "WM_HSCROLLCLIPBOARD"},        ;
  1901.     {WM_ASKCBFORMATNAME,    "WM_ASKCBFORMATNAME"},        ;
  1902.     {WM_CHANGECBCHAIN,    "WM_CHANGECBCHAIN"}        ;
  1903. }
  1904. static    lNotDone := .t.
  1905. local    i, n := len(aMsg), cRet := alltrim(str(nMsg))
  1906.  
  1907. if lNotDone
  1908.     aeval(aMsg2, {|a| aadd(aMsg, a)})
  1909. //    MessageBox( , atail(aMsg)[2], "Should be CHANGECBCHAIN")
  1910.     lNotDone := .f.
  1911. endif
  1912. for i = 1 to n
  1913.     if aMsg[i, 1] == nMsg
  1914.         cRet = aMsg[i, 2]
  1915.         exit
  1916.     endif
  1917. next i
  1918. return cRet
  1919.  
  1920.  
  1921.  
  1922.  
  1923.  
  1924. function aShow(aChoices)
  1925. local    aDlg, nRet, cText
  1926. aDlg = CreateDialog("aShow",                        ;
  1927.             WS_CAPTION + WS_SYSMENU + WS_GROUP + WS_TABSTOP    ;
  1928.             + WS_THICKFRAME + WS_VISIBLE + WS_POPUP,        ;
  1929.             20, 10, 300, 200)
  1930.  
  1931. aDlg = AppendDialog(aDlg, "listbox", DLG_LISTBOX,            ;
  1932.             WS_CHILD + WS_VISIBLE + WS_VSCROLL + WS_BORDER    ;
  1933.             + WS_TABSTOP + LBS_USETABSTOPS,            ;
  1934.             10, 10, 280, 160,                    ;
  1935.             aChoices)
  1936. aDlg = AppendDialog(aDlg, "ok", DLG_BUTTON,                ;
  1937.             BS_DEFPUSHBUTTON + WS_TABSTOP + WS_CHILD + WS_VISIBLE,  ;
  1938.             100, 175, 40, 15,                    ;
  1939.             "&Ok")
  1940. aDlg = AppendDialog(aDlg, "cancel", DLG_BUTTON,                ;
  1941.             BS_PUSHBUTTON + WS_TABSTOP + WS_CHILD + WS_VISIBLE,    ;
  1942.             160, 175, 40, 15,                    ;
  1943.             "&Cancel")
  1944.  
  1945. if ModalDialog(aDlg) = 0 .or. GetDialogResult(aDlg, "cancel") = .T.
  1946.     nRet = 0
  1947. else
  1948.     cText = GetDialogResult(aDlg, "listbox")
  1949.     nRet = ascan(aChoices, cText)
  1950. endif
  1951.  
  1952. return nRet
  1953.  
  1954.  
  1955.  
  1956. static procedure DumpDlog()
  1957. local    i, n := len(aDlog), a := {}, aDlogi
  1958. MessageBox( , asString(n), "len(aDlog)")
  1959. for i = 1 to n
  1960.     aDlogi = aDlog[i]
  1961.     aadd(a, asString(aDlogi[1])                ;
  1962.         + chr(9) + asMsg(aDlogi[2])            ;
  1963.         + chr(9) + asString(aDlogi[3])            ;
  1964.         + chr(9) + asString(C4W_LoWord(aDlogi[4]))    ;
  1965.         + chr(9) + asString(C4W_HiWord(aDlogi[4])))
  1966. next i
  1967. aShow(a)
  1968. return
  1969.  
  1970.  
  1971.  
  1972. static procedure DumpEdit()
  1973. local    i, n := len(aEdit), a := {}, aEditi
  1974. for i = 1 to n
  1975.     aEditi = aEdit[i]
  1976.     aadd(a, asString(aEditi[1])                ;
  1977.         + chr(9) + asMsg(aEditi[2])            ;
  1978.         + chr(9) + asString(aEditi[3])            ;
  1979.         + chr(9) + asString(C4W_LoWord(aEditi[4]))    ;
  1980.         + chr(9) + asString(C4W_HiWord(aEditi[4])))
  1981. next i
  1982. aShow(a)
  1983. return
  1984.  
  1985. #endif // SEE_MESSAGES
  1986.  
  1987.  
  1988.  
  1989. static function ToggleItem(cItem)
  1990. local hMenu := GetMenu(hWnd)       // retrieve reference to main menu
  1991. local nCheck := CheckMenuItem(hMenu, cItem)
  1992. CheckMenuItem(hMenu, cItem, if(nCheck == MF_CHECKED, MF_UNCHECKED, MF_CHECKED))
  1993. return nil
  1994.  
  1995.  
  1996.  
  1997. function MenuSetup()
  1998. local    hWnd := SelectWindow(), hMenu, hPopupMenu
  1999.  
  2000. if (hMenu := GetMenu(hWnd)) != nil
  2001.     DestroyMenu(hMenu)
  2002. endif
  2003.  
  2004. // do new one (forget old value)
  2005. hMenu = CreateMenu()
  2006. hPopupMenu = CreatePopupMenu()
  2007. AppendMenu(hMenu, "file", MF_ENABLED + MF_POPUP, "&File", hPopupMenu)
  2008. AppendMenu(hPopupMenu, "exit", MF_ENABLED + MF_STRING, "E&xit", {|c| DoExit(c) })
  2009. hPopupMenu = CreatePopupMenu()
  2010. AppendMenu(hMenu, "view", MF_ENABLED + MF_POPUP, "&View", hPopupMenu)
  2011. AppendMenu(hPopupMenu, "big", MF_ENABLED + MF_STRING, "&Big Dialog", {|| BigDialog()})
  2012. hPopupMenu = CreatePopupMenu()
  2013. AppendMenu(hMenu, "modal", MF_ENABLED + MF_POPUP, "&Modal", hPopupMenu)
  2014. AppendMenu(hPopupMenu, "dynmodal", MF_ENABLED + MF_STRING, "&Dynamic", {|| DynModal()})
  2015. AppendMenu(hPopupMenu, "dynget", MF_ENABLED + MF_STRING, "Dynamic &Get", {|| DynModalGet()})
  2016. AppendMenu(hPopupMenu, "dynusermodal", MF_ENABLED + MF_STRING, "&User details (dyn)", {|| DynUserModal()})
  2017. AppendMenu(hPopupMenu, "resmodal", MF_ENABLED + MF_STRING, "&Resource", {|| ResModal()})
  2018. AppendMenu(hPopupMenu, "resmodify", MF_ENABLED + MF_STRING, "&Modified Res", {|| ResModify()})
  2019. AppendMenu(hPopupMenu, "usermodal", MF_ENABLED + MF_STRING, "&User details (res)", {|| UserModal()})
  2020. hPopupMenu = CreatePopupMenu()
  2021. AppendMenu(hMenu, "modeless", MF_ENABLED + MF_POPUP, "Modele&ss", hPopupMenu)
  2022. AppendMenu(hPopupMenu, "dynmodeless", MF_ENABLED + MF_STRING, "&Dynamic", {|| DynModeless()})
  2023. AppendMenu(hPopupMenu, "resmodeless", MF_ENABLED + MF_STRING, "&Resource", {|| ResModeless()})
  2024. hPopupMenu = CreatePopupMenu()
  2025. AppendMenu(hMenu, "options", MF_ENABLED + MF_POPUP, "&Options", hPopupMenu)
  2026. AppendMenu(hPopupMenu, "font", MF_ENABLED + MF_STRING, "&Font", {|| DoFont()})
  2027. AppendMenu(hPopupMenu, "3d", MF_ENABLED + MF_STRING, "3&d Effects", {|c| DoMenu3d(c)})
  2028. hPopupMenu = CreatePopupMenu()
  2029. AppendMenu(hMenu, "help", MF_ENABLED + MF_POPUP, "&Help", hPopupMenu)
  2030. AppendMenu(hPopupMenu, "about", MF_ENABLED + MF_STRING, "&About", {|| DoAbout()})
  2031. SetMenu(hWnd, hMenu)
  2032. return hMenu
  2033.  
  2034.  
  2035.