/* BitMapButton's have a normal and a selected bitmap.
   Bitmaps are part of the .exe and are named.
   BitMapButton Parent's responsibilities:
      Propagate WM_DRAWITEM messages to the proper button.
      Implement command( buttonID, ignorableCode ).
      Resize/Move via: setCRect(but, rect); moveWindow(but); invalidate(self)
      destroy(but) when closing.

 Misc Notes:
    A bitMapButton has BS_OWNERDRAW in its style bits.
    A bitMapButton's initial size is 0 0 0 0.
    show( but, any ) does not do anything useful -- use invalidate.
 */!!

inherit(Button, #BitMapButton, #(normalBM
selectedBM), 2, nil)!!

now(class(BitMapButton))!!

/* PUBLIC */
Def style(self)
{ ^( style(self:ancestor) bitOr BS_OWNERDRAW bitOr WS_BORDER )
}
!!

/* PUBLIC -- normID and selectID are bitmap resource numbers */
Def new(self, id, par, name, normIDstr, selectIDstr | theBut)
{ theBut := new(self:Behavior);
  if init(theBut, id, par, normIDstr, selectIDstr)
  then
    create(theBut, name, "BUTTON", 
              WS_VISIBLE bitOr WS_CHILD bitOr BS_OWNERDRAW);
    ^theBut;
  else
    /*@@ break("failed button"); @@*/
    ^nil ; /* failed */
  endif ;
}!!

now(BitMapButton)!!

/* WINDOWS -- from ownerdraw buttons */
Def WM_DRAWITEM(self, wP, lP )
{ 
/*@@{
   printLine("WM_DRAWITEM: (wP, lP) = ("
             + asHex(wP) + ", " + asHex(lP) + ")" );
   printLine("itemAction = " + asHex(wordAt(lP+6)) +
             ", itemState = " + asHex(wordAt(lP+8)) ) ;
}@@*/

  /* lP is a pointer to a DRAWITEMSTRUCT struct */
  /* itemState is lP+8 ; hDC is lP+12 */
  if (wordAt(lP+8) bitAnd ODS_SELECTED) = ODS_SELECTED
  then
    drawSelected( self, wordAt(lP+12) ) ;
  else 
    drawNormal(   self, wordAt(lP+12) ) ;
  endif ;
}
!!

/* PRIVATE */
Def drawSelected(self, hDC | clientRectangle)
{ /*@@ printLine("Drawing Selected"); @@*/
  clientRectangle := clientRect( self ) ;
  draw( self, left(clientRectangle), top(clientRectangle), 
        clientRectangle, hDC, selectedBM ) ;
}
!!

/* PRIVATE */
Def drawNormal(self, hDC | clientRectangle)
{ /*@@ printLine("Drawing Normal"); @@*/
  clientRectangle := clientRect( self ) ;
  draw( self, left(clientRectangle), top(clientRectangle), 
        clientRectangle, hDC, normalBM ) ;
}
!!

Def destroy(self)
{ 
  (normalBM <> 0)   cand Call DeleteObject( normalBM ) ;
  (selectedBM <> 0) cand Call DeleteObject( selectedBM ) ; 
  destroy( self:ancestor ) ;
}!!

/* PRIVATE -- returns nil on failure */
Def init(self, id, par, normIDstr, selectIDstr | bitmapStruct)
{
  bitmapStruct := new( Struct, 14 ) ;
  setContID(self, id);
  setParent(self, par);
  normalBM := Call LoadBitmap( HInstance, id);
  if (normalBM = 0) then 
    displayFormattedError(ErrorTextLibClass$Inst, 
       ER_CANT_LOAD_BITMAP, FORCE_POPUP, nil, nil, nil);
    ^nil 
  endif ;
  selectedBM := Call LoadBitmap( HInstance, asInt(selectIDstr,10) ) ;
  if (selectedBM = 0) then 
    displayFormattedError(ErrorTextLibClass$Inst, 
       ER_CANT_LOAD_BITMAP, FORCE_POPUP, nil, nil, nil);
    ^nil 
  endif ;
}
!!

/* PRIVATE */
Def draw(self, x, y, rct, hDC, bitMap | hMemDC, w, h)
{
  if bitMap
  then
    w := width( rct )  - x ;
    h := height( rct ) - y ;
    hMemDC := Call CreateCompatibleDC( hDC ) ;
    Call SelectObject( hMemDC, bitMap ) ;
    Call BitBlt( hDC, x, y, w, h, hMemDC, 0, 0, SRCCOPY );
    Call DeleteDC( hMemDC ) ;
  endif ;
}
!!
