发新话题
打印

如何做漂亮的HintWindow

如何做漂亮的HintWindow

在Delphi中,如何做类似下面图片中的黄色提示窗口,在Delphi中。
文字与黄色长方形窗口有间隔,看着更清楚美观。


下图是网上的光标跟随窗口,文字与提示窗口没有间隔,看着很小不是很舒服。



上图效果代码如下。如何修改单元代码,使之变为图1的效果,谢谢!
unit  HintWindow;
interface
procedure Active_Hint(Left, Top: Integer; const Text: string); // 激活HintWindow
implementation
uses
  Windows, Messages;
var
  HintText: string;  // Hint窗体要显示的提示文字
  No_Enter: Boolean; // 鼠标尚未进入HintWindow内
  HintHandle: DWORD; // HintWindow窗体句柄
  
    // 重新引入API函数以便Active_Hint()调用
function GetTabbedTextExtent(hDC: HDC; lpString: PChar; nCount,
  nTabPositions: Integer; pnTabStopPositions: Pointer): LongWord; stdcall;
  external user32 name 'GetTabbedTextExtentA';
    // 激活提示窗体
procedure Active_Hint(Left, Top: Integer; const Text: string);
var
  TextWidth, TextHeight, ScreenWidth, HintDC: Integer;
begin
  HintText := Text;
  No_Enter := TRUE;
// 去字符串对应范围
  HintDC := GetDC(HintHandle);
  TextWidth := GetTabbedTextExtent(HintDC, PChar(HintText), Length(HintText), 0, nil);
  ReleaseDC(HintHandle, HintDC);
  TextHeight := HIWORD(TextWidth);
  TextWidth := LOWORD(TextWidth);
// 是否超出屏幕宽度
  ScreenWidth := Word(GetSystemMetrics(SM_CXSCREEN));
  if ((Left + TextWidth) > ScreenWidth) then Left := ScreenWidth - TextWidth - 5;
// (合适位置)显示窗体
  SetWindowPos(HintHandle, HWND_TOPMOST, Left, Top, TextWidth, TextHeight, SWP_NOACTIVATE);
  ShowWindow(HintHandle, SW_SHOWNOACTIVATE);
end;
    // 窗体过程回调函数
function HintProc(hHint, MsgID, WParam, LParam: DWORD): DWORD; stdcall;
const
{$J+}
  EventTrack: TTrackMouseEvent =
   ( cbSize: SizeOf(TTrackMouseEvent);
     dwFlags: TME_LEAVE;
     hwndTrack: 0;
     dwHoverTime: HOVER_DEFAULT );
  TempFont: DWORD = 0;     
{$J-}
var
  CurPos: TPoint;
  CurWin, HintDC: DWORD;
  Ps: TPaintStruct;  
begin
  Result:= 0;
  case MsgID of
    WM_PAINT: // 绘制
      begin
        HintDC := BeginPaint(hHint, Ps);
        SetBkMode(HintDC, TRANSPARENT);
        SelectObject(HintDC, TempFont);
        TextOut(HintDC, 1, 1, PChar(HintText), Length(HintText));
        EndPaint(hHint, Ps);
      end;
    WM_MOUSEMOVE,
    WM_LBUTTONDOWN,
    WM_RBUTTONDOWN:
      begin
        if No_Enter then  // 初入 HintWindow ..
        begin              // 则要求鼠标离开通知
          No_Enter := FALSE;
          EventTrack.hwndTrack := hHint;
          TrackMouseEvent(EventTrack);
        end else
        begin // 隐藏自己并转发消息给下面控件
          CurPos.X := LOWORD(LParam);
          CurPos.Y := HIWORD(LParam);
          ClientToScreen(hHint, CurPos);
          ShowWindow(hHint, SW_HIDE);
          CurWin := WindowFromPoint(CurPos);
          ScreenToClient(CurWin, CurPos);
          LParam := (CurPos.Y shl 16) or CurPos.X;
          SendMessage(CurWin, MsgID, WParam, LParam);
        end;
      end;
    WM_MOUSELEAVE: // 鼠标离开通知
      begin
        ShowWindow(hHint, SW_HIDE);
        No_Enter := TRUE;
      end;
    WM_CREATE:
     begin
       TempFont := CreateFont(12, 6, 0, 0, FW_EXTRALIGHT, Byte(FALSE), Byte(FALSE),
                     Byte(FALSE), GB2312_CHARSET, OUT_DEFAULT_PRECIS,
                     CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, '宋体');
     end;
      
    WM_DESTROY:
      begin
        DeleteObject(TempFont); // 删除字体对象
      end;
    else
      Result := DefWindowProc(hHint, MsgID, WParam, LParam); // 标准处理
  end;
end;
procedure Create_HintWindow;
var
  HintClass: TWndClass;
begin
  HintClass.Style := CS_HREDRAW or CS_VREDRAW;
  HintClass.lpfnWndProc := @HintProc;
  HintClass.cbClsExtra := 0;
  HintClass.cbWndExtra := 0;
  HintClass.hInstance := SysInit.HInstance;
  HintClass.hIcon := 0;
  HintClass.hCursor := LoadCursor(0, IDC_ARROW);
  HintClass.hbrBackground := COLOR_INFOBK + 1;
  HintClass.lpszMenuName := nil;
  HintClass.lpszClassName := 'HintWindow';
  RegisterClass(HintClass);
  HintHandle := CreateWindowEx(WS_EX_TOPMOST or WS_EX_TOOLWINDOW, HintClass.lpszClassName,
    'I_Love_Mazi_XiXi_:-P', WS_POPUP or WS_BORDER, 0, 0, 0, 0, 0, 0, HInstance, nil);
end;
procedure Destroy_HintWindow;
begin  
  DestroyWindow(HintHandle);
end;
initialization
  Create_HintWindow;
finalization
  Destroy_HintWindow;
end.

TOP

HintDC := GetDC(HintHandle);
TextWidth := GetTabbedTextExtent(HintDC, PChar(HintText), Length(HintText), 0, nil);
ReleaseDC(HintHandle, HintDC);
TextHeight := HIWORD(TextWidth);
TextWidth := LOWORD(TextWidth);

这几句如何修改,使之达到图1中的效果,可以容纳任意长度文字,并且全部显示。文字与长方形黄色背景之间有空隙,并且文字大方一点,谢谢。

TOP

继承 THintWindow 类,重载 CalcHintRect 过程
超级简单易用的音视频转换组件 支持RMVB解码 FFmpeg for Delphi / VB http://www.CCAVC.com

TOP

有很多控件
你才是国家队的,你全家都是国家队的

TOP

我记得ToolTipCtrl可以发送消息设置Margin

TOP

自己画一个
What?

TOP

发新话题