如题
类似photoshop的工具窗口,它是独立于主窗口的,有句柄,类名PSFloatC

解决方案 »

  1.   

    给窗体的 GWL_STYLE, 或 GWL_EXSTYLE 加上
     WS_EX_NOACTIVATE
      

  2.   

    回楼上,那样窗体上的东西全部不能用了photoshop工具窗口上的工具是可以点的,点了原来窗口上的焦点不会丢失.
      

  3.   

    一个障眼法:
    procedure TForm2.FormActivate(Sender: TObject);
    begin
      SendMessage(Application.MainForm.Handle, WM_NCACTIVATE, Integer(True), 0);
    end;
      

  4.   

    楼上的放一个speedbutton放form2上再点点看......
      

  5.   

    哈终于完成了,参考如下代码:
    unit Unit1;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls;type  TFloatWnd = class(TForm)
      private
        procedure WMActivate(var Message: TWMActivate); message WM_ACTIVATE;
        procedure FormClose(Sender: TObject; var Action: TCloseAction);
      public
        constructor CreateEx(AOwner: TComponent; CFrame: TWinControlClass);
        procedure ShowAt(X, Y: Integer);
      end;  TForm1 = class(TForm)
        Button1: TButton;
        procedure Button1Click(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
        procedure WMActivate(var Message: TWMActivate); message WM_ACTIVATE;
      end;var
      Form1: TForm1;implementation
    uses
      Unit2;
    {$R *.dfm}{ TFloatWnd }constructor TFloatWnd.CreateEx(AOwner: TComponent; CFrame: TWinControlClass);
    begin
      inherited CreateNew(AOwner);
      AutoSize := True;
      FormStyle := fsStayOnTop;
      BorderStyle := bsToolWindow;
      with CFrame.Create(self) do
        Parent := Self;
      OnClose := FormClose;
    end;procedure TFloatWnd.FormClose(Sender: TObject; var Action: TCloseAction);
    begin
      Action := caFree;
    end;procedure TFloatWnd.ShowAt(X, Y: Integer);
    begin
      Left := X;
      Top := Y;
      Show;
    end;procedure TFloatWnd.WMActivate(var Message: TWMActivate);
    var
      i: Integer;
    begin
      for i := 0 to Screen.FormCount - 1 do
        if Screen.Forms[i].Handle <> Handle then
          SendMessage(Screen.Forms[i].Handle, WM_NCACTIVATE,
            Ord(Message.Active <> WA_INACTIVE), 0);
    end;procedure TForm1.Button1Click(Sender: TObject);
    var
      FloatWnd: TFloatWnd;
    begin
      FloatWnd := TFloatWnd.CreateEx(Self, TFrame2);
      FloatWnd.ShowAt(Left + 10, Top + 20);
    end;procedure TForm1.WMActivate(var Message: TWMActivate);
    var
      i: Integer;
    begin
      for i := 0 to Screen.FormCount - 1 do
        if Screen.Forms[i].Handle <> Handle then
          SendMessage(Screen.Forms[i].Handle, WM_NCACTIVATE,
            Ord(Message.Active <> WA_INACTIVE), 0);
    end;end.
      

  6.   

    unit Unit2;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 
      Dialogs, StdCtrls, Buttons;type
      TFrame2 = class(TFrame)
        SpeedButton1: TSpeedButton;
        SpeedButton2: TSpeedButton;
        SpeedButton3: TSpeedButton;
        SpeedButton4: TSpeedButton;
        BitBtn1: TBitBtn;
        BitBtn2: TBitBtn;
        Edit1: TEdit;
        Edit2: TEdit;
      private
        { Private declarations }
      public
        { Public declarations }
      end;implementation{$R *.dfm}end.
      

  7.   

    Toolbar2000就做得很好,楼主可以去下载来参考一下,
    事实上上面的代码也参考了Toolbar2000中的一些代码的。建一个工程试试看效果吧,反正我试了一下觉得还可以。
      

  8.   


    http://www.delphibbs.com/keylife/iblog_show.asp?xid=965
    IME类是实现IME用户界面部分的预定义全局窗口类。“IME”类与预定义的公共控制窗口类有许多相同的特点,IME窗口实例与静态控制一样通过CreateWindowEx函数创建,IME类窗口自己不响应用户输入,取而代之的是接收不同类型的控制消息实现全部IME用户接口。应用程序可以使用IME类创建自己的IME窗口,还可以使用ImmGetDefaultIMEWnd函数获取缺省IME窗口。
      

  9.   

    TO  linzhengqun(风。我回来了)
        你的程序....只是让窗口看起来和主窗口同时激活,而实际上它还是会抢去其它窗口的焦点,比如主窗口上有个edit,焦点在edit上时点你的窗口,edit会失去焦点,而我要的效果是不失去焦点!toolbar2000的代码我看了半天还没找到他是怎么实现的,它的工具窗口是不会抢焦点的,除非工具窗口里有可以获得焦点的控件TO aiirii:
        不会创建一个无焦点窗口一定要用IME接口吧?
      

  10.   

    好吧,你研究一下TB2Dock单元的TTBFloatingWindowParent类吧,它应该就是所有浮动窗口的外壳。
      

  11.   

    我记得
      CreateWindowex 有一个参数可以设置,但一时没找到
      

  12.   

    CreateWindowex 好象没有哪个参数可以实现这样的功能.....试着把TTBFloatingWindowParent从toolbar2000分离出来,没成功:(
    好象子类还实现了一些功能,分离出来后建立一个实例Show不出来
      

  13.   

    createwindowEx用WS_EX_TOOLWINDOW 就OK啦
      

  14.   


    输入法的窗口为什么不会得到“焦点”呢?因为它是一个“禁用”的窗口!在建立窗口的时候指定WS_DISABLED风格或事后EnableWindow()都可以的,那么这个窗口如何响应鼠标动作呢?答案是利用WM_SETCURSOR消息………
      

  15.   

    这是我写的一个输入法状态条窗口:unit Unit_Stat;interfaceuses Windows;function StatusWndProc(hStatWnd: hWnd; uMsg: uInt; wParam: WParam; lParam: LParam): LResult; stdcall;
    function RegisterStatClass(): Bool;
    function CreateStatWindow(hUIWnd: hWnd): hWnd;implementationuses Messages, Unit_Class, Unit_Bmp, Unit_Public;  // Stat窗口回调
    function StatusWndProc(hStatWnd: hWnd; uMsg: uInt; wParam: WParam; lParam: LParam): LResult; stdcall;
    const {$J+}
      OldPoint: TPoint = (X: 0; Y: 0); {$J-} // 每次只可能"拖拽"一个状态条, 所以只用一个全局变量就够了..
    var
      pCurStat: PStatus;
      hStatDC: HDC;
      ps: TPaintStruct;
      StatRect, ScreenRect: TRect;
      CurPoint: TPoint;
    begin
      case (uMsg) of
        WM_CREATE:
          begin
            GetMem(pCurStat, SizeOf(TStatus));
            SetWindowLong(hStatWnd, 0, Integer(pCurStat));        if (pCurStat = nil) then
              Result := -1
            else begin
              pCurStat.Chinese := True;
              pCurStat.FullShape := False;
              pCurStat.Symbol := False;          Result := 0;
            end;
          end;    WM_DESTROY:
          begin
            pCurStat := PStatus(GetWindowLong(hStatWnd, 0));
            if (pCurStat <> nil) then FreeMem(pCurStat);        Result := 0;
          end;    WM_PAINT:
          begin
            hStatDC := BeginPaint(hStatWnd, ps);        pCurStat := PStatus(GetWindowLong(hStatWnd, 0));
            if (pCurStat <> nil) then DrawStatus(hStatDC, pCurStat^);        EndPaint(hStatWnd, ps);        Result := 0;
          end;    WM_SETCURSOR:
          begin
            if (HiWord(lParam) = WM_LBUTTONDOWN) then
            begin
              SetCursor(LoadCursor(0, IDC_HAND));
              pCurStat := PStatus(GetWindowLong(hStatWnd, 0));          GetCursorPos(CurPoint);
              ScreenToClient(hStatWnd, CurPoint);          case ButtonPos(CurPoint) of
                0: begin // 麻子头像
                   end;            1: begin // 单拼字样
                     SetCursor(LoadCursor(0, IDC_SIZEALL));                 GetCursorPos(OldPoint);
                     SetCapture(hStatWnd); // 接收鼠标消息
                   end;            2: begin // 全角半角
                     if (pCurStat <> nil) then
                     begin
                       pCurStat.FullShape := not pCurStat.FullShape;
                       InvalidateRect(hStatWnd, nil, True);
                     end;
                   end;            3: begin // 标点符号
                     if (pCurStat <> nil) then
                     begin
                       pCurStat.Symbol := not pCurStat.Symbol;
                       InvalidateRect(hStatWnd, nil, True);
                     end;
                   end;            4: begin // 中文英文
                     if (pCurStat <> nil) then
                     begin
                       pCurStat.Chinese := not pCurStat.Chinese;
                       InvalidateRect(hStatWnd, nil, True);
                     end;
                   end;
              end; // case of ..          Result := 0;
            end else
              Result := DefWindowProc(hStatWnd, uMsg, wParam, lParam);
          end;    WM_LBUTTONUP:
          begin
            ReleaseCapture();
            Result := 0;
          end;    WM_MOUSEMOVE:
          begin
            SetCursor(LoadCursor(0, IDC_SIZEALL));        GetCursorPos(CurPoint);
            GetWindowRect(hStatWnd, StatRect);
            OffsetRect(StatRect, CurPoint.X - OldPoint.X, CurPoint.Y - OldPoint.Y);        SystemParametersInfo(SPI_GETWORKAREA, 0, @ScreenRect, 0);        if (StatRect.Right > ScreenRect.Right) then StatRect.Left := ScreenRect.Right - BmpWidth
            else if (StatRect.Left < ScreenRect.Left) then StatRect.Left := ScreenRect.Left;        if (StatRect.Bottom > ScreenRect.Bottom) then StatRect.Top := ScreenRect.Bottom - BmpHeight
            else if (StatRect.Top < ScreenRect.Top) then StatRect.Top := ScreenRect.Top;        MoveWindow(hStatWnd, StatRect.Left, StatRect.Top, BmpWidth, BmpHeight, True);        GetCursorPos(OldPoint);
            Result := 0;
          end;    else Result := DefWindowProc(hStatWnd, uMsg, wParam, lParam);
      end;
    end;  // 注册stat类
    function RegisterStatClass(): Bool;
    var
      StatClass: TWndClass;
    begin
      StatClass.style         := CS_VREDRAW or CS_HREDRAW or CS_IME;
      StatClass.lpfnWndProc   := @StatusWndProc;
      StatClass.cbClsExtra    := 0;
      StatClass.cbWndExtra    := SizeOf(PStatus); // **
      StatClass.hInstance     := HInstance;
      StatClass.hCursor       := LoadCursor(0, IDC_HAND);
      StatClass.hIcon         := 0;
      StatClass.lpszMenuName  := nil;
      StatClass.lpszClassName := Stat_ClassName;
      StatClass.hbrBackground := COLOR_BTNFACE + 1;  Result := RegisterClass(StatClass) <> 0;
    end;  // 建立stat窗口
    function CreateStatWindow(hUIWnd: hWnd): hWnd;
    var
      ScreenRect: TRect;
    begin
      SystemParametersInfo(SPI_GETWORKAREA, 0, @ScreenRect, 0);  Result := CreateWindow(Stat_ClassName, nil, WS_DISABLED or WS_POPUP,
        ScreenRect.Left + 5, ScreenRect.Bottom - BmpHeight - 5,
        BmpWidth, BmpHeight, hUIWnd, 0, HInstance, nil);  ShowWindow(Result, SW_SHOWNOACTIVATE); // **
    end;end.
      

  16.   

    有兴趣的话,请看看这个:http://www.2ccc.com/article.asp?articleid=2850
      

  17.   

    很明显Toolbar2000不是用的DISABLE窗口,它是继承自TCustomForm用VCL在设计程序时要简单得多,直接用API的话我还不如拿着toolbar2000就用...自己处理WM_MOUSEACTIVATE消息,返回MA_NOACTIVATE可以让鼠标点窗体客户区不抢焦点,但不能点标题和边框.要处理标题和边框的点击好象要处理WM_NCHITTEST消息......它里面的代码有点杂,分离出来达不到效果...
      

  18.   

    用VCL在设计程序时要简单得多,直接用API的话我还不如拿着toolbar2000就用...
    -------------------------------------------------------
    嘿嘿,的确,我贴的是API代码,但不代表就一定要完全用API来写呀? ^^
    VCL和SDK有本质区别吗?我看是没有!SDK能实现的,VCL就更能实现了…
    指定窗口风格,重载CreateParams不就可以了?处理WM_SETCURSOR消息,方法就更多了。。
    楼主应该是老鸟了,这些应该都知道的吧,俺就不在这里班门弄斧啦… :~)
      

  19.   

    当然,Toolbar2000如何实现的,是另一回事了,我只是路过说了两句,楼主莫怪……
      

  20.   

    也许是我表达得不太好,photoshop的工具窗口有两种,左边的是绘图工具,是不能获得焦点的,右边的一系列窗口分两种情况,1是窗口里没有可以获得焦点的控件,那么它也是不能获得焦点的,2是窗口里有能获得焦点的控件,点客户区不会抢走焦点,点能获得焦点的控件是可以获得焦点的,和toolbar2000实现的效果完全一样,我想要的就是这种效果.刘麻子兄的方法是完全不能获得焦点的了,这种窗口也有它的用处,当然不止是IME其实我现在都用不着-_-  研究研究嘛,呵呵
    从toolbar2000以及dfw的lich的回答来看,应该从TForm类继承的普通窗口响应WM_MOUSEACTIVATE及WM_NCHITTEST消息就能做到我说的那种效果,前一个简单,第二个好象复杂点,还没研究过这个消息,希望不要自画~
      

  21.   

    在DFW上看了很多刘麻子兄的帖子,高手了。
    ,怎么高手都跑到csdn里来了。