home *** CD-ROM | disk | FTP | other *** search
/ BUG 4 / BUGCD1997_05.BIN / aplic / clip4win / clip4win.exe / C4W30E.HUF / SOURCE / ODRAW.PRG < prev    next >
Text File  |  1993-10-19  |  11KB  |  413 lines

  1. ////////////////////////////
  2. //
  3. //    odraw.prg
  4. //
  5. //    Copyright (C) 1993 Skelton Software, Kendal Cottage, Hillam, Leeds, UK.
  6. //    All Rights Reserved.
  7. //
  8. //    Owner Draw examples.
  9. //
  10. ////////////////////////////
  11.  
  12. #define    WIN_WANT_ALL
  13. #include "windows.ch"
  14. #include "msg.ch"
  15. #include "paint.ch"
  16. #include "drawitem.ch"
  17.  
  18. // You can define this to get TAB, arrows, etc. between controls,
  19. // like in a dialog.  Don't define it if you don't want these keystrokes
  20. // used that way!
  21. #define    LIKE_DIALOG
  22.  
  23. #define    APPNAME    "ODRAW"
  24.  
  25. #ifdef    LIKE_DIALOG
  26. #define    BUTTONSTYLE    WS_CHILD + WS_VISIBLE + BS_OWNERDRAW + WS_TABSTOP
  27. #else
  28. #define    BUTTONSTYLE    WS_CHILD + WS_VISIBLE + BS_OWNERDRAW
  29. #endif    // LIKE_DIALOG
  30.  
  31. #define    IDC_BTN0    10
  32. #define    IDC_BTN1    11
  33. #define    IDC_BTN2    12
  34. #define    IDC_BTN3    13
  35.  
  36.  
  37. static    nBtn := 0            // the button id
  38. static    nBN := 0            // notification code
  39.  
  40.  
  41. function main()
  42. local    hWnd
  43. local    aMsg[MSG_LENGTH]
  44. local    hBtn0, hBtn1, hBtn2, hBtn3
  45.  
  46. // set up the main window
  47. hWnd = WndSetup(APPNAME, "Clip-4-Win Owner Draw Demo",    ;
  48.         {|hWnd, nMsg, nwParam, nlParam|        ;
  49.          WndProc(hWnd, nMsg, nwParam, nlParam)},;
  50.         {WM_DESTROY,    WM_COMMAND,        ;
  51.          WM_PAINT,                ;
  52.          WM_RBUTTONDOWN,            ;
  53.          WM_DRAWITEM},    ; // sent when time to draw the owner-draw item
  54.         ,,,,        ; // default x,y,w,h
  55.         ,,,        ; // default icon, cursor, background brush
  56.         WS_OVERLAPPEDWINDOW + WS_CLIPCHILDREN)    // window style
  57.  
  58. // a pre-packaged owner-drawn button  (PRG source for BitmapButton() is below)
  59. hBtn0 = BitmapButton(hWnd,        ; // parent
  60.              300, 150,        ; // x,y
  61.              40, 20,        ; // width, height
  62.              ReadDIB("play.bmp"),; // bitmap to show
  63.              {|| SetPos(1,1), qout("single click")},;
  64.              {|| SetPos(1,1), qout("double click")},;
  65.              IDC_BTN0)          // id to use
  66.  
  67. // let's have some owner-drawn buttons
  68. hBtn1 = CreateWindow("button",            ; // wind class
  69.              "",            ; // text
  70.              BUTTONSTYLE,        ; // style
  71.              250, 200,            ; // x,y
  72.              40, 20,            ; // w,h
  73.              hWnd,            ; // parent
  74.              IDC_BTN1)    // the id's are what tell these apart
  75.                 // (hBtn1, hBtn2 etc. would do, too)
  76. hBtn2 = CreateWindow("button",            ;
  77.              "",            ;
  78.              BUTTONSTYLE,        ;
  79.              350, 200,            ;
  80.              40, 20,            ;
  81.              hWnd,            ;
  82.              IDC_BTN2)
  83. hBtn3 = CreateWindow("button",            ;
  84.              "",            ;
  85.              BUTTONSTYLE,        ;
  86.              280, 250,            ;
  87.              80, 40,            ;
  88.              hWnd,            ;
  89.              IDC_BTN3)
  90.  
  91. #ifdef    LIKE_DIALOG
  92.  
  93. SetFocus(hBtn0)
  94.  
  95. do while GetMessage(aMsg, 0, 0, 0)
  96.     if IsWindow(hWnd) .and. !IsDialogMessage(hWnd, aMsg)
  97.     TranslateMessage(aMsg)
  98.     DispatchMessage(aMsg)    // WndProc() often gets called from here
  99.     endif
  100. enddo
  101.  
  102. #else
  103.  
  104. do while GetMessage(aMsg, 0, 0, 0)
  105.     TranslateMessage(aMsg)
  106.     DispatchMessage(aMsg)    // WndProc() often gets called from here
  107. enddo
  108.  
  109. #endif    // LIKE_DIALOG
  110.  
  111. if IsWindow(hWnd)
  112.     DestroyWindow(hWnd)
  113. endif
  114.  
  115. UnregisterClass(APPNAME, _GetInstance())
  116.  
  117. return aMsg[MSG_wParam]
  118.  
  119.  
  120.  
  121. function WndProc(hWnd, nMsg, nwParam, nlParam)
  122. local    aPaint[PS_LENGTH], hDC
  123.  
  124. do case
  125.     case nMsg == WM_PAINT
  126.         hDC = BeginPaint(hWnd, aPaint)
  127.         TextOut(hDC, 50, 100, "Id" + str(nBtn))
  128.         TextOut(hDC, 50, 120, "Notification code" + str(nBN))
  129.         EndPaint(hWnd, aPaint)
  130.         return 0    // 0 means we processed the msg
  131.  
  132.     case nMsg == WM_DRAWITEM
  133.         // decode what/why/who from
  134.         // (using the id, but you could test
  135.         //  C4W_LoWord(nlParam) == hBtn1, etc.)
  136.         do case
  137.         case nwParam == IDC_BTN1
  138.             return DrawBtn1(hWnd, nMsg, nwParam, nlParam)
  139.         case nwParam == IDC_BTN2
  140.             return DrawBtn2(hWnd, nMsg, nwParam, nlParam)
  141.         case nwParam == IDC_BTN3
  142.             return DrawBtn3(hWnd, nMsg, nwParam, nlParam)
  143.         endcase
  144.  
  145.     case nMsg == WM_COMMAND
  146.         do case
  147.         case nwParam == IDC_BTN1    ;
  148.         .or. nwParam == IDC_BTN2    ;
  149.         .or. nwParam == IDC_BTN3
  150.             nBtn = nwParam        // save the id
  151.             nBN = C4W_HiWord(nlParam)  // save the notification code
  152.             InvalidateRect(hWnd)
  153. //    This doesn't appear to be needed...
  154. //#ifdef    LIKE_DIALOG
  155. //            SetFocus(C4W_LoWord(nlParam))
  156. //#endif    // LIKE_DIALOG
  157.             return 0    // 0 means we processed the msg
  158.         endcase
  159.  
  160.     case nMsg == WM_DESTROY
  161.         // leave out this, and you can't exit!!
  162.         PostQuitMessage(0)
  163.         return 0    // 0 means we processed the msg
  164.  
  165.     case nMsg == WM_RBUTTONDOWN
  166.         // GetDlgItem() works for a parent and child
  167.         DestroyWindow(GetDlgItem(hWnd, IDC_BTN0))
  168. endcase
  169.  
  170. // This could _only_ get used with WM_USER and above msgs -- because of
  171. // the array of msgs we specified with RegisterClass() -- and we're
  172. // not using WM_USER etc.  However, it's always a good idea to allow
  173. // for the unexpected.
  174.  
  175. return DefWindowProc(hWnd, nMsg, nwParam, nlParam)
  176.  
  177.  
  178.  
  179. #ifdef    LIKE_DIALOG
  180. #define    BMPBTNSTYLE     WS_CHILD + WS_VISIBLE + WS_TABSTOP
  181. #else
  182. #define    BMPBTNSTYLE     WS_CHILD + WS_VISIBLE
  183. #endif    // LIKE_DIALOG
  184.  
  185. //
  186. // BitmapButton() -- general-purpose function for a button showing a bitmap
  187. //
  188. function BitmapButton(hWnd, nX, nY, nW, nH, cDIB, bClick, bDblClick, nId)
  189. static    lWClass := .f., aBtn := {}
  190. local    hWin, hBtn, hCurWnd := SelectWindow()
  191. if !lWClass
  192.     // register a window class to capture the button messages
  193.     if !(lWClass := RegisterClass(0, , , , , "BmpButtn",    ;
  194.                 {|hW, nMsg, nw, nl|        ;
  195.                  DoBmpBtn(hW, nMsg, nw, nl, aBtn)},;
  196.                 {WM_COMMAND, WM_DESTROY,    ;
  197.                  WM_DRAWITEM, WM_SETFOCUS}))
  198.         return 0    // failed
  199.     endif
  200. endif
  201.  
  202. if (hWin := CreateWindow("BmpButtn", , BMPBTNSTYLE,        ;
  203.              nX, nY, nW, nH, hWnd, nId)) == 0    ;
  204. .or. (hBtn := CreateWindow("button", "", BUTTONSTYLE,        ;
  205.                0, 0, nW, nH, hWin, nId)) == 0
  206.     return 0            // failed
  207. endif
  208.  
  209. aadd(aBtn, {hWin, cDIB, bClick, bDblClick})
  210. SelectWindow(hCurWnd)
  211. return hBtn
  212.  
  213.  
  214.  
  215. static function DoBmpBtn(hWnd, nMsg, nwParam, nlParam, aBtn)
  216. local    i, nBN
  217. local    aDIS, hDC
  218. local    nDX, nDY
  219. local    nLeft, nTop, nRight, nBottom
  220. local    lSelected, hOldPen
  221.  
  222. do case
  223. case nMsg == WM_DRAWITEM
  224.     // nlParam is LPDRAWITEMSTRUCT (i.e. a C pointer to 26 bytes of data)
  225.     aDIS := bin2a(c4w_peek(nlParam, 26), DIS_STRUCT_DEF)
  226.     hDC  := aDIS[DIS_hDC]
  227.     nDX  := nDY := 0
  228.     nLeft := aDIS[DIS_rcLeft]
  229.     nTop := aDIS[DIS_rcTop]
  230.     nRight := aDIS[DIS_rcRight] - 1
  231.     nBottom := aDIS[DIS_rcBottom] - 1
  232.  
  233.     if (i := ascan(aBtn, {|a| a[1] == hWnd})) == 0    ;
  234.     .or. aDIS[DIS_CtlType] != ODT_BUTTON
  235.         return DefWindowProc(hWnd, nMsg, nwParam, nlParam)
  236.     endif
  237.  
  238.     if lSelected := (C4W_And(aDIS[DIS_itemState], ODS_SELECTED) != 0)
  239.         nDX := nDY := 2        // shift across and down
  240.     endif
  241.  
  242.     ShowDIB(hDC, aBtn[i, 2], nDX, nDY)
  243.  
  244.     if C4W_And(aDIS[DIS_itemState], ODS_FOCUS) != 0
  245.         DrawFocusRect(hDC, {nLeft + 4, nTop + 4, nRight - 4, nBottom - 4})
  246.     endif
  247.  
  248.     hOldPen = SelectObject(hDC, GetStockObject(BLACK_PEN))
  249.     // draw border
  250.     MoveTo(hDC, nLeft, nBottom)
  251.     LineTo(hDC, nLeft, nTop)
  252.     LineTo(hDC, nRight, nTop)
  253.     LineTo(hDC, nRight, nBottom)
  254.     LineTo(hDC, nLeft, nBottom)
  255.     // draw 3-d effect
  256.     SelectObject(hDC, GetStockObject(iif(lSelected, BLACK_PEN, WHITE_PEN)))
  257.     nLeft++ ; nRight-- ; nTop++ ; nBottom--
  258.     MoveTo(hDC, nLeft, nBottom)
  259.     LineTo(hDC, nLeft, nTop)
  260.     LineTo(hDC, nRight, nTop)
  261.     SelectObject(hDC, GetStockObject(iif(lSelected, WHITE_PEN, BLACK_PEN)))
  262.     LineTo(hDC, nRight, nBottom)
  263.     LineTo(hDC, nLeft, nBottom)
  264.     SelectObject(hDC, hOldPen)
  265.  
  266.     return 0    // 0 means we processed the msg
  267.  
  268. case nMsg == WM_COMMAND
  269.     if (i := ascan(aBtn, {|a| a[1] == hWnd})) != 0
  270.         // found the button
  271.         if (nBN := C4W_HiWord(nlParam)) == BN_CLICKED
  272.             eval(aBtn[i, 3])
  273.         elseif nBN == BN_DOUBLECLICKED
  274.             eval(aBtn[i, 4])
  275.         endif
  276. //    This doesn't appear to be needed...
  277. //#ifdef    LIKE_DIALOG
  278. //        SetFocus(C4W_LoWord(nlParam))
  279. //#endif    // LIKE_DIALOG
  280.         return 0
  281.     endif
  282.  
  283. #ifdef    LIKE_DIALOG
  284. case nMsg == WM_SETFOCUS
  285. //    ? "SetFocus"
  286.     if (i := ascan(aBtn, {|a| a[1] == hWnd})) != 0
  287. //        ?? " to child", i
  288.         SetFocus(GetWindow(hWnd, GW_CHILD))    // focus to the button
  289.     endif
  290. #endif    // LIKE_DIALOG
  291.  
  292. case nMsg == WM_DESTROY
  293.     if (i := ascan(aBtn, {|a| a[1] == hWnd})) != 0
  294.         adel(aBtn, i)        // remove it, now it's gone
  295.         asize(aBtn, len(aBtn) - 1)
  296.     endif
  297. endcase
  298. return DefWindowProc(hWnd, nMsg, nwParam, nlParam)
  299.  
  300.  
  301.  
  302. // this one's very simple, but doesn't do much
  303. static function DrawBtn1(hWnd, nMsg, nwParam, nlParam)
  304. static    cDIB
  305. // nMsg == WM_DRAWITEM, so nlParam is LPDRAWITEMSTRUCT (i.e. a C pointer)
  306. local    aDIS := bin2a(c4w_peek(nlParam, 26), DIS_STRUCT_DEF)
  307. local    hDC  := aDIS[DIS_hDC]
  308.  
  309. if cDIB == nil
  310.     cDIB = ReadDIB("play.bmp")
  311. endif
  312.  
  313. if aDIS[DIS_CtlType] == ODT_BUTTON
  314.     ShowDIB(hDC, cDIB)
  315.     return 0    // 0 means we processed the msg
  316. endif
  317.  
  318. return DefWindowProc(hWnd, nMsg, nwParam, nlParam)
  319.  
  320.  
  321. // this one's more interesting
  322. static function DrawBtn2(hWnd, nMsg, nwParam, nlParam)
  323. static    cDIB
  324. local    aDIS := bin2a(c4w_peek(nlParam, 26), DIS_STRUCT_DEF)
  325. local    hDC  := aDIS[DIS_hDC]
  326. local    nDX  := 0, nDY := 0
  327. local    nLeft := aDIS[DIS_rcLeft], nTop := aDIS[DIS_rcTop],    ;
  328.     nRight := aDIS[DIS_rcRight] - 1, nBottom := aDIS[DIS_rcBottom] - 1
  329. local    lSelected, hOldPen
  330.  
  331. if aDIS[DIS_CtlType] != ODT_BUTTON
  332.     return DefWindowProc(hWnd, nMsg, nwParam, nlParam)
  333. endif
  334.  
  335. if cDIB == nil
  336.     cDIB = ReadDIB("play.bmp")
  337. endif
  338.  
  339. if lSelected := (C4W_And(aDIS[DIS_itemState], ODS_SELECTED) != 0)
  340.     nDX := nDY := 2            // shift across and down
  341. endif
  342.  
  343. ShowDIB(hDC, cDIB, nDX, nDY)
  344.  
  345. hOldPen = SelectObject(hDC, GetStockObject(BLACK_PEN))
  346. // draw border
  347. MoveTo(hDC, nLeft, nBottom)
  348. LineTo(hDC, nLeft, nTop)
  349. LineTo(hDC, nRight, nTop)
  350. LineTo(hDC, nRight, nBottom)
  351. LineTo(hDC, nLeft, nBottom)
  352. // draw 3-d effect
  353. SelectObject(hDC, GetStockObject(iif(lSelected, BLACK_PEN, WHITE_PEN)))
  354. nLeft++ ; nRight-- ; nTop++ ; nBottom--
  355. MoveTo(hDC, nLeft, nBottom)
  356. LineTo(hDC, nLeft, nTop)
  357. LineTo(hDC, nRight, nTop)
  358. SelectObject(hDC, GetStockObject(iif(lSelected, WHITE_PEN, BLACK_PEN)))
  359. LineTo(hDC, nRight, nBottom)
  360. LineTo(hDC, nLeft, nBottom)
  361. SelectObject(hDC, hOldPen)
  362.  
  363. return 0    // 0 means we processed the msg
  364.  
  365.  
  366. // this one's more interesting
  367. static function DrawBtn3(hWnd, nMsg, nwParam, nlParam)
  368. static    cDIB
  369. local    aDIS := bin2a(c4w_peek(nlParam, 26), DIS_STRUCT_DEF)
  370. local    hDC  := aDIS[DIS_hDC]
  371. local    nDX  := 0, nDY := 0
  372. local    nLeft := aDIS[DIS_rcLeft], nTop := aDIS[DIS_rcTop],    ;
  373.     nRight := aDIS[DIS_rcRight] - 1, nBottom := aDIS[DIS_rcBottom] - 1
  374. local    lSelected, hOldPen
  375.  
  376. if aDIS[DIS_CtlType] != ODT_BUTTON
  377.     return DefWindowProc(hWnd, nMsg, nwParam, nlParam)
  378. endif
  379.  
  380. if cDIB == nil
  381.     cDIB = ReadDIB("play.bmp")
  382. endif
  383.  
  384. if lSelected := (C4W_And(aDIS[DIS_itemState], ODS_SELECTED) != 0)
  385.     nDX := nDY := 2            // shift across and down
  386. endif
  387.  
  388. StretchDIBits(hDC,                ;
  389.           nDX, nDY, nRight, nBottom,    ;
  390.            , , , ,                ;
  391.            , cDIB)
  392.  
  393. hOldPen = SelectObject(hDC, GetStockObject(BLACK_PEN))
  394. // draw border
  395. MoveTo(hDC, nLeft, nBottom)
  396. LineTo(hDC, nLeft, nTop)
  397. LineTo(hDC, nRight, nTop)
  398. LineTo(hDC, nRight, nBottom)
  399. LineTo(hDC, nLeft, nBottom)
  400. // draw 3-d effect
  401. SelectObject(hDC, GetStockObject(iif(lSelected, BLACK_PEN, WHITE_PEN)))
  402. nLeft++ ; nRight-- ; nTop++ ; nBottom--
  403. MoveTo(hDC, nLeft, nBottom)
  404. LineTo(hDC, nLeft, nTop)
  405. LineTo(hDC, nRight, nTop)
  406. SelectObject(hDC, GetStockObject(iif(lSelected, WHITE_PEN, BLACK_PEN)))
  407. LineTo(hDC, nRight, nBottom)
  408. LineTo(hDC, nLeft, nBottom)
  409. SelectObject(hDC, hOldPen)
  410.  
  411. return 0    // 0 means we processed the msg
  412.  
  413.