home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wclass.zip / CLASSLIB.CPP < prev    next >
Text File  |  1994-04-25  |  15KB  |  527 lines

  1. /*----------------------------------------------------------------------------*/
  2. /* (c) 1993, 1994 Larry Morley / Enlightened Computer Solutions               */
  3. /*----------------------------------------------------------------------------*/
  4. /*   module: classlib.cpp              created_on: 1 May 1993   by: LJM       */
  5. /*   desc  : Main framework class lib source file                             */
  6. /*   complr: icc /Fi /Fd /c /Ss /Sp1 /Gm+ /G4 /Kb+ [/Ti+ intrnl, /Ti- rel]    */
  7. /*   lnkr  : link386 /a:4 [/deb intrnl,rel=<none> /base:65536 /noe            */
  8. /*           rc $*.res                                                        */
  9. /*   etc   : rc -r $*.rc                                                      */
  10. /*   mkfile: makefile                                                         */
  11. /*   depend: (see makefile)                                                   */
  12. /*   mhist : LJM 02 May 1993           Added functionality to Menu class      */
  13. /*----------------------------------------------------------------------------*/
  14.  
  15. #define INCL_WIN
  16. #define INCL_DOS
  17. #define INCL_GPI
  18. #include <os2.h>
  19.  
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #include <string.h>
  23.  
  24. #include "cppapp.hpp"
  25. #include "classlib.hpp"
  26.  
  27. /*----------------------------------------------------------------------------*/
  28. // Class names
  29.  
  30. CHAR    szClientClass[]   = "C++ClientWindow";
  31. CHAR    szFrameClass[]    = "C++FrameWindow";
  32. CHAR    szStatLineClass[] = "C++StatusWindow";
  33.  
  34. CHAR    szStatLineText[256];
  35.  
  36. // Standard style flags
  37. ULONG   ulFrameFlags = FCF_TITLEBAR      | FCF_SYSMENU  |
  38.                        FCF_SIZEBORDER    | FCF_MINMAX   |
  39.                        FCF_SHELLPOSITION | FCF_TASKLIST |
  40.                        FCF_MENU          | FCF_ICON     ;
  41.  
  42. HAB     hab;
  43. HMQ     hmq;
  44. QMSG    qmsg;
  45.  
  46. PFNWP   pfnOrigFrameProc;
  47. USHORT  cbFrameExtra;
  48.  
  49. /*----------------------------------------------------------------------------*/
  50. // These are all pretty straightforward -
  51. //    start by creating an App,
  52. //    create windows or whatever else is needed,
  53. //    and run the App (App->Run()).
  54.  
  55. // Sets up the message queue
  56. App :: App()
  57. {
  58.  
  59.    hab = WinInitialize((USHORT)0);
  60.    hmq = WinCreateMsgQueue(hab,(SHORT)0);
  61.  
  62. }
  63.  
  64. /*----------------------------------------------------------------------------*/
  65. // The message loop
  66.  
  67. void App :: Run()
  68. {
  69.    while (WinGetMsg(hab,&qmsg,(HWND)0,(USHORT)0,(USHORT)0))
  70.       WinDispatchMsg(hab,&qmsg);
  71. }
  72.  
  73. /*----------------------------------------------------------------------------*/
  74. // Cleanup
  75.  
  76. App :: ~App()
  77. {
  78.    WinDestroyMsgQueue(hmq);
  79.    WinTerminate(hab);
  80. }
  81.  
  82. /*----------------------------------------------------------------------------*/
  83. // Cleanup
  84.  
  85. Window :: ~Window()
  86. {
  87.    WinDestroyWindow(hwndFrame);
  88. }
  89.  
  90. /*----------------------------------------------------------------------------*/
  91. // These methods all apply to the hwndMenu member of the window -
  92. //    I won't describe them in detail, since they're pretty much
  93. //    straightforward.
  94.  
  95. void Menu :: DisableItem(Window *pWindow,USHORT idItem)
  96. {
  97.    WinSendMsg(
  98.       pWindow->hwndMenu,
  99.       MM_SETITEMATTR,
  100.       MPFROM2SHORT(
  101.          idItem,
  102.          TRUE),
  103.       MPFROM2SHORT(
  104.          MIA_DISABLED,
  105.          MIA_DISABLED));
  106. }
  107.  
  108. /*----------------------------------------------------------------------------*/
  109.  
  110. void Menu :: EnableItem(Window *pWindow,USHORT idItem)
  111. {
  112.    WinSendMsg(
  113.       pWindow->hwndMenu,
  114.       MM_SETITEMATTR,
  115.       MPFROM2SHORT(
  116.          idItem,
  117.          TRUE),
  118.       MPFROM2SHORT(
  119.          MIA_DISABLED,
  120.          FALSE));
  121. }
  122.  
  123. /*----------------------------------------------------------------------------*/
  124.  
  125. void Menu :: CheckItem(Window *pWindow,USHORT idItem)
  126. {
  127.    WinSendMsg(
  128.       pWindow->hwndMenu,
  129.       MM_SETITEMATTR,
  130.       MPFROM2SHORT(
  131.          idItem,
  132.          TRUE),
  133.       MPFROM2SHORT(
  134.          MIA_CHECKED,
  135.          MIA_CHECKED));
  136. }
  137.  
  138. /*----------------------------------------------------------------------------*/
  139.  
  140. void Menu :: UnCheckItem(Window *pWindow,USHORT idItem)
  141. {
  142.    WinSendMsg(
  143.       pWindow->hwndMenu,
  144.       MM_SETITEMATTR,
  145.       MPFROM2SHORT(
  146.          idItem,
  147.          TRUE),
  148.       MPFROM2SHORT(
  149.          MIA_CHECKED,
  150.          FALSE));
  151. }
  152.  
  153. /*----------------------------------------------------------------------------*/
  154. // Create a frame window with a status bar / message bar at the bottom
  155.  
  156. BOOL Window :: Create()
  157. {
  158.    // Take an existing class (WC_FRAME), get its
  159.    // window proc, add extra room (window words)
  160.    // and re-register it under my own classname.
  161.    CLASSINFO ci;
  162.    WinQueryClassInfo(hab,WC_FRAME,&ci);
  163.    pfnOrigFrameProc = ci.pfnWindowProc;
  164.    cbFrameExtra     = ci.cbWindowData;
  165.  
  166.    // Try to re-register; return FALSE if
  167.    // attempt fails
  168.    if (!WinRegisterClass(
  169.       hab,
  170.       szFrameClass,
  171.       FrameWndProc,
  172.       ci.flClassStyle & (~CS_PUBLIC),
  173.       ci.cbWindowData+sizeof(this)))
  174.          return FALSE;
  175.  
  176.    // Register the client window class
  177.    // (I should probably check here)
  178.    WinRegisterClass(
  179.       hab,
  180.       szClientClass,
  181.       ClientWndProc,
  182.       CS_SIZEREDRAW,
  183.       sizeof(this));
  184.  
  185.    // Register the status window class
  186.    // (should probably check here too)
  187.    WinRegisterClass(
  188.       hab,
  189.       szStatLineClass,
  190.       StatLineWndProc,
  191.       CS_SIZEREDRAW,
  192.       sizeof(this));
  193.  
  194.    // Start creating windows: I don't use WinCreateStdWindow(),
  195.    // create each piece individually.  That gives me the
  196.    // flexibility of being able to put a pointer to "this" in
  197.    // the components of the window.
  198.    // To do it this way, start with the frame:
  199.    hwndFrame = WinCreateWindow(
  200.       HWND_DESKTOP,             /* parent        */
  201.       szFrameClass,             /* class         */
  202.       "Main Window",            /* title         */
  203.       0L,                       /* style         */
  204.       0,                        /* x             */
  205.       0,                        /* y             */
  206.       0,                        /* cx            */
  207.       0,                        /* cy            */
  208.       (HWND)0,                  /* owner         */
  209.       HWND_TOP,                 /* z-order       */
  210.       ID_RESOURCE,              /* window id     */
  211.       this,                     /* control parms */
  212.       (PVOID)0);                /* pres parms    */
  213.  
  214.    if (!hwndFrame)
  215.       return FALSE;
  216.  
  217.    // Then, create the client with an id
  218.    // of FID_CLIENT (very important)
  219.    hwndClient = WinCreateWindow(
  220.       hwndFrame,
  221.       szClientClass,
  222.       (PSZ)0,
  223.       0L,
  224.       0,
  225.       0,
  226.       0,
  227.       0,
  228.       hwndFrame,
  229.       HWND_TOP,
  230.       FID_CLIENT,
  231.       (PVOID)this,
  232.       (PVOID)0);
  233.  
  234.    if (!hwndClient)
  235.       return FALSE;
  236.  
  237.    // And lastly, I create the status
  238.    // bar window
  239.    hwndStatus = WinCreateWindow(
  240.       hwndFrame,
  241.       szStatLineClass,
  242.       (PSZ)0,
  243.       0L,
  244.       0,
  245.       0,
  246.       0,
  247.       0,
  248.       hwndFrame,
  249.       HWND_TOP,
  250.       FID_STATUS,
  251.       (PVOID)this,
  252.       (PVOID)0);
  253.  
  254.    if (!hwndStatus)
  255.       return FALSE;
  256.  
  257.    // Set the window's text and show it
  258.    WinSetWindowText(hwndFrame,"C++ PM Application by Larry Morley");
  259.    WinShowWindow(hwndFrame,TRUE);
  260.  
  261.    return TRUE;
  262.  
  263. }
  264.  
  265. /*----------------------------------------------------------------------------*/
  266. // Event handler for WM_PAINT
  267.  
  268. MRESULT Window :: PaintEventHandler(HWND hwnd,ULONG msg,MPARAM mp1,MPARAM mp2)
  269. {
  270.    HPS   hPS;
  271.    RECTL rcl;
  272.  
  273.    hPS = WinBeginPaint(hwnd,(HPS)0,&rcl);
  274.    GpiErase(hPS);
  275.    WinEndPaint(hPS);
  276.  
  277.    return (MRESULT)0;
  278. }
  279.  
  280. /*----------------------------------------------------------------------------*/
  281. // Event handler for WM_MENUSELECT
  282.  
  283. MRESULT Window :: MenuSelectEventHandler
  284.    (HWND hwnd,ULONG msg,MPARAM mp1,MPARAM mp2)
  285. {
  286.    return WinDefWindowProc(hwnd,msg,mp1,mp2);
  287. }
  288.  
  289. /*----------------------------------------------------------------------------*/
  290. // Event handler for WM_COMMAND (mostly for menu)
  291.  
  292. MRESULT Window :: CommandEventHandler(HWND hwnd,ULONG msg,MPARAM mp1,MPARAM mp2)
  293. {
  294.    return WinDefWindowProc(hwnd,msg,mp1,mp2);
  295. }
  296.  
  297. /*----------------------------------------------------------------------------*/
  298. // This is how I make room for the status bar window at the bottom, and
  299. // actually make it an integral part of the frame.
  300.  
  301. MRESULT Window :: FormatFrameEventHandler
  302.    (HWND hwnd,ULONG msg,MPARAM mp1,MPARAM mp2)
  303. {
  304.    int origCount;
  305.    // The original proc returns the number of items in the frame window
  306.    origCount = (int)((*pfnOrigFrameProc)(hwnd,msg,mp1,mp2));
  307.    // Enumerate them and look for FID_CLIENT
  308.    if (origCount)
  309.    {
  310.       int i;
  311.       for (i=0;i<origCount;i++)
  312.       {
  313.          if (WinQueryWindowUShort(((PSWP)mp1)[i].hwnd,QWS_ID)
  314.             == FID_CLIENT)
  315.          {
  316.             HWND hwndTemp;
  317.  
  318.             // Position the status / message / whatever bar
  319.             hwndTemp=WinWindowFromID(hwnd,FID_STATUS);
  320.  
  321.             if (hwndTemp)
  322.                WinSetWindowPos(hwndTemp,
  323.                   HWND_TOP,
  324.                   ((PSWP)mp1)[i].x,
  325.                   ((PSWP)mp1)[i].y,
  326.                   ((PSWP)mp1)[i].cx,
  327.                   25,
  328.                   ((PSWP)mp1)[i].fl);
  329.  
  330.             // And adjust the size of the client
  331.             // area accordingly (it's fixed at 25
  332.             // right now; you could base it on
  333.             // pretty much anything you wish)
  334.             ((PSWP)mp1)[i].y  += 25;
  335.             ((PSWP)mp1)[i].cy -= 25;
  336.  
  337.          }
  338.       }
  339.    }
  340.    // Tell PM how many parts are in the frame
  341.    return (MRESULT)origCount;
  342. }
  343.  
  344. /*----------------------------------------------------------------------------*/
  345.  
  346. MRESULT EXPENTRY ClientWndProc(HWND hwnd,ULONG msg,MPARAM mp1,MPARAM mp2)
  347. {
  348.  
  349.    Window *w;
  350.    MRESULT rc;
  351.  
  352.    // See if the window contains a pointer to
  353.    // a Window object.
  354.    w = (Window *)WinQueryWindowPtr(hwnd,0);
  355.  
  356.    switch (msg)
  357.    {
  358.       // WM_CREATE is called directly, not sent; when you
  359.       // call WinCreateWindow() the function calls the window
  360.       // proc with WM_CREATE.  That's why it's safe to set
  361.       // the pointer to the owner object here - I'm guaranteed
  362.       // that nothing else will happen in the meantime.
  363.       case WM_CREATE:
  364.  
  365.          WinSetWindowPtr(hwnd,0,(PVOID)mp1);
  366.  
  367.          ((Window *)mp1)->hwndMenu =
  368.             WinWindowFromID(
  369.                WinQueryWindow(hwnd,QW_PARENT),FID_MENU);
  370.  
  371.          break;
  372.  
  373.       // The rest of the code just dispatches messages
  374.       // to the appropriate event handlers.
  375.       case WM_PAINT:
  376.  
  377.          rc = w->PaintEventHandler(hwnd,msg,mp1,mp2);
  378.          return rc;
  379.  
  380.       case WM_COMMAND:
  381.  
  382.          rc = w->CommandEventHandler(hwnd,msg,mp1,mp2);
  383.          return rc;
  384.  
  385.       case WM_MENUSELECT:
  386.  
  387.          rc = w->MenuSelectEventHandler(hwnd,msg,mp1,mp2);
  388.          return rc;
  389.  
  390.    }
  391.  
  392.    return WinDefWindowProc(hwnd,msg,mp1,mp2);
  393.  
  394. }
  395.  
  396. /*----------------------------------------------------------------------------*/
  397. // This is my "replacement" frame window procedure -
  398. //    I get the information I want, then pass the rest along
  399. //    to the default procedure.  It's also where I catch the
  400. //    WM_FORMATFRAME message.
  401.  
  402. MRESULT EXPENTRY FrameWndProc(HWND hwnd,ULONG msg,MPARAM mp1,MPARAM mp2)
  403. {
  404.    switch (msg)
  405.    {
  406.       case WM_CREATE:
  407.          // mp1 is a pointer to "this" -
  408.          //    set it up here for the same
  409.          //    reasons as for the client window.
  410.          WinSetWindowPtr(hwnd,cbFrameExtra,(PVOID)mp1);
  411.  
  412.          // Alter the frame data that I want
  413.          // to change...
  414.          FRAMECDATA fcdata;
  415.          fcdata.cb = sizeof(fcdata);
  416.          fcdata.flCreateFlags = ulFrameFlags;
  417.          fcdata.hmodResources = (HMODULE)0L;
  418.          fcdata.idResources = ID_RESOURCE;
  419.          return (*pfnOrigFrameProc)(hwnd,msg,(MPARAM)&fcdata,mp2);
  420.  
  421.       case WM_FORMATFRAME:
  422.          // Invoke Window::FormatFrameEventHandler()
  423.          Window *w;
  424.          MRESULT rc;
  425.          w = (Window *)WinQueryWindowPtr(hwnd,cbFrameExtra);
  426.          rc = w->FormatFrameEventHandler(hwnd,msg,mp1,mp2);
  427.          return rc;
  428.  
  429.       case WM_MENUSELECT:
  430.          // This case is nescessary in the frame window proc
  431.          // because that's where the system menu MENUSELECTS
  432.          // are sent.
  433.          w = (Window *)WinQueryWindowPtr(hwnd,cbFrameExtra);
  434.          rc = w->MenuSelectEventHandler(hwnd,msg,mp1,mp2);
  435.          return rc;
  436.  
  437.       default:
  438.          break;
  439.  
  440.    }
  441.  
  442.    // Can't use WinDefWindowProc(); have to use the default
  443.    // WC_FRAME window proc.
  444.    return (*pfnOrigFrameProc)(hwnd,msg,mp1,mp2);
  445.  
  446. }
  447.  
  448. /*----------------------------------------------------------------------------*/
  449. // This is a pretty straightforward window procedure; it's the window proc
  450. // for the status / message / whatever area.
  451.  
  452. MRESULT EXPENTRY StatLineWndProc(HWND hwnd,ULONG msg,MPARAM mp1,MPARAM mp2)
  453. {
  454.    HPS    hPS;
  455.    RECTL  rcl;
  456.    POINTL ptl;
  457.    LONG   lColor;
  458.  
  459.    static SHORT cxClient;
  460.    static SHORT cyClient;
  461.    static int   cyChar;
  462.    static int   cyDesc;
  463.    static int   cxChar;
  464.    static int   cxCaps;
  465.  
  466.    switch (msg)
  467.    {
  468.       case WM_CREATE:
  469.  
  470.          FONTMETRICS fm;
  471.          hPS = WinGetPS(hwnd);
  472.          GpiQueryFontMetrics(hPS,(LONG)sizeof(fm),&fm);
  473.          cyChar = (int)fm.lMaxBaselineExt;
  474.          cyDesc = (int)fm.lMaxDescender;
  475.          cxChar = (int)fm.lEmInc;
  476.          cxCaps = (int)fm.lAveCharWidth;
  477.          WinReleasePS(hPS);
  478.  
  479.          strcpy(szStatLineText,"Ready.");
  480.  
  481.          break;
  482.  
  483.       case WM_SIZE:
  484.  
  485.          cxClient = SHORT1FROMMP(mp2);
  486.          cyClient = SHORT2FROMMP(mp2);
  487.  
  488.          break;
  489.  
  490.       case WM_PAINT:
  491.  
  492.          hPS = WinBeginPaint(hwnd,(HPS)0,&rcl);
  493.          WinFillRect(hPS,&rcl,CLR_PALEGRAY);
  494.  
  495.          lColor = GpiQueryColor(hPS);
  496.          GpiSetColor(hPS,CLR_DARKGRAY);
  497.  
  498.          ptl.x = 0;
  499.          ptl.y = cyClient-1;
  500.          GpiMove(hPS,&ptl);
  501.          ptl.x = cxClient-1;
  502.          ptl.y = cyClient-1;
  503.          GpiLine(hPS,&ptl);
  504.          ptl.x = cxClient-1;
  505.          ptl.y = 0;
  506.          GpiLine(hPS,&ptl);
  507.  
  508.          GpiSetColor(hPS,lColor);
  509.  
  510.          ptl.x = 2;
  511.          ptl.y = cyClient-cyChar-1;
  512.          GpiCharStringAt(hPS,&ptl,strlen(szStatLineText),szStatLineText);
  513.  
  514.          WinEndPaint(hPS);
  515.  
  516.          break;
  517.  
  518.       default:
  519.  
  520.          return WinDefWindowProc(hwnd,msg,mp1,mp2);
  521.  
  522.    }
  523.    return (MRESULT)0L;
  524. }
  525.  
  526. /*----------------------------------------------------------------------------*/
  527.