首页
社区
课程
招聘
[求助]关于移动窗口的问题, 做了几天..也未做成...
2006-9-14 07:37 6338

[求助]关于移动窗口的问题, 做了几天..也未做成...

2006-9-14 07:37
6338
我想做一个程序(DELPHI的)...只想让我的主程序(有一张动图片..坐着的人)可以坐在前台窗口上的标题栏上.....

下面的得到前台窗口的代码(自已觉得下面的写法不好)...
var

  OldHandle, NewHandle, MyThread : THandle;//定义一个句柄
  MyThreadID : DWord;
  ThreadEvent : Boolean = False;

function MyGetForegroundWindow(P : Pointer) : LongInt; stdcall;
begin
  repeat
    NewHandle := GetForegroundWindow;
      if NewHandle <> OldHandle then
      begin
      OldHandle := NewHandle;
      坐上去(用 SetWindowPos 把自已的Form1...设为 TOPMOST...不改变活动窗口)
      end;
  until ThreadEvent;
end;

procedure Form1.FormCreate(Sender: TObject);
begin
  // 不好啊...占用率太了点, 不过我没办法...
  MyThread := CreateThread(nil, 0, @SetForegroundWindowTitle, nil, 0, MyThreadID);
end;

现在....当用户拖动前台窗口时...我的窗口也要一起拖动...
我试过用 Hook 来取 WM_MOVE后再处理我的窗口(要和前台窗口一起拖动)...

但水平不够......
也在 大富翁编程网站 上找了半天...也找不到....

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
点赞7
打赏
分享
最新回复 (13)
雪    币: 721
活跃值: (350)
能力值: ( LV9,RANK:1250 )
在线值:
发帖
回帖
粉丝
happytown 31 2006-9-14 14:29
2
0
你用你的程序来拦截前台窗口的移动消息的思路应该没错,好像《Delphi编程经典》上有如何Hook的例子,Delphi的FAQ(具体那个我忘了)好像也有可以帮你忙的东东。
雪    币: 372
活跃值: (31)
能力值: ( LV12,RANK:410 )
在线值:
发帖
回帖
粉丝
vxin 10 2006-9-14 19:09
3
0
Releasecapture;
PerForm(WM_syscommand,$f012,0);
雪    币: 746
活跃值: (4030)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
kagayaki 2006-9-15 03:19
4
0
现在....当用户拖动前台窗口时...我的窗口也要一起拖动...
我试过用 Hook 来取 WM_MOVE后再处理我的窗口(要和前台窗口一起拖动)...

我试了用HOOK来取WM_MOVE, MESSAGE 总是不能正常取出....
大家能帮我写个 HOOK WM_MOVE  MESSAGE 的 HOOK 吗? 还有...上面的功能做在 DLL 有 HOOK中...会不会比上面的线程好....
雪    币: 746
活跃值: (4030)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
kagayaki 2006-9-16 04:07
5
0
顶一下.......
雪    币: 117
活跃值: (20)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
无奈无赖 2006-9-16 13:55
6
0
我以前用VB做过一个类似的东东,就是在当前活动的窗口标题上显示一个当前的系统时间。
用的是定时器,不停地获取前台窗口程序的坐标,并根据这个来设定自己的窗口坐标。
雪    币: 236
活跃值: (26)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
红火蚁 3 2006-9-16 15:28
7
0
我感觉只要你用HOOK处理这个
LRESULT CALLBACK GetMsgProc(
  int code,       // hook code
  WPARAM wParam,  // removal flag
  LPARAM lParam   // address of structure with message
);
在这个
typedef struct tagMSG {     // msg
    HWND   hwnd;     
    UINT   message;
    WPARAM wParam;
    LPARAM lParam;
    DWORD  time;
    POINT  pt;
} MSG;
里面判断你的要求,然后每当移动的时候你就画你想画的东西
我这些都是在vc中的函数和结构
雪    币: 746
活跃值: (4030)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
kagayaki 2006-9-18 02:06
8
0
function HookMsgProc(nCode, wParam, lParam : Integer): Integer;stdcall;
var
  PCWP : PMSG;
begin
  Result:=0;
  if nCode = HC_ACTION then
  begin
  PCWP:=PMSG(lParam);
    case PCWP.message of   //就是这里不能正常接收 WM_MOVE
      WM_MOVE: begin
               ReleaseCapture;
               SendMessage(FindWindow('Form2', nil), WM_SYSCOMMAND,

SC_MOVE + 1, 0);
                end;
    end;
  end;
  if nCode < 0 then
    Result := CallNextHookEx(HookHandle, nCode, wParam, lParam);        
end;

不知是什么地方写错了....请指教........
雪    币: 236
活跃值: (26)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
红火蚁 3 2006-9-18 03:51
9
0
第一个窗口移动发送的不是WM_MOVE消息
而是其他的
你可以用SPY++看看到底是哪个消息

另外你可以多试试其它的函数
可能其它的函数可以拦截这个消息
雪    币: 202
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
tjz_xaut 2006-9-18 15:11
10
0
用SendMessage不可以吗?
雪    币: 236
活跃值: (26)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
红火蚁 3 2006-9-18 22:59
11
0
呵呵
找了个时间给你把这个问题解决了
你自己看代码啊

dll中的代码
CTestDllApp theApp;
HHOOK g_hook = NULL;
HWND g_hWnd = NULL;

LRESULT CALLBACK CallWndProc(
  int nCode,      // hook code
  WPARAM wParam,  // current-process flag
  LPARAM lParam   // address of structure with message data
)
{
        if (nCode == HC_ACTION)
        {
                g_hWnd = ::FindWindow(NULL, TEXT("lc.txt - 记事本"));
                if (g_hWnd == NULL)
                {
                        MessageBox(NULL, TEXT("没有找到窗口"), NULL, MB_OK);
                }
                else
                {
                        CWPSTRUCT *p = (CWPSTRUCT*)lParam;

                        if ( (g_hWnd == p->hwnd) && (WM_MOVING == p->message) )
                        {
                                MessageBox(NULL, TEXT("得到消息"), NULL, MB_OK);
                        }
                }
        }

        return CallNextHookEx(g_hook, nCode, wParam, lParam);
}

extern "C" _declspec(dllexport) void SetHook()
{
        g_hook = SetWindowsHookEx(
                                                                  WH_CALLWNDPROC,        // type of hook to install
                                                                  CallWndProc,     // address of hook procedure
                                                                  theApp.m_hInstance,    // handle to application instance
                                                                  0   // identity of thread to install hook for
                                                                );
    if (g_hook == NULL)
        {
                MessageBox(NULL, TEXT("SetHook don't get g_hook"), NULL, MB_OK);
        }
}

extern "C" _declspec(dllexport) void EndHook()
{
        if (g_hook != NULL)
        {
                UnhookWindowsHookEx(g_hook);
                g_hook = NULL;
        }
}

你调用程序的代码
extern "C" _declspec(dllimport) void SetHook();
extern "C" _declspec(dllimport) void EndHook();

void CTestDlg::OnButton1()
{
        // TODO: Add your control notification handler code here
        SetHook();
}

void CTestDlg::OnButton2()
{
        // TODO: Add your control notification handler code here
        EndHook();
}

程序执行的结果就是你移动窗口的时候,先谈出对话框,你确认了后才开始移动窗口
现在你想做什么操作,就把哪个messageBox替换就OK 了
雪    币: 746
活跃值: (4030)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
kagayaki 2006-9-19 02:10
12
0
多谢大家了......祝大家身体健康....心想事成.....
雪    币: 746
活跃值: (4030)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
kagayaki 2006-9-19 04:16
13
0
天啊.....上面的问题是完美地解决了......
但新的问题又来了....
还请大家帮一下.....

var
  FW : THandle;  //句柄
  Rect_A : TRect;

function CallWndProc(nCode, wParam, lParam : Integer): Integer;
stdcall;   
begin
  if nCode = HC_ACTION then
  begin
  FW := GetForegroundWindow;
    if (FW = PCWPSTRUCT(lParam)^.hwnd) and (PCWPSTRUCT(lParam)^.message = WM_MOVING) then
    begin
    GetWindowRect(FW, Rect_A);
    SetWindowPos(DLLForm.Handle, HWND_TOPMOST, Rect_A.Left, Rect_A.Top - 70, 0, 0, SWP_NOSIZE or SWP_NOACTIVATE);
   // DLLForm 是 DLL 中的窗口, 用来放图片的
  //问题有 2 个:
  // 1.  Message 是正常得到了...但用 SetWindowPos 来定位 DLL 中的窗口, 效果不好(不可以像一些"磁性"  窗口 一样实时同步移动)
  // 2.  DLLForm 是 DLL 中的窗口, 发觉, 如果 GetForegroundWindow 得到的时其它外部程序的窗口..会出现下面的错误:
   // "0x032c1f7f" 指令引用的 "0x00000180" 内存。该内存不能为 "read"。
   //要终止程序,请单击“确定”。
  //  要调试程序,请单击“取消”。""

    end;
  end;

  if nCode < 0 then
    Result := CallNextHookEx(HookHandle, nCode, wParam, lParam);                             
end;

function InstallHook : Boolean; stdcall;
begin
  Result:=False;
  HookHandle:=SetWindowsHookEx(WH_CALLWNDPROC, @CallWndProc,
                  HInstance, 0);            

  DLLForm:= TDLLForm.Create(Application);  // 我想...在这里开始创建窗口
  DLLForm.Show;
  Result := HookHandle <> 0;
end;
雪    币: 746
活跃值: (4030)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
kagayaki 2006-9-20 02:04
14
0
顶一下.......
游客
登录 | 注册 方可回帖
返回