home *** CD-ROM | disk | FTP | other *** search
/ Chip 1999 March / Chip_1999-03_cd.bin / zkuste / delphi / D / XBALOON.ZIP / xbaloon.pas < prev    next >
Pascal/Delphi Source File  |  1999-01-24  |  14KB  |  469 lines

  1. {*************************************************************}
  2. {            XBaloon Component for Delphi 16/32               }
  3. { Version:   1.01                                             }
  4. { Author:    Aleksey Kuznetsov, Kiev, Ukraine                 }
  5. {            └δσΩ±σΘ ╩≤τφσ÷εΓ (Xacker), ╩ΦσΓ, ╙Ω≡αΦφα         }
  6. { E-Mail:    xacker@phreaker.net                              }
  7. { Created:   January, 20, 1999                                }
  8. { Modified:  January, 24, 1999                                }
  9. { Legal:     Copyright (c) 1999 by Xacker from Droids Clan    }
  10. {                             http://droids.virtualave.net    }
  11. {*************************************************************}
  12. {                    IMPORTANT NOTE:                          }
  13. {  This code may be used and modified by anyone so long as    }
  14. { this header and copyright information remains intact. By    }
  15. { using this code you agree to indemnify Aleksey Xacker from  }
  16. { any liability that might arise from its use. You must       }
  17. { obtain written consent before selling or redistributing     }
  18. { this code.                                                  }
  19. {*************************************************************}
  20. {  Methods:                                                   }
  21. {       Show(Point: TPoint; Text: String);                    }
  22. {       Hide                                                  }
  23. { See demonstration program.                                  }
  24. {*************************************************************}
  25. { Thanks for using XBaloon component.                         }
  26. { If at occurrence of any questions concerning these          }
  27. { components, mail me: xacker@phreaker.net.                   }
  28. {*************************************************************}
  29. { 24.I.1999: Added IsShowing, GetX and GetY public functions. }
  30. {*************************************************************}
  31. unit XBaloon;
  32.  
  33. interface
  34.  
  35. uses
  36.   {$IFDEF WIN32} Windows, {$ELSE} WinTypes, WinProcs, {$ENDIF}
  37.   SysUtils, Messages, Classes, Graphics, Controls, Forms;
  38.  
  39. {$IFDEF WIN32}
  40. {$R XBALOON.R32}
  41. {$ELSE}
  42. {$R XBALOON.R16}
  43. {$ENDIF}
  44.  
  45. type
  46.   TPShape = (sRoundRect, sRectangle);
  47.   TTextAlign = (taCenter, taLeft, taRight);
  48.  
  49.   TBaloonWindow = class(TCustomControl)
  50.   private
  51.     Tail: TBitmap;
  52.     Underground: TBitmap;
  53.  
  54.     procedure DrawTransparentBitmap(ahdc: HDC;
  55.                                     xStart, yStart, x1,y1,x2,y2: Word);
  56.  
  57.     procedure Show(var Rect: TRect; x, y: Integer; Text: String; Shape: TPShape;
  58.                    TextAlign: TTextAlign; DivChar: Char);
  59.     procedure WMMouseMove(var Msg: TMessage); message wm_MouseMove;
  60.     {$IFDEF WIN32}
  61.     procedure WMMouseDown(var Msg: TMessage); message wm_LButtonDown;
  62.     {$ENDIF}
  63.   protected
  64.     procedure CreateParams(var Params: TCreateParams); override;
  65.     procedure Paint; override;
  66.   public
  67.     Showing: Boolean;
  68.     HideIfMouseMove: Boolean;
  69.     {$IFDEF WIN32}
  70.     HideIfMouseClick: Boolean;
  71.     {$ENDIF}
  72.  
  73.     constructor Create(AOwner: TComponent); override;
  74.     destructor Destroy; override;
  75.     procedure Activate(Point: TPoint; Text: String; Shape: TPShape;
  76.                        TextAlign: TTextAlign; DivChar: Char); virtual;
  77.     procedure Deactivate;
  78.   end;
  79.  
  80.   TXBaloon = class(TComponent)
  81.   private
  82.     FColor: TColor;
  83.     FFont: TFont;
  84.     FDivisionChar: Char;
  85.     FHideIfMouseMove: Boolean;
  86.     {$IFDEF WIN32}
  87.     FHideIfMouseClick: Boolean;
  88.     {$ENDIF}
  89.     FShape: TPShape;
  90.     FTextAlign: TTextAlign;
  91.  
  92.     Baloon: TBaloonWindow;
  93.     LastX, LastY: Integer;
  94.   protected
  95.   public
  96.     constructor Create(aOwner: TComponent); override;
  97.     destructor Destroy; override;
  98.  
  99.     procedure Show(Point: TPoint; Text: String);
  100.     procedure Hide;
  101.     function IsShowing: Boolean;
  102.     function GetX: Integer;
  103.     function GetY: Integer;
  104.   published
  105.     property Color: TColor read FColor write FColor;
  106.     property Font: TFont read FFont write FFont;
  107.     property DivisionChar: Char read FDivisionChar write FDivisionChar;
  108.     property HideIfMouseMove: Boolean read FHideIfMouseMove write FHideIfMouseMove;
  109.     {$IFDEF WIN32}
  110.     property HideIfMouseClick: Boolean read FHideIfMouseClick write FHideIfMouseClick;
  111.     {$ENDIF}
  112.     property Shape: TPShape read FShape write FShape;
  113.     property TextAlign: TTextAlign read FTextAlign write FTextAlign;
  114.   end;
  115.  
  116.  
  117. procedure Register;
  118.  
  119. implementation
  120.  
  121. procedure TBaloonWindow.DrawTransparentBitmap(ahdc: HDC;
  122.                                  xStart, yStart, x1,y1,x2,y2: Word);
  123. var
  124.   TransparentColor: TColor;
  125.   cColor          : TColorRef;
  126.   bmAndBack,
  127.   bmAndObject,
  128.   bmAndMem,
  129.   bmSave,
  130.   bmBackOld,
  131.   bmObjectOld,
  132.   bmMemOld,
  133.   bmSaveOld       : HBitmap;
  134.   hdcMem,
  135.   hdcBack,
  136.   hdcObject,
  137.   hdcTemp,
  138.   hdcSave         : HDC;
  139.   ptSize          : TPoint;
  140. begin
  141.   { set the transparent to black }
  142.   TransparentColor := clYellow;
  143.   TransparentColor := TransparentColor or $02000000;
  144.  
  145.   hdcTemp := CreateCompatibleDC (ahdc);
  146.   SelectObject (hdcTemp, Tail.Handle); { select the bitmap }
  147.  
  148.   { convert bitmap dimensions from device to logical points }
  149.   ptSize.x := x2-x1;
  150.   ptSize.y := y2-y1;
  151.   DPToLP (hdcTemp, ptSize, 1);  { convert from device logical points }
  152.  
  153.   { create some DCs to hold temporary data }
  154.   hdcBack   := CreateCompatibleDC(ahdc);
  155.   hdcObject := CreateCompatibleDC(ahdc);
  156.   hdcMem    := CreateCompatibleDC(ahdc);
  157.   hdcSave   := CreateCompatibleDC(ahdc);
  158.  
  159.   { create a bitmap for each DC }
  160.  
  161.   { monochrome DC }
  162.   bmAndBack   := CreateBitmap (ptSize.x, ptSize.y, 1, 1, nil);
  163.   bmAndObject := CreateBitmap (ptSize.x, ptSize.y, 1, 1, nil);
  164.  
  165.   bmAndMem    := CreateCompatibleBitmap (ahdc, ptSize.x, ptSize.y);
  166.   bmSave      := CreateCompatibleBitmap (ahdc, ptSize.x, ptSize.y);
  167.  
  168.   { each DC must select a bitmap object to store pixel data }
  169.   bmBackOld   := SelectObject (hdcBack, bmAndBack);
  170.   bmObjectOld := SelectObject (hdcObject, bmAndObject);
  171.   bmMemOld    := SelectObject (hdcMem, bmAndMem);
  172.   bmSaveOld   := SelectObject (hdcSave, bmSave);
  173.  
  174.   { set proper mapping mode }
  175.   SetMapMode (hdcTemp, GetMapMode (ahdc));
  176.  
  177.   { save the bitmap sent here, because it will be overwritten }
  178.   BitBlt (hdcSave, 0, 0, ptSize.x, ptSize.y, hdcTemp, x1, y1, SRCCOPY);
  179.  
  180.   { set the background color of the source DC to the color.
  181.     contained in the parts of the bitmap that should be transparent }
  182.   cColor := SetBkColor (hdcTemp, TransparentColor);
  183.  
  184.   { create the object mask for the bitmap by performing a BitBlt()
  185.     from the source bitmap to a monochrome bitmap }
  186.   BitBlt (hdcObject, 0, 0, ptSize.x, ptSize.y, hdcTemp, x1, y1, SRCCOPY);
  187.  
  188.   { set the background color of the source DC back to the original color }
  189.   SetBkColor (hdcTemp, cColor);
  190.  
  191.   { create the inverse of the object mask }
  192.   BitBlt (hdcBack, 0, 0, ptSize.x, ptSize.y, hdcObject, 0, 0, NOTSRCCOPY);
  193.  
  194.   { copy the background of the main DC to the destination }
  195.   BitBlt (hdcMem, 0, 0, ptSize.x, ptSize.y, ahdc, xStart, yStart, SRCCOPY);
  196.  
  197.   { mask out the places where the bitmap will be placed }
  198.   BitBlt (hdcMem, 0, 0, ptSize.x, ptSize.y, hdcObject, 0, 0, SRCAND);
  199.  
  200.   { mask out the transparent colored pixels on the bitmap }
  201.   BitBlt (hdcTemp, x1, y1, ptSize.x, ptSize.y, hdcBack, 0, 0, SRCAND);
  202.  
  203.   { XOR the bitmap with the background on the destination DC }
  204.   BitBlt (hdcMem, 0, 0, ptSize.x, ptSize.y, hdcTemp, x1, y1, SRCPAINT);
  205.  
  206.   { copy the destination to the screen }
  207.   BitBlt (ahdc, xStart, yStart, ptSize.x, ptSize.y, hdcMem, 0, 0, SRCCOPY);
  208.  
  209.   { place the original bitmap back into the bitmap sent here }
  210.   BitBlt (hdcTemp, x1, y1, ptSize.x, ptSize.y, hdcSave, 0, 0, SRCCOPY);
  211.  
  212.   { delete the memory bitmaps }
  213.   DeleteObject (SelectObject (hdcBack, bmBackOld));
  214.   DeleteObject (SelectObject (hdcObject, bmObjectOld));
  215.   DeleteObject (SelectObject (hdcMem, bmMemOld));
  216.   DeleteObject (SelectObject (hdcSave, bmSaveOld));
  217.  
  218.   { delete the memory DCs }
  219.   DeleteDC (hdcMem);
  220.   DeleteDC (hdcBack);
  221.   DeleteDC (hdcObject);
  222.   DeleteDC (hdcSave);
  223.   DeleteDC (hdcTemp);
  224. end;
  225.  
  226. { TBaloonWindow }
  227.  
  228. constructor TBaloonWindow.Create(AOwner: TComponent);
  229. begin
  230.   inherited Create(AOwner);
  231.   HideIfMouseMove := TXBaloon(AOwner).HideIfMouseMove;
  232.   {$IFDEF WIN32}
  233.   HideIfMouseClick := TXBaloon(AOwner).HideIfMouseClick;
  234.   {$ENDIF}
  235.   Tail := TBitmap.Create;
  236.   Tail.Handle := LoadBitmap(hInstance, 'TAIL');
  237.   Underground := TBitmap.Create;
  238. end;
  239.  
  240. destructor TBaloonWindow.Destroy;
  241. begin
  242.   Underground.Free;
  243.   Tail.Free;
  244.   inherited Destroy;
  245. end;
  246.  
  247. procedure TBaloonWindow.CreateParams(var Params: TCreateParams);
  248. begin
  249.   inherited CreateParams(Params);
  250.   {$IFDEF WIN32}
  251.   with Params do
  252.   begin
  253.     Style := WS_POPUP;
  254.     WindowClass.Style := WindowClass.Style or CS_SAVEBITS;
  255.     if NewStyleControls then ExStyle := WS_EX_TOOLWINDOW;
  256.   end;
  257.   {$ELSE}
  258.   with Params do
  259.   begin
  260.     if HideIfMouseMove then Style := WS_POPUP
  261.     else Style := WS_POPUP or WS_DISABLED;
  262.     WindowClass.Style := WindowClass.Style or CS_SAVEBITS;
  263.   end;
  264.   {$ENDIF}
  265. end;
  266.  
  267. procedure TBaloonWindow.Show(var Rect: TRect; x, y: Integer; Text: String; Shape: TPShape;
  268.                              TextAlign: TTextAlign; DivChar: Char);
  269. var
  270.   q, i: Integer;
  271.   MaxWidth, FontHeight: Integer;
  272.   SL: TStringList;
  273.   h: Integer;
  274.   DC: hDC;
  275. begin
  276.   if Length(Text) <> 0 then
  277.    begin
  278.     SL := TStringList.Create;
  279.     with Underground.Canvas do
  280.      begin
  281.       q := 1;
  282.       for i := 1 to Length(Text) do
  283.        if Text[i] = '@' then
  284.         begin
  285.          SL.Add(Copy(Text, q, i - q));
  286.          q := i + 1;
  287.         end;
  288.       SL.Add(Copy(Text, q, i));
  289.  
  290.       MaxWidth := 0;
  291.  
  292.       FontHeight := 0;
  293.       for i := 0 to SL.Count - 1 do
  294.        begin
  295.         FontHeight := FontHeight + TextHeight(SL[i]);
  296.         h := TextWidth(SL[i]);
  297.         if MaxWidth < h then
  298.          MaxWidth := h;
  299.        end;
  300.  
  301.       Underground.Width := MaxWidth + 23;
  302.       Underground.Height := y - (y - FontHeight - 2) + 18;
  303.       DC := GetDC(0);
  304.       BitBlt(Underground.Canvas.Handle, 0, 0, Underground.Width, Underground.Height, DC,
  305.              x, y - FontHeight - 2, SrcCopy);
  306.       ReleaseDC(0, DC);
  307.  
  308.       Brush.Color := clBlack;
  309.       if Shape = sRoundRect then
  310.        RoundRect(12, 2,
  311.                  MaxWidth + 23, FontHeight + 5, 15, 15)
  312.       else
  313.        Rectangle(12, 2,
  314.                  MaxWidth + 23, FontHeight + 5);
  315.       Brush.Color := Color;
  316.       if Shape = sRoundRect then
  317.        RoundRect(10, 0,
  318.                  MaxWidth + 21, FontHeight + 3, 15, 15)
  319.       else
  320.        Rectangle(10, 0,
  321.                  MaxWidth + 21, FontHeight + 3);
  322.  
  323.       DrawTransparentBitmap(Underground.Canvas.Handle,
  324.                             0, FontHeight - 2, 0, 0, 15, 21);
  325.  
  326.       FloodFill(12, FontHeight - 3, clBlack, fsBorder);
  327.       Pixels[3, FontHeight + 13] := Color;
  328.       Pixels[3, FontHeight + 14] := Color;
  329.       Pixels[2, FontHeight + 15] := Color;
  330.  
  331.       h := 1;
  332.       for i := 0 to SL.Count - 1 do
  333.        begin
  334.         if TextAlign = taLeft then
  335.          TextOut(15, h, SL[i])
  336.         else
  337.          begin
  338.           q := TextWidth(SL[i]);
  339.           if TextAlign = taCenter then
  340.            begin
  341.             q := MaxWidth div 2 - q div 2;
  342.             TextOut(q + 15, h, SL[i])
  343.            end
  344.           else
  345.            TextOut(MaxWidth - q + 15, h, SL[i]);
  346.          end;
  347.         inc(h, TextHeight(SL[i]));
  348.        end;
  349.      end;
  350.     SL.Free;
  351.   with Rect do
  352.    begin
  353.     left := x;
  354.     top := y - FontHeight - 2;
  355.     right := x + MaxWidth + 23;
  356.     bottom := y + 18;
  357.    end;
  358.   end;
  359. end;
  360.  
  361. procedure TBaloonWindow.WMMouseMove(var Msg: TMessage);
  362. begin
  363.   {$IFDEF WIN32}
  364.   if HideIfMouseMove then {$ENDIF}
  365.    Deactivate;
  366. end;
  367.  
  368. {$IFDEF WIN32}
  369. procedure TBaloonWindow.WMMouseDown(var Msg: TMessage);
  370. begin
  371.   if HideIfMouseClick then Deactivate;
  372. end;
  373. {$ENDIF}
  374.  
  375. procedure TBaloonWindow.Paint;
  376. begin
  377.   Canvas.Draw(0, 0, Underground);
  378. end;
  379.  
  380. procedure TBaloonWindow.Deactivate;
  381. begin
  382.   Showing := False;
  383.   DestroyHandle;
  384. end;
  385.  
  386. procedure TBaloonWindow.Activate(Point: TPoint; Text: String; Shape: TPShape;
  387.                                                               TextAlign: TTextAlign;
  388.                                                               DivChar: Char);
  389. var
  390.   Rect: TRect;
  391. begin
  392.   if Showing then DestroyHandle;
  393.   Show(Rect, Point.x, Point.y - 15, Text, Shape, TextAlign, DivChar);
  394.   BoundsRect := Rect;
  395.  
  396.   SetWindowPos(Handle, HWND_TOPMOST, Rect.Left, Rect.Top, 0,
  397.     0, SWP_SHOWWINDOW or SWP_NOACTIVATE or SWP_NOSIZE);
  398.   Showing := True;  
  399. end;
  400.  
  401. { TXBaloon }
  402.  
  403. constructor TXBaloon.Create(aOwner: TComponent);
  404. begin
  405.   inherited Create(aOwner);
  406.   FDivisionChar := '@';
  407.   FFont := TFont.Create;
  408.   FFont.Name := 'MS Sans Serif';
  409.   FFont.Size := 8;
  410.   FColor := clWindow;
  411.   FHideIfMouseMove := True;
  412. end;
  413.  
  414. destructor TXBaloon.Destroy;
  415. begin
  416.   if Baloon <> nil then Hide;
  417.   FFont.Free;
  418.   inherited Destroy;
  419. end;
  420.  
  421. procedure TXBaloon.Show(Point: TPoint; Text: String);
  422. begin
  423.   if Text <> '' then
  424.    begin
  425.     if Baloon <> nil then Hide;
  426.     Baloon := TBaloonWindow.Create(Self);
  427.     Baloon.Underground.Canvas.Font.Assign(Font);
  428.     Baloon.Color := FColor;
  429.     LastX := Point.x;
  430.     LastY := Point.y;
  431.     Baloon.Activate(Point, Text, FShape, FTextAlign, FDivisionChar);
  432.    end;
  433. end;
  434.  
  435. procedure TXBaloon.Hide;
  436. begin
  437.   if Baloon <> nil then
  438.    Baloon.Deactivate;
  439. end;
  440.  
  441. function TXBaloon.IsShowing: Boolean;
  442. begin
  443.   if Baloon <> nil then
  444.    Result := Baloon.Showing
  445.   else
  446.    Result := False;
  447. end;
  448.  
  449. function TXBaloon.GetX: Integer;
  450. begin
  451.   if IsShowing then Result := LastX
  452.   else Result := -1;
  453. end;
  454.  
  455. function TXBaloon.GetY: Integer;
  456. begin
  457.   if IsShowing then Result := LastY
  458.   else Result := -1;
  459. end;
  460.  
  461. { -------- }
  462.  
  463. procedure Register;
  464. begin
  465.   RegisterComponents('Xacker', [TXBaloon]);
  466. end;
  467.  
  468. end.
  469.