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.
uj5u.com熱心網友回復:
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);
還是無法解決這個問題
uj5u.com熱心網友回復:
不就是 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;
uj5u.com熱心網友回復:
3樓的兄弟,我是在UNITY里面呼叫api來實作無邊框,無標題欄視窗,然后自己寫dll來實作縮放。你的方法試了下,感覺整個視窗都是非客戶區呢,點任何地方都可以移動。縮放的話,滑鼠必須指到四個角那一個像素上才能縮放。
我想實作的功能是:
1、我的行程是一個POPUP視窗,沒有標題欄和sizebox,我在客戶區自己做了標題欄。
2、拖動標題欄,視窗任意移動。標題欄上最大化,最小化,關閉使用sendmessage的方式實作功能。
3、滑鼠靠近邊框5個像素,靠近4個角10個像素范圍內出現縮放視窗的滑滑鼠記,并且拖動滑鼠可以實作視窗縮放。
uj5u.com熱心網友回復:
1 整個視窗都是非客戶區, 對 你可以改 bottom2 滑鼠必須指到四個角那一個像素上才能縮放。只 做了 4 個
3 TestBorder = 5個像素
uj5u.com熱心網友回復:
5樓,修改掉非客戶去的問題后,你的代碼邏輯上跟我的沒啥分別啊,除了4條邊+5個像素的范圍是非客戶去,其他都是客戶區,對不對?解決不了我的問題啊,我推測是
SendMessage(myWindowHandle, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, 0); 執行后,有什么狀態沒復位,導致這個時候去拖拉邊框縮放依然執行到我的標題欄移動事件了,如果我移動視窗后執行一次SendMessage(myWindowHandle, WM_SYSCOMMAND, SC_MAXIMIZE, 0); 然后再去縮放視窗就一切正常
uj5u.com熱心網友回復:
使用;了 SetCapture(); ?uj5u.com熱心網友回復:
沒有設定過SetCapture(),應該不是這個問題。現在是我拖動自定義的標題欄,觸發標題欄的ondrag事件之后,滑鼠在WM_NCHITTEST中非客戶區的部分拖拽就依然會觸發標題欄的ondrag事件。如果最大化或者最小化一次后,再去WM_NCHITTEST中非客戶區的部分拖拽就正常縮放了,不會觸發標題欄的ondrag事件。
uj5u.com熱心網友回復:
看看你的 ondrag 代碼uj5u.com熱心網友回復:
我現在根據滑鼠當前坐標判斷是否在標題欄可以拖拽范圍內,如果不在直接return,暫時解決了這個問題。希望后面的朋友能解釋下SendMessage(myWindowHandle, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, 0)后,滑鼠有什么狀態不對,導致拖拉邊框也會觸發自定義標題欄的ondrag事件。
uj5u.com熱心網友回復:
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);
}
uj5u.com熱心網友回復:
ReleaseCapture(); ??你不是說 “沒有設定過SetCapture()”
哪里要 ReleaseCapture(); ?
uj5u.com熱心網友回復:
本來 就應該 有if(PtInRect(&rc,pt))
{
return HTCAPTION;
}
uj5u.com熱心網友回復:
SendMessage(myWindowHandle, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, 0);這句實作視窗移動,但是整個行程中的東西感覺全部暫停了,連socket連接也不收發包了,請問有什么辦法可以讓行程不暫停嗎
uj5u.com熱心網友回復:
把其他 作業 放 執行緒 中,如 socket連接uj5u.com熱心網友回復:
除了放執行緒還有么有其它方法呢uj5u.com熱心網友回復:
socket 肯定要放 執行緒中,uj5u.com熱心網友回復:
我socket放執行緒中了,還是要中斷。uj5u.com熱心網友回復:
還是要中斷 ??什么意思,程式出錯 ?
uj5u.com熱心網友回復:
現在還有兩個問題1、SendMessage(myWindowHandle, WM_SYSCOMMAND, SC_MAXIMIZE, 0);實作最大化后,拖動自制標題欄視窗就會還原到之前的狀態,感覺是自動呼叫了Restore。
2、我限制了視窗最大最小尺寸,現在拖拉視窗邊緣縮放視窗大小到最大或者最小值以后視窗開始移動,最終可以移動到螢屏邊緣,然后就消失了,請問怎么能做到縮小到最小尺寸后,視窗不會移動
uj5u.com熱心網友回復:
丟包,在拖動程序中收不到包uj5u.com熱心網友回復:
我是unity做得游戲,就算socket連接沒問題,我的影片這些全都停止了,請問SC_MOVE + HTCAPTION這個程序中是否有什么設定是可以讓行程正常運行的uj5u.com熱心網友回復:
"我的影片這些全都停止了"停一下 有 何妨 ?
拖動 時 程式是 柱塞 的 !
uj5u.com熱心網友回復:
"在拖動程序中收不到包"在拖動程序中程式 不回應其他 訊息
uj5u.com熱心網友回復:
建議 取消 “拖動” 功能,由按鈕 代替uj5u.com熱心網友回復:
windows的標題欄拖動行程沒有阻塞是怎么做到的呢,兄弟能有辦法幫忙查一下么uj5u.com熱心網友回復:
我說的就是 windows的標題欄拖動時 行程會被阻塞,不過 拖動時 只顯示 一個 方框的話會 好的 多。uj5u.com熱心網友回復:
只顯示一個方框怎么實作呢?uj5u.com熱心網友回復:
可以改變 系統 設定,即 SPI_DRAGFULLWINDOW 屬性,你 選擇 重繪 功能 是 用 什么 觸發 的 Timer ?
uj5u.com熱心網友回復:
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;
}
}
uj5u.com熱心網友回復:
@31我是在C#里面呼叫
SendMessage(myWindowHandle, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, 0); 來實作的移動功能
你說的重繪 和 timer 我都沒有設定過相關的屬性,系統默認的,請問怎么能修改呢
uj5u.com熱心網友回復:
在拖動一開始 (按鍵,拖動), 訊息 會 阻塞,不過 一會兒 就恢復 了,"在拖動程序中收不到包",應該采用主程式 收到 后,給執行緒回答一個訊息uj5u.com熱心網友回復:
關于行程阻塞這個問題,我現在放棄用SendMessage來實作視窗拖動,換成在drag事件里面根據滑鼠坐標的變化重新計算視窗位置,然后使用MoveWindow來移動視窗的方法,問題解決了。不過后面看到帖子的朋友,希望能繼續解答SendMessage造成行程停滯的原因及解決方法。uj5u.com熱心網友回復:
//偽標題欄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 );
}
uj5u.com熱心網友回復:
SendMessage 這個函式本來就是設計為阻塞的,沒有為什么,PostMessage 則設計為不阻塞的轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/62485.html
標籤:界面
