1、修改窗口样式SetWindowLong(myWindowHandle, GWL_STYLE, WS_POPUP);
2、在客户区自己创建了一个标题栏,标题栏的背景图ondrag事件里面执行以下代码实现窗口移动
 
           ReleaseCapture();
            SendMessage(myWindowHandle, WM_NCLBUTTONDOWN, HTCAPTION, 0);
            SendMessage(myWindowHandle, WM_LBUTTONUP, 0, 0);
  
3、自己写了一个dll,用SubWndProc方法拦截WndProc方法,WM_NCHITTEST事件里面执行一下代码if (pt.x >= rcClient.right - 10 && pt.y >= rcClient.bottom - 10)
{
SetCursor(LoadCursor(NULL, MAKEINTRESOURCE(IDC_SIZENWSE)));
return HTBOTTOMRIGHT;
}
else if (pt.x <= rcClient.left + 10 && pt.y >= rcClient.bottom - 10)
{
SetCursor(LoadCursor(NULL, MAKEINTRESOURCE(IDC_SIZENESW)));
return HTBOTTOMLEFT;
}
else if (pt.x <= rcClient.left + 10 && pt.y <= rcClient.top + 10)
{
SetCursor(LoadCursor(NULL, MAKEINTRESOURCE(IDC_SIZENWSE)));
return HTTOPLEFT;
}
else if (pt.x >= rcClient.right - 10 && pt.y <= rcClient.top + 10)
{
SetCursor(LoadCursor(NULL, MAKEINTRESOURCE(IDC_SIZENESW)));
return HTTOPRIGHT;
}
else if (pt.x >= rcClient.right - 5)
{
SetCursor(LoadCursor(NULL, MAKEINTRESOURCE(IDC_SIZEWE)));
return HTRIGHT;
}
else if (pt.x <= rcClient.left + 5)
{
SetCursor(LoadCursor(NULL, MAKEINTRESOURCE(IDC_SIZEWE)));
return HTLEFT;

else if (pt.y <= rcClient.top + 5)
{
SetCursor(LoadCursor(NULL, MAKEINTRESOURCE(IDC_SIZENS)));
return HTTOP;
}
else if (pt.y >= rcClient.bottom - 5)
{
SetCursor(LoadCursor(NULL, MAKEINTRESOURCE(IDC_SIZENS)));
return HTBOTTOM;
}
else
{
SetCursor(LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW)));
return HTCLIENT;
}
现在遇到的问题是,只要先点击自制标题栏移动了窗口
1、缩放就不起作用了,缩放时鼠标样式变成缩放样式,但是,鼠标拖动后,整个窗口在移动,而不是缩放。
2、最小化以后,鼠标点击任务栏的的窗口,窗口粘在鼠标上跟随鼠标移动,必须点击一下左键后,才不跟随鼠标移动。
3、SendMessage(myWindowHandle, WM_NCLBUTTONDOWN, HTCAPTION, 0);这行报错:An abnormal situation has occurred: the PlayerLoop internal function has been called recursively. Please contact Customer Support with a sample project so that we can reproduce the problem and troubleshoot it.

解决方案 »

  1.   

            ReleaseCapture();
            SendMessage(myWindowHandle, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
            SendMessage(myWindowHandle, WM_LBUTTONUP, 0, 0);
    我执行一次最大化,再去缩放窗口就不会出错了
    另外我发现 SendMessage(myWindowHandle, WM_NCLBUTTONDOWN, HTCAPTION, 0); 这句在拖动自制标题栏完毕放开鼠标左键的时候就会报错:An abnormal situation has occurred: the PlayerLoop internal function has been called recursively. Please contact Customer Support with a sample project so that we can reproduce the problem and troubleshoot it. ,
    改成SendMessage(myWindowHandle, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, 0);就不会报错,但是拖动完后去缩放窗体还是无法缩放变成了移动窗口,放开鼠标左键的时候这行还是会报上面的错误。
    我的疑问主要是为什么我移动自定义标题栏后,缩放窗口会触发自制标题栏的ondrag事件,我以为是鼠标没有重置,所以ondrag事件后我加了个ondragend事件,在里面执行
            ReleaseCapture();
            SendMessage(myWindowHandle, WM_LBUTTONUP, 0, 0);
            SendMessage(myWindowHandle, WM_NCLBUTTONUP, 0, 0);
    依然出错
    运行
            ReleaseCapture();
            SendMessage(myWindowHandle, WM_SYSCOMMAND, SC_RESTORE, 0);
            SendMessage(myWindowHandle, WM_LBUTTONUP, 0, 0);
    还是无法解决这个问题
      

  2.   

    不就是 NCHITTEST 吗? 干嘛 要 Dll ?        case WM_NCHITTEST: 
                pt.x = LOWORD(lParam); 
                pt.y = HIWORD(lParam); 
    GetWindowRect(hwnd, &rc); 
     // move window
    rc.top+=TestBorder;
    rc.bottom-=TestBorder;
    rc.left+=TestBorder;
    rc.right-=TestBorder;
    if(PtInRect(&rc,pt))
    {
    return HTCAPTION; 
    }
    // size window
    if (pt.x < rc.left && pt.y < rc.top)

    return HTTOPLEFT; 

    if (pt.x>rc.right && pt.y<rc.top)

    return HTTOPRIGHT; 

    if (pt.x<rc.left && pt.y>rc.bottom)

    return HTBOTTOMLEFT; 

    if (pt.x>rc.right && pt.y>rc.bottom)

    return HTBOTTOMRIGHT; 

    break; 
      

  3.   

    3楼的兄弟,我是在UNITY里面调用api来实现无边框,无标题栏窗口,然后自己写dll来实现缩放。
    你的方法试了下,感觉整个窗口都是非客户区呢,点任何地方都可以移动。缩放的话,鼠标必须指到四个角那一个像素上才能缩放。
    我想实现的功能是:
    1、我的进程是一个POPUP窗口,没有标题栏和sizebox,我在客户区自己做了标题栏。
    2、拖动标题栏,窗口任意移动。标题栏上最大化,最小化,关闭使用sendmessage的方式实现功能。
    3、鼠标靠近边框5个像素,靠近4个角10个像素范围内出现缩放窗口的鼠标标记,并且拖动鼠标可以实现窗口缩放。
      

  4.   

    1 整个窗口都是非客户区, 对 你可以改 bottom
    2 鼠标必须指到四个角那一个像素上才能缩放。只 做了 4 个
    3 TestBorder = 5个像素
      

  5.   

    5楼,修改掉非客户去的问题后,你的代码逻辑上跟我的没啥分别啊,除了4条边+5个像素的范围是非客户去,其他都是客户区,对不对?
    解决不了我的问题啊,我推测是 
    SendMessage(myWindowHandle, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, 0); 执行后,有什么状态没复位,导致这个时候去拖拉边框缩放依然执行到我的标题栏移动事件了,如果我移动窗口后执行一次SendMessage(myWindowHandle, WM_SYSCOMMAND, SC_MAXIMIZE, 0); 然后再去缩放窗口就一切正常
      

  6.   

    使用;了  SetCapture(); ?
      

  7.   

    没有设置过SetCapture(),应该不是这个问题。
    现在是我拖动自定义的标题栏,触发标题栏的ondrag事件之后,鼠标在WM_NCHITTEST中非客户区的部分拖拽就依然会触发标题栏的ondrag事件。如果最大化或者最小化一次后,再去WM_NCHITTEST中非客户区的部分拖拽就正常缩放了,不会触发标题栏的ondrag事件。
      

  8.   

    看看你的 ondrag 代码
      

  9.   

    我现在根据鼠标当前坐标判断是否在标题栏可以拖拽范围内,如果不在直接return,暂时解决了这个问题。
    希望后面的朋友能解释下SendMessage(myWindowHandle, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, 0)后,鼠标有什么状态不对,导致拖拉边框也会触发自定义标题栏的ondrag事件。
      

  10.   


            void Title_OnDrag(GameObject go, PointerEventData eventData)
            {
                if (!RectTransformUtility.RectangleContainsScreenPoint(TitleBgRect, eventData.position, m_UICamera)) return;            
                ReleaseCapture(); 
                SendMessage(myWindowHandle, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, 0); 
                SendMessage(myWindowHandle, WM_LBUTTONUP, 0, 0); 
            }
      

  11.   

    ReleaseCapture(); ??
    你不是说 “没有设置过SetCapture()”
    哪里要 ReleaseCapture(); ?
      

  12.   

    本来 就应该 有
                if(PtInRect(&rc,pt))
                {
                    return HTCAPTION; 
                }
      

  13.   

                SendMessage(myWindowHandle, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, 0); 
    这句实现窗口移动,但是整个进程中的东西感觉全部暂停了,连socket连接也不收发包了,请问有什么办法可以让进程不暂停吗
      

  14.   

    把其他 工作 放 线程 中,如 socket连接
      

  15.   

    socket 肯定要放 线程中, 
      

  16.   

    我socket放线程中了,还是要中断。
      

  17.   

    现在还有两个问题
    1、SendMessage(myWindowHandle, WM_SYSCOMMAND, SC_MAXIMIZE, 0);实现最大化后,拖动自制标题栏窗口就会还原到之前的状态,感觉是自动调用了Restore。
    2、我限制了窗口最大最小尺寸,现在拖拉窗口边缘缩放窗口大小到最大或者最小值以后窗口开始移动,最终可以移动到屏幕边缘,然后就消失了,请问怎么能做到缩小到最小尺寸后,窗口不会移动
      

  18.   

    我是unity做得游戏,就算socket连接没问题,我的动画这些全都停止了,请问SC_MOVE + HTCAPTION这个过程中是否有什么设置是可以让进程正常运行的
      

  19.   

    windows的标题栏拖动进程没有阻塞是怎么做到的呢,兄弟能有办法帮忙查一下么
      

  20.   

    我说的就是 windows的标题栏拖动时 进程会被阻塞,不过 拖动时 只显示 一个 方框的话会 好的 多。
      

  21.   

    可以改变 系统 设置,即 SPI_DRAGFULLWINDOW 属性,
    你 选择 重绘 功能 是 用 什么 触发 的 Timer ?
      

  22.   

    22楼两个问题已经解决,以后遇到得朋友可以参考下:
    1、没有用发送SC_MAXIMIZE得方法,我在最大化得时候取得当前工作区域范围,然后用movewindow方法实现最大化。同时用SystemParametersInfo方法记录下最大化之前的窗口信息,用于恢复按钮调用。
    2、错误是由于我在 WM_SIZING里面不管哪条边判断达到最小值时都是设置RIGHT和BOTTOM造成的,现在根据不同的边来设置就没有这个问题了,比如:                                        if (myMinW > 0)   //myMinW是窗口最小宽度
    {
    if (lpRect->right - lpRect->left < myMinW)
    {
    if (wParam == WMSZ_RIGHT || wParam == WMSZ_TOPRIGHT || wParam == WMSZ_BOTTOMRIGHT)
    lpRect->right = lpRect->left + myMinW;
    else
    lpRect->left = lpRect->right - myMinW;
    }
    }
      

  23.   

    @31
    我是在C#里面调用
    SendMessage(myWindowHandle, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, 0); 来实现的移动功能
    你说的重绘 和 timer 我都没有设置过相关的属性,系统默认的,请问怎么能修改呢
      

  24.   

    关于进程阻塞这个问题,我现在放弃用SendMessage来实现窗口拖动,换成在drag事件里面根据鼠标坐标的变化重新计算窗口位置,然后使用MoveWindow来移动窗口的方法,问题解决了。不过后面看到帖子的朋友,希望能继续解答SendMessage造成进程停滞的原因及解决方法。
      

  25.   

    //伪标题栏
    private: System::Void panTitleBar_MouseDown(System::Object^  sender, System::Windows::Forms::MouseEventArgs^  e) {
     //仅接受左键移动窗体
     static Point MousePoint;
     if (e->Button == System::Windows::Forms::MouseButtons::Left ) {
    if (!(MousePoint.X== e->X) && !(MousePoint.Y == e->Y) ){
     ::ReleaseCapture();
     ::SendMessage((HWND)this->Handle.ToInt32(), WM_NCLBUTTONDOWN, HTCAPTION, 0);
     }
     }  MousePoint = Point(e->X,e->Y );
     }
      

  26.   

    SendMessage 这个函数本来就是设计为阻塞的,没有为什么,PostMessage 则设计为不阻塞的