home *** CD-ROM | disk | FTP | other *** search
/ BUG 4 / BUGCD1997_05.BIN / aplic / clip4win / clip4win.exe / C4W30E.HUF / SOURCE / TOOLBAR.PRG < prev    next >
Text File  |  1994-08-30  |  10KB  |  341 lines

  1. ////////////////////////////
  2. //
  3. //    toolbar.prg
  4. //
  5. //    Copyright (C) 1993 Skelton Software, Kendal Cottage, Hillam, Leeds, UK.
  6. //    All Rights Reserved.
  7. //
  8. //    Example toolbar program.
  9. //
  10. ////////////////////////////
  11.  
  12. #define    WIN_WANT_ALL
  13. #include "windows.ch"
  14. #include "msg.ch"
  15. #include "paint.ch"
  16.  
  17.  
  18. #define    APPNAME        "ToolBar"
  19. #define    ID_TOOLBAR    1000
  20. #define    ID_BTN1        101
  21. #define    ID_BTN2        102
  22. #define    ID_BTN3        103
  23. #define    ID_BTN4        104
  24. #define    ID_BTN5        105
  25. #define    ID_CHILD    2000        // this is the window the user
  26.                     // doesn't know about
  27. #define    TB_HEIGHT    30
  28.  
  29.  
  30. #ifndef LIB_ONLY
  31.  
  32.  
  33. function main()
  34. local    hWnd, aRect, hTBWnd
  35. local    aMsg[MSG_LENGTH]
  36. local    cDIB := ReadDIB("play.bmp")
  37. local    aButtons := { {10, 5, 40, 20, cDIB, ID_BTN1},    ; // all the
  38.               {60, 5, 40, 20, cDIB, ID_BTN2},    ; // same
  39.               {110, 5, 40, 20, cDIB, ID_BTN3},    ; // bitmap
  40.               {160, 5, 40, 20, cDIB, ID_BTN4},    ; // for simplicity
  41.               {210, 5, 40, 20, cDIB, ID_BTN5} }
  42.  
  43. // set up the main window
  44. hWnd = WndSetup(APPNAME, "Clip-4-Win Tool Bar Demo",    ;
  45.         {|hWnd, nMsg, nwParam, nlParam|        ;
  46.          WndProc(hWnd, nMsg, nwParam, nlParam)},;
  47.         {WM_DESTROY, WM_COMMAND, WM_SIZE},    ;
  48.         ,,,,        ; // default x,y,w,h
  49.         ,,,        ; // default icon, cursor, background brush
  50.         WS_OVERLAPPEDWINDOW + WS_CLIPCHILDREN)    // window style
  51. /*
  52.  *  This sample puts the toolbar at the top of the main window's client
  53.  *  area.  You could use the remaining part as normal, but this can be
  54.  *  painful, as it's all too easy to cause output in the part occupied
  55.  *  by the toolbar.  Instead, create a child window with no borders (so
  56.  *  the user doesn't know it exists) and make it fill the area not used
  57.  *  by the toolbar.  Of course, this means changing its size if the main
  58.  *  window changes size (msg WM_SIZE).  The toolbar size needs to change
  59.  *  as well (just the width in this example).
  60.  *
  61.  *  This same technique can be useful at other times, e.g. the child
  62.  *  might be a multi-line edit control.
  63.  *
  64.  *  If you had a status bar, the easiest way to handle it is to put it
  65.  *  at the bottom of the main window, and reduce the child window's height
  66.  *  by the height of the status bar.
  67.  */
  68.  
  69. aRect = GetClientRect(hWnd)
  70. hTBWnd = ToolBar(hWnd, 0, 0, aRect[3], TB_HEIGHT, aButtons, ID_TOOLBAR)
  71. if !RegisterClass(CS_HREDRAW + CS_VREDRAW + CS_DBLCLKS, , , , , "MyChild",;
  72.           {|hW, nMsg, nw, nl| DoChild(hW, nMsg, nw, nl)},    ;
  73.           {WM_PAINT, WM_COMMAND})
  74.     MessageBox( , "Can't register class", "Error", MB_ICONSTOP)
  75.     quit    // failed
  76. endif
  77. CreateWindow("MyChild", , WS_CHILD + WS_VISIBLE,    ;
  78.          0, TB_HEIGHT, aRect[3], aRect[4] - TB_HEIGHT, hWnd, ID_CHILD)
  79.  
  80. do while GetMessage(aMsg, 0, 0, 0)
  81.     TranslateMessage(aMsg)
  82.     DispatchMessage(aMsg)    // WndProc() often gets called from here
  83. enddo
  84.  
  85. if IsWindow(hWnd)
  86.     DestroyWindow(hWnd)
  87. endif
  88.  
  89. UnregisterClass(APPNAME, _GetInstance())
  90.  
  91. return 0
  92.  
  93.  
  94.  
  95. function WndProc(hWnd, nMsg, nwParam, nlParam)
  96. local    hTBWnd, hWndChild, nW, nH
  97.  
  98. do case
  99. case nMsg == WM_COMMAND
  100.     // You could send it on to the child:
  101.     //    SendDlgItemMessage(hWnd, ID_CHILD, nMsg, nwParam, nlParam)
  102.     // (try it -- this works for a parent/child as well as for a dialog).
  103.     // However, the child is the selected window, so Clipper's
  104.     // output will go there:
  105.     @ 5,1 say "Parent: WM_COMMAND id = " + ltrim(str(nwParam)) + "     "
  106. case nMsg == WM_SIZE
  107.     hTBWnd = GetDlgItem(hWnd, ID_TOOLBAR)    // works for non-dialogs too
  108.     hWndChild = GetDlgItem(hWnd, ID_CHILD)
  109.     if nwParam == SIZE_RESTORED .or. nwParam == SIZE_MAXIMIZED
  110.         nW = C4W_LoWord(nlParam)
  111.         nH = C4W_HiWord(nlParam)
  112.         // put toolbar at top of main client area, then child client
  113.         if IsWindow(hTBWnd)    // this should be true
  114.             MoveWindow(hTBWnd, 0, 0, nW, TB_HEIGHT, .t.)
  115.         endif
  116.         if IsWindow(hWndChild)
  117.             MoveWindow(hWndChild, 0, TB_HEIGHT, nW, nH - TB_HEIGHT, .t.)
  118.         endif
  119.     endif
  120. case nMsg == WM_DESTROY
  121.     // leave out this, and you can't exit!!
  122.     PostQuitMessage(0)
  123.  
  124. otherwise
  125.     // This could _only_ get used with WM_USER and above msgs -- because
  126.     // of the array of msgs we specified with RegisterClass() -- and we're
  127.     // not using WM_USER etc.  However, it's always a good idea to allow
  128.     // for the unexpected.
  129.  
  130.     return DefWindowProc(hWnd, nMsg, nwParam, nlParam)
  131. endcase
  132.  
  133. return 0    // 0 means we processed the msg
  134.  
  135.  
  136.  
  137. function DoChild(hWnd, nMsg, nwParam, nlParam)
  138. local    aPaint[PS_LENGTH], hDC
  139.  
  140. do case
  141. case nMsg == WM_COMMAND
  142.     @ 5,1 say "Child: WM_COMMAND id = " + ltrim(str(nwParam)) + "     "
  143. case nMsg == WM_PAINT
  144.     hDC = BeginPaint(hWnd, aPaint)
  145.     TextOut(hDC, 150, 150, "Clip-4-Win ToolBar Test")
  146.     EndPaint(hWnd, aPaint)
  147. otherwise
  148.     return DefWindowProc(hWnd, nMsg, nwParam, nlParam)
  149. endcase
  150.  
  151. return 0    // 0 means we processed the msg
  152.  
  153.  
  154. #endif // !LIB_ONLY
  155.  
  156.  
  157. //
  158. // ToolBar() -- general-purpose function for a toolbar of bitmap buttons
  159. //
  160. //    hWnd        parent window to own the toolbar
  161. //    nX, nY, nW, nH    toolbar position & size within parent
  162. //    aButtons    array of buttons:
  163. //            { {x,y,w,h, cDIB | hBmp, nMenuId} , ... }
  164. //        where
  165. //            x,y,w,h    position & size of button in toolbar
  166. //            cDIB    device-independent bitmap
  167. //            hBmp    a bitmap handle
  168. //            nMenuId    the menu id to send if the button is
  169. //                pressed (and released)
  170. //    nId        ID of toolbar
  171. //    hBrush        optional brush for background
  172. //
  173. function ToolBar(hWnd, nX, nY, nW, nH, aButtons, nId, hBrush)
  174. static    lWClass := .f., aBtn
  175. local    hWin, hCurWnd := SelectWindow()
  176. if hBrush == nil
  177.     hBrush = GetStockObject(LTGRAY_BRUSH)    // typical colour for a toolbar
  178. endif
  179. aBtn = aButtons
  180. if !lWClass
  181.     // register a window class to capture the mouse messages
  182.     if !(lWClass := RegisterClass(CS_HREDRAW + CS_VREDRAW,    ;
  183.                 , , , hBrush, "C4WTlBar",    ;
  184.                 {|hW, nMsg, nw, nl|        ;
  185.                  DoToolBar(hW, nMsg, nw, nl, aBtn, hWnd)},;
  186.                 {WM_PAINT,            ;
  187.                  WM_LBUTTONDOWN, WM_MOUSEMOVE,    ;
  188.                  WM_LBUTTONUP}))
  189.         return 0    // failed
  190.     endif
  191. endif
  192.  
  193. if (hWin := CreateWindow("C4WTlBar", , WS_CHILD + WS_VISIBLE,    ;
  194.              nX, nY, nW, nH, hWnd, nId)) == 0
  195.     return 0            // failed
  196. endif
  197.  
  198. SelectWindow(hCurWnd)
  199. return hWin
  200.  
  201.  
  202.  
  203. static function DoToolBar(hWnd, nMsg, nwParam, nlParam, aButtons, hWin)
  204. static    lPressed := .f., aBtn, lDrawnDown := .f.
  205. local    nBtn
  206. local    aPaint[PS_LENGTH], hDC, aRect, hOldPen
  207. local    nX, nY
  208.  
  209. do case
  210. case nMsg == WM_MOUSEMOVE
  211.     nX = C4W_LoWord(nlParam)    // mouse pos
  212.     nY = C4W_HiWord(nlParam)
  213.     if lPressed
  214.         // may have moved on or off the button
  215.         if aBtn[1] <= nX .and. nX < aBtn[1]+aBtn[3]    ;
  216.         .and. aBtn[2] <= nY .and. nY < aBtn[2]+aBtn[4]
  217.             // inside the selected button
  218.             if !lDrawnDown
  219.                 // gone back inside the button, so draw it down
  220.                 hDC = GetDC(hWnd)
  221.                 DrawBtn(hDC, aBtn, lDrawnDown := .t.)
  222.                 ReleaseDC(hWnd, hDC)
  223.             endif
  224.         else
  225.             if lDrawnDown
  226.                 // gone outside the button, so draw it up
  227.                 hDC = GetDC(hWnd)
  228.                 DrawBtn(hDC, aBtn, lDrawnDown := .f.)
  229.                 ReleaseDC(hWnd, hDC)
  230.             endif
  231.         endif
  232.     endif
  233.  
  234. case nMsg == WM_LBUTTONDOWN
  235.     nX = C4W_LoWord(nlParam)    // mouse pos
  236.     nY = C4W_HiWord(nlParam)
  237.     nBtn = ascan(aButtons,                        ;
  238.              {|aBtn| aBtn[1] <= nX .and. nX < aBtn[1]+aBtn[3]    ;
  239.                  .and. aBtn[2] <= nY .and. nY < aBtn[2]+aBtn[4]})
  240.     if lPressed := (nBtn != 0)
  241.         hDC = GetDC(hWnd)
  242.         DrawBtn(hDC, aBtn := aButtons[nBtn], lDrawnDown := .t.)
  243.         ReleaseDC(hWnd, hDC)
  244.         SetCapture(hWnd)    // steal all mouse messages
  245.     endif
  246.  
  247. case nMsg == WM_LBUTTONUP
  248.     ReleaseCapture()        // finished stealing mouse messages
  249.     nX = C4W_LoWord(nlParam)    // mouse pos
  250.     nY = C4W_HiWord(nlParam)
  251.     if lDrawnDown
  252.         hDC = GetDC(hWnd)
  253.         DrawBtn(hDC, aBtn, .f.)
  254.         ReleaseDC(hWnd, hDC)
  255.     endif
  256.     // only button up when inside a pressed button sends a message
  257.     if lPressed                        ;
  258.     .and. aBtn[1] <= nX .and. nX < aBtn[1]+aBtn[3]        ;
  259.     .and. aBtn[2] <= nY .and. nY < aBtn[2]+aBtn[4]
  260.         PostMessage(hWin, WM_COMMAND, aBtn[6], 0)
  261.     endif
  262.     lPressed := lDrawnDown := .f.
  263.  
  264. case nMsg == WM_PAINT
  265.     hDC = BeginPaint(hWnd, aPaint)
  266.     aeval(aButtons, {|aBtn| DrawBtn(hDC, aBtn, .f.)})
  267.     // draw a border (if you want 3-D see DrawBtn() for ideas)
  268.     aRect = GetClientRect(hWnd)
  269.     hOldPen = SelectObject(hDC, GetStockObject(BLACK_PEN))
  270.     MoveTo(hDC, 0, 0)
  271.     LineTo(hDC, nX := aRect[3] - 1, 0)    // -1 to be inside aRect
  272.     LineTo(hDC, nX, nY := aRect[4] - 1)
  273.     LineTo(hDC, 0, nY)
  274.     LineTo(hDC, 0, 0)
  275.     SelectObject(hDC, hOldPen)
  276.     EndPaint(hWnd, aPaint)
  277.  
  278. otherwise
  279.     return DefWindowProc(hWnd, nMsg, nwParam, nlParam)
  280. endcase
  281.  
  282. return 0    // 0 means we processed the msg
  283.  
  284.  
  285.  
  286. static procedure DrawBtn(hDC, aBtn, lPressed)
  287. local    nDX, nDY
  288. local    nLeft, nTop, nRight, nBottom
  289. local    hMemDC, hOldBmp
  290. local    hOldPen
  291.  
  292. nLeft = aBtn[1]
  293. nTop = aBtn[2]
  294. nRight = nLeft + aBtn[3]
  295. nBottom = nTop + aBtn[4]
  296.  
  297. if lPressed
  298.     nDX := nDY := 2        // shift across and down
  299. else
  300.     nDX := nDY := 0
  301. endif
  302.  
  303. if valtype(aBtn[5]) == "N"
  304.     // a bitmap handle
  305.     hMemDC := CreateCompatibleDC(hDC)
  306.     hOldBmp := SelectObject(hMemDC, aBtn[5])
  307.     BitBlt(hDC, nLeft + nDX, nTop + nDY, aBtn[3], aBtn[4],    ;
  308.            hMemDC, 0, 0)
  309.     SelectObject(hMemDC, hOldBmp)
  310.     DeleteDC(hMemDC)
  311. else
  312.     ShowDIB(hDC, aBtn[5], nLeft + nDX, nTop + nDY)
  313. endif
  314.  
  315. hOldPen = SelectObject(hDC, GetStockObject(BLACK_PEN))
  316. // draw border
  317. MoveTo(hDC, nLeft, nBottom)
  318. LineTo(hDC, nLeft, nTop)
  319. LineTo(hDC, nRight, nTop)
  320. LineTo(hDC, nRight, nBottom)
  321. LineTo(hDC, nLeft, nBottom)
  322. // draw 3-d effect
  323. SelectObject(hDC, GetStockObject(iif(lPressed, BLACK_PEN, WHITE_PEN)))
  324. nLeft++ ; nRight-- ; nTop++ ; nBottom--
  325. MoveTo(hDC, nLeft, nBottom)
  326. LineTo(hDC, nLeft, nTop)
  327. LineTo(hDC, nRight, nTop)
  328. SelectObject(hDC, GetStockObject(iif(lPressed, WHITE_PEN, BLACK_PEN)))
  329. LineTo(hDC, nRight, nBottom)
  330. LineTo(hDC, nLeft, nBottom)
  331. SelectObject(hDC, hOldPen)
  332.  
  333. return
  334.  
  335.  
  336. static function CreateCompatibleDC(hDC)
  337. local hLib := LoadLibrary("GDI.EXE")
  338. local c := GetProcAddress(hLib, "CreateCompatibleDC", "Pascal", ;
  339.               "int", "int")
  340. return CallDLL(c, hDC)
  341.