home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / vos2-121.zip / v / srcos2 / vbtncmd.cpp < prev    next >
C/C++ Source or Header  |  1999-02-25  |  15KB  |  442 lines

  1. //===============================================================
  2. // vbtncmd.cpp - button Cmd - Windows
  3. //
  4. // Copyright (C) 1995-1999  Bruce E. Wampler
  5. //
  6. // This file is part of the V C++ GUI Framework, and is covered
  7. // under the terms of the GNU Library General Public License,
  8. // Version 2. This library has NO WARRANTY. See the source file
  9. // vapp.cxx for more complete information about license terms.
  10. //===============================================================
  11. #include <v/vos2.h>     // for OS/2 stuff
  12. #include <v/vbtncmd.h>  // our definitions
  13. #include <v/vcmdprnt.h> // a command parent
  14. #include <v/vutil.h>
  15. #include <v/vicon.h>
  16. #include <v/vapp.h>
  17.  
  18.   // Toggle buttons are subclassed to this procedure
  19.   MRESULT EXPENTRY BtnToggleProc(HWND hDlg, ULONG uMsg, MPARAM mp1, MPARAM mp2);
  20.   // this is a pointer to the original button procedure that is subclassed
  21.   PFNWP orgBtnProc;
  22.  
  23. //====================>>> vButtonCmd::vButtonCmd <<<=======================
  24.   vButtonCmd::vButtonCmd(vCmdParent* dp, CommandObject* dc) :
  25.     vCmd(dp, dc)
  26.   {
  27.     initialize();
  28.   }
  29. //====================>>> vButtonCmd::~vButtonCmd <<<=======================
  30.   vButtonCmd::~vButtonCmd()
  31.   {
  32.     SysDebug(Destructor,"vButtonCmd::~vButtonCmd() destructor\n")
  33.   }
  34. //=====================>>> vButtonCmd::initialize <<<=======================
  35.   void vButtonCmd::initialize()
  36.   {
  37.     // build a button command for use in a parent window
  38.     SysDebug(Constructor,"vButtonCmd::vButtonCmd() constructor\n")
  39.     long style;
  40.  
  41.     // set the Pres Params to the system default color
  42.     _PPColor[0].PPtype = PP_BACKGROUNDCOLORINDEX;
  43.     _PPColor[0].PPval.color = SYSCLR_BUTTONMIDDLE;
  44.     _PPColor[1].PPtype = PP_FOREGROUNDCOLORINDEX;
  45.     _PPColor[1].PPval.color = SYSCLR_MENUTEXT;
  46.     _PPColor[2].PPtype = 0;    // end of array marker
  47.  
  48.     if (_parentWin->_dialogType != aCmdBar)
  49.     style = WS_TABSTOP | WS_GROUP;  // default for a dialog button
  50.     else
  51.     style = WS_GROUP | BS_NOPOINTERFOCUS;
  52.  
  53.     CopyToLocal();                      // Make local copies of CmdObject
  54.  
  55.     if (!(dlgCmd->attrs & CA_Hidden))   // Check for Hidden
  56.     style |= WS_VISIBLE;
  57.  
  58.     if ((dlgCmd->cmdType == C_IconButton || dlgCmd->cmdType == C_ToggleIconButton)
  59.     && _itemList != 0) // icon
  60.     {
  61.       initIconButton(style);          // Special init if icon
  62.       return;
  63.     }
  64.  
  65.     if (dlgCmd->cmdType == C_ColorButton) // just set PPs to get a color button
  66.     {
  67.       style |= BS_PUSHBUTTON;
  68.       initColorButton();
  69.     }
  70.     else if (dlgCmd->cmdType == C_ToggleButton) // noop for toggle
  71.     style |= BS_PUSHBUTTON;
  72.  
  73.     else if ((dlgCmd->attrs & CA_DefaultButton))   // default button?
  74.     style |= BS_DEFAULT;
  75.  
  76.     else
  77.     style |= BS_PUSHBUTTON;         // Plain old button
  78.  
  79.     _w = LabelWidth(_title)+14;         // set my width
  80.     _h = LabelHeight() + 5;             // was _h = 14;
  81.  
  82.     if ((dlgCmd->cmdType == C_Button || dlgCmd->cmdType == C_ToggleButton)
  83.       && dlgCmd->size > 0)
  84.     {
  85.       // make sure button is big enough to hold text
  86.       int w = LabelWidth(_title)+14;         // set my width
  87.       if (w < dlgCmd->size)
  88.       {
  89.         _w = dlgCmd->size;
  90.       }
  91.     }
  92.     else if ( dlgCmd->cmdType == C_ColorButton && dlgCmd->size > 0)
  93.     {
  94.       // each y dialog unit is 1/8 the max system font height and
  95.       // each x dialog unit is 1/4 max system font width.  The system
  96.       // proportional font is 8x20 so in pixels one x dialog unit = 2 pixels
  97.       // and one y dialog unit = 2.5 pixels.  Since we want square
  98.       // buttons we need to multiply y by 4/5 to get same size as
  99.       // x on the screen. We then multiply by 1/2 to convert to
  100.       // pixels as desired.
  101.       _w = dlgCmd->size*5/4;          // size - square (color buttons)
  102.       _h = dlgCmd->size;      // simulate pixels using dialog units
  103.     }
  104.     else if (dlgCmd->size > 0)  // size - square (icons)
  105.     {
  106.       _w = dlgCmd->size*5/4;
  107.       _h = dlgCmd->size;
  108.     }
  109.  
  110.     _parentWin->SetPosition(_x, _y, _w, _h, dlgCmd->cFrame, dlgCmd->cRightOf,
  111.       dlgCmd->cBelow);
  112. /*
  113.     if (dlgCmd->cmdType == C_Button || dlgCmd->cmdType == C_ToggleButton)
  114.     {
  115.       _y += 1;     // center better
  116.     }
  117. */
  118.     _CtrlOffset = _parentWin->AddDlgControl(_x, _y, _w, _h, _cmdId,
  119.       style, WC_BUTTON, _title, _parentWin->AssyPresParams(_PPColor), 0, NULL);
  120.   }
  121.  
  122. //=====================>>> vButtonCmd::initColorButton <<<=======================
  123.   void vButtonCmd::initColorButton(void)
  124.   {
  125.     // wCmd is the widget of this button
  126.     _origColor = 0;
  127.     if (_itemList != 0)                         // an RGB provided
  128.     {
  129.       _origColor = (vColor*)_itemList;        // point to the rgb
  130.       _color = *_origColor;
  131.     }
  132.     // set the Pres Params to the specified color
  133.     // we use the RGB version for the background
  134.     _PPColor[0].PPtype = PP_BACKGROUNDCOLOR;
  135.     _PPColor[0].PPval.color = (LONG) _color.pixel();
  136.     _PPColor[1].PPtype = PP_FOREGROUNDCOLORINDEX;
  137.     _PPColor[1].PPval.color = SYSCLR_MENUTEXT;
  138.     _PPColor[2].PPtype = 0;    // end of array marker
  139.   }
  140.  
  141.  
  142. //=====================>>> vButtonCmd::initIconButton <<<====================
  143.   void vButtonCmd::initIconButton(long style)
  144.   {
  145.     style |= BS_BITMAP;
  146.  
  147.     _ip = (vIcon *) _itemList;  // to access bitmap
  148.     _h = LONG( (_ip->height / 2.5) + 6 );
  149.     _w = LONG( (_ip->width / 2) + 6 );
  150.  
  151.     // build up the button control data to point to the desired bitmap
  152.     _btncData.cb = sizeof(BTNCDATA);
  153.     _btncData.fsCheckState = 0;
  154.     _btncData.fsHiliteState = 0;
  155.  
  156.     // get icon HBITMAP
  157.     _btncData.hImage = _ip->GetIconDLG(dlgCmd->cmdType, SYSCLR_BUTTONMIDDLE);
  158.  
  159.     _parentWin->SetPosition(_x, _y, _w, _h, dlgCmd->cFrame,
  160.          dlgCmd->cRightOf, dlgCmd->cBelow);
  161. /*
  162.     // set the Pres Params to the specified color
  163.     // we use the RGB version for the background
  164.     _PPColor[0].PPtype = 13;
  165.     _PPColor[0].PPval.color = SETRGB(0,0,0);
  166.     _PPColor[1].PPtype = 1;
  167.     _PPColor[1].PPval.color = SETRGB(0,0,0);
  168.     _PPColor[2].PPtype = 0;    // end of array marker
  169.  
  170.     _CtrlOffset = _parentWin->AddDlgControl(_x, _y , _w, _h, _cmdId,
  171.        style, WC_BUTTON, "", _parentWin->AssyPresParams(_PPColor),
  172.        _btncData.cb, &_btncData);
  173. */
  174.     _CtrlOffset = _parentWin->AddDlgControl(_x, _y , _w, _h, _cmdId,
  175.        style, WC_BUTTON, "", NULL, _btncData.cb, &_btncData);
  176.  
  177.   }
  178. //==================>>> vButtonCmd::GetCmdValue <<<=========================
  179.   int vButtonCmd::GetCmdValue(ItemVal id) VCONST
  180.   {
  181.     if (id != _cmdId)
  182.       return -1;
  183.     return _retVal;
  184.   }
  185. //==================>>> vButtonCmd::GetCmdValue <<<=========================
  186.   int vButtonCmd::GetOwnCmdValue(void)
  187.   {
  188.     // subclassed toggle buttons call this method to determine
  189.     // the buttons current state. Unfortunately it cannot be
  190.     // private, so... security through obscurity.
  191.     return _retVal;
  192.   }
  193. //================>>> vButtonCmd::ResetItemValue <<<======================
  194.   void vButtonCmd::ResetItemValue(void)
  195.   {
  196.     // We have to toggle things
  197.     if (dlgCmd->cmdType != C_ToggleIconButton &&
  198.       dlgCmd->cmdType != C_ToggleButton)
  199.     return;
  200.     if (_retVal == _origVal)    // No op if no change
  201.     return;
  202.  
  203.     _retVal = _origVal;         // restore
  204.  
  205.     if (_retVal)                        // depends on state
  206.       {
  207.     SetCmdVal(1, Checked);
  208.       }
  209.     else
  210.       {
  211.     SetCmdVal(0, Checked);
  212.       }
  213.  
  214. //    HWND myHwnd = GetMyHwnd(_cmdId);
  215. //    WinShowWindow (myHwnd, FALSE);  // trick to repaint button
  216. //    WinShowWindow (myHwnd, TRUE);
  217.  
  218.     // let parent window handle now
  219.     _parentWin->ProcessCmd(_cmdId, _retVal, dlgCmd->cmdType);
  220.   }
  221.  
  222. //================>>> vButtonCmd::SetCmdVal <<<============================
  223.   void vButtonCmd::SetCmdVal(ItemVal val, ItemSetType st)
  224.   {
  225.     SysDebug1(Misc,"vButtonCmd::SetCmdVal(val:%d)\n",val)
  226.     HWND myHwnd = GetMyHwnd(_cmdId);
  227.  
  228.     switch (st)
  229.     {
  230.       case Sensitive:
  231.     _Sensitive = val;               // set
  232.     WinEnableWindow (myHwnd, val);
  233.     break;
  234.  
  235.       case Hidden:
  236.     if (val)
  237.       {
  238.         WinShowWindow (myHwnd, FALSE);
  239.       }
  240.     else
  241.       {
  242.         WinShowWindow (myHwnd, TRUE);
  243.       }
  244.     break;
  245.  
  246.       case Value:
  247.       case Checked:
  248.     _retVal = val;                  // set
  249.     if (dlgCmd->cmdType != C_ToggleIconButton &&   // only toggles need attention
  250.         dlgCmd->cmdType != C_ToggleButton)
  251.       return;
  252.  
  253. //    WinCheckButton(_parentWin->getParent(),_cmdId, val);
  254.     SysDebug2(OS2Dev,"--> val:%d _retVal:%d \n",val, _retVal)
  255.     WinSendDlgItemMsg(_parentWin->getParent(), _cmdId,
  256.       BM_SETHILITE, MPFROMSHORT(val), (MPARAM)NULL);
  257.  
  258. //    HWND myHwnd = GetMyHwnd(_cmdId);
  259.     break;
  260.  
  261.       case ChangeColor:               // changed original vColor
  262.       {
  263.     _color = *_origColor;       // recopy color
  264.  
  265.     // set the Pres Params to the specified color
  266.     // we use the RGB version of the PP_
  267.     _PPColor[0].PPtype = PP_BACKGROUNDCOLOR;
  268.     _PPColor[0].PPval.color = (LONG) _color.pixel();
  269.  
  270.         // if the user calls ChangeColor before the dialog is
  271.         // displayed then the control won't exist and WinSetPresParams
  272.         // will fail.  We need to check for this and change the dialog
  273.         // template PresParams instead if the dialog has not been created.
  274.         if (myHwnd)
  275.         {
  276.       WinSetPresParam(myHwnd, _PPColor[0].PPtype, (ULONG) sizeof(RGB),
  277.         (PVOID) &_PPColor[0].PPval.color);
  278.         }
  279.         else
  280.         {
  281.           _parentWin->ChangeDlgTButtonColor(_CtrlOffset, _cmdId,
  282.             _PPColor[0].PPval.color );
  283.         }
  284.     break;
  285.       }
  286.  
  287.       case Red:
  288.     _color.SetR(val);
  289.     break;
  290.  
  291.       case Green:
  292.     _color.SetG(val);
  293.     break;
  294.  
  295.       case Blue:
  296.       {
  297.     _color.SetB(val);
  298.     _PPColor[0].PPtype = PP_BACKGROUNDCOLOR;
  299.     _PPColor[0].PPval.color = (LONG) _color.pixel();
  300.     WinSetPresParam(myHwnd, _PPColor[0].PPtype, (ULONG) sizeof(RGB),
  301.       (PVOID) &_PPColor[0].PPval.color);
  302.  
  303.     break;
  304.       }
  305.     }
  306.   }
  307.  
  308. //==================>>> vButtonCmd::ToggleCmdValue <<<=========================
  309.   int vButtonCmd::ToggleCmdValue(void)
  310.   {
  311.     SysDebug1(OS2Dev,"ToggleCmdValue org _retVal:%d \n",_retVal)
  312.     SetCmdVal(!_retVal, Checked);
  313.     return _retVal;
  314.   }
  315.  
  316. //==================>>> vButtonCmd::userClick <<<=========================
  317.   int vButtonCmd::userClick(int clicked)
  318.   {
  319.     // This routine lets the first BM_SETHILITE message sent
  320.     // after a user clicks on the button to be passed
  321.     // through to the button control unaltered.  This is
  322.     // necessary so that the button can change state and issue
  323.     // the required WM_COMMAND.  All BM_SETHILITE messages after
  324.     // the first one are filtered and set to _retVal
  325.     SysDebug1(OS2Dev,"Userclick click:%d \n",_click)
  326.     if (clicked)
  327.     {
  328.       _click = 1;
  329.       return _click;
  330.     }
  331.     else
  332.     {
  333.       if (_click)
  334.       {
  335.     _click = 0;
  336.     return 1;
  337.       }
  338.       return 0;
  339.     }
  340.   }
  341.  
  342. //================>>> vButtonCmd::SetCmdStr <<<============================
  343.   void vButtonCmd::SetCmdStr(char* str)
  344.   {
  345.     // Set the string value of button
  346.     SysDebug1(Misc,"vButtonCmd::SetCmdStr(str:%s)\n",str)
  347.     WinSetDlgItemText(_parentWin->getParent(),_cmdId, str);
  348.     _title = str;
  349.   }
  350.  
  351.  
  352. //================>>> vButtonCmd::DRAWITEM <<<============================
  353.   int vButtonCmd::DRAWITEM(int id, OWNERITEM* poi)
  354.   {
  355.     // This really has nothing to do with DRAWITEM, but its
  356.     // an unused procedure that we can hijak and use to subclass
  357.     // toggle buttons during the WM_INITDLG setup
  358.  
  359.     if (dlgCmd->cmdType == C_ToggleIconButton ||
  360.        dlgCmd->cmdType == C_ToggleButton)
  361.     {
  362.       // This is called during WM_INITDLG for toggle buttons
  363.       // so we can subclass the button procedure
  364. //      HWND hBtn = WinWindowFromID((HWND)poi, id);
  365.       HWND hBtn = GetMyHwnd(id);
  366.       WinSetWindowULong(hBtn, QWL_USER, (LONG) this);
  367.       WinSendMsg(hBtn, BM_SETHILITE, MPFROMSHORT(_retVal), (MPARAM)NULL);
  368.       _orgBtnProc = WinSubclassWindow(hBtn, BtnToggleProc);
  369.       SysDebug2(OS2Dev,"DRAWITEM this:%x hBtn:%x \n", this, hBtn)
  370. //         HWND myHwnd = GetMyHwnd(_cmdId);
  371. //         if (SHORT1FROMMP((MPARAM) poi) == FALSE)  // losing focus
  372. //           WinPostMsg(myHwnd, BM_SETHILITE, MPFROMSHORT(_retVal), (MPARAM)NULL);
  373.     }
  374.     return (0);
  375.   }
  376.  
  377. //====================>>> BtnToggleProc <<<=======================
  378. // we subclass the C_ToggleButton so we can control its
  379. // hilited state and stop the WC_FRAME class from interfering
  380.   MRESULT EXPENTRY BtnToggleProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
  381.   {
  382.     vButtonCmd* thisCmd = (vButtonCmd*) WinQueryWindowULong( hwnd, QWL_USER ); // Pointer from window word
  383.     if (!thisCmd)
  384.     {
  385.       return (MRESULT) WinDefDlgProc(hwnd, msg, mp1, mp2);
  386.     }
  387.     else
  388.       return (MRESULT) thisCmd->vBtnToggleProc(hwnd, msg, mp1, mp2);
  389.   }
  390.  
  391.  
  392.  
  393. //====================>>> vBtnToggleProc <<<=======================
  394. // we subclass the C_ToggleButton so we can control its
  395. // hilited state and stop the WC_FRAME class from interfering
  396.   MRESULT vButtonCmd::vBtnToggleProc(HWND hBtn, ULONG uMsg, MPARAM mp1, MPARAM mp2)
  397.   {
  398.     // set the original frame procedure
  399.     orgBtnProc = (PFNWP) _orgBtnProc;
  400.  
  401.     switch (uMsg)
  402.     {
  403.       case BM_SETHILITE:
  404.       {
  405.         // prevent frame from altering toggle button state
  406.         // by trapping any attempt to alter buttons state
  407.         // with its private BM_SETHILITE messages and replacing
  408.         // it with the desired state
  409.         if (!userClick(0))  // check if pending click
  410.       mp1 = MPFROMSHORT(GetOwnCmdValue());
  411.         SysDebug3(OS2Dev,"BtnToggleProc this:%x hBtn:%x mp1:%x \n", this, hBtn, mp1)
  412.       }
  413.       break;
  414.  
  415.       case WM_BUTTON1DOWN:
  416.       {
  417.         // user has clicked on the button, so toggle the button state
  418.         // so that _retVal gets updated befor the BM_SETHILITE is sent
  419.         userClick(1);     // button is clicked so pass through next
  420.                           // BM_SETHILITE
  421.       }
  422.       break;
  423.   }
  424.   return orgBtnProc(hBtn, uMsg, mp1, mp2);
  425. }
  426.  
  427. //====================>>> vButtondCmd::CmdCallback <<<=======================
  428.   void vButtonCmd::CmdCallback(UINT uMsg, MPARAM mp1, MPARAM mp2)
  429.   {
  430.     if (uMsg == WM_COMMAND)
  431.     {
  432.       if (dlgCmd->cmdType == C_ToggleIconButton ||        // depends on state
  433.       dlgCmd->cmdType == C_ToggleButton)
  434.       {
  435.         SysDebug3(OS2Dev,"CmdCallBack uMsg:%x mp1:%x mp2:%x \n", uMsg, mp1, mp2)
  436.         SetCmdVal(!_retVal, Checked);
  437.       }
  438.     }
  439.     // let parent window handle now
  440.     _parentWin->ProcessCmd(_cmdId, _retVal, dlgCmd->cmdType);
  441.   }
  442.