home *** CD-ROM | disk | FTP | other *** search
/ QBasic & Borland Pascal & C / Delphi5.iso / Pascal / BPASCAL.700 / D11 / RWDEMOS.ZIP / BITBTN.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1992-10-01  |  21.7 KB  |  722 lines

  1. {************************************************}
  2. {                                                }
  3. {   Resource Workshop Demo library               }
  4. {   Copyright (c) 1992 by Borland International  }
  5. {                                                }
  6. {************************************************}
  7.  
  8. library BitBtn;
  9.  
  10. uses WinTypes, WinProcs, Strings, CustCntl, BitBtnCo;
  11.  
  12. {$R BITBTN.RES}
  13.  
  14. { ==============================================================
  15.   Bitmaped button custom control.
  16.   ============================================================== }
  17.  
  18. const
  19.   ofReserved    = 0;  { Used by the dialog manager }
  20.   ofState       = 2;
  21.   ofDownBits    = 4;
  22.   ofUpBits      = 6;
  23.   ofFocUpBits   = 8;
  24.   ofSize        = 10; { Amount of window extra bytes to use }
  25.  
  26. const
  27.   bdBorderWidth = 1;
  28.  
  29. const
  30.   bsDisabled    = $0001;
  31.   bsFocus       = $0002;
  32.   bsKeyDown     = $0004;
  33.   bsMouseDown   = $0008;
  34.   bsMouseUpDown = $0010;
  35.   bsDefault     = $0020;
  36.  
  37. { GetAppInstance -----------------------------------------------
  38.     Returns a handle to the current client application.
  39.   -------------------------------------------------------------- }
  40. function GetAppInstance: THandle; near; assembler;
  41. asm
  42.     PUSH    SS
  43.     CALL    GlobalHandle
  44. end;
  45.  
  46. { IsWorkshopWindow ---------------------------------------------
  47.     Returns true if the window belongs to Resource Workshop.
  48.     Used to determine if the control is being edited; allowing
  49.     the LoadResRW function to be called.
  50.   -------------------------------------------------------------- }
  51. function IsWorkshopWindow(Wnd: HWnd): Boolean;
  52. var
  53.   Parent: HWnd;
  54.   ClassName: array[0..80] of Char;
  55. begin
  56.   Parent := Wnd;
  57.   repeat
  58.     Wnd := Parent;
  59.     Parent := GetParent(Wnd);
  60.   until Parent = 0;
  61.   GetClassName(Wnd, ClassName, SizeOf(ClassName));
  62.   IsWorkshopWindow := StrComp(ClassName, 'rwswnd') = 0;
  63. end;
  64.  
  65. { LoadResRW ----------------------------------------------------
  66.     Load a resource from Resource Workshop. Initialized by
  67.     ListClasses below.
  68.   -------------------------------------------------------------- }
  69. var
  70.   LoadResRW: TLoad;
  71.  
  72. { LoadBitmapRW -------------------------------------------------
  73.     Load a bitmap from Resource Workshop.  *MUST* be called from
  74.     inside resource workshop (IsWorkshopWindow must be true).
  75.   -------------------------------------------------------------- }
  76. function LoadBitmapRW(szTitle: PChar): HBitmap;
  77. var
  78.   Res: THandle;
  79.   Bits: PBitMapInfoHeader;
  80.   DC: HDC;
  81.   nColors: Integer;
  82.   Ret: HBitmap;
  83.  
  84. function GetDInColors(BitCount: Integer): Integer;
  85. begin
  86.   case BitCount of
  87.     1, 3, 4, 8: GetDInColors := 1 shl BitCount;
  88.   else
  89.     GetDInColors := 0;
  90.   end;
  91. end;
  92.  
  93. begin
  94.   LoadBitmapRW := 0;
  95.   Res := LoadResRW(rt_Bitmap, szTitle);
  96.   if Res <> 0 then
  97.   begin
  98.     Bits := GlobalLock(Res);
  99.     if Bits^.biSize = SizeOf(TBitMapInfoHeader) then
  100.     begin
  101.       nColors := GetDInColors(Bits^.biBitCount);
  102.       DC := GetDC(0);
  103.       if DC <> 0 then
  104.       begin
  105.     LoadBitmapRW := CreateDIBitmap(DC, Bits^, cbm_Init,
  106.       Pointer(LongInt(Bits) + SizeOf(Bits^) +
  107.       nColors * SizeOf(TRGBQuad)), PBitmapInfo(Bits)^,
  108.       dib_RGB_Colors);
  109.     ReleaseDC(0, DC);
  110.       end;
  111.     end;
  112.     GlobalUnlock(Res);
  113.     GlobalFree(Res);
  114.   end;
  115. end;
  116.  
  117. { BitButtonWinFn -----------------------------------------------
  118.     Button window procedure.
  119.   -------------------------------------------------------------- }
  120. function BitButtonWinFn(HWindow: HWnd; Message: Word; wParam: Word;
  121.   lParam: Longint): Longint; export;
  122. var
  123.   DC: HDC;
  124.   BitsNumber: Integer;
  125.   Bitmap: TBitmap;
  126.   Rect: TRect;
  127.   Pt: TPoint;
  128.   PS: TPaintStruct;
  129.  
  130. { Get ----------------------------------------------------------
  131.     Get a window instance word.
  132.   -------------------------------------------------------------- }
  133. function Get(Ofs: Integer): Word;
  134. begin
  135.   Get := GetWindowWord(HWindow, Ofs);
  136. end;
  137.  
  138. { SetWord ------------------------------------------------------
  139.     Set the value of a window instance word.
  140.   -------------------------------------------------------------- }
  141. procedure SetWord(Ofs: Integer; Val: Word);
  142. begin
  143.   SetWindowWord(HWindow, Ofs, Val);
  144. end;
  145.  
  146. { State --------------------------------------------------------
  147.     Get the button's state word.
  148.   -------------------------------------------------------------- }
  149. function State: Word;
  150. begin
  151.   State := Get(ofState);
  152. end;
  153.  
  154. { DownBits -----------------------------------------------------
  155.     Get the "down" bitmap of the button.
  156.   -------------------------------------------------------------- }
  157. function DownBits: Word;
  158. begin
  159.   DownBits := Get(ofDownBits);
  160. end;
  161.  
  162. { UpBits -------------------------------------------------------
  163.     Get the "up" bitmap of the button.
  164.   -------------------------------------------------------------- }
  165. function UpBits: Word;
  166. begin
  167.   UpBits := Get(ofUpBits);
  168. end;
  169.  
  170. { FocUpBits ----------------------------------------------------
  171.     Get the "focused up" bitmap of the button.
  172.   -------------------------------------------------------------- }
  173. function FocUpBits: Word;
  174. begin
  175.   FocUpBits := Get(ofFocUpBits);
  176. end;
  177.  
  178. { GetState -----------------------------------------------------
  179.     Get the value of a state bit.
  180.   -------------------------------------------------------------- }
  181. function GetState(AState: Word): Boolean;
  182. begin
  183.   GetState := (State and AState) = AState;
  184. end;
  185.  
  186. { Paint --------------------------------------------------------
  187.     Paint the button.  Called in responce to a WM_PAINT message
  188.     and whenever the button changes state (called by Repaint).
  189.   -------------------------------------------------------------- }
  190. procedure Paint(DC: HDC);
  191. const
  192.   coGray = $00C0C0C0;
  193. var
  194.   MemDC: HDC;
  195.   Bits, Oldbitmap: HBitmap;
  196.   BorderBrush, OldBrush: HBrush;
  197.   LogBrush: TLogBrush;
  198.   DisableBits: HBitmap;
  199.   Frame: TRect;
  200.   Height, Width: Integer;
  201. begin
  202.   if (State and (bsMouseDown + bsKeyDown) <> 0) and
  203.       not GetState(bsMouseUpDown) then
  204.     Bits := DownBits
  205.   else
  206.     if GetState(bsFocus) then
  207.       Bits := FocUpBits
  208.     else
  209.       Bits := UpBits;
  210.  
  211.   { Draw border }
  212.   GetClientRect(HWindow, Frame);
  213.   Height := Frame.bottom - Frame.top;
  214.   Width := Frame.right - Frame.left;
  215.  
  216.   if GetState(bsDefault) then
  217.     BorderBrush := GetStockObject(Black_Brush)
  218.   else BorderBrush := GetStockObject(White_Brush);
  219.   OldBrush := SelectObject(DC, BorderBrush);
  220.   PatBlt(DC, Frame.left, Frame.top, Width, bdBorderWidth, PatCopy);
  221.   PatBlt(DC, Frame.left, Frame.top, bdBorderWidth, Height, PatCopy);
  222.   PatBlt(DC, Frame.left, Frame.bottom - bdBorderWidth, Width,
  223.     bdBorderWidth, PatCopy);
  224.   PatBlt(DC, Frame.right - bdBorderWidth, Frame.top, bdBorderWidth,
  225.     Height, PatCopy);
  226.   SelectObject(DC, OldBrush);
  227.  
  228.   { Draw bitmap }
  229.   MemDC := CreateCompatibleDC(DC);
  230.   OldBitmap := SelectObject(MemDC, Bits);
  231.   GetObject(Bits, Sizeof(Bitmap), @Bitmap);
  232.   if GetState(bsDisabled) then
  233.   begin
  234.     { Gray out the button }
  235.     OldBrush := SelectObject(DC, CreateSolidBrush(coGray));
  236.     PatBlt(DC, bdBorderWidth, bdBorderWidth, Bitmap.bmWidth,
  237.       Bitmap.bmHeight, PatCopy);
  238.     DeleteObject(SelectObject(DC, OldBrush));
  239.  
  240.     { Draw the bitmap through a checked brush }
  241.     LogBrush.lbStyle := bs_Pattern;
  242.     LogBrush.lbHatch := LoadBitmap(HInstance, MakeIntResource(btDisableBits));
  243.     OldBrush := SelectObject(DC, CreateBrushIndirect(LogBrush));
  244.     BitBlt(DC, bdBorderWidth, bdBorderWidth, Bitmap.bmWidth,
  245.       Bitmap.bmHeight, MemDC, 0, 0, $00A803A9 {DPSoa});
  246.     DeleteObject(SelectObject(DC, OldBrush));
  247.     DeleteObject(LogBrush.lbHatch);
  248.   end
  249.   else
  250.     BitBlt(DC, bdBorderWidth, bdBorderWidth, Bitmap.bmWidth,
  251.       Bitmap.bmHeight, MemDC, 0, 0, srcCopy);
  252.   SelectObject(MemDC, OldBitmap);
  253.  
  254.   DeleteDC(MemDC);
  255. end;
  256.  
  257. { Repaint ------------------------------------------------------
  258.     Repaint the button. Called whenever the button changes
  259.     state.
  260.   -------------------------------------------------------------- }
  261. procedure Repaint;
  262. var
  263.   DC: HDC;
  264. begin
  265.   DC := GetDC(HWindow);
  266.   Paint(DC);
  267.   ReleaseDC(HWindow, DC);
  268. end;
  269.  
  270. { SetState -----------------------------------------------------
  271.     Sets the value of a state bit.  If the word changes value
  272.     the button is repainted.
  273.   -------------------------------------------------------------- }
  274. procedure SetState(AState: Word; Enable: Boolean);
  275. var
  276.   OldState, NewState: Word;
  277. begin
  278.   OldState := State;
  279.   if Enable then NewState := OldState or AState
  280.   else NewState := OldState and not AState;
  281.   if NewState <> OldState then
  282.   begin
  283.     SetWord(ofState, NewState);
  284.     Repaint;
  285.   end;
  286. end;
  287.  
  288. { InMe ---------------------------------------------------------
  289.     Returns true if the given point is in within the border of
  290.     the button.
  291.   -------------------------------------------------------------- }
  292. function InMe(lPoint: Longint): Boolean;
  293. var
  294.   R: TRect;
  295.   Point: TPoint absolute lPoint;
  296. begin
  297.   GetClientRect(HWindow, R);
  298.   InflateRect(R, -bdBorderWidth, -bdBorderWidth);
  299.   InMe := PtInRect(R, Point);
  300. end;
  301.  
  302. { ButtonPressed ------------------------------------------------
  303.     Called when the button is pressed by either the keyboard or
  304.     by the mouse.
  305.   -------------------------------------------------------------- }
  306. procedure ButtonPressed;
  307. begin
  308.   SetState(bsMouseDown + bsMouseUpDown + bsKeyDown, False);
  309.   SendMessage(GetParent(HWindow), wm_Command, GetDlgCtrlID(HWindow),
  310.     Longint(HWindow));
  311. end;
  312.  
  313. { LoadBits -----------------------------------------------------
  314.     Load the bitmap for the button or the "NO BITMAP" version
  315.     if it does not exist.
  316.   -------------------------------------------------------------- }
  317. procedure LoadBits(Wrd: Word; MapNumber: Word);
  318. var
  319.   MapBits: HBitmap;
  320. begin
  321.   MapBits := LoadBitmap(HInstance, pChar(MapNumber));
  322.   if MapBits = 0 then
  323.     if IsWorkshopWindow(HWindow) then
  324.       MapBits := LoadBitmapRW(pChar(MapNumber))
  325.     else
  326.       MapBits := LoadBitmap(GetAppInstance, pChar(MapNumber));
  327.   if MapBits = 0 then
  328.     MapBits := LoadBitmap(HInstance, pChar(MapNumber - Get(gww_ID)));
  329.   SetWord(Wrd, MapBits);
  330. end;
  331.  
  332. begin
  333.   BitButtonWinFn := 0;
  334.   case Message of
  335.     wm_Create:
  336.       begin
  337.     { Detect EGA monitor }
  338.     DC := GetDC(0);
  339.     if (GetSystemMetrics(sm_CYScreen) < 480) or
  340.         (GetDeviceCaps(DC, numColors) < 16) then
  341.       BitsNumber := 2000 + Get(gww_ID)
  342.     else
  343.       BitsNumber := 1000 + Get(gww_ID);
  344.     ReleaseDC(0, DC);
  345.  
  346.     { Load bitmaps from resource }
  347.     LoadBits(ofUpBits, BitsNumber);
  348.     LoadBits(ofDownBits, BitsNumber + 2000);
  349.     LoadBits(ofFocUpBits, BitsNumber + 4000);
  350.  
  351.     { Adjust size of button to size of bitmap }
  352.     GetObject(DownBits, SizeOf(Bitmap), @Bitmap);
  353.     GetWindowRect(HWindow, Rect);
  354.     Pt.X := Rect.Left;
  355.     Pt.Y := Rect.Top;
  356.     ScreenToClient(PCreateStruct (lParam)^.hwndParent, Pt);
  357.       MoveWindow(HWindow, Pt.X, Pt.Y,
  358.       Bitmap.bmWidth + bdBorderWidth * 2,
  359.       Bitmap.bmHeight + bdBorderWidth * 2, False);
  360.  
  361.     { Intialize button state }
  362.     with PCreateStruct(lParam)^ do
  363.     begin
  364.       if style and $1F = bs_DefPushButton then
  365.         SetState(bsDefault, True);
  366.       if style and ws_Disabled <> 0 then
  367.         SetState(bsDisabled, True);
  368.     end;
  369.       end;
  370.     wm_NCDestroy:
  371.       begin
  372.     { Destroy all saved bitmaps before the button is destroyed }
  373.     BitButtonWinFn := DefWindowProc(HWindow, Message, wParam, lParam);
  374.     DeleteObject(UpBits);
  375.     DeleteObject(DownBits);
  376.     DeleteObject(FocUpBits);
  377.       end;
  378.     wm_Paint:
  379.       begin
  380.     BeginPaint(HWindow, PS);
  381.     Paint(PS.hDC);
  382.     EndPaint(HWindow, PS);
  383.       end;
  384.     wm_EraseBkGnd:
  385.       begin
  386.     { Squelch the painting of the background to eliminate flicker }
  387.       end;
  388.     wm_Enable:
  389.       SetState(bsDisabled, wParam <> 0);
  390.     wm_SetFocus:
  391.       SetState(bsFocus, True);
  392.     wm_KillFocus:
  393.       SetState(bsFocus or bsKeyDown or bsMouseDown or bsMouseUpDown, False);
  394.     wm_KeyDown:
  395.       if (wParam = $20) and not GetState(bsKeyDown) and
  396.       not GetState(bsMouseDown) then
  397.     SetState(bsKeyDown, True);
  398.     wm_KeyUp:
  399.       if (wParam = $20) and GetState(bsKeyDown) then
  400.         ButtonPressed;
  401.     wm_LButtonDblClk, wm_LButtonDown:
  402.       if InMe(lParam) and not GetState(bsKeyDown) then
  403.       begin
  404.     if GetFocus <> HWindow then SetFocus(HWindow);
  405.     SetState(bsMouseDown, True);
  406.     SetCapture(HWindow);
  407.       end;
  408.     wm_MouseMove:
  409.       if GetState(bsMouseDown) then
  410.     SetState(bsMouseUpDown, not InMe(lParam));
  411.     wm_LButtonUp:
  412.       if GetState(bsMouseDown) then
  413.       begin
  414.     ReleaseCapture;
  415.     if not GetState(bsMouseUpDown) then ButtonPressed
  416.     else SetState(bsMouseDown + bsMouseUpDown, False);
  417.       end;
  418.  
  419.     { *** Handling the rest of these messages are what, at least for
  420.           the dialog manager, makes a push button a push button.  ***}
  421.     wm_GetDlgCode:
  422.       { Sent by the dialog manager to determine the control kind of
  423.     a child window.  Returning dlgc_DefPushButton or
  424.     dlgc_UndefPushButton causes the dialog manager to treat the
  425.     control like a button, sending the bm_SetStyle message to
  426.     move the default button style to the currenly focused button.
  427.  
  428.         The dlgc_Button constant is not documented by Microsoft
  429.         (however, it is documented for OS/2 PM, and appears to work
  430.         the same). If this constant is or'd in, the windows dialog
  431.         manager will take care of all accelerator key processing,
  432.         sending bm_SetState and bm_SetStyle messages when an
  433.         acclerator key is pressed. There is a side effect to using
  434.         the message, however, the dialog manager messes with the word
  435.         at offset 0 from the user Window words. }
  436.  
  437.       if GetState(bsDefault) then
  438.     BitButtonWinFn:= dlgc_DefPushButton or dlgc_Button
  439.       else
  440.     BitButtonWinFn := dlgc_UndefPushButton or dlgc_Button;
  441.     bm_GetState:
  442.       BitButtonWinFn := Integer(GetState(bsKeyDown));
  443.     bm_SetState:
  444.       SetState(bsKeyDown, wParam <> 0);
  445.     bm_SetStyle:
  446.       { Sent by the dialog manager when the button receives or looses
  447.     focus and is not the default button, or when another button
  448.     receives the focus and this button is the default button. }
  449.       SetState(bsDefault, wParam = bs_DefPushButton);
  450.   else
  451.     BitButtonWinFn := DefWindowProc(HWindow, Message, wParam, lParam);
  452.   end;
  453. end;
  454.  
  455. { ==============================================================
  456.   Custom contol interface routines.
  457.   ============================================================== }
  458.  
  459. { BitBtnInfo ---------------------------------------------------
  460.    Return the information about the capabilities of the
  461.    bit button class.
  462.   -------------------------------------------------------------- }
  463. function BitBtnInfo: THandle; export;
  464. var
  465.   hInfo: THandle;
  466.   Info: PRWCtlInfo;
  467. begin
  468.   hInfo := GlobalAlloc(gmem_Share or gmem_ZeroInit,
  469.     SizeOf(TRWCtlInfo));
  470.   if hInfo <> 0 then
  471.   begin
  472.     Info := GlobalLock(hInfo);
  473.     with Info^ do
  474.     begin
  475.       wVersion := $100;         { Version 1.00 }
  476.       wCtlTypes := 2;           { 2 types }
  477.       StrCopy(szClass, 'BitButton');
  478.       StrCopy(szTitle, 'Button');
  479.  
  480.       { Normal (Un-default) push button type }
  481.       with ctType[0] do
  482.       begin
  483.     wWidth := 63 or $8000;
  484.     wHeight := 39 or $8000;
  485.     StrCopy(szDescr, 'Push Button');
  486.     dwStyle := bs_PushButton or ws_TabStop;
  487.     hToolBit := LoadBitmap(HInstance, MakeIntResource(btUndefBits));
  488.     hDropCurs := LoadCursor(HInstance, MakeIntResource(crUndefCurs));
  489.       end;
  490.  
  491.       { Default push button type }
  492.       with ctType[1] do
  493.       begin
  494.     wWidth := 63 or $8000;
  495.     wHeight := 39 or $8000;
  496.     StrCopy(szDescr, 'Default Push Button');
  497.     dwStyle := bs_DefPushButton or ws_TabStop;
  498.     hToolBit := LoadBitmap(HInstance, MakeIntResource(btDefBits));
  499.     hDropCurs := LoadCursor(HInstance, MakeIntResource(crDefCurs));
  500.       end;
  501.     end;
  502.     GlobalUnlock(hInfo);
  503.   end;
  504.   BitBtnInfo := hInfo;
  505. end;
  506.  
  507. type
  508.   PParamRec = ^TParamRec;
  509.   TParamRec = record
  510.     CtlStyle: THandle;
  511.     IdToStr: TIdToStr;
  512.     StrToId: TStrToId;
  513.   end;
  514.  
  515. { BitBtnStyleDlg -----------------------------------------------
  516.     Style dialog's dialog hook.  Used by the dialog and called
  517.     when the control is double-clicked inside the dialog
  518.     editor.
  519.   -------------------------------------------------------------- }
  520. function BitBtnStyleDlg(HWindow: HWnd; Message: Word; wParam: Word;
  521.   lParam: Longint): Longint; export;
  522. const
  523.   Prop = 'Prop';
  524. var
  525.   hRec: THandle;
  526.   Rec: PParamRec;
  527.   Style: PCtlStyle;
  528.   S: array[0..256] of Char;
  529.   Radio: Integer;
  530. begin
  531.   case Message of
  532.     wm_InitDialog:
  533.       begin
  534.     hRec := LoWord(lParam);
  535.     Rec := GlobalLock(hRec);
  536.     Style := GlobalLock(Rec^.CtlStyle);
  537.     SetProp(HWindow, Prop, hRec);
  538.     with Rec^, Style^ do
  539.     begin
  540.       { Set caption }
  541.       SetDlgItemText(HWindow, idCaption, szTitle);
  542.  
  543.       { Set control id }
  544.       IdToStr(wId, S, SizeOf(S));
  545.       SetDlgItemText(HWindow, idControlId, S);
  546.  
  547.       { Set type radio buttons }
  548.       if dwStyle and $F = bs_DefPushButton then
  549.         Radio := idDefaultButton
  550.       else
  551.             Radio := idPushButton;
  552.       CheckRadioButton(HWindow, idDefaultButton, idPushButton,
  553.         Radio);
  554.  
  555.       { Initialize Tab Stop check box }
  556.       CheckDlgButton(HWindow, idTabStop,
  557.         Integer(dwStyle and ws_TabStop <> 0));
  558.  
  559.       { Initialize Disabled check box }
  560.       CheckDlgButton(HWindow, idDisabled,
  561.         Integer(dwStyle and ws_Disabled <> 0));
  562.  
  563.       { Initialize Group check box }
  564.       CheckDlgButton(HWindow, idGroup,
  565.         Integer(dwStyle and ws_Group <> 0));
  566.     end;
  567.     GlobalUnlock(Rec^.CtlStyle);
  568.     GlobalUnlock(hRec);
  569.       end;
  570.     wm_Command:
  571.       case wParam of
  572.     idCancel:
  573.       EndDialog(HWindow, 0);
  574.     idOk:
  575.       begin
  576.         hRec := GetProp(HWindow, Prop);
  577.         Rec := GlobalLock(hRec);
  578.         Style := GlobalLock(Rec^.CtlStyle);
  579.         with Rec^, Style^ do
  580.         begin
  581.           { Get caption }
  582.           GetDlgItemText(HWindow, idCaption, szTitle, SizeOf(szTitle));
  583.  
  584.           { Get control id }
  585.           GetDlgItemText(HWindow, idControlId, S, SizeOf(S));
  586.           wId := StrToId(S);
  587.  
  588.           { Get button type }
  589.           if IsDlgButtonChecked(HWindow, idDefaultButton) <> 0 then
  590.         dwStyle := bs_DefPushButton
  591.           else
  592.                 dwStyle := bs_PushButton;
  593.  
  594.           { Get tab stop }
  595.           if IsDlgButtonChecked(HWindow, idTabStop) <> 0 then
  596.         dwStyle := dwStyle or ws_TabStop;
  597.  
  598.           { Get disabled }
  599.           if IsDlgButtonChecked(HWindow, idDisabled) <> 0 then
  600.         dwStyle := dwStyle or ws_Disabled;
  601.  
  602.           { Get group }
  603.           if IsDlgButtonChecked(HWindow, idGroup) <> 0 then
  604.         dwStyle := dwStyle or ws_Group;
  605.         end;
  606.         GlobalUnlock(Rec^.CtlStyle);
  607.         GlobalUnlock(hRec);
  608.         EndDialog(HWindow, 1);
  609.       end;
  610.       else
  611.     BitBtnStyleDlg := 0;
  612.       end;
  613.     wm_Destroy:
  614.       RemoveProp(HWindow, Prop);
  615.   else
  616.     BitBtnStyleDlg := 0;
  617.   end;
  618. end;
  619.  
  620. { BitBtnStyle --------------------------------------------------
  621.     The function will bring up a dialog box to modify the style
  622.     of the button.  Called when the button is double-clicked in
  623.     the dialog editor.
  624.   -------------------------------------------------------------- }
  625. function BitBtnStyle(hWindow: HWnd; CtlStyle: THandle;
  626.   StrToId: TStrToId; IdToStr: TIdToStr): Bool; export;
  627. var
  628.   hRec: THandle;
  629.   Rec: PParamRec;
  630.   hFocus: HWnd;
  631. begin
  632.   BitBtnStyle := False;
  633.   hRec := GlobalAlloc(gmem_Share, SizeOf(TParamRec));
  634.   if hRec <> 0 then
  635.   begin
  636.     Rec := GlobalLock(hRec);
  637.     Rec^.IdToStr := IdToStr;
  638.     Rec^.StrToId := StrToId;
  639.     Rec^.CtlStyle := CtlStyle;
  640.     GlobalUnlock(hRec);
  641.  
  642.     hFocus := GetFocus;
  643.     BitBtnStyle := Bool(DialogBoxParam(HInstance,
  644.       MakeIntResource(idButtonStyle), HWindow, @BitBtnStyleDlg,
  645.       hRec));
  646.     if hFocus <> 0 then SetFocus(hFocus);
  647.     GlobalFree(hRec);
  648.   end;
  649. end;
  650.  
  651. { BitBtnFlags --------------------------------------------------
  652.     Called to decompose the style double word into the .RC
  653.     script expression that it represents.  This only needs to
  654.     decompose the style bits added to the style double word,
  655.     it need not decompose the, for example, the ws_XXX bits.
  656.     The expression returned must be a valid .RC expression
  657.     (i.e. C syntax, case sensitive).
  658.   -------------------------------------------------------------- }
  659. function BitBtnFlags(Style: LongInt; Buff: PChar;
  660.   BuffLength: Word): Word; export;
  661. begin
  662.   if Style and $F = bs_DefPushButton then
  663.     StrLCopy(Buff, 'BS_DEFPUSHBUTTON', BuffLength)
  664.   else StrLCopy(Buff, 'BS_PUSHBUTTON', BuffLength);
  665. end;
  666.  
  667. { ListClasses --------------------------------------------------
  668.     Called by Resource Workshop retrieve the information
  669.     necessary to edit the custom controls contain in this DLL.
  670.     This is an alternative to the Microsoft xxxStyle convention.
  671.   -------------------------------------------------------------- }
  672. function ListClasses(szAppName: PChar; wVersion: Word;
  673.   fnLoad: TLoad; fnEdit: TEdit): THandle; export;
  674. var
  675.   hClasses: THandle;
  676.   Classes: PCtlClassList;
  677. begin
  678.   LoadResRW := fnLoad;
  679.   hClasses := GlobalAlloc(gmem_Share or gmem_ZeroInit,
  680.     SizeOf(Integer) + SizeOf(TRWCtlClass));
  681.   if hClasses <> 0 then
  682.   begin
  683.     Classes := GlobalLock(hClasses);
  684.     with Classes^ do
  685.     begin
  686.       nClasses := 1;
  687.       with Classes[0] do
  688.       begin
  689.     fnInfo  := BitBtnInfo;
  690.     fnStyle := BitBtnStyle;
  691.     fnFlags := BitBtnFlags;
  692.       end;
  693.     end;
  694.     GlobalUnlock(hClasses);
  695.   end;
  696.   ListClasses := hClasses;
  697. end;
  698.  
  699. exports
  700.   ListClasses,
  701.   BitButtonWinFn;
  702.  
  703. var
  704.   Class: TWndClass;
  705.  
  706. begin
  707.   with Class do
  708.   begin
  709.     lpszClassName := 'BitButton';
  710.     hCursor       := LoadCursor(0, idc_Arrow);
  711.     lpszMenuName  := nil;
  712.     style         := cs_HRedraw or cs_VRedraw or cs_DblClks or cs_GlobalClass;
  713.     lpfnWndProc   := TFarProc(@BitButtonWinFn);
  714.     hInstance     := System.hInstance;
  715.     hIcon         := 0;
  716.     cbWndExtra    := ofSize;
  717.     cbClsExtra    := 0;
  718.     hbrBackground := 0;
  719.   end;
  720.   RegisterClass(Class);
  721. end.
  722.